github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/gossip/discovery/discovery_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package discovery
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  	"math/rand"
    23  	"net"
    24  	"sort"
    25  	"strconv"
    26  	"strings"
    27  	"sync"
    28  	"sync/atomic"
    29  	"testing"
    30  	"time"
    31  
    32  	"github.com/hyperledger/fabric/core/config"
    33  	"github.com/hyperledger/fabric/gossip/common"
    34  	"github.com/hyperledger/fabric/gossip/util"
    35  	proto "github.com/hyperledger/fabric/protos/gossip"
    36  	"github.com/spf13/viper"
    37  	"github.com/stretchr/testify/assert"
    38  	"github.com/stretchr/testify/mock"
    39  	"golang.org/x/net/context"
    40  	"google.golang.org/grpc"
    41  )
    42  
    43  var timeout = time.Second * time.Duration(15)
    44  
    45  func init() {
    46  	util.SetupTestLogging()
    47  	aliveTimeInterval := time.Duration(time.Millisecond * 100)
    48  	SetAliveTimeInterval(aliveTimeInterval)
    49  	SetAliveExpirationTimeout(10 * aliveTimeInterval)
    50  	SetAliveExpirationCheckInterval(aliveTimeInterval)
    51  	SetReconnectInterval(10 * aliveTimeInterval)
    52  	maxConnectionAttempts = 10000
    53  }
    54  
    55  type dummyCommModule struct {
    56  	id           string
    57  	presumeDead  chan common.PKIidType
    58  	detectedDead chan string
    59  	streams      map[string]proto.Gossip_GossipStreamClient
    60  	conns        map[string]*grpc.ClientConn
    61  	lock         *sync.RWMutex
    62  	incMsgs      chan *proto.SignedGossipMessage
    63  	lastSeqs     map[string]uint64
    64  	shouldGossip bool
    65  	mock         *mock.Mock
    66  }
    67  
    68  type gossipMsg struct {
    69  	*proto.GossipMessage
    70  }
    71  
    72  func (m *gossipMsg) GetGossipMessage() *proto.GossipMessage {
    73  	return m.GossipMessage
    74  }
    75  
    76  type gossipInstance struct {
    77  	comm *dummyCommModule
    78  	Discovery
    79  	gRGCserv      *grpc.Server
    80  	lsnr          net.Listener
    81  	shouldGossip  bool
    82  	syncInitiator *time.Ticker
    83  	stopChan      chan struct{}
    84  	port          int
    85  }
    86  
    87  func (comm *dummyCommModule) ValidateAliveMsg(am *proto.SignedGossipMessage) bool {
    88  	return true
    89  }
    90  
    91  func (comm *dummyCommModule) SignMessage(am *proto.GossipMessage, internalEndpoint string) *proto.Envelope {
    92  	am.NoopSign()
    93  
    94  	secret := &proto.Secret{
    95  		Content: &proto.Secret_InternalEndpoint{
    96  			InternalEndpoint: internalEndpoint,
    97  		},
    98  	}
    99  	signer := func(msg []byte) ([]byte, error) {
   100  		return nil, nil
   101  	}
   102  	env := am.NoopSign().Envelope
   103  	env.SignSecret(signer, secret)
   104  	return env
   105  }
   106  
   107  func (comm *dummyCommModule) Gossip(msg *proto.SignedGossipMessage) {
   108  	if !comm.shouldGossip {
   109  		return
   110  	}
   111  	comm.lock.Lock()
   112  	defer comm.lock.Unlock()
   113  	for _, conn := range comm.streams {
   114  		conn.Send(msg.Envelope)
   115  	}
   116  }
   117  
   118  func (comm *dummyCommModule) SendToPeer(peer *NetworkMember, msg *proto.SignedGossipMessage) {
   119  	comm.lock.RLock()
   120  	_, exists := comm.streams[peer.Endpoint]
   121  	mock := comm.mock
   122  	comm.lock.RUnlock()
   123  
   124  	if mock != nil {
   125  		mock.Called(peer, msg)
   126  	}
   127  
   128  	if !exists {
   129  		if comm.Ping(peer) == false {
   130  			fmt.Printf("Ping to %v failed\n", peer.Endpoint)
   131  			return
   132  		}
   133  	}
   134  	comm.lock.Lock()
   135  	comm.streams[peer.Endpoint].Send(msg.NoopSign().Envelope)
   136  	comm.lock.Unlock()
   137  }
   138  
   139  func (comm *dummyCommModule) Ping(peer *NetworkMember) bool {
   140  	comm.lock.Lock()
   141  	defer comm.lock.Unlock()
   142  
   143  	if comm.mock != nil {
   144  		comm.mock.Called()
   145  	}
   146  
   147  	_, alreadyExists := comm.streams[peer.Endpoint]
   148  	if !alreadyExists {
   149  		newConn, err := grpc.Dial(peer.Endpoint, grpc.WithInsecure())
   150  		if err != nil {
   151  			return false
   152  		}
   153  		if stream, err := proto.NewGossipClient(newConn).GossipStream(context.Background()); err == nil {
   154  			comm.conns[peer.Endpoint] = newConn
   155  			comm.streams[peer.Endpoint] = stream
   156  			return true
   157  		}
   158  		return false
   159  	}
   160  	conn := comm.conns[peer.Endpoint]
   161  	if _, err := proto.NewGossipClient(conn).Ping(context.Background(), &proto.Empty{}); err != nil {
   162  		return false
   163  	}
   164  	return true
   165  }
   166  
   167  func (comm *dummyCommModule) Accept() <-chan *proto.SignedGossipMessage {
   168  	return comm.incMsgs
   169  }
   170  
   171  func (comm *dummyCommModule) PresumedDead() <-chan common.PKIidType {
   172  	return comm.presumeDead
   173  }
   174  
   175  func (comm *dummyCommModule) CloseConn(peer *NetworkMember) {
   176  	comm.lock.Lock()
   177  	defer comm.lock.Unlock()
   178  
   179  	if _, exists := comm.streams[peer.Endpoint]; !exists {
   180  		return
   181  	}
   182  
   183  	comm.streams[peer.Endpoint].CloseSend()
   184  	comm.conns[peer.Endpoint].Close()
   185  }
   186  
   187  func (g *gossipInstance) initiateSync(frequency time.Duration, peerNum int) {
   188  	g.syncInitiator = time.NewTicker(frequency)
   189  	g.stopChan = make(chan struct{})
   190  	go func() {
   191  		for {
   192  			select {
   193  			case <-g.syncInitiator.C:
   194  				g.Discovery.InitiateSync(peerNum)
   195  			case <-g.stopChan:
   196  				g.syncInitiator.Stop()
   197  				return
   198  			}
   199  		}
   200  	}()
   201  }
   202  
   203  func (g *gossipInstance) GossipStream(stream proto.Gossip_GossipStreamServer) error {
   204  	for {
   205  		envelope, err := stream.Recv()
   206  		if err == io.EOF {
   207  			return nil
   208  		}
   209  		if err != nil {
   210  			return err
   211  		}
   212  		lgr := g.Discovery.(*gossipDiscoveryImpl).logger
   213  		gMsg, err := envelope.ToGossipMessage()
   214  		if err != nil {
   215  			lgr.Warning("Failed deserializing GossipMessage from envelope:", err)
   216  			continue
   217  		}
   218  
   219  		lgr.Debug(g.Discovery.Self().Endpoint, "Got message:", gMsg)
   220  		g.comm.incMsgs <- gMsg
   221  
   222  		if aliveMsg := gMsg.GetAliveMsg(); aliveMsg != nil {
   223  			g.tryForwardMessage(gMsg)
   224  		}
   225  	}
   226  }
   227  
   228  func (g *gossipInstance) tryForwardMessage(msg *proto.SignedGossipMessage) {
   229  	g.comm.lock.Lock()
   230  
   231  	aliveMsg := msg.GetAliveMsg()
   232  
   233  	forward := false
   234  	id := string(aliveMsg.Membership.PkiId)
   235  	seqNum := aliveMsg.Timestamp.SeqNum
   236  	if last, exists := g.comm.lastSeqs[id]; exists {
   237  		if last < seqNum {
   238  			g.comm.lastSeqs[id] = seqNum
   239  			forward = true
   240  		}
   241  	} else {
   242  		g.comm.lastSeqs[id] = seqNum
   243  		forward = true
   244  	}
   245  
   246  	g.comm.lock.Unlock()
   247  
   248  	if forward {
   249  		g.comm.Gossip(msg)
   250  	}
   251  }
   252  
   253  func (g *gossipInstance) Stop() {
   254  	if g.syncInitiator != nil {
   255  		g.stopChan <- struct{}{}
   256  	}
   257  	g.gRGCserv.Stop()
   258  	g.lsnr.Close()
   259  	for _, stream := range g.comm.streams {
   260  		stream.CloseSend()
   261  	}
   262  	for _, conn := range g.comm.conns {
   263  		conn.Close()
   264  	}
   265  	g.Discovery.Stop()
   266  }
   267  
   268  func (g *gossipInstance) Ping(context.Context, *proto.Empty) (*proto.Empty, error) {
   269  	return &proto.Empty{}, nil
   270  }
   271  
   272  var noopPolicy = func(remotePeer *NetworkMember) (Sieve, EnvelopeFilter) {
   273  	return func(msg *proto.SignedGossipMessage) bool {
   274  			return true
   275  		}, func(message *proto.SignedGossipMessage) *proto.Envelope {
   276  			return message.Envelope
   277  		}
   278  }
   279  
   280  func createDiscoveryInstance(port int, id string, bootstrapPeers []string) *gossipInstance {
   281  	return createDiscoveryInstanceThatGossips(port, id, bootstrapPeers, true, noopPolicy)
   282  }
   283  
   284  func createDiscoveryInstanceWithNoGossip(port int, id string, bootstrapPeers []string) *gossipInstance {
   285  	return createDiscoveryInstanceThatGossips(port, id, bootstrapPeers, false, noopPolicy)
   286  }
   287  
   288  func createDiscoveryInstanceWithNoGossipWithDisclosurePolicy(port int, id string, bootstrapPeers []string, pol DisclosurePolicy) *gossipInstance {
   289  	return createDiscoveryInstanceThatGossips(port, id, bootstrapPeers, false, pol)
   290  }
   291  
   292  func createDiscoveryInstanceThatGossips(port int, id string, bootstrapPeers []string, shouldGossip bool, pol DisclosurePolicy) *gossipInstance {
   293  	comm := &dummyCommModule{
   294  		conns:        make(map[string]*grpc.ClientConn),
   295  		streams:      make(map[string]proto.Gossip_GossipStreamClient),
   296  		incMsgs:      make(chan *proto.SignedGossipMessage, 1000),
   297  		presumeDead:  make(chan common.PKIidType, 10000),
   298  		id:           id,
   299  		detectedDead: make(chan string, 10000),
   300  		lock:         &sync.RWMutex{},
   301  		lastSeqs:     make(map[string]uint64),
   302  		shouldGossip: shouldGossip,
   303  	}
   304  
   305  	endpoint := fmt.Sprintf("localhost:%d", port)
   306  	self := NetworkMember{
   307  		Metadata:         []byte{},
   308  		PKIid:            []byte(endpoint),
   309  		Endpoint:         endpoint,
   310  		InternalEndpoint: endpoint,
   311  	}
   312  
   313  	listenAddress := fmt.Sprintf("%s:%d", "", port)
   314  	ll, err := net.Listen("tcp", listenAddress)
   315  	if err != nil {
   316  		fmt.Printf("Error listening on %v, %v", listenAddress, err)
   317  	}
   318  	s := grpc.NewServer()
   319  
   320  	discSvc := NewDiscoveryService(bootstrapPeers, self, comm, comm, pol)
   321  	gossInst := &gossipInstance{comm: comm, gRGCserv: s, Discovery: discSvc, lsnr: ll, shouldGossip: shouldGossip, port: port}
   322  
   323  	proto.RegisterGossipServer(s, gossInst)
   324  	go s.Serve(ll)
   325  
   326  	return gossInst
   327  }
   328  
   329  func bootPeer(port int) string {
   330  	return fmt.Sprintf("localhost:%d", port)
   331  }
   332  
   333  func TestToString(t *testing.T) {
   334  	nm := NetworkMember{
   335  		Endpoint:         "a",
   336  		InternalEndpoint: "b",
   337  	}
   338  	assert.Equal(t, "b", nm.PreferredEndpoint())
   339  	nm = NetworkMember{
   340  		Endpoint: "a",
   341  	}
   342  	assert.Equal(t, "a", nm.PreferredEndpoint())
   343  
   344  	now := time.Now()
   345  	ts := &timestamp{
   346  		incTime: now,
   347  		seqNum:  uint64(42),
   348  	}
   349  	assert.Equal(t, fmt.Sprintf("%d, %d", now.UnixNano(), 42), fmt.Sprint(ts))
   350  }
   351  
   352  func TestBadInput(t *testing.T) {
   353  	inst := createDiscoveryInstance(2048, fmt.Sprintf("d%d", 0), []string{})
   354  	inst.Discovery.(*gossipDiscoveryImpl).handleMsgFromComm(nil)
   355  	inst.Discovery.(*gossipDiscoveryImpl).handleMsgFromComm((&proto.GossipMessage{
   356  		Content: &proto.GossipMessage_DataMsg{
   357  			DataMsg: &proto.DataMessage{},
   358  		},
   359  	}).NoopSign())
   360  }
   361  
   362  func TestConnect(t *testing.T) {
   363  	t.Parallel()
   364  	nodeNum := 10
   365  	instances := []*gossipInstance{}
   366  	firstSentMemReqMsgs := make(chan *proto.SignedGossipMessage, nodeNum)
   367  	for i := 0; i < nodeNum; i++ {
   368  		inst := createDiscoveryInstance(7611+i, fmt.Sprintf("d%d", i), []string{})
   369  
   370  		inst.comm.lock.Lock()
   371  		inst.comm.mock = &mock.Mock{}
   372  		inst.comm.mock.On("SendToPeer", mock.Anything, mock.Anything).Run(func(arguments mock.Arguments) {
   373  			inst := inst
   374  			msg := arguments.Get(1).(*proto.SignedGossipMessage)
   375  			if req := msg.GetMemReq(); req != nil {
   376  				selfMsg, _ := req.SelfInformation.ToGossipMessage()
   377  				firstSentMemReqMsgs <- selfMsg
   378  				inst.comm.lock.Lock()
   379  				inst.comm.mock = nil
   380  				inst.comm.lock.Unlock()
   381  			}
   382  		})
   383  		inst.comm.mock.On("Ping", mock.Anything)
   384  		inst.comm.lock.Unlock()
   385  
   386  		instances = append(instances, inst)
   387  		j := (i + 1) % 10
   388  		endpoint := fmt.Sprintf("localhost:%d", 7611+j)
   389  		netMember2Connect2 := NetworkMember{Endpoint: endpoint, PKIid: []byte(endpoint)}
   390  		inst.Connect(netMember2Connect2, func() bool { return false })
   391  	}
   392  
   393  	time.Sleep(time.Second * 3)
   394  	assert.Len(t, firstSentMemReqMsgs, 10)
   395  	close(firstSentMemReqMsgs)
   396  	for firstSentSelfMsg := range firstSentMemReqMsgs {
   397  		assert.Nil(t, firstSentSelfMsg.Envelope.SecretEnvelope)
   398  	}
   399  
   400  	fullMembership := func() bool {
   401  		return nodeNum-1 == len(instances[nodeNum-1].GetMembership())
   402  	}
   403  	waitUntilOrFail(t, fullMembership)
   404  
   405  	discInst := instances[rand.Intn(len(instances))].Discovery.(*gossipDiscoveryImpl)
   406  	am, _ := discInst.createMembershipRequest(true).GetMemReq().SelfInformation.ToGossipMessage()
   407  	assert.NotNil(t, am.SecretEnvelope)
   408  	am, _ = discInst.createMembershipRequest(false).GetMemReq().SelfInformation.ToGossipMessage()
   409  	assert.Nil(t, am.SecretEnvelope)
   410  	stopInstances(t, instances)
   411  }
   412  
   413  func TestUpdate(t *testing.T) {
   414  	t.Parallel()
   415  	nodeNum := 5
   416  	bootPeers := []string{bootPeer(6611), bootPeer(6612)}
   417  	instances := []*gossipInstance{}
   418  
   419  	inst := createDiscoveryInstance(6611, "d1", bootPeers)
   420  	instances = append(instances, inst)
   421  
   422  	inst = createDiscoveryInstance(6612, "d2", bootPeers)
   423  	instances = append(instances, inst)
   424  
   425  	for i := 3; i <= nodeNum; i++ {
   426  		id := fmt.Sprintf("d%d", i)
   427  		inst = createDiscoveryInstance(6610+i, id, bootPeers)
   428  		instances = append(instances, inst)
   429  	}
   430  
   431  	fullMembership := func() bool {
   432  		return nodeNum-1 == len(instances[nodeNum-1].GetMembership())
   433  	}
   434  
   435  	waitUntilOrFail(t, fullMembership)
   436  
   437  	instances[0].UpdateMetadata([]byte("bla bla"))
   438  	instances[nodeNum-1].UpdateEndpoint("localhost:5511")
   439  
   440  	checkMembership := func() bool {
   441  		for _, member := range instances[nodeNum-1].GetMembership() {
   442  			if string(member.PKIid) == instances[0].comm.id {
   443  				if "bla bla" != string(member.Metadata) {
   444  					return false
   445  				}
   446  			}
   447  		}
   448  
   449  		for _, member := range instances[0].GetMembership() {
   450  			if string(member.PKIid) == instances[nodeNum-1].comm.id {
   451  				if "localhost:5511" != string(member.Endpoint) {
   452  					return false
   453  				}
   454  			}
   455  		}
   456  		return true
   457  	}
   458  
   459  	waitUntilOrFail(t, checkMembership)
   460  	stopInstances(t, instances)
   461  }
   462  
   463  func TestInitiateSync(t *testing.T) {
   464  	t.Parallel()
   465  	nodeNum := 10
   466  	bootPeers := []string{bootPeer(3611), bootPeer(3612)}
   467  	instances := []*gossipInstance{}
   468  
   469  	toDie := int32(0)
   470  	for i := 1; i <= nodeNum; i++ {
   471  		id := fmt.Sprintf("d%d", i)
   472  		inst := createDiscoveryInstanceWithNoGossip(3610+i, id, bootPeers)
   473  		instances = append(instances, inst)
   474  		go func() {
   475  			for {
   476  				if atomic.LoadInt32(&toDie) == int32(1) {
   477  					return
   478  				}
   479  				time.Sleep(getAliveExpirationTimeout() / 3)
   480  				inst.InitiateSync(9)
   481  			}
   482  		}()
   483  	}
   484  	time.Sleep(getAliveExpirationTimeout() * 4)
   485  	assertMembership(t, instances, nodeNum-1)
   486  	atomic.StoreInt32(&toDie, int32(1))
   487  	stopInstances(t, instances)
   488  }
   489  
   490  func TestExpiration(t *testing.T) {
   491  	t.Parallel()
   492  	nodeNum := 5
   493  	bootPeers := []string{bootPeer(2611), bootPeer(2612)}
   494  	instances := []*gossipInstance{}
   495  
   496  	inst := createDiscoveryInstance(2611, "d1", bootPeers)
   497  	instances = append(instances, inst)
   498  
   499  	inst = createDiscoveryInstance(2612, "d2", bootPeers)
   500  	instances = append(instances, inst)
   501  
   502  	for i := 3; i <= nodeNum; i++ {
   503  		id := fmt.Sprintf("d%d", i)
   504  		inst = createDiscoveryInstance(2610+i, id, bootPeers)
   505  		instances = append(instances, inst)
   506  	}
   507  
   508  	assertMembership(t, instances, nodeNum-1)
   509  
   510  	waitUntilOrFailBlocking(t, instances[nodeNum-1].Stop)
   511  	waitUntilOrFailBlocking(t, instances[nodeNum-2].Stop)
   512  
   513  	assertMembership(t, instances, nodeNum-3)
   514  
   515  	stopAction := &sync.WaitGroup{}
   516  	for i, inst := range instances {
   517  		if i+2 == nodeNum {
   518  			break
   519  		}
   520  		stopAction.Add(1)
   521  		go func(inst *gossipInstance) {
   522  			defer stopAction.Done()
   523  			inst.Stop()
   524  		}(inst)
   525  	}
   526  
   527  	waitUntilOrFailBlocking(t, stopAction.Wait)
   528  }
   529  
   530  func TestGetFullMembership(t *testing.T) {
   531  	t.Parallel()
   532  	nodeNum := 15
   533  	bootPeers := []string{bootPeer(5511), bootPeer(5512)}
   534  	instances := []*gossipInstance{}
   535  	var inst *gossipInstance
   536  
   537  	for i := 3; i <= nodeNum; i++ {
   538  		id := fmt.Sprintf("d%d", i)
   539  		inst = createDiscoveryInstance(5510+i, id, bootPeers)
   540  		instances = append(instances, inst)
   541  	}
   542  
   543  	time.Sleep(time.Second)
   544  
   545  	inst = createDiscoveryInstance(5511, "d1", bootPeers)
   546  	instances = append(instances, inst)
   547  
   548  	inst = createDiscoveryInstance(5512, "d2", bootPeers)
   549  	instances = append(instances, inst)
   550  
   551  	assertMembership(t, instances, nodeNum-1)
   552  
   553  	// Ensure that internal endpoint was propagated to everyone
   554  	for _, inst := range instances {
   555  		for _, member := range inst.GetMembership() {
   556  			assert.NotEmpty(t, member.InternalEndpoint)
   557  			assert.NotEmpty(t, member.Endpoint)
   558  		}
   559  	}
   560  
   561  	// Check that Lookup() is valid
   562  	for _, inst := range instances {
   563  		for _, member := range inst.GetMembership() {
   564  			assert.Equal(t, string(member.PKIid), inst.Lookup(member.PKIid).Endpoint)
   565  			assert.Equal(t, member.PKIid, inst.Lookup(member.PKIid).PKIid)
   566  		}
   567  	}
   568  
   569  	stopInstances(t, instances)
   570  }
   571  
   572  func TestGossipDiscoveryStopping(t *testing.T) {
   573  	t.Parallel()
   574  	inst := createDiscoveryInstance(9611, "d1", []string{bootPeer(9611)})
   575  	time.Sleep(time.Second)
   576  	waitUntilOrFailBlocking(t, inst.Stop)
   577  }
   578  
   579  func TestGossipDiscoverySkipConnectingToLocalhostBootstrap(t *testing.T) {
   580  	t.Parallel()
   581  	inst := createDiscoveryInstance(11611, "d1", []string{"localhost:11611", "127.0.0.1:11611"})
   582  	inst.comm.lock.Lock()
   583  	inst.comm.mock = &mock.Mock{}
   584  	inst.comm.mock.On("SendToPeer", mock.Anything).Run(func(mock.Arguments) {
   585  		t.Fatal("Should not have connected to any peer")
   586  	})
   587  	inst.comm.mock.On("Ping", mock.Anything).Run(func(mock.Arguments) {
   588  		t.Fatal("Should not have connected to any peer")
   589  	})
   590  	inst.comm.lock.Unlock()
   591  	time.Sleep(time.Second * 3)
   592  	waitUntilOrFailBlocking(t, inst.Stop)
   593  }
   594  
   595  func TestConvergence(t *testing.T) {
   596  	t.Parallel()
   597  	// scenario:
   598  	// {boot peer: [peer list]}
   599  	// {d1: d2, d3, d4}
   600  	// {d5: d6, d7, d8}
   601  	// {d9: d10, d11, d12}
   602  	// connect all boot peers with d13
   603  	// take down d13
   604  	// ensure still full membership
   605  	instances := []*gossipInstance{}
   606  	for _, i := range []int{1, 5, 9} {
   607  		bootPort := 4610 + i
   608  		id := fmt.Sprintf("d%d", i)
   609  		leader := createDiscoveryInstance(bootPort, id, []string{})
   610  		instances = append(instances, leader)
   611  		for minionIndex := 1; minionIndex <= 3; minionIndex++ {
   612  			id := fmt.Sprintf("d%d", i+minionIndex)
   613  			minion := createDiscoveryInstance(4610+minionIndex+i, id, []string{bootPeer(bootPort)})
   614  			instances = append(instances, minion)
   615  		}
   616  	}
   617  
   618  	assertMembership(t, instances, 3)
   619  	connector := createDiscoveryInstance(4623, "d13", []string{bootPeer(4611), bootPeer(4615), bootPeer(4619)})
   620  	instances = append(instances, connector)
   621  	assertMembership(t, instances, 12)
   622  	connector.Stop()
   623  	instances = instances[:len(instances)-1]
   624  	assertMembership(t, instances, 11)
   625  	stopInstances(t, instances)
   626  }
   627  
   628  func TestDisclosurePolicyWithPull(t *testing.T) {
   629  	t.Parallel()
   630  	// Scenario: run 2 groups of peers that simulate 2 organizations:
   631  	// {p0, p1, p2, p3, p4}
   632  	// {p5, p6, p7, p8, p9}
   633  	// Only peers that have an even id have external addresses
   634  	// and only these peers should be published to peers of the other group,
   635  	// while the only ones that need to know about them are peers
   636  	// that have an even id themselves.
   637  	// Furthermore, peers in different sets, should not know about internal addresses of
   638  	// other peers.
   639  
   640  	// This is a bootstrap map that matches for each peer its own bootstrap peer.
   641  	// In practice (production) peers should only use peers of their orgs as bootstrap peers,
   642  	// but the discovery layer is ignorant of organizations.
   643  	bootPeerMap := map[int]int{
   644  		8610: 8616,
   645  		8611: 8610,
   646  		8612: 8610,
   647  		8613: 8610,
   648  		8614: 8610,
   649  		8615: 8616,
   650  		8616: 8610,
   651  		8617: 8616,
   652  		8618: 8616,
   653  		8619: 8616,
   654  	}
   655  
   656  	// This map matches each peer, the peers it should know about in the test scenario.
   657  	peersThatShouldBeKnownToPeers := map[int][]int{
   658  		8610: {8611, 8612, 8613, 8614, 8616, 8618},
   659  		8611: {8610, 8612, 8613, 8614},
   660  		8612: {8610, 8611, 8613, 8614, 8616, 8618},
   661  		8613: {8610, 8611, 8612, 8614},
   662  		8614: {8610, 8611, 8612, 8613, 8616, 8618},
   663  		8615: {8616, 8617, 8618, 8619},
   664  		8616: {8610, 8612, 8614, 8615, 8617, 8618, 8619},
   665  		8617: {8615, 8616, 8618, 8619},
   666  		8618: {8610, 8612, 8614, 8615, 8616, 8617, 8619},
   667  		8619: {8615, 8616, 8617, 8618},
   668  	}
   669  	// Create the peers in the two groups
   670  	instances1, instances2 := createDisjointPeerGroupsWithNoGossip(bootPeerMap)
   671  	// Sleep a while to let them establish membership. This time should be more than enough
   672  	// because the instances are configured to pull membership in very high frequency from
   673  	// up to 10 peers (which results in - pulling from everyone)
   674  	waitUntilOrFail(t, func() bool {
   675  		for _, inst := range append(instances1, instances2...) {
   676  			// Ensure the expected membership is equal in size to the actual membership
   677  			// of each peer.
   678  			portsOfKnownMembers := portsOfMembers(inst.GetMembership())
   679  			if len(peersThatShouldBeKnownToPeers[inst.port]) != len(portsOfKnownMembers) {
   680  				return false
   681  			}
   682  		}
   683  		return true
   684  	})
   685  	for _, inst := range append(instances1, instances2...) {
   686  		portsOfKnownMembers := portsOfMembers(inst.GetMembership())
   687  		// Ensure the expected membership is equal to the actual membership
   688  		// of each peer. the portsOfMembers returns a sorted slice so assert.Equal does the job.
   689  		assert.Equal(t, peersThatShouldBeKnownToPeers[inst.port], portsOfKnownMembers)
   690  		// Next, check that internal endpoints aren't leaked across groups,
   691  		for _, knownPeer := range inst.GetMembership() {
   692  			// If internal endpoint is known, ensure the peers are in the same group
   693  			// unless the peer in question is a peer that has a public address.
   694  			// We cannot control what we disclose about ourselves when we send a membership request
   695  			if len(knownPeer.InternalEndpoint) > 0 && inst.port%2 != 0 {
   696  				bothInGroup1 := portOfEndpoint(knownPeer.Endpoint) < 8615 && inst.port < 8615
   697  				bothInGroup2 := portOfEndpoint(knownPeer.Endpoint) >= 8615 && inst.port >= 8615
   698  				assert.True(t, bothInGroup1 || bothInGroup2, "%v knows about %v's internal endpoint", inst.port, knownPeer.InternalEndpoint)
   699  			}
   700  		}
   701  	}
   702  
   703  	t.Log("Shutting down instance 0...")
   704  	// Now, we shutdown instance 0 and ensure that peers that shouldn't know it,
   705  	// do not know it via membership requests
   706  	stopInstances(t, []*gossipInstance{instances1[0]})
   707  	time.Sleep(time.Second * 3)
   708  	for _, inst := range append(instances1[1:], instances2...) {
   709  		if peersThatShouldBeKnownToPeers[inst.port][0] == 8610 {
   710  			assert.Equal(t, 1, inst.Discovery.(*gossipDiscoveryImpl).deadMembership.Size())
   711  		} else {
   712  			assert.Equal(t, 0, inst.Discovery.(*gossipDiscoveryImpl).deadMembership.Size())
   713  		}
   714  	}
   715  	stopInstances(t, instances1[1:])
   716  	stopInstances(t, instances2)
   717  }
   718  
   719  func createDisjointPeerGroupsWithNoGossip(bootPeerMap map[int]int) ([]*gossipInstance, []*gossipInstance) {
   720  	instances1 := []*gossipInstance{}
   721  	instances2 := []*gossipInstance{}
   722  	for group := 0; group < 2; group++ {
   723  		for i := 0; i < 5; i++ {
   724  			group := group
   725  			id := fmt.Sprintf("id%d", group*5+i)
   726  			port := 8610 + group*5 + i
   727  			bootPeers := []string{bootPeer(bootPeerMap[port])}
   728  			pol := discPolForPeer(port)
   729  			inst := createDiscoveryInstanceWithNoGossipWithDisclosurePolicy(8610+group*5+i, id, bootPeers, pol)
   730  			inst.initiateSync(getAliveExpirationTimeout()/3, 10)
   731  			if group == 0 {
   732  				instances1 = append(instances1, inst)
   733  			} else {
   734  				instances2 = append(instances2, inst)
   735  			}
   736  		}
   737  	}
   738  	return instances1, instances2
   739  }
   740  
   741  func discPolForPeer(selfPort int) DisclosurePolicy {
   742  	return func(remotePeer *NetworkMember) (Sieve, EnvelopeFilter) {
   743  		targetPortStr := strings.Split(remotePeer.Endpoint, ":")[1]
   744  		targetPort, _ := strconv.ParseInt(targetPortStr, 10, 64)
   745  		return func(msg *proto.SignedGossipMessage) bool {
   746  				portOfAliveMsgStr := strings.Split(msg.GetAliveMsg().Membership.Endpoint, ":")[1]
   747  				portOfAliveMsg, _ := strconv.ParseInt(portOfAliveMsgStr, 10, 64)
   748  
   749  				if portOfAliveMsg < 8615 && targetPort < 8615 {
   750  					return true
   751  				}
   752  				if portOfAliveMsg >= 8615 && targetPort >= 8615 {
   753  					return true
   754  				}
   755  
   756  				// Else, expose peers with even ids to other peers with even ids
   757  				return portOfAliveMsg%2 == 0 && targetPort%2 == 0
   758  			}, func(msg *proto.SignedGossipMessage) *proto.Envelope {
   759  				if selfPort < 8615 && targetPort >= 8615 {
   760  					msg.Envelope.SecretEnvelope = nil
   761  				}
   762  
   763  				if selfPort >= 8615 && targetPort < 8615 {
   764  					msg.Envelope.SecretEnvelope = nil
   765  				}
   766  
   767  				return msg.Envelope
   768  			}
   769  	}
   770  }
   771  
   772  func TestConfigFromFile(t *testing.T) {
   773  	preAliveTimeInterval := getAliveTimeInterval()
   774  	preAliveExpirationTimeout := getAliveExpirationTimeout()
   775  	preAliveExpirationCheckInterval := getAliveExpirationCheckInterval()
   776  	preReconnectInterval := getReconnectInterval()
   777  
   778  	// Recover the config values in order to avoid impacting other tests
   779  	defer func() {
   780  		SetAliveTimeInterval(preAliveTimeInterval)
   781  		SetAliveExpirationTimeout(preAliveExpirationTimeout)
   782  		SetAliveExpirationCheckInterval(preAliveExpirationCheckInterval)
   783  		SetReconnectInterval(preReconnectInterval)
   784  	}()
   785  
   786  	// Verify if using default values when config is missing
   787  	viper.Reset()
   788  	aliveExpirationCheckInterval = 0 * time.Second
   789  	assert.Equal(t, time.Duration(5)*time.Second, getAliveTimeInterval())
   790  	assert.Equal(t, time.Duration(25)*time.Second, getAliveExpirationTimeout())
   791  	assert.Equal(t, time.Duration(25)*time.Second/10, getAliveExpirationCheckInterval())
   792  	assert.Equal(t, time.Duration(25)*time.Second, getReconnectInterval())
   793  
   794  	//Verify reading the values from config file
   795  	viper.Reset()
   796  	aliveExpirationCheckInterval = 0 * time.Second
   797  	viper.SetConfigName("core")
   798  	viper.SetEnvPrefix("CORE")
   799  	config.AddDevConfigPath(nil)
   800  	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
   801  	viper.AutomaticEnv()
   802  	err := viper.ReadInConfig()
   803  	assert.NoError(t, err)
   804  	assert.Equal(t, time.Duration(5)*time.Second, getAliveTimeInterval())
   805  	assert.Equal(t, time.Duration(25)*time.Second, getAliveExpirationTimeout())
   806  	assert.Equal(t, time.Duration(25)*time.Second/10, getAliveExpirationCheckInterval())
   807  	assert.Equal(t, time.Duration(25)*time.Second, getReconnectInterval())
   808  }
   809  
   810  func TestFilterOutLocalhost(t *testing.T) {
   811  	t.Parallel()
   812  	endpoints := []string{"localhost:5611", "127.0.0.1:5611", "1.2.3.4:5611"}
   813  	assert.Len(t, filterOutLocalhost(endpoints, 5611), 1)
   814  	endpoints = []string{"1.2.3.4:5611"}
   815  	assert.Len(t, filterOutLocalhost(endpoints, 5611), 1)
   816  	endpoints = []string{"localhost:5611", "127.0.0.1:5611"}
   817  	assert.Len(t, filterOutLocalhost(endpoints, 5611), 0)
   818  	// Check slice returned is a copy
   819  	endpoints = []string{"localhost:5611", "127.0.0.1:5611", "1.2.3.4:5611"}
   820  	endpoints2 := filterOutLocalhost(endpoints, 5611)
   821  	endpoints2[0] = "bla bla"
   822  	assert.NotEqual(t, endpoints[2], endpoints[0])
   823  }
   824  
   825  func TestMsgStoreExpiration(t *testing.T) {
   826  	t.Parallel()
   827  	nodeNum := 4
   828  	bootPeers := []string{bootPeer(12611), bootPeer(12612)}
   829  	instances := []*gossipInstance{}
   830  
   831  	inst := createDiscoveryInstance(12611, "d1", bootPeers)
   832  	instances = append(instances, inst)
   833  
   834  	inst = createDiscoveryInstance(12612, "d2", bootPeers)
   835  	instances = append(instances, inst)
   836  
   837  	for i := 3; i <= nodeNum; i++ {
   838  		id := fmt.Sprintf("d%d", i)
   839  		inst = createDiscoveryInstance(12610+i, id, bootPeers)
   840  		instances = append(instances, inst)
   841  	}
   842  
   843  	assertMembership(t, instances, nodeNum-1)
   844  
   845  	waitUntilOrFailBlocking(t, instances[nodeNum-1].Stop)
   846  	waitUntilOrFailBlocking(t, instances[nodeNum-2].Stop)
   847  
   848  	assertMembership(t, instances, nodeNum-3)
   849  
   850  	checkMessages := func() bool {
   851  		for _, inst := range instances[:len(instances)-2] {
   852  			for _, downInst := range instances[len(instances)-2:] {
   853  				downCastInst := inst.Discovery.(*gossipDiscoveryImpl)
   854  				downCastInst.lock.RLock()
   855  				if _, exist := downCastInst.aliveLastTS[string(downInst.Discovery.(*gossipDiscoveryImpl).self.PKIid)]; exist {
   856  					downCastInst.lock.RUnlock()
   857  					return false
   858  				}
   859  				if _, exist := downCastInst.deadLastTS[string(downInst.Discovery.(*gossipDiscoveryImpl).self.PKIid)]; exist {
   860  					downCastInst.lock.RUnlock()
   861  					return false
   862  				}
   863  				if _, exist := downCastInst.id2Member[string(downInst.Discovery.(*gossipDiscoveryImpl).self.PKIid)]; exist {
   864  					downCastInst.lock.RUnlock()
   865  					return false
   866  				}
   867  				if downCastInst.aliveMembership.MsgByID(downInst.Discovery.(*gossipDiscoveryImpl).self.PKIid) != nil {
   868  					downCastInst.lock.RUnlock()
   869  					return false
   870  				}
   871  				if downCastInst.deadMembership.MsgByID(downInst.Discovery.(*gossipDiscoveryImpl).self.PKIid) != nil {
   872  					downCastInst.lock.RUnlock()
   873  					return false
   874  				}
   875  				downCastInst.lock.RUnlock()
   876  			}
   877  		}
   878  		return true
   879  	}
   880  
   881  	waitUntilTimeoutOrFail(t, checkMessages, timeout*2)
   882  
   883  	assertMembership(t, instances[:len(instances)-2], nodeNum-3)
   884  
   885  	peerToResponse := &NetworkMember{
   886  		Metadata:         []byte{},
   887  		PKIid:            []byte(fmt.Sprintf("localhost:%d", 12612)),
   888  		Endpoint:         fmt.Sprintf("localhost:%d", 12612),
   889  		InternalEndpoint: fmt.Sprintf("localhost:%d", 12612),
   890  	}
   891  
   892  	downCastInstance := instances[0].Discovery.(*gossipDiscoveryImpl)
   893  	memResp := downCastInstance.createMembershipResponse(peerToResponse)
   894  
   895  	downCastInstance.comm.SendToPeer(peerToResponse, (&proto.GossipMessage{
   896  		Tag:   proto.GossipMessage_EMPTY,
   897  		Nonce: uint64(0),
   898  		Content: &proto.GossipMessage_MemRes{
   899  			MemRes: memResp,
   900  		},
   901  	}).NoopSign())
   902  
   903  	time.Sleep(getAliveExpirationTimeout())
   904  
   905  	assert.True(t, checkMessages(), "Validating lost message with already dead and expired nodes failed")
   906  
   907  	stopInstances(t, instances[:len(instances)-2])
   908  }
   909  
   910  func waitUntilOrFail(t *testing.T, pred func() bool) {
   911  	waitUntilTimeoutOrFail(t, pred, timeout)
   912  }
   913  
   914  func waitUntilTimeoutOrFail(t *testing.T, pred func() bool, timeout time.Duration) {
   915  	start := time.Now()
   916  	limit := start.UnixNano() + timeout.Nanoseconds()
   917  	for time.Now().UnixNano() < limit {
   918  		if pred() {
   919  			return
   920  		}
   921  		time.Sleep(timeout / 10)
   922  	}
   923  	assert.Fail(t, "Timeout expired!")
   924  }
   925  
   926  func waitUntilOrFailBlocking(t *testing.T, f func()) {
   927  	successChan := make(chan struct{}, 1)
   928  	go func() {
   929  		f()
   930  		successChan <- struct{}{}
   931  	}()
   932  	select {
   933  	case <-time.NewTimer(timeout).C:
   934  		break
   935  	case <-successChan:
   936  		return
   937  	}
   938  	assert.Fail(t, "Timeout expired!")
   939  }
   940  
   941  func stopInstances(t *testing.T, instances []*gossipInstance) {
   942  	stopAction := &sync.WaitGroup{}
   943  	for _, inst := range instances {
   944  		stopAction.Add(1)
   945  		go func(inst *gossipInstance) {
   946  			defer stopAction.Done()
   947  			inst.Stop()
   948  		}(inst)
   949  	}
   950  
   951  	waitUntilOrFailBlocking(t, stopAction.Wait)
   952  }
   953  
   954  func assertMembership(t *testing.T, instances []*gossipInstance, expectedNum int) {
   955  	fullMembership := func() bool {
   956  		for _, inst := range instances {
   957  			if len(inst.GetMembership()) == expectedNum {
   958  				return true
   959  			}
   960  		}
   961  		return false
   962  	}
   963  	waitUntilOrFail(t, fullMembership)
   964  }
   965  
   966  func portsOfMembers(members []NetworkMember) []int {
   967  	ports := make([]int, len(members))
   968  	for i := range members {
   969  		ports[i] = portOfEndpoint(members[i].Endpoint)
   970  	}
   971  	sort.Ints(ports)
   972  	return ports
   973  }
   974  
   975  func portOfEndpoint(endpoint string) int {
   976  	port, _ := strconv.ParseInt(strings.Split(endpoint, ":")[1], 10, 64)
   977  	return int(port)
   978  }