github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/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/tls" 22 "fmt" 23 "math/rand" 24 "os" 25 "strings" 26 "sync" 27 "testing" 28 "time" 29 30 "github.com/hyperledger/fabric/gossip/api" 31 "github.com/hyperledger/fabric/gossip/common" 32 "github.com/hyperledger/fabric/gossip/identity" 33 "github.com/hyperledger/fabric/gossip/util" 34 proto "github.com/hyperledger/fabric/protos/gossip" 35 "github.com/spf13/viper" 36 "github.com/stretchr/testify/assert" 37 "golang.org/x/net/context" 38 "google.golang.org/grpc" 39 "google.golang.org/grpc/credentials" 40 ) 41 42 func init() { 43 rand.Seed(42) 44 } 45 46 func acceptAll(msg interface{}) bool { 47 return true 48 } 49 50 var naiveSec = &naiveSecProvider{} 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, signedBlock api.SignedBlock) 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 return msg, nil 74 } 75 76 // Verify checks that signature is a valid signature of message under a peer's verification key. 77 // If the verification succeeded, Verify returns nil meaning no error occurred. 78 // If peerCert is nil, then the signature is verified against this peer's verification key. 79 func (*naiveSecProvider) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error { 80 equal := bytes.Equal(signature, message) 81 if !equal { 82 return fmt.Errorf("Wrong certificate:%v, %v", signature, message) 83 } 84 return nil 85 } 86 87 // VerifyByChannel verifies a peer's signature on a message in the context 88 // of a specific channel 89 func (*naiveSecProvider) VerifyByChannel(_ common.ChainID, _ api.PeerIdentityType, _, _ []byte) error { 90 return nil 91 } 92 93 func newCommInstance(port int, sec api.MessageCryptoService) (Comm, error) { 94 endpoint := fmt.Sprintf("localhost:%d", port) 95 inst, err := NewCommInstanceWithServer(port, identity.NewIdentityMapper(sec), []byte(endpoint)) 96 return inst, err 97 } 98 99 func handshaker(endpoint string, comm Comm, t *testing.T, sigMutator func([]byte) []byte, pkiIDmutator func([]byte) []byte) <-chan proto.ReceivedMessage { 100 c := &commImpl{} 101 err := generateCertificates("key.pem", "cert.pem") 102 defer os.Remove("cert.pem") 103 defer os.Remove("key.pem") 104 cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem") 105 ta := credentials.NewTLS(&tls.Config{ 106 InsecureSkipVerify: true, 107 Certificates: []tls.Certificate{cert}, 108 }) 109 acceptChan := comm.Accept(acceptAll) 110 conn, err := grpc.Dial("localhost:9611", grpc.WithTransportCredentials(&authCreds{tlsCreds: ta}), grpc.WithBlock(), grpc.WithTimeout(time.Second)) 111 assert.NoError(t, err, "%v", err) 112 if err != nil { 113 return nil 114 } 115 cl := proto.NewGossipClient(conn) 116 stream, err := cl.GossipStream(context.Background()) 117 assert.NoError(t, err, "%v", err) 118 if err != nil { 119 return nil 120 } 121 clientCertHash := certHashFromRawCert(cert.Certificate[0]) 122 123 pkiID := common.PKIidType(endpoint) 124 if pkiIDmutator != nil { 125 pkiID = common.PKIidType(pkiIDmutator([]byte(endpoint))) 126 } 127 assert.NoError(t, err, "%v", err) 128 msg := c.createConnectionMsg(pkiID, clientCertHash, []byte(endpoint), func(msg []byte) ([]byte, error) { 129 return msg, nil 130 }) 131 132 if sigMutator != nil { 133 msg.Envelope.Signature = sigMutator(msg.Envelope.Signature) 134 } 135 136 stream.Send(msg.Envelope) 137 envelope, err := stream.Recv() 138 assert.NoError(t, err, "%v", err) 139 msg, err = envelope.ToGossipMessage() 140 assert.NoError(t, err, "%v", err) 141 if sigMutator == nil { 142 hash := extractCertificateHashFromContext(stream.Context()) 143 expectedMsg := c.createConnectionMsg(common.PKIidType("localhost:9611"), hash, []byte("localhost:9611"), func(msg []byte) ([]byte, error) { 144 return msg, nil 145 }) 146 assert.Equal(t, expectedMsg.Envelope.Signature, msg.Envelope.Signature) 147 } 148 assert.Equal(t, []byte("localhost:9611"), msg.GetConn().PkiID) 149 msg2Send := createGossipMsg() 150 nonce := uint64(rand.Int()) 151 msg2Send.Nonce = nonce 152 go stream.Send(msg2Send.Envelope) 153 return acceptChan 154 } 155 156 func TestViperConfig(t *testing.T) { 157 viper.SetConfigName("core") 158 viper.SetEnvPrefix("CORE") 159 viper.AddConfigPath("./../../peer") 160 viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) 161 viper.AutomaticEnv() 162 err := viper.ReadInConfig() 163 if err != nil { // Handle errors reading the config file 164 panic(fmt.Errorf("Fatal error config file: %s \n", err)) 165 } 166 167 assert.Equal(t, time.Duration(2)*time.Second, util.GetDurationOrDefault("peer.gossip.connTimeout", 0)) 168 assert.Equal(t, time.Duration(300)*time.Millisecond, util.GetDurationOrDefault("peer.gossip.dialTimeout", 0)) 169 assert.Equal(t, 20, util.GetIntOrDefault("peer.gossip.recvBuffSize", 0)) 170 assert.Equal(t, 20, util.GetIntOrDefault("peer.gossip.sendBuffSize", 0)) 171 } 172 173 func TestHandshake(t *testing.T) { 174 t.Parallel() 175 comm, _ := newCommInstance(9611, naiveSec) 176 defer comm.Stop() 177 178 acceptChan := handshaker("localhost:9610", comm, t, nil, nil) 179 time.Sleep(2 * time.Second) 180 assert.Equal(t, 1, len(acceptChan)) 181 182 // negative path, nothing should be read from the channel because the signature is wrong 183 mutateSig := func(b []byte) []byte { 184 if b[0] == 0 { 185 b[0] = 1 186 } else { 187 b[0] = 0 188 } 189 return b 190 } 191 acceptChan = handshaker("localhost:9612", comm, t, mutateSig, nil) 192 time.Sleep(time.Second) 193 assert.Equal(t, 0, len(acceptChan)) 194 195 // negative path, nothing should be read from the channel because the PKIid doesn't match the identity 196 mutatePKIID := func(b []byte) []byte { 197 return []byte("localhost:9650") 198 } 199 acceptChan = handshaker("localhost:9613", comm, t, nil, mutatePKIID) 200 time.Sleep(time.Second) 201 assert.Equal(t, 0, len(acceptChan)) 202 } 203 204 func TestBasic(t *testing.T) { 205 t.Parallel() 206 comm1, _ := newCommInstance(2000, naiveSec) 207 comm2, _ := newCommInstance(3000, naiveSec) 208 defer comm1.Stop() 209 defer comm2.Stop() 210 m1 := comm1.Accept(acceptAll) 211 m2 := comm2.Accept(acceptAll) 212 out := make(chan uint64, 2) 213 reader := func(ch <-chan proto.ReceivedMessage) { 214 m := <-ch 215 out <- m.GetGossipMessage().Nonce 216 } 217 go reader(m1) 218 go reader(m2) 219 comm1.Send(createGossipMsg(), remotePeer(3000)) 220 time.Sleep(time.Second) 221 comm2.Send(createGossipMsg(), remotePeer(2000)) 222 waitForMessages(t, out, 2, "Didn't receive 2 messages") 223 } 224 225 func TestGetPKIID(t *testing.T) { 226 t.Parallel() 227 comm1, _ := newCommInstance(6000, naiveSec) 228 comm2, _ := newCommInstance(7000, naiveSec) 229 defer comm1.Stop() 230 defer comm2.Stop() 231 m1 := comm1.Accept(acceptAll) 232 comm2.Send(createGossipMsg(), remotePeer(6000)) 233 select { 234 case <-time.After(time.Second * 10): 235 t.Fatal("Didn't receive a message in time") 236 case msg := <-m1: 237 assert.Equal(t, comm2.GetPKIid(), msg.GetPKIID()) 238 } 239 } 240 241 func TestBlackListPKIid(t *testing.T) { 242 t.Parallel() 243 comm1, _ := newCommInstance(1611, naiveSec) 244 comm2, _ := newCommInstance(1612, naiveSec) 245 comm3, _ := newCommInstance(1613, naiveSec) 246 comm4, _ := newCommInstance(1614, naiveSec) 247 defer comm1.Stop() 248 defer comm2.Stop() 249 defer comm3.Stop() 250 defer comm4.Stop() 251 252 reader := func(instance string, out chan uint64, in <-chan proto.ReceivedMessage) { 253 for { 254 msg := <-in 255 if msg == nil { 256 return 257 } 258 out <- msg.GetGossipMessage().Nonce 259 } 260 } 261 262 out1 := make(chan uint64, 4) 263 out2 := make(chan uint64, 4) 264 out3 := make(chan uint64, 4) 265 out4 := make(chan uint64, 4) 266 267 go reader("comm1", out1, comm1.Accept(acceptAll)) 268 go reader("comm2", out2, comm2.Accept(acceptAll)) 269 go reader("comm3", out3, comm3.Accept(acceptAll)) 270 go reader("comm4", out4, comm4.Accept(acceptAll)) 271 272 // have comm1 BL comm3 273 comm1.BlackListPKIid([]byte("localhost:1613")) 274 275 // make comm3 send to 1 and 2 276 comm3.Send(createGossipMsg(), remotePeer(1612)) // out2++ 277 comm3.Send(createGossipMsg(), remotePeer(1611)) 278 279 waitForMessages(t, out2, 1, "comm2 should have received 1 message") 280 281 // make comm1 and comm2 send to comm3 282 comm1.Send(createGossipMsg(), remotePeer(1613)) 283 comm2.Send(createGossipMsg(), remotePeer(1613)) // out3++ 284 waitForMessages(t, out3, 1, "comm3 should have received 1 message") 285 286 // make comm1 and comm2 send to comm4 which is not blacklisted // out4 += 4 287 comm1.Send(createGossipMsg(), remotePeer(1614)) 288 comm2.Send(createGossipMsg(), remotePeer(1614)) 289 comm1.Send(createGossipMsg(), remotePeer(1614)) 290 comm2.Send(createGossipMsg(), remotePeer(1614)) 291 292 // blacklist comm3 by comm2 293 comm2.BlackListPKIid([]byte("localhost:1613")) 294 295 // send from comm1 and comm2 to comm3 again 296 comm1.Send(createGossipMsg(), remotePeer(1613)) // shouldn't have an effect 297 comm2.Send(createGossipMsg(), remotePeer(1613)) // shouldn't have an effect 298 299 waitForMessages(t, out4, 4, "comm1 should have received 4 messages") 300 } 301 302 func TestParallelSend(t *testing.T) { 303 t.Parallel() 304 comm1, _ := newCommInstance(5411, naiveSec) 305 comm2, _ := newCommInstance(5412, naiveSec) 306 defer comm1.Stop() 307 defer comm2.Stop() 308 309 messages2Send := util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize) 310 311 wg := sync.WaitGroup{} 312 go func() { 313 for i := 0; i < messages2Send; i++ { 314 wg.Add(1) 315 emptyMsg := createGossipMsg() 316 go func() { 317 defer wg.Done() 318 comm1.Send(emptyMsg, remotePeer(5412)) 319 }() 320 } 321 wg.Wait() 322 }() 323 324 c := 0 325 waiting := true 326 ticker := time.NewTicker(time.Duration(5) * time.Second) 327 ch := comm2.Accept(acceptAll) 328 for waiting { 329 select { 330 case <-ch: 331 c++ 332 if c == messages2Send { 333 waiting = false 334 } 335 break 336 case <-ticker.C: 337 waiting = false 338 break 339 } 340 } 341 assert.Equal(t, messages2Send, c) 342 } 343 344 func TestResponses(t *testing.T) { 345 t.Parallel() 346 comm1, _ := newCommInstance(8611, naiveSec) 347 comm2, _ := newCommInstance(8612, naiveSec) 348 349 defer comm1.Stop() 350 defer comm2.Stop() 351 352 msg := createGossipMsg() 353 go func() { 354 inChan := comm1.Accept(acceptAll) 355 for m := range inChan { 356 reply := createGossipMsg() 357 reply.Nonce = m.GetGossipMessage().Nonce + 1 358 m.Respond(reply.GossipMessage) 359 } 360 }() 361 expectedNOnce := uint64(msg.Nonce + 1) 362 responsesFromComm1 := comm2.Accept(acceptAll) 363 364 ticker := time.NewTicker(time.Duration(6000) * time.Millisecond) 365 comm2.Send(msg, remotePeer(8611)) 366 time.Sleep(time.Duration(100) * time.Millisecond) 367 368 select { 369 case <-ticker.C: 370 assert.Fail(t, "Haven't got response from comm1 within a timely manner") 371 break 372 case resp := <-responsesFromComm1: 373 ticker.Stop() 374 assert.Equal(t, expectedNOnce, resp.GetGossipMessage().Nonce) 375 break 376 } 377 } 378 379 func TestAccept(t *testing.T) { 380 t.Parallel() 381 comm1, _ := newCommInstance(7611, naiveSec) 382 comm2, _ := newCommInstance(7612, naiveSec) 383 384 evenNONCESelector := func(m interface{}) bool { 385 return m.(proto.ReceivedMessage).GetGossipMessage().Nonce%2 == 0 386 } 387 388 oddNONCESelector := func(m interface{}) bool { 389 return m.(proto.ReceivedMessage).GetGossipMessage().Nonce%2 != 0 390 } 391 392 evenNONCES := comm1.Accept(evenNONCESelector) 393 oddNONCES := comm1.Accept(oddNONCESelector) 394 395 var evenResults []uint64 396 var oddResults []uint64 397 398 out := make(chan uint64, util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize)) 399 sem := make(chan struct{}, 0) 400 401 readIntoSlice := func(a *[]uint64, ch <-chan proto.ReceivedMessage) { 402 for m := range ch { 403 *a = append(*a, m.GetGossipMessage().Nonce) 404 out <- m.GetGossipMessage().Nonce 405 } 406 sem <- struct{}{} 407 } 408 409 go readIntoSlice(&evenResults, evenNONCES) 410 go readIntoSlice(&oddResults, oddNONCES) 411 412 for i := 0; i < util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize); i++ { 413 comm2.Send(createGossipMsg(), remotePeer(7611)) 414 } 415 416 waitForMessages(t, out, util.GetIntOrDefault("peer.gossip.recvBuffSize", defRecvBuffSize), "Didn't receive all messages sent") 417 418 comm1.Stop() 419 comm2.Stop() 420 421 <-sem 422 <-sem 423 424 assert.NotEmpty(t, evenResults) 425 assert.NotEmpty(t, oddResults) 426 427 remainderPredicate := func(a []uint64, rem uint64) { 428 for _, n := range a { 429 assert.Equal(t, n%2, rem) 430 } 431 } 432 433 remainderPredicate(evenResults, 0) 434 remainderPredicate(oddResults, 1) 435 } 436 437 func TestReConnections(t *testing.T) { 438 t.Parallel() 439 comm1, _ := newCommInstance(3611, naiveSec) 440 comm2, _ := newCommInstance(3612, naiveSec) 441 442 reader := func(out chan uint64, in <-chan proto.ReceivedMessage) { 443 for { 444 msg := <-in 445 if msg == nil { 446 return 447 } 448 out <- msg.GetGossipMessage().Nonce 449 } 450 } 451 452 out1 := make(chan uint64, 10) 453 out2 := make(chan uint64, 10) 454 455 go reader(out1, comm1.Accept(acceptAll)) 456 go reader(out2, comm2.Accept(acceptAll)) 457 458 // comm1 connects to comm2 459 comm1.Send(createGossipMsg(), remotePeer(3612)) 460 waitForMessages(t, out2, 1, "Comm2 didn't receive a message from comm1 in a timely manner") 461 time.Sleep(time.Second) 462 // comm2 sends to comm1 463 comm2.Send(createGossipMsg(), remotePeer(3611)) 464 waitForMessages(t, out1, 1, "Comm1 didn't receive a message from comm2 in a timely manner") 465 466 comm1.Stop() 467 comm1, _ = newCommInstance(3611, naiveSec) 468 time.Sleep(time.Second) 469 out1 = make(chan uint64, 1) 470 go reader(out1, comm1.Accept(acceptAll)) 471 comm2.Send(createGossipMsg(), remotePeer(3611)) 472 waitForMessages(t, out1, 1, "Comm1 didn't receive a message from comm2 in a timely manner") 473 } 474 475 func TestProbe(t *testing.T) { 476 t.Parallel() 477 comm1, _ := newCommInstance(6611, naiveSec) 478 defer comm1.Stop() 479 comm2, _ := newCommInstance(6612, naiveSec) 480 time.Sleep(time.Duration(1) * time.Second) 481 assert.NoError(t, comm1.Probe(remotePeer(6612))) 482 assert.Error(t, comm1.Probe(remotePeer(9012))) 483 comm2.Stop() 484 time.Sleep(time.Second) 485 assert.Error(t, comm1.Probe(remotePeer(6612))) 486 comm2, _ = newCommInstance(6612, naiveSec) 487 defer comm2.Stop() 488 time.Sleep(time.Duration(1) * time.Second) 489 assert.NoError(t, comm2.Probe(remotePeer(6611))) 490 assert.NoError(t, comm1.Probe(remotePeer(6612))) 491 } 492 493 func TestPresumedDead(t *testing.T) { 494 t.Parallel() 495 comm1, _ := newCommInstance(4611, naiveSec) 496 comm2, _ := newCommInstance(4612, naiveSec) 497 go comm1.Send(createGossipMsg(), remotePeer(4612)) 498 <-comm2.Accept(acceptAll) 499 comm2.Stop() 500 go func() { 501 for i := 0; i < 5; i++ { 502 comm1.Send(createGossipMsg(), remotePeer(4612)) 503 time.Sleep(time.Millisecond * 200) 504 } 505 }() 506 507 ticker := time.NewTicker(time.Second * time.Duration(3)) 508 select { 509 case <-ticker.C: 510 assert.Fail(t, "Didn't get a presumed dead message within a timely manner") 511 break 512 case <-comm1.PresumedDead(): 513 ticker.Stop() 514 break 515 } 516 } 517 518 func createGossipMsg() *proto.SignedGossipMessage { 519 return (&proto.GossipMessage{ 520 Tag: proto.GossipMessage_EMPTY, 521 Nonce: uint64(rand.Int()), 522 Content: &proto.GossipMessage_DataMsg{ 523 DataMsg: &proto.DataMessage{}, 524 }, 525 }).NoopSign() 526 } 527 528 func remotePeer(port int) *RemotePeer { 529 endpoint := fmt.Sprintf("localhost:%d", port) 530 return &RemotePeer{Endpoint: endpoint, PKIID: []byte(endpoint)} 531 } 532 533 func waitForMessages(t *testing.T, msgChan chan uint64, count int, errMsg string) { 534 c := 0 535 waiting := true 536 ticker := time.NewTicker(time.Duration(10) * time.Second) 537 for waiting { 538 select { 539 case <-msgChan: 540 c++ 541 if c == count { 542 waiting = false 543 } 544 break 545 case <-ticker.C: 546 waiting = false 547 break 548 } 549 } 550 assert.Equal(t, count, c, errMsg) 551 } 552 553 func TestMain(m *testing.M) { 554 SetDialTimeout(time.Duration(300) * time.Millisecond) 555 556 ret := m.Run() 557 os.Exit(ret) 558 }