github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/gossip/service/integration_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package service
     8  
     9  import (
    10  	"fmt"
    11  	"sync"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/hyperledger/fabric/core/deliverservice"
    16  	"github.com/hyperledger/fabric/core/deliverservice/blocksprovider"
    17  	"github.com/hyperledger/fabric/gossip/api"
    18  	"github.com/hyperledger/fabric/gossip/election"
    19  	"github.com/hyperledger/fabric/gossip/identity"
    20  	"github.com/hyperledger/fabric/gossip/state"
    21  	"github.com/spf13/viper"
    22  	"github.com/stretchr/testify/assert"
    23  )
    24  
    25  type embeddingDeliveryService struct {
    26  	deliverclient.DeliverService
    27  	startSignal sync.WaitGroup
    28  	stopSignal  sync.WaitGroup
    29  }
    30  
    31  func newEmbeddingDeliveryService(ds deliverclient.DeliverService) *embeddingDeliveryService {
    32  	eds := &embeddingDeliveryService{
    33  		DeliverService: ds,
    34  	}
    35  	eds.startSignal.Add(1)
    36  	eds.stopSignal.Add(1)
    37  	return eds
    38  }
    39  
    40  func (eds *embeddingDeliveryService) waitForDeliveryServiceActivation() {
    41  	eds.startSignal.Wait()
    42  }
    43  
    44  func (eds *embeddingDeliveryService) waitForDeliveryServiceTermination() {
    45  	eds.stopSignal.Wait()
    46  }
    47  
    48  func (eds *embeddingDeliveryService) StartDeliverForChannel(chainID string, ledgerInfo blocksprovider.LedgerInfo, finalizer func()) error {
    49  	eds.startSignal.Done()
    50  	return eds.DeliverService.StartDeliverForChannel(chainID, ledgerInfo, finalizer)
    51  }
    52  
    53  func (eds *embeddingDeliveryService) StopDeliverForChannel(chainID string) error {
    54  	eds.stopSignal.Done()
    55  	return eds.DeliverService.StopDeliverForChannel(chainID)
    56  }
    57  
    58  func (eds *embeddingDeliveryService) Stop() {
    59  	eds.DeliverService.Stop()
    60  }
    61  
    62  type embeddingDeliveryServiceFactory struct {
    63  	DeliveryServiceFactory
    64  }
    65  
    66  func (edsf *embeddingDeliveryServiceFactory) Service(g GossipService, endpoints []string, mcs api.MessageCryptoService) (deliverclient.DeliverService, error) {
    67  	ds, _ := edsf.DeliveryServiceFactory.Service(g, endpoints, mcs)
    68  	return newEmbeddingDeliveryService(ds), nil
    69  }
    70  
    71  func TestLeaderYield(t *testing.T) {
    72  	// Scenario: Spawn 2 peers and wait for the first one to be the leader
    73  	// There isn't any orderer present so the leader peer won't be able to
    74  	// connect to the orderer, and should relinquish its leadership after a while.
    75  	// Make sure the other peer declares itself as the leader soon after.
    76  	deliverclient.SetReconnectTotalTimeThreshold(time.Second * 5)
    77  	viper.Set("peer.gossip.useLeaderElection", true)
    78  	viper.Set("peer.gossip.orgLeader", false)
    79  	n := 2
    80  	portPrefix := 30000
    81  	gossips := startPeers(t, n, portPrefix)
    82  	defer stopPeers(gossips)
    83  	channelName := "channelA"
    84  	peerIndexes := []int{0, 1}
    85  	// Add peers to the channel
    86  	addPeersToChannel(t, n, portPrefix, channelName, gossips, peerIndexes)
    87  	// Prime the membership view of the peers
    88  	waitForFullMembership(t, gossips, n, time.Second*30, time.Second*2)
    89  	mcs := &naiveCryptoService{}
    90  	// Helper function that creates a gossipService instance
    91  	newGossipService := func(i int) *gossipServiceImpl {
    92  		peerIdentity := api.PeerIdentityType(fmt.Sprintf("localhost:%d", portPrefix+i))
    93  		gs := &gossipServiceImpl{
    94  			mcs:             mcs,
    95  			gossipSvc:       gossips[i],
    96  			chains:          make(map[string]state.GossipStateProvider),
    97  			leaderElection:  make(map[string]election.LeaderElectionService),
    98  			deliveryFactory: &embeddingDeliveryServiceFactory{&deliveryFactoryImpl{}},
    99  			idMapper:        identity.NewIdentityMapper(mcs, peerIdentity),
   100  			peerIdentity:    peerIdentity,
   101  			secAdv:          &secAdvMock{},
   102  		}
   103  		gossipServiceInstance = gs
   104  		gs.InitializeChannel(channelName, &mockLedgerInfo{1}, []string{"localhost:7050"})
   105  		return gs
   106  	}
   107  
   108  	p0 := newGossipService(0)
   109  	p1 := newGossipService(1)
   110  
   111  	// Returns index of the leader or -1 if no leader elected
   112  	getLeader := func() int {
   113  		if p0.leaderElection[channelName].IsLeader() {
   114  			// Ensure p1 isn't a leader at the same time
   115  			assert.False(t, p1.leaderElection[channelName].IsLeader())
   116  			return 0
   117  		}
   118  		if p1.leaderElection[channelName].IsLeader() {
   119  			return 1
   120  		}
   121  		return -1
   122  	}
   123  
   124  	ds0 := p0.deliveryService.(*embeddingDeliveryService)
   125  	ds1 := p1.deliveryService.(*embeddingDeliveryService)
   126  
   127  	// Wait for p0 to connect to the ordering service
   128  	ds0.waitForDeliveryServiceActivation()
   129  	t.Log("p0 started its delivery service")
   130  	// Ensure it's a leader
   131  	assert.Equal(t, 0, getLeader())
   132  	// Wait for p0 to lose its leadership
   133  	ds0.waitForDeliveryServiceTermination()
   134  	t.Log("p0 stopped its delivery service")
   135  	// Ensure there is no leader
   136  	assert.Equal(t, -1, getLeader())
   137  	// Wait for p1 to take over
   138  	ds1.waitForDeliveryServiceActivation()
   139  	t.Log("p1 started its delivery service")
   140  	// Ensure it's a leader now
   141  	assert.Equal(t, 1, getLeader())
   142  	p0.chains[channelName].Stop()
   143  	p1.chains[channelName].Stop()
   144  	p0.deliveryService.Stop()
   145  	p1.deliveryService.Stop()
   146  }