github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/internal/pkg/peer/blocksprovider/blocksprovider_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package blocksprovider_test 8 9 import ( 10 "crypto/x509" 11 "fmt" 12 "sync" 13 "time" 14 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/gomega" 17 18 "github.com/hyperledger/fabric-protos-go/common" 19 "github.com/hyperledger/fabric-protos-go/gossip" 20 "github.com/hyperledger/fabric-protos-go/orderer" 21 "github.com/hyperledger/fabric/common/flogging" 22 gossipcommon "github.com/hyperledger/fabric/gossip/common" 23 "github.com/hyperledger/fabric/internal/pkg/peer/blocksprovider" 24 "github.com/hyperledger/fabric/internal/pkg/peer/blocksprovider/fake" 25 "github.com/hyperledger/fabric/internal/pkg/peer/orderers" 26 "github.com/hyperledger/fabric/protoutil" 27 28 "github.com/golang/protobuf/proto" 29 "google.golang.org/grpc" 30 "google.golang.org/grpc/connectivity" 31 ) 32 33 var _ = Describe("Blocksprovider", func() { 34 var ( 35 d *blocksprovider.Deliverer 36 ccs []*grpc.ClientConn 37 fakeDialer *fake.Dialer 38 fakeGossipServiceAdapter *fake.GossipServiceAdapter 39 fakeOrdererConnectionSource *fake.OrdererConnectionSource 40 fakeLedgerInfo *fake.LedgerInfo 41 fakeBlockVerifier *fake.BlockVerifier 42 fakeSigner *fake.Signer 43 fakeDeliverStreamer *fake.DeliverStreamer 44 fakeDeliverClient *fake.DeliverClient 45 fakeSleeper *fake.Sleeper 46 doneC chan struct{} 47 recvStep chan struct{} 48 endC chan struct{} 49 mutex sync.Mutex 50 ) 51 52 BeforeEach(func() { 53 doneC = make(chan struct{}) 54 recvStep = make(chan struct{}) 55 56 // appease the race detector 57 recvStep := recvStep 58 doneC := doneC 59 60 fakeDialer = &fake.Dialer{} 61 ccs = nil 62 fakeDialer.DialStub = func(string, *x509.CertPool) (*grpc.ClientConn, error) { 63 mutex.Lock() 64 defer mutex.Unlock() 65 cc, err := grpc.Dial("", grpc.WithInsecure()) 66 ccs = append(ccs, cc) 67 Expect(err).NotTo(HaveOccurred()) 68 Expect(cc.GetState()).NotTo(Equal(connectivity.Shutdown)) 69 return cc, nil 70 } 71 72 fakeGossipServiceAdapter = &fake.GossipServiceAdapter{} 73 fakeBlockVerifier = &fake.BlockVerifier{} 74 fakeSigner = &fake.Signer{} 75 76 fakeLedgerInfo = &fake.LedgerInfo{} 77 fakeLedgerInfo.LedgerHeightReturns(7, nil) 78 79 fakeOrdererConnectionSource = &fake.OrdererConnectionSource{} 80 fakeOrdererConnectionSource.RandomEndpointReturns(&orderers.Endpoint{ 81 Address: "orderer-address", 82 }, nil) 83 84 fakeDeliverClient = &fake.DeliverClient{} 85 fakeDeliverClient.RecvStub = func() (*orderer.DeliverResponse, error) { 86 select { 87 case <-recvStep: 88 return nil, fmt.Errorf("fake-recv-step-error") 89 case <-doneC: 90 return nil, nil 91 } 92 } 93 94 fakeDeliverClient.CloseSendStub = func() error { 95 select { 96 case recvStep <- struct{}{}: 97 case <-doneC: 98 } 99 return nil 100 } 101 102 fakeDeliverStreamer = &fake.DeliverStreamer{} 103 fakeDeliverStreamer.DeliverReturns(fakeDeliverClient, nil) 104 105 d = &blocksprovider.Deliverer{ 106 ChannelID: "channel-id", 107 Gossip: fakeGossipServiceAdapter, 108 Ledger: fakeLedgerInfo, 109 BlockVerifier: fakeBlockVerifier, 110 Dialer: fakeDialer, 111 Orderers: fakeOrdererConnectionSource, 112 DoneC: doneC, 113 Signer: fakeSigner, 114 DeliverStreamer: fakeDeliverStreamer, 115 Logger: flogging.MustGetLogger("blocksprovider"), 116 TLSCertHash: []byte("tls-cert-hash"), 117 MaxRetryDuration: time.Hour, 118 MaxRetryDelay: 10 * time.Second, 119 InitialRetryDelay: 100 * time.Millisecond, 120 } 121 122 fakeSleeper = &fake.Sleeper{} 123 blocksprovider.SetSleeper(d, fakeSleeper) 124 }) 125 126 JustBeforeEach(func() { 127 endC = make(chan struct{}) 128 go func() { 129 d.DeliverBlocks() 130 close(endC) 131 }() 132 }) 133 134 AfterEach(func() { 135 close(doneC) 136 <-endC 137 }) 138 139 It("waits patiently for new blocks from the orderer", func() { 140 Consistently(endC).ShouldNot(BeClosed()) 141 mutex.Lock() 142 defer mutex.Unlock() 143 Expect(ccs[0].GetState()).NotTo(Equal(connectivity.Shutdown)) 144 }) 145 146 It("checks the ledger height", func() { 147 Eventually(fakeLedgerInfo.LedgerHeightCallCount).Should(Equal(1)) 148 }) 149 150 When("the ledger returns an error", func() { 151 BeforeEach(func() { 152 fakeLedgerInfo.LedgerHeightReturns(0, fmt.Errorf("fake-ledger-error")) 153 }) 154 155 It("exits the loop", func() { 156 Eventually(endC).Should(BeClosed()) 157 }) 158 }) 159 160 It("signs the seek info request", func() { 161 Eventually(fakeSigner.SignCallCount).Should(Equal(1)) 162 // Note, the signer is used inside a util method 163 // which has its own set of tests, so checking the args 164 // in this test is unnecessary 165 }) 166 167 When("the signer returns an error", func() { 168 BeforeEach(func() { 169 fakeSigner.SignReturns(nil, fmt.Errorf("fake-signer-error")) 170 }) 171 172 It("exits the loop", func() { 173 Eventually(endC).Should(BeClosed()) 174 }) 175 }) 176 177 It("gets a random endpoint to connect to from the orderer connection source", func() { 178 Eventually(fakeOrdererConnectionSource.RandomEndpointCallCount).Should(Equal(1)) 179 }) 180 181 When("the orderer connection source returns an error", func() { 182 BeforeEach(func() { 183 fakeOrdererConnectionSource.RandomEndpointReturnsOnCall(0, nil, fmt.Errorf("fake-endpoint-error")) 184 fakeOrdererConnectionSource.RandomEndpointReturnsOnCall(1, &orderers.Endpoint{ 185 Address: "orderer-address", 186 }, nil) 187 }) 188 189 It("sleeps and retries until a valid endpoint is selected", func() { 190 Eventually(fakeOrdererConnectionSource.RandomEndpointCallCount).Should(Equal(2)) 191 Expect(fakeSleeper.SleepCallCount()).To(Equal(1)) 192 Expect(fakeSleeper.SleepArgsForCall(0)).To(Equal(100 * time.Millisecond)) 193 }) 194 }) 195 196 When("the orderer connect is refreshed", func() { 197 BeforeEach(func() { 198 refreshedC := make(chan struct{}) 199 close(refreshedC) 200 fakeOrdererConnectionSource.RandomEndpointReturnsOnCall(0, &orderers.Endpoint{ 201 Address: "orderer-address", 202 Refreshed: refreshedC, 203 }, nil) 204 fakeOrdererConnectionSource.RandomEndpointReturnsOnCall(1, &orderers.Endpoint{ 205 Address: "orderer-address", 206 }, nil) 207 }) 208 209 It("does not sleep, but disconnects and immediately tries to reconnect", func() { 210 Eventually(fakeOrdererConnectionSource.RandomEndpointCallCount).Should(Equal(2)) 211 Expect(fakeSleeper.SleepCallCount()).To(Equal(0)) 212 }) 213 }) 214 215 It("dials the random endpoint", func() { 216 Eventually(fakeDialer.DialCallCount).Should(Equal(1)) 217 addr, tlsCerts := fakeDialer.DialArgsForCall(0) 218 Expect(addr).To(Equal("orderer-address")) 219 Expect(tlsCerts).To(BeNil()) // TODO 220 }) 221 222 When("the dialer returns an error", func() { 223 BeforeEach(func() { 224 fakeDialer.DialReturnsOnCall(0, nil, fmt.Errorf("fake-dial-error")) 225 cc, err := grpc.Dial("", grpc.WithInsecure()) 226 Expect(err).NotTo(HaveOccurred()) 227 fakeDialer.DialReturnsOnCall(1, cc, nil) 228 }) 229 230 It("sleeps and retries until dial is successful", func() { 231 Eventually(fakeDialer.DialCallCount).Should(Equal(2)) 232 Expect(fakeSleeper.SleepCallCount()).To(Equal(1)) 233 Expect(fakeSleeper.SleepArgsForCall(0)).To(Equal(100 * time.Millisecond)) 234 }) 235 }) 236 237 It("constructs a deliver client", func() { 238 Eventually(fakeDeliverStreamer.DeliverCallCount).Should(Equal(1)) 239 }) 240 241 When("the deliver client cannot be created", func() { 242 BeforeEach(func() { 243 fakeDeliverStreamer.DeliverReturnsOnCall(0, nil, fmt.Errorf("deliver-error")) 244 fakeDeliverStreamer.DeliverReturnsOnCall(1, fakeDeliverClient, nil) 245 }) 246 247 It("closes the grpc connection, sleeps, and tries again", func() { 248 Eventually(fakeDeliverStreamer.DeliverCallCount).Should(Equal(2)) 249 Expect(fakeSleeper.SleepCallCount()).To(Equal(1)) 250 Expect(fakeSleeper.SleepArgsForCall(0)).To(Equal(100 * time.Millisecond)) 251 }) 252 }) 253 254 When("there are consecutive errors", func() { 255 BeforeEach(func() { 256 fakeDeliverStreamer.DeliverReturnsOnCall(0, nil, fmt.Errorf("deliver-error")) 257 fakeDeliverStreamer.DeliverReturnsOnCall(1, nil, fmt.Errorf("deliver-error")) 258 fakeDeliverStreamer.DeliverReturnsOnCall(2, nil, fmt.Errorf("deliver-error")) 259 fakeDeliverStreamer.DeliverReturnsOnCall(3, fakeDeliverClient, nil) 260 }) 261 262 It("sleeps in an exponential fashion and retries until dial is successful", func() { 263 Eventually(fakeDeliverStreamer.DeliverCallCount).Should(Equal(4)) 264 Expect(fakeSleeper.SleepCallCount()).To(Equal(3)) 265 Expect(fakeSleeper.SleepArgsForCall(0)).To(Equal(100 * time.Millisecond)) 266 Expect(fakeSleeper.SleepArgsForCall(1)).To(Equal(120 * time.Millisecond)) 267 Expect(fakeSleeper.SleepArgsForCall(2)).To(Equal(144 * time.Millisecond)) 268 }) 269 }) 270 271 When("the consecutive errors are unbounded", func() { 272 BeforeEach(func() { 273 fakeDeliverStreamer.DeliverReturns(nil, fmt.Errorf("deliver-error")) 274 fakeDeliverStreamer.DeliverReturnsOnCall(500, fakeDeliverClient, nil) 275 }) 276 277 It("the sleep time hits the maximum value in an exponential fashion and retries until exceeding the max retry duration", func() { 278 Eventually(fakeSleeper.SleepCallCount).Should(Equal(380)) 279 Expect(fakeSleeper.SleepArgsForCall(25)).To(Equal(9539 * time.Millisecond)) 280 Expect(fakeSleeper.SleepArgsForCall(26)).To(Equal(10 * time.Second)) 281 Expect(fakeSleeper.SleepArgsForCall(27)).To(Equal(10 * time.Second)) 282 Expect(fakeSleeper.SleepArgsForCall(379)).To(Equal(10 * time.Second)) 283 }) 284 }) 285 286 When("an error occurs, then a block is successfully delivered", func() { 287 BeforeEach(func() { 288 fakeDeliverStreamer.DeliverReturnsOnCall(0, nil, fmt.Errorf("deliver-error")) 289 fakeDeliverStreamer.DeliverReturnsOnCall(1, fakeDeliverClient, nil) 290 fakeDeliverStreamer.DeliverReturnsOnCall(1, nil, fmt.Errorf("deliver-error")) 291 fakeDeliverStreamer.DeliverReturnsOnCall(2, nil, fmt.Errorf("deliver-error")) 292 }) 293 294 It("sleeps in an exponential fashion and retries until dial is successful", func() { 295 Eventually(fakeDeliverStreamer.DeliverCallCount).Should(Equal(4)) 296 Expect(fakeSleeper.SleepCallCount()).To(Equal(3)) 297 Expect(fakeSleeper.SleepArgsForCall(0)).To(Equal(100 * time.Millisecond)) 298 Expect(fakeSleeper.SleepArgsForCall(1)).To(Equal(120 * time.Millisecond)) 299 Expect(fakeSleeper.SleepArgsForCall(2)).To(Equal(144 * time.Millisecond)) 300 }) 301 }) 302 303 It("sends a request to the deliver client for new blocks", func() { 304 Eventually(fakeDeliverClient.SendCallCount).Should(Equal(1)) 305 mutex.Lock() 306 defer mutex.Unlock() 307 Expect(len(ccs)).To(Equal(1)) 308 }) 309 310 When("the send fails", func() { 311 BeforeEach(func() { 312 fakeDeliverClient.SendReturnsOnCall(0, fmt.Errorf("fake-send-error")) 313 fakeDeliverClient.SendReturnsOnCall(1, nil) 314 fakeDeliverClient.CloseSendStub = nil 315 }) 316 317 It("disconnects, sleeps and retries until the send is successful", func() { 318 Eventually(fakeDeliverClient.SendCallCount).Should(Equal(2)) 319 Expect(fakeDeliverClient.CloseSendCallCount()).To(Equal(1)) 320 Expect(fakeSleeper.SleepCallCount()).To(Equal(1)) 321 Expect(fakeSleeper.SleepArgsForCall(0)).To(Equal(100 * time.Millisecond)) 322 mutex.Lock() 323 defer mutex.Unlock() 324 Expect(len(ccs)).To(Equal(2)) 325 Eventually(ccs[0].GetState).Should(Equal(connectivity.Shutdown)) 326 }) 327 }) 328 329 It("attempts to read blocks from the deliver stream", func() { 330 Eventually(fakeDeliverClient.RecvCallCount).Should(Equal(1)) 331 }) 332 333 When("reading blocks from the deliver stream fails", func() { 334 BeforeEach(func() { 335 // appease the race detector 336 doneC := doneC 337 recvStep := recvStep 338 fakeDeliverClient := fakeDeliverClient 339 340 fakeDeliverClient.CloseSendStub = nil 341 fakeDeliverClient.RecvStub = func() (*orderer.DeliverResponse, error) { 342 if fakeDeliverClient.RecvCallCount() == 1 { 343 return nil, fmt.Errorf("fake-recv-error") 344 } 345 select { 346 case <-recvStep: 347 return nil, fmt.Errorf("fake-recv-step-error") 348 case <-doneC: 349 return nil, nil 350 } 351 } 352 }) 353 354 It("disconnects, sleeps, and retries until the recv is successfull", func() { 355 Eventually(fakeDeliverClient.RecvCallCount).Should(Equal(2)) 356 Expect(fakeSleeper.SleepCallCount()).To(Equal(1)) 357 Expect(fakeSleeper.SleepArgsForCall(0)).To(Equal(100 * time.Millisecond)) 358 }) 359 }) 360 361 When("reading blocks from the deliver stream fails and then recovers", func() { 362 BeforeEach(func() { 363 // appease the race detector 364 doneC := doneC 365 recvStep := recvStep 366 fakeDeliverClient := fakeDeliverClient 367 368 fakeDeliverClient.CloseSendStub = func() error { 369 if fakeDeliverClient.CloseSendCallCount() >= 5 { 370 select { 371 case <-doneC: 372 case recvStep <- struct{}{}: 373 } 374 } 375 return nil 376 } 377 fakeDeliverClient.RecvStub = func() (*orderer.DeliverResponse, error) { 378 switch fakeDeliverClient.RecvCallCount() { 379 case 1, 2, 4: 380 return nil, fmt.Errorf("fake-recv-error") 381 case 3: 382 return &orderer.DeliverResponse{ 383 Type: &orderer.DeliverResponse_Block{ 384 Block: &common.Block{ 385 Header: &common.BlockHeader{ 386 Number: 8, 387 }, 388 }, 389 }, 390 }, nil 391 default: 392 select { 393 case <-recvStep: 394 return nil, fmt.Errorf("fake-recv-step-error") 395 case <-doneC: 396 return nil, nil 397 } 398 } 399 } 400 }) 401 402 It("disconnects, sleeps, and retries until the recv is successfull and resets the failure count", func() { 403 Eventually(fakeDeliverClient.RecvCallCount).Should(Equal(5)) 404 Expect(fakeSleeper.SleepCallCount()).To(Equal(3)) 405 Expect(fakeSleeper.SleepArgsForCall(0)).To(Equal(100 * time.Millisecond)) 406 Expect(fakeSleeper.SleepArgsForCall(1)).To(Equal(120 * time.Millisecond)) 407 Expect(fakeSleeper.SleepArgsForCall(2)).To(Equal(100 * time.Millisecond)) 408 }) 409 }) 410 411 When("the deliver client returns a block", func() { 412 BeforeEach(func() { 413 // appease the race detector 414 doneC := doneC 415 recvStep := recvStep 416 fakeDeliverClient := fakeDeliverClient 417 418 fakeDeliverClient.RecvStub = func() (*orderer.DeliverResponse, error) { 419 if fakeDeliverClient.RecvCallCount() == 1 { 420 return &orderer.DeliverResponse{ 421 Type: &orderer.DeliverResponse_Block{ 422 Block: &common.Block{ 423 Header: &common.BlockHeader{ 424 Number: 8, 425 }, 426 }, 427 }, 428 }, nil 429 } 430 select { 431 case <-recvStep: 432 return nil, fmt.Errorf("fake-recv-step-error") 433 case <-doneC: 434 return nil, nil 435 } 436 } 437 }) 438 439 It("receives the block and loops, not sleeping", func() { 440 Eventually(fakeDeliverClient.RecvCallCount).Should(Equal(2)) 441 Expect(fakeSleeper.SleepCallCount()).To(Equal(0)) 442 }) 443 444 It("checks the validity of the block", func() { 445 Eventually(fakeBlockVerifier.VerifyBlockCallCount).Should(Equal(1)) 446 channelID, blockNum, block := fakeBlockVerifier.VerifyBlockArgsForCall(0) 447 Expect(channelID).To(Equal(gossipcommon.ChannelID("channel-id"))) 448 Expect(blockNum).To(Equal(uint64(8))) 449 Expect(proto.Equal(block, &common.Block{ 450 Header: &common.BlockHeader{ 451 Number: 8, 452 }, 453 })).To(BeTrue()) 454 }) 455 456 When("the block is invalid", func() { 457 BeforeEach(func() { 458 fakeBlockVerifier.VerifyBlockReturns(fmt.Errorf("fake-verify-error")) 459 }) 460 461 It("disconnects, sleeps, and tries again", func() { 462 Eventually(fakeSleeper.SleepCallCount).Should(Equal(1)) 463 Expect(fakeDeliverClient.CloseSendCallCount()).To(Equal(1)) 464 mutex.Lock() 465 defer mutex.Unlock() 466 Expect(len(ccs)).To(Equal(2)) 467 }) 468 }) 469 470 It("adds the payload to gossip", func() { 471 Eventually(fakeGossipServiceAdapter.AddPayloadCallCount).Should(Equal(1)) 472 channelID, payload := fakeGossipServiceAdapter.AddPayloadArgsForCall(0) 473 Expect(channelID).To(Equal("channel-id")) 474 Expect(payload).To(Equal(&gossip.Payload{ 475 Data: protoutil.MarshalOrPanic(&common.Block{ 476 Header: &common.BlockHeader{ 477 Number: 8, 478 }, 479 }), 480 SeqNum: 8, 481 })) 482 }) 483 484 When("adding the payload fails", func() { 485 BeforeEach(func() { 486 fakeGossipServiceAdapter.AddPayloadReturns(fmt.Errorf("payload-error")) 487 }) 488 489 It("disconnects, sleeps, and tries again", func() { 490 Eventually(fakeSleeper.SleepCallCount).Should(Equal(1)) 491 Expect(fakeDeliverClient.CloseSendCallCount()).To(Equal(1)) 492 mutex.Lock() 493 defer mutex.Unlock() 494 Expect(len(ccs)).To(Equal(2)) 495 }) 496 }) 497 498 It("gossips the block to the other peers", func() { 499 Eventually(fakeGossipServiceAdapter.GossipCallCount).Should(Equal(1)) 500 msg := fakeGossipServiceAdapter.GossipArgsForCall(0) 501 Expect(msg).To(Equal(&gossip.GossipMessage{ 502 Nonce: 0, 503 Tag: gossip.GossipMessage_CHAN_AND_ORG, 504 Channel: []byte("channel-id"), 505 Content: &gossip.GossipMessage_DataMsg{ 506 DataMsg: &gossip.DataMessage{ 507 Payload: &gossip.Payload{ 508 Data: protoutil.MarshalOrPanic(&common.Block{ 509 Header: &common.BlockHeader{ 510 Number: 8, 511 }, 512 }), 513 SeqNum: 8, 514 }, 515 }, 516 }, 517 })) 518 }) 519 }) 520 521 When("the deliver client returns a status", func() { 522 var ( 523 status common.Status 524 ) 525 526 BeforeEach(func() { 527 // appease the race detector 528 doneC := doneC 529 recvStep := recvStep 530 fakeDeliverClient := fakeDeliverClient 531 532 status = common.Status_SUCCESS 533 fakeDeliverClient.RecvStub = func() (*orderer.DeliverResponse, error) { 534 if fakeDeliverClient.RecvCallCount() == 1 { 535 return &orderer.DeliverResponse{ 536 Type: &orderer.DeliverResponse_Status{ 537 Status: status, 538 }, 539 }, nil 540 } 541 select { 542 case <-recvStep: 543 return nil, fmt.Errorf("fake-recv-step-error") 544 case <-doneC: 545 return nil, nil 546 } 547 } 548 }) 549 550 It("disconnects with an error, and sleeps because the block request is infinite and should never complete", func() { 551 Eventually(fakeSleeper.SleepCallCount).Should(Equal(1)) 552 }) 553 554 When("the status is not successful", func() { 555 BeforeEach(func() { 556 status = common.Status_FORBIDDEN 557 }) 558 559 It("still disconnects with an error", func() { 560 Eventually(fakeSleeper.SleepCallCount).Should(Equal(1)) 561 }) 562 }) 563 }) 564 })