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 := ×tamp{ 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 }