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