github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/gossip/comm/comm_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package comm 8 9 import ( 10 "bytes" 11 "crypto/hmac" 12 "crypto/sha256" 13 "crypto/tls" 14 "fmt" 15 "math/rand" 16 "net" 17 "os" 18 "strings" 19 "sync" 20 "testing" 21 "time" 22 23 "github.com/hyperledger/fabric/bccsp/factory" 24 "github.com/hyperledger/fabric/core/config" 25 "github.com/hyperledger/fabric/gossip/api" 26 "github.com/hyperledger/fabric/gossip/common" 27 "github.com/hyperledger/fabric/gossip/identity" 28 "github.com/hyperledger/fabric/gossip/util" 29 proto "github.com/hyperledger/fabric/protos/gossip" 30 "github.com/spf13/viper" 31 "github.com/stretchr/testify/assert" 32 "golang.org/x/net/context" 33 "google.golang.org/grpc" 34 "google.golang.org/grpc/credentials" 35 ) 36 37 func init() { 38 util.SetupTestLogging() 39 rand.Seed(time.Now().UnixNano()) 40 factory.InitFactories(nil) 41 } 42 43 func acceptAll(msg interface{}) bool { 44 return true 45 } 46 47 var ( 48 naiveSec = &naiveSecProvider{} 49 hmacKey = []byte{0, 0, 0} 50 ) 51 52 type naiveSecProvider struct { 53 } 54 55 func (*naiveSecProvider) ValidateIdentity(peerIdentity api.PeerIdentityType) error { 56 return nil 57 } 58 59 // GetPKIidOfCert returns the PKI-ID of a peer's identity 60 func (*naiveSecProvider) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType { 61 return common.PKIidType(peerIdentity) 62 } 63 64 // VerifyBlock returns nil if the block is properly signed, 65 // else returns error 66 func (*naiveSecProvider) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error { 67 return nil 68 } 69 70 // Sign signs msg with this peer's signing key and outputs 71 // the signature if no error occurred. 72 func (*naiveSecProvider) Sign(msg []byte) ([]byte, error) { 73 mac := hmac.New(sha256.New, hmacKey) 74 mac.Write(msg) 75 return mac.Sum(nil), nil 76 } 77 78 // Verify checks that signature is a valid signature of message under a peer's verification key. 79 // If the verification succeeded, Verify returns nil meaning no error occurred. 80 // If peerCert is nil, then the signature is verified against this peer's verification key. 81 func (*naiveSecProvider) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error { 82 mac := hmac.New(sha256.New, hmacKey) 83 mac.Write(message) 84 expected := mac.Sum(nil) 85 if !bytes.Equal(signature, expected) { 86 return fmt.Errorf("Wrong certificate:%v, %v", signature, message) 87 } 88 return nil 89 } 90 91 // VerifyByChannel verifies a peer's signature on a message in the context 92 // of a specific channel 93 func (*naiveSecProvider) VerifyByChannel(_ common.ChainID, _ api.PeerIdentityType, _, _ []byte) error { 94 return nil 95 } 96 97 func newCommInstance(port int, sec api.MessageCryptoService) (Comm, error) { 98 endpoint := fmt.Sprintf("localhost:%d", port) 99 id := []byte(endpoint) 100 inst, err := NewCommInstanceWithServer(port, identity.NewIdentityMapper(sec, id), id, nil) 101 return inst, err 102 } 103 104 type msgMutator func(*proto.SignedGossipMessage) *proto.SignedGossipMessage 105 106 type tlsType int 107 108 const ( 109 none tlsType = iota 110 oneWayTLS 111 mutualTLS 112 ) 113 114 func handshaker(endpoint string, comm Comm, t *testing.T, connMutator msgMutator, connType tlsType) <-chan proto.ReceivedMessage { 115 c := &commImpl{} 116 cert := GenerateCertificatesOrPanic() 117 tlsCfg := &tls.Config{ 118 InsecureSkipVerify: true, 119 } 120 if connType == mutualTLS { 121 tlsCfg.Certificates = []tls.Certificate{cert} 122 } 123 ta := credentials.NewTLS(tlsCfg) 124 secureOpts := grpc.WithTransportCredentials(ta) 125 if connType == none { 126 secureOpts = grpc.WithInsecure() 127 } 128 acceptChan := comm.Accept(acceptAll) 129 conn, err := grpc.Dial("localhost:9611", secureOpts, grpc.WithBlock(), grpc.WithTimeout(time.Second)) 130 assert.NoError(t, err, "%v", err) 131 if err != nil { 132 return nil 133 } 134 cl := proto.NewGossipClient(conn) 135 stream, err := cl.GossipStream(context.Background()) 136 assert.NoError(t, err, "%v", err) 137 if err != nil { 138 return nil 139 } 140 141 var clientCertHash []byte 142 if len(tlsCfg.Certificates) > 0 { 143 clientCertHash = certHashFromRawCert(tlsCfg.Certificates[0].Certificate[0]) 144 } 145 146 pkiID := common.PKIidType(endpoint) 147 assert.NoError(t, err, "%v", err) 148 msg, _ := c.createConnectionMsg(pkiID, clientCertHash, []byte(endpoint), func(msg []byte) ([]byte, error) { 149 mac := hmac.New(sha256.New, hmacKey) 150 mac.Write(msg) 151 return mac.Sum(nil), nil 152 }) 153 // Mutate connection message to test negative paths 154 msg = connMutator(msg) 155 // Send your own connection message 156 stream.Send(msg.Envelope) 157 // Wait for connection message from the other side 158 envelope, err := stream.Recv() 159 if err != nil { 160 return acceptChan 161 } 162 assert.NoError(t, err, "%v", err) 163 msg, err = envelope.ToGossipMessage() 164 assert.NoError(t, err, "%v", err) 165 assert.Equal(t, []byte("localhost:9611"), msg.GetConn().PkiId) 166 assert.Equal(t, extractCertificateHashFromContext(stream.Context()), msg.GetConn().TlsCertHash) 167 msg2Send := createGossipMsg() 168 nonce := uint64(rand.Int()) 169 msg2Send.Nonce = nonce 170 go stream.Send(msg2Send.Envelope) 171 return acceptChan 172 } 173 174 func TestViperConfig(t *testing.T) { 175 viper.SetConfigName("core") 176 viper.SetEnvPrefix("CORE") 177 config.AddDevConfigPath(nil) 178 viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) 179 viper.AutomaticEnv() 180 err := viper.ReadInConfig() 181 if err != nil { // Handle errors reading the config file 182 panic(fmt.Errorf("fatal error config file: %s", err)) 183 } 184 185 assert.Equal(t, time.Duration(2)*time.Second, util.GetDurationOrDefault("peer.gossip.connTimeout", 0)) 186 assert.Equal(t, time.Duration(300)*time.Millisecond, util.GetDurationOrDefault("peer.gossip.dialTimeout", 0)) 187 assert.Equal(t, 20, util.GetIntOrDefault("peer.gossip.recvBuffSize", 0)) 188 assert.Equal(t, 200, util.GetIntOrDefault("peer.gossip.sendBuffSize", 0)) 189 } 190 191 func TestHandshake(t *testing.T) { 192 t.Parallel() 193 signer := func(msg []byte) ([]byte, error) { 194 mac := hmac.New(sha256.New, hmacKey) 195 mac.Write(msg) 196 return mac.Sum(nil), nil 197 } 198 mutator := func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage { 199 return msg 200 } 201 assertPositivePath := func(msg proto.ReceivedMessage, endpoint string) { 202 expectedPKIID := common.PKIidType(endpoint) 203 assert.Equal(t, expectedPKIID, msg.GetConnectionInfo().ID) 204 assert.Equal(t, api.PeerIdentityType(endpoint), msg.GetConnectionInfo().Identity) 205 assert.NotNil(t, msg.GetConnectionInfo().Auth) 206 assert.True(t, msg.GetConnectionInfo().IsAuthenticated()) 207 sig, _ := (&naiveSecProvider{}).Sign(msg.GetConnectionInfo().Auth.SignedData) 208 assert.Equal(t, sig, msg.GetConnectionInfo().Auth.Signature) 209 } 210 211 // Positive path 1 - check authentication without TLS 212 ll, err := net.Listen("tcp", fmt.Sprintf("%s:%d", "", 9611)) 213 assert.NoError(t, err) 214 s := grpc.NewServer() 215 go s.Serve(ll) 216 217 id := []byte("localhost:9611") 218 idMapper := identity.NewIdentityMapper(naiveSec, id) 219 inst, err := NewCommInstance(s, nil, idMapper, api.PeerIdentityType("localhost:9611"), func() []grpc.DialOption { 220 return []grpc.DialOption{grpc.WithInsecure()} 221 }) 222 assert.NoError(t, err) 223 var msg proto.ReceivedMessage 224 225 acceptChan := handshaker("localhost:9608", inst, t, mutator, none) 226 select { 227 case <-time.After(time.Duration(time.Second * 4)): 228 assert.FailNow(t, "Didn't receive a message, seems like handshake failed") 229 case msg = <-acceptChan: 230 } 231 assert.Equal(t, common.PKIidType("localhost:9608"), msg.GetConnectionInfo().ID) 232 assert.Equal(t, api.PeerIdentityType("localhost:9608"), msg.GetConnectionInfo().Identity) 233 assert.Nil(t, msg.GetConnectionInfo().Auth) 234 assert.False(t, msg.GetConnectionInfo().IsAuthenticated()) 235 236 inst.Stop() 237 s.Stop() 238 ll.Close() 239 time.Sleep(time.Second) 240 241 comm, err := newCommInstance(9611, naiveSec) 242 assert.NoError(t, err) 243 defer comm.Stop() 244 // Positive path 2: initiating peer sends its own certificate 245 acceptChan = handshaker("localhost:9609", comm, t, mutator, mutualTLS) 246 247 select { 248 case <-time.After(time.Second * 2): 249 assert.FailNow(t, "Didn't receive a message, seems like handshake failed") 250 case msg = <-acceptChan: 251 } 252 assertPositivePath(msg, "localhost:9609") 253 254 // Negative path: initiating peer doesn't send its own certificate 255 acceptChan = handshaker("localhost:9610", comm, t, mutator, oneWayTLS) 256 time.Sleep(time.Second) 257 assert.Equal(t, 0, len(acceptChan)) 258 // Negative path, signature is wrong 259 mutator = func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage { 260 msg.Signature = append(msg.Signature, 0) 261 return msg 262 } 263 acceptChan = handshaker("localhost:9612", comm, t, mutator, mutualTLS) 264 time.Sleep(time.Second) 265 assert.Equal(t, 0, len(acceptChan)) 266 267 // Negative path, the PKIid doesn't match the identity 268 mutator = func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage { 269 msg.GetConn().PkiId = []byte("localhost:9650") 270 // Sign the message again 271 msg.Sign(signer) 272 return msg 273 } 274 acceptChan = handshaker("localhost:9613", comm, t, mutator, mutualTLS) 275 time.Sleep(time.Second) 276 assert.Equal(t, 0, len(acceptChan)) 277 278 // Negative path, the cert hash isn't what is expected 279 mutator = func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage { 280 msg.GetConn().TlsCertHash = append(msg.GetConn().TlsCertHash, 0) 281 msg.Sign(signer) 282 return msg 283 } 284 acceptChan = handshaker("localhost:9615", comm, t, mutator, mutualTLS) 285 time.Sleep(time.Second) 286 assert.Equal(t, 0, len(acceptChan)) 287 288 // Negative path, no PKI-ID was sent 289 mutator = func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage { 290 msg.GetConn().PkiId = nil 291 msg.Sign(signer) 292 return msg 293 } 294 acceptChan = handshaker("localhost:9616", comm, t, mutator, mutualTLS) 295 time.Sleep(time.Second) 296 assert.Equal(t, 0, len(acceptChan)) 297 298 // Negative path, connection message is of a different type 299 mutator = func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage { 300 msg.Content = &proto.GossipMessage_Empty{ 301 Empty: &proto.Empty{}, 302 } 303 msg.Sign(signer) 304 return msg 305 } 306 acceptChan = handshaker("localhost:9617", comm, t, mutator, mutualTLS) 307 time.Sleep(time.Second) 308 assert.Equal(t, 0, len(acceptChan)) 309 310 // Negative path, the peer didn't respond to the handshake in due time 311 mutator = func(msg *proto.SignedGossipMessage) *proto.SignedGossipMessage { 312 time.Sleep(time.Second * 5) 313 return msg 314 } 315 acceptChan = handshaker("localhost:9618", comm, t, mutator, mutualTLS) 316 time.Sleep(time.Second) 317 assert.Equal(t, 0, len(acceptChan)) 318 } 319 320 func TestBasic(t *testing.T) { 321 t.Parallel() 322 comm1, _ := newCommInstance(2000, naiveSec) 323 comm2, _ := newCommInstance(3000, naiveSec) 324 comm1.(*commImpl).SetDialOpts() 325 comm2.(*commImpl).SetDialOpts() 326 defer comm1.Stop() 327 defer comm2.Stop() 328 m1 := comm1.Accept(acceptAll) 329 m2 := comm2.Accept(acceptAll) 330 out := make(chan uint64, 2) 331 reader := func(ch <-chan proto.ReceivedMessage) { 332 m := <-ch 333 out <- m.GetGossipMessage().Nonce 334 } 335 go reader(m1) 336 go reader(m2) 337 comm1.Send(createGossipMsg(), remotePeer(3000)) 338 time.Sleep(time.Second) 339 comm2.Send(createGossipMsg(), remotePeer(2000)) 340 waitForMessages(t, out, 2, "Didn't receive 2 messages") 341 } 342 343 func TestProdConstructor(t *testing.T) { 344 t.Parallel() 345 peerIdentity := GenerateCertificatesOrPanic() 346 srv, lsnr, dialOpts, certHash := createGRPCLayer(20000) 347 defer srv.Stop() 348 defer lsnr.Close() 349 id := []byte("localhost:20000") 350 comm1, _ := NewCommInstance(srv, &peerIdentity, identity.NewIdentityMapper(naiveSec, id), id, dialOpts) 351 comm1.(*commImpl).selfCertHash = certHash 352 go srv.Serve(lsnr) 353 354 peerIdentity = GenerateCertificatesOrPanic() 355 srv, lsnr, dialOpts, certHash = createGRPCLayer(30000) 356 defer srv.Stop() 357 defer lsnr.Close() 358 id = []byte("localhost:30000") 359 comm2, _ := NewCommInstance(srv, &peerIdentity, identity.NewIdentityMapper(naiveSec, id), id, dialOpts) 360 comm2.(*commImpl).selfCertHash = certHash 361 go srv.Serve(lsnr) 362 defer comm1.Stop() 363 defer comm2.Stop() 364 m1 := comm1.Accept(acceptAll) 365 m2 := comm2.Accept(acceptAll) 366 out := make(chan uint64, 2) 367 reader := func(ch <-chan proto.ReceivedMessage) { 368 m := <-ch 369 out <- m.GetGossipMessage().Nonce 370 } 371 go reader(m1) 372 go reader(m2) 373 comm1.Send(createGossipMsg(), remotePeer(30000)) 374 time.Sleep(time.Second) 375 comm2.Send(createGossipMsg(), remotePeer(20000)) 376 waitForMessages(t, out, 2, "Didn't receive 2 messages") 377 } 378 379 func TestGetConnectionInfo(t *testing.T) { 380 t.Parallel() 381 comm1, _ := newCommInstance(6000, naiveSec) 382 comm2, _ := newCommInstance(7000, naiveSec) 383 defer comm1.Stop() 384 defer comm2.Stop() 385 m1 := comm1.Accept(acceptAll) 386 comm2.Send(createGossipMsg(), remotePeer(6000)) 387 select { 388 case <-time.After(time.Second * 10): 389 t.Fatal("Didn't receive a message in time") 390 case msg := <-m1: 391 assert.Equal(t, comm2.GetPKIid(), msg.GetConnectionInfo().ID) 392 assert.NotNil(t, msg.GetSourceEnvelope()) 393 } 394 } 395 396 func TestCloseConn(t *testing.T) { 397 t.Parallel() 398 comm1, _ := newCommInstance(1611, naiveSec) 399 defer comm1.Stop() 400 acceptChan := comm1.Accept(acceptAll) 401 402 cert := GenerateCertificatesOrPanic() 403 tlsCfg := &tls.Config{ 404 InsecureSkipVerify: true, 405 Certificates: []tls.Certificate{cert}, 406 } 407 ta := credentials.NewTLS(tlsCfg) 408 409 conn, err := grpc.Dial("localhost:1611", grpc.WithTransportCredentials(ta), grpc.WithBlock(), grpc.WithTimeout(time.Second)) 410 assert.NoError(t, err, "%v", err) 411 cl := proto.NewGossipClient(conn) 412 stream, err := cl.GossipStream(context.Background()) 413 assert.NoError(t, err, "%v", err) 414 c := &commImpl{} 415 tlsCertHash := certHashFromRawCert(tlsCfg.Certificates[0].Certificate[0]) 416 connMsg, _ := c.createConnectionMsg(common.PKIidType("pkiID"), tlsCertHash, api.PeerIdentityType("pkiID"), func(msg []byte) ([]byte, error) { 417 mac := hmac.New(sha256.New, hmacKey) 418 mac.Write(msg) 419 return mac.Sum(nil), nil 420 }) 421 assert.NoError(t, stream.Send(connMsg.Envelope)) 422 stream.Send(createGossipMsg().Envelope) 423 select { 424 case <-acceptChan: 425 case <-time.After(time.Second): 426 assert.Fail(t, "Didn't receive a message within a timely period") 427 } 428 comm1.CloseConn(&RemotePeer{PKIID: common.PKIidType("pkiID")}) 429 time.Sleep(time.Second * 10) 430 gotErr := false 431 msg2Send := createGossipMsg() 432 msg2Send.GetDataMsg().Payload = &proto.Payload{ 433 Data: make([]byte, 1024*1024), 434 } 435 msg2Send.NoopSign() 436 for i := 0; i < defRecvBuffSize; i++ { 437 err := stream.Send(msg2Send.Envelope) 438 if err != nil { 439 gotErr = true 440 break 441 } 442 } 443 assert.True(t, gotErr, "Should have failed because connection is closed") 444 } 445 446 func TestParallelSend(t *testing.T) { 447 t.Parallel() 448 comm1, _ := newCommInstance(5411, naiveSec) 449 comm2, _ := newCommInstance(5412, naiveSec) 450 defer comm1.Stop() 451 defer comm2.Stop() 452 453 messages2Send := util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize) 454 455 wg := sync.WaitGroup{} 456 go func() { 457 for i := 0; i < messages2Send; i++ { 458 wg.Add(1) 459 emptyMsg := createGossipMsg() 460 go func() { 461 defer wg.Done() 462 comm1.Send(emptyMsg, remotePeer(5412)) 463 }() 464 } 465 wg.Wait() 466 }() 467 468 c := 0 469 waiting := true 470 ticker := time.NewTicker(time.Duration(5) * time.Second) 471 ch := comm2.Accept(acceptAll) 472 for waiting { 473 select { 474 case <-ch: 475 c++ 476 if c == messages2Send { 477 waiting = false 478 } 479 case <-ticker.C: 480 waiting = false 481 } 482 } 483 assert.Equal(t, messages2Send, c) 484 } 485 486 type nonResponsivePeer struct { 487 net.Listener 488 *grpc.Server 489 port int 490 } 491 492 func newNonResponsivePeer() *nonResponsivePeer { 493 rand.Seed(time.Now().UnixNano()) 494 port := 50000 + rand.Intn(1000) 495 s, l, _, _ := createGRPCLayer(port) 496 nrp := &nonResponsivePeer{ 497 Listener: l, 498 Server: s, 499 port: port, 500 } 501 proto.RegisterGossipServer(s, nrp) 502 go s.Serve(l) 503 return nrp 504 } 505 506 func (bp *nonResponsivePeer) Ping(context.Context, *proto.Empty) (*proto.Empty, error) { 507 time.Sleep(time.Second * 15) 508 return &proto.Empty{}, nil 509 } 510 511 func (bp *nonResponsivePeer) GossipStream(stream proto.Gossip_GossipStreamServer) error { 512 return nil 513 } 514 515 func (bp *nonResponsivePeer) stop() { 516 bp.Server.Stop() 517 bp.Listener.Close() 518 } 519 520 func TestNonResponsivePing(t *testing.T) { 521 t.Parallel() 522 port := 50000 - rand.Intn(1000) 523 c, _ := newCommInstance(port, naiveSec) 524 defer c.Stop() 525 nonRespPeer := newNonResponsivePeer() 526 defer nonRespPeer.stop() 527 s := make(chan struct{}) 528 go func() { 529 c.Probe(remotePeer(nonRespPeer.port)) 530 s <- struct{}{} 531 }() 532 select { 533 case <-time.After(time.Second * 10): 534 assert.Fail(t, "Request wasn't cancelled on time") 535 case <-s: 536 } 537 538 } 539 540 func TestResponses(t *testing.T) { 541 t.Parallel() 542 comm1, _ := newCommInstance(8611, naiveSec) 543 comm2, _ := newCommInstance(8612, naiveSec) 544 545 defer comm1.Stop() 546 defer comm2.Stop() 547 548 wg := sync.WaitGroup{} 549 550 msg := createGossipMsg() 551 wg.Add(1) 552 go func() { 553 inChan := comm1.Accept(acceptAll) 554 wg.Done() 555 for m := range inChan { 556 reply := createGossipMsg() 557 reply.Nonce = m.GetGossipMessage().Nonce + 1 558 m.Respond(reply.GossipMessage) 559 } 560 }() 561 expectedNOnce := uint64(msg.Nonce + 1) 562 responsesFromComm1 := comm2.Accept(acceptAll) 563 564 ticker := time.NewTicker(10 * time.Second) 565 wg.Wait() 566 comm2.Send(msg, remotePeer(8611)) 567 568 select { 569 case <-ticker.C: 570 assert.Fail(t, "Haven't got response from comm1 within a timely manner") 571 break 572 case resp := <-responsesFromComm1: 573 ticker.Stop() 574 assert.Equal(t, expectedNOnce, resp.GetGossipMessage().Nonce) 575 break 576 } 577 } 578 579 func TestAccept(t *testing.T) { 580 t.Parallel() 581 comm1, _ := newCommInstance(7611, naiveSec) 582 comm2, _ := newCommInstance(7612, naiveSec) 583 584 evenNONCESelector := func(m interface{}) bool { 585 return m.(proto.ReceivedMessage).GetGossipMessage().Nonce%2 == 0 586 } 587 588 oddNONCESelector := func(m interface{}) bool { 589 return m.(proto.ReceivedMessage).GetGossipMessage().Nonce%2 != 0 590 } 591 592 evenNONCES := comm1.Accept(evenNONCESelector) 593 oddNONCES := comm1.Accept(oddNONCESelector) 594 595 var evenResults []uint64 596 var oddResults []uint64 597 598 out := make(chan uint64, util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize)) 599 sem := make(chan struct{}, 0) 600 601 readIntoSlice := func(a *[]uint64, ch <-chan proto.ReceivedMessage) { 602 for m := range ch { 603 *a = append(*a, m.GetGossipMessage().Nonce) 604 out <- m.GetGossipMessage().Nonce 605 } 606 sem <- struct{}{} 607 } 608 609 go readIntoSlice(&evenResults, evenNONCES) 610 go readIntoSlice(&oddResults, oddNONCES) 611 612 for i := 0; i < util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize); i++ { 613 comm2.Send(createGossipMsg(), remotePeer(7611)) 614 } 615 616 waitForMessages(t, out, util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize), "Didn't receive all messages sent") 617 618 comm1.Stop() 619 comm2.Stop() 620 621 <-sem 622 <-sem 623 624 assert.NotEmpty(t, evenResults) 625 assert.NotEmpty(t, oddResults) 626 627 remainderPredicate := func(a []uint64, rem uint64) { 628 for _, n := range a { 629 assert.Equal(t, n%2, rem) 630 } 631 } 632 633 remainderPredicate(evenResults, 0) 634 remainderPredicate(oddResults, 1) 635 } 636 637 func TestReConnections(t *testing.T) { 638 t.Parallel() 639 comm1, _ := newCommInstance(3611, naiveSec) 640 comm2, _ := newCommInstance(3612, naiveSec) 641 642 reader := func(out chan uint64, in <-chan proto.ReceivedMessage) { 643 for { 644 msg := <-in 645 if msg == nil { 646 return 647 } 648 out <- msg.GetGossipMessage().Nonce 649 } 650 } 651 652 out1 := make(chan uint64, 10) 653 out2 := make(chan uint64, 10) 654 655 go reader(out1, comm1.Accept(acceptAll)) 656 go reader(out2, comm2.Accept(acceptAll)) 657 658 // comm1 connects to comm2 659 comm1.Send(createGossipMsg(), remotePeer(3612)) 660 waitForMessages(t, out2, 1, "Comm2 didn't receive a message from comm1 in a timely manner") 661 time.Sleep(time.Second) 662 // comm2 sends to comm1 663 comm2.Send(createGossipMsg(), remotePeer(3611)) 664 waitForMessages(t, out1, 1, "Comm1 didn't receive a message from comm2 in a timely manner") 665 666 comm1.Stop() 667 comm1, _ = newCommInstance(3611, naiveSec) 668 time.Sleep(time.Second) 669 out1 = make(chan uint64, 1) 670 go reader(out1, comm1.Accept(acceptAll)) 671 comm2.Send(createGossipMsg(), remotePeer(3611)) 672 waitForMessages(t, out1, 1, "Comm1 didn't receive a message from comm2 in a timely manner") 673 } 674 675 func TestProbe(t *testing.T) { 676 t.Parallel() 677 comm1, _ := newCommInstance(6611, naiveSec) 678 defer comm1.Stop() 679 comm2, _ := newCommInstance(6612, naiveSec) 680 time.Sleep(time.Duration(1) * time.Second) 681 assert.NoError(t, comm1.Probe(remotePeer(6612))) 682 _, err := comm1.Handshake(remotePeer(6612)) 683 assert.NoError(t, err) 684 assert.Error(t, comm1.Probe(remotePeer(9012))) 685 _, err = comm1.Handshake(remotePeer(9012)) 686 assert.Error(t, err) 687 comm2.Stop() 688 time.Sleep(time.Second) 689 assert.Error(t, comm1.Probe(remotePeer(6612))) 690 _, err = comm1.Handshake(remotePeer(6612)) 691 assert.Error(t, err) 692 comm2, _ = newCommInstance(6612, naiveSec) 693 defer comm2.Stop() 694 time.Sleep(time.Duration(1) * time.Second) 695 assert.NoError(t, comm2.Probe(remotePeer(6611))) 696 _, err = comm2.Handshake(remotePeer(6611)) 697 assert.NoError(t, err) 698 assert.NoError(t, comm1.Probe(remotePeer(6612))) 699 _, err = comm1.Handshake(remotePeer(6612)) 700 assert.NoError(t, err) 701 // Now try a deep probe with an expected PKI-ID that doesn't match 702 wrongRemotePeer := remotePeer(6612) 703 if wrongRemotePeer.PKIID[0] == 0 { 704 wrongRemotePeer.PKIID[0] = 1 705 } else { 706 wrongRemotePeer.PKIID[0] = 0 707 } 708 _, err = comm1.Handshake(wrongRemotePeer) 709 assert.Error(t, err) 710 // Try a deep probe with a nil PKI-ID 711 id, err := comm1.Handshake(&RemotePeer{Endpoint: "localhost:6612"}) 712 assert.NoError(t, err) 713 assert.Equal(t, api.PeerIdentityType("localhost:6612"), id) 714 } 715 716 func TestPresumedDead(t *testing.T) { 717 t.Parallel() 718 comm1, _ := newCommInstance(4611, naiveSec) 719 comm2, _ := newCommInstance(4612, naiveSec) 720 721 wg := sync.WaitGroup{} 722 wg.Add(1) 723 go func() { 724 wg.Wait() 725 comm1.Send(createGossipMsg(), remotePeer(4612)) 726 }() 727 728 ticker := time.NewTicker(time.Duration(10) * time.Second) 729 acceptCh := comm2.Accept(acceptAll) 730 wg.Done() 731 select { 732 case <-acceptCh: 733 ticker.Stop() 734 case <-ticker.C: 735 assert.Fail(t, "Didn't get first message") 736 } 737 738 comm2.Stop() 739 go func() { 740 for i := 0; i < 5; i++ { 741 comm1.Send(createGossipMsg(), remotePeer(4612)) 742 time.Sleep(time.Millisecond * 200) 743 } 744 }() 745 746 ticker = time.NewTicker(time.Second * time.Duration(3)) 747 select { 748 case <-ticker.C: 749 assert.Fail(t, "Didn't get a presumed dead message within a timely manner") 750 break 751 case <-comm1.PresumedDead(): 752 ticker.Stop() 753 break 754 } 755 } 756 757 func createGossipMsg() *proto.SignedGossipMessage { 758 msg, _ := (&proto.GossipMessage{ 759 Tag: proto.GossipMessage_EMPTY, 760 Nonce: uint64(rand.Int()), 761 Content: &proto.GossipMessage_DataMsg{ 762 DataMsg: &proto.DataMessage{}, 763 }, 764 }).NoopSign() 765 return msg 766 } 767 768 func remotePeer(port int) *RemotePeer { 769 endpoint := fmt.Sprintf("localhost:%d", port) 770 return &RemotePeer{Endpoint: endpoint, PKIID: []byte(endpoint)} 771 } 772 773 func waitForMessages(t *testing.T, msgChan chan uint64, count int, errMsg string) { 774 c := 0 775 waiting := true 776 ticker := time.NewTicker(time.Duration(10) * time.Second) 777 for waiting { 778 select { 779 case <-msgChan: 780 c++ 781 if c == count { 782 waiting = false 783 } 784 case <-ticker.C: 785 waiting = false 786 } 787 } 788 assert.Equal(t, count, c, errMsg) 789 } 790 791 func TestMain(m *testing.M) { 792 SetDialTimeout(time.Duration(300) * time.Millisecond) 793 794 ret := m.Run() 795 os.Exit(ret) 796 }