github.com/lzy4123/fabric@v2.1.1+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 and the peer is not a static leader", func() { 272 BeforeEach(func() { 273 fakeDeliverStreamer.DeliverReturns(nil, fmt.Errorf("deliver-error")) 274 fakeDeliverStreamer.DeliverReturnsOnCall(500, fakeDeliverClient, nil) 275 }) 276 277 It("hits the maximum sleep time value in an exponential fashion and retries until exceeding the max retry duration", func() { 278 d.YieldLeadership = true 279 Eventually(fakeSleeper.SleepCallCount).Should(Equal(380)) 280 Expect(fakeSleeper.SleepArgsForCall(25)).To(Equal(9539 * time.Millisecond)) 281 Expect(fakeSleeper.SleepArgsForCall(26)).To(Equal(10 * time.Second)) 282 Expect(fakeSleeper.SleepArgsForCall(27)).To(Equal(10 * time.Second)) 283 Expect(fakeSleeper.SleepArgsForCall(379)).To(Equal(10 * time.Second)) 284 }) 285 }) 286 287 When("the consecutive errors are unbounded and the peer is static leader", func() { 288 BeforeEach(func() { 289 fakeDeliverStreamer.DeliverReturns(nil, fmt.Errorf("deliver-error")) 290 fakeDeliverStreamer.DeliverReturnsOnCall(500, fakeDeliverClient, nil) 291 }) 292 293 It("hits the maximum sleep time value in an exponential fashion and retries indefinitely", func() { 294 d.YieldLeadership = false 295 Eventually(fakeSleeper.SleepCallCount).Should(Equal(500)) 296 Expect(fakeSleeper.SleepArgsForCall(25)).To(Equal(9539 * time.Millisecond)) 297 Expect(fakeSleeper.SleepArgsForCall(26)).To(Equal(10 * time.Second)) 298 Expect(fakeSleeper.SleepArgsForCall(27)).To(Equal(10 * time.Second)) 299 Expect(fakeSleeper.SleepArgsForCall(379)).To(Equal(10 * time.Second)) 300 }) 301 }) 302 303 When("an error occurs, then a block is successfully delivered", func() { 304 BeforeEach(func() { 305 fakeDeliverStreamer.DeliverReturnsOnCall(0, nil, fmt.Errorf("deliver-error")) 306 fakeDeliverStreamer.DeliverReturnsOnCall(1, fakeDeliverClient, nil) 307 fakeDeliverStreamer.DeliverReturnsOnCall(1, nil, fmt.Errorf("deliver-error")) 308 fakeDeliverStreamer.DeliverReturnsOnCall(2, nil, fmt.Errorf("deliver-error")) 309 }) 310 311 It("sleeps in an exponential fashion and retries until dial is successful", func() { 312 Eventually(fakeDeliverStreamer.DeliverCallCount).Should(Equal(4)) 313 Expect(fakeSleeper.SleepCallCount()).To(Equal(3)) 314 Expect(fakeSleeper.SleepArgsForCall(0)).To(Equal(100 * time.Millisecond)) 315 Expect(fakeSleeper.SleepArgsForCall(1)).To(Equal(120 * time.Millisecond)) 316 Expect(fakeSleeper.SleepArgsForCall(2)).To(Equal(144 * time.Millisecond)) 317 }) 318 }) 319 320 It("sends a request to the deliver client for new blocks", func() { 321 Eventually(fakeDeliverClient.SendCallCount).Should(Equal(1)) 322 mutex.Lock() 323 defer mutex.Unlock() 324 Expect(len(ccs)).To(Equal(1)) 325 }) 326 327 When("the send fails", func() { 328 BeforeEach(func() { 329 fakeDeliverClient.SendReturnsOnCall(0, fmt.Errorf("fake-send-error")) 330 fakeDeliverClient.SendReturnsOnCall(1, nil) 331 fakeDeliverClient.CloseSendStub = nil 332 }) 333 334 It("disconnects, sleeps and retries until the send is successful", func() { 335 Eventually(fakeDeliverClient.SendCallCount).Should(Equal(2)) 336 Expect(fakeDeliverClient.CloseSendCallCount()).To(Equal(1)) 337 Expect(fakeSleeper.SleepCallCount()).To(Equal(1)) 338 Expect(fakeSleeper.SleepArgsForCall(0)).To(Equal(100 * time.Millisecond)) 339 mutex.Lock() 340 defer mutex.Unlock() 341 Expect(len(ccs)).To(Equal(2)) 342 Eventually(ccs[0].GetState).Should(Equal(connectivity.Shutdown)) 343 }) 344 }) 345 346 It("attempts to read blocks from the deliver stream", func() { 347 Eventually(fakeDeliverClient.RecvCallCount).Should(Equal(1)) 348 }) 349 350 When("reading blocks from the deliver stream fails", func() { 351 BeforeEach(func() { 352 // appease the race detector 353 doneC := doneC 354 recvStep := recvStep 355 fakeDeliverClient := fakeDeliverClient 356 357 fakeDeliverClient.CloseSendStub = nil 358 fakeDeliverClient.RecvStub = func() (*orderer.DeliverResponse, error) { 359 if fakeDeliverClient.RecvCallCount() == 1 { 360 return nil, fmt.Errorf("fake-recv-error") 361 } 362 select { 363 case <-recvStep: 364 return nil, fmt.Errorf("fake-recv-step-error") 365 case <-doneC: 366 return nil, nil 367 } 368 } 369 }) 370 371 It("disconnects, sleeps, and retries until the recv is successfull", func() { 372 Eventually(fakeDeliverClient.RecvCallCount).Should(Equal(2)) 373 Expect(fakeSleeper.SleepCallCount()).To(Equal(1)) 374 Expect(fakeSleeper.SleepArgsForCall(0)).To(Equal(100 * time.Millisecond)) 375 }) 376 }) 377 378 When("reading blocks from the deliver stream fails and then recovers", func() { 379 BeforeEach(func() { 380 // appease the race detector 381 doneC := doneC 382 recvStep := recvStep 383 fakeDeliverClient := fakeDeliverClient 384 385 fakeDeliverClient.CloseSendStub = func() error { 386 if fakeDeliverClient.CloseSendCallCount() >= 5 { 387 select { 388 case <-doneC: 389 case recvStep <- struct{}{}: 390 } 391 } 392 return nil 393 } 394 fakeDeliverClient.RecvStub = func() (*orderer.DeliverResponse, error) { 395 switch fakeDeliverClient.RecvCallCount() { 396 case 1, 2, 4: 397 return nil, fmt.Errorf("fake-recv-error") 398 case 3: 399 return &orderer.DeliverResponse{ 400 Type: &orderer.DeliverResponse_Block{ 401 Block: &common.Block{ 402 Header: &common.BlockHeader{ 403 Number: 8, 404 }, 405 }, 406 }, 407 }, nil 408 default: 409 select { 410 case <-recvStep: 411 return nil, fmt.Errorf("fake-recv-step-error") 412 case <-doneC: 413 return nil, nil 414 } 415 } 416 } 417 }) 418 419 It("disconnects, sleeps, and retries until the recv is successfull and resets the failure count", func() { 420 Eventually(fakeDeliverClient.RecvCallCount).Should(Equal(5)) 421 Expect(fakeSleeper.SleepCallCount()).To(Equal(3)) 422 Expect(fakeSleeper.SleepArgsForCall(0)).To(Equal(100 * time.Millisecond)) 423 Expect(fakeSleeper.SleepArgsForCall(1)).To(Equal(120 * time.Millisecond)) 424 Expect(fakeSleeper.SleepArgsForCall(2)).To(Equal(100 * time.Millisecond)) 425 }) 426 }) 427 428 When("the deliver client returns a block", func() { 429 BeforeEach(func() { 430 // appease the race detector 431 doneC := doneC 432 recvStep := recvStep 433 fakeDeliverClient := fakeDeliverClient 434 435 fakeDeliverClient.RecvStub = func() (*orderer.DeliverResponse, error) { 436 if fakeDeliverClient.RecvCallCount() == 1 { 437 return &orderer.DeliverResponse{ 438 Type: &orderer.DeliverResponse_Block{ 439 Block: &common.Block{ 440 Header: &common.BlockHeader{ 441 Number: 8, 442 }, 443 }, 444 }, 445 }, nil 446 } 447 select { 448 case <-recvStep: 449 return nil, fmt.Errorf("fake-recv-step-error") 450 case <-doneC: 451 return nil, nil 452 } 453 } 454 }) 455 456 It("receives the block and loops, not sleeping", func() { 457 Eventually(fakeDeliverClient.RecvCallCount).Should(Equal(2)) 458 Expect(fakeSleeper.SleepCallCount()).To(Equal(0)) 459 }) 460 461 It("checks the validity of the block", func() { 462 Eventually(fakeBlockVerifier.VerifyBlockCallCount).Should(Equal(1)) 463 channelID, blockNum, block := fakeBlockVerifier.VerifyBlockArgsForCall(0) 464 Expect(channelID).To(Equal(gossipcommon.ChannelID("channel-id"))) 465 Expect(blockNum).To(Equal(uint64(8))) 466 Expect(proto.Equal(block, &common.Block{ 467 Header: &common.BlockHeader{ 468 Number: 8, 469 }, 470 })).To(BeTrue()) 471 }) 472 473 When("the block is invalid", func() { 474 BeforeEach(func() { 475 fakeBlockVerifier.VerifyBlockReturns(fmt.Errorf("fake-verify-error")) 476 }) 477 478 It("disconnects, sleeps, and tries again", func() { 479 Eventually(fakeSleeper.SleepCallCount).Should(Equal(1)) 480 Expect(fakeDeliverClient.CloseSendCallCount()).To(Equal(1)) 481 mutex.Lock() 482 defer mutex.Unlock() 483 Expect(len(ccs)).To(Equal(2)) 484 }) 485 }) 486 487 It("adds the payload to gossip", func() { 488 Eventually(fakeGossipServiceAdapter.AddPayloadCallCount).Should(Equal(1)) 489 channelID, payload := fakeGossipServiceAdapter.AddPayloadArgsForCall(0) 490 Expect(channelID).To(Equal("channel-id")) 491 Expect(payload).To(Equal(&gossip.Payload{ 492 Data: protoutil.MarshalOrPanic(&common.Block{ 493 Header: &common.BlockHeader{ 494 Number: 8, 495 }, 496 }), 497 SeqNum: 8, 498 })) 499 }) 500 501 When("adding the payload fails", func() { 502 BeforeEach(func() { 503 fakeGossipServiceAdapter.AddPayloadReturns(fmt.Errorf("payload-error")) 504 }) 505 506 It("disconnects, sleeps, and tries again", func() { 507 Eventually(fakeSleeper.SleepCallCount).Should(Equal(1)) 508 Expect(fakeDeliverClient.CloseSendCallCount()).To(Equal(1)) 509 mutex.Lock() 510 defer mutex.Unlock() 511 Expect(len(ccs)).To(Equal(2)) 512 }) 513 }) 514 515 It("gossips the block to the other peers", func() { 516 Eventually(fakeGossipServiceAdapter.GossipCallCount).Should(Equal(1)) 517 msg := fakeGossipServiceAdapter.GossipArgsForCall(0) 518 Expect(msg).To(Equal(&gossip.GossipMessage{ 519 Nonce: 0, 520 Tag: gossip.GossipMessage_CHAN_AND_ORG, 521 Channel: []byte("channel-id"), 522 Content: &gossip.GossipMessage_DataMsg{ 523 DataMsg: &gossip.DataMessage{ 524 Payload: &gossip.Payload{ 525 Data: protoutil.MarshalOrPanic(&common.Block{ 526 Header: &common.BlockHeader{ 527 Number: 8, 528 }, 529 }), 530 SeqNum: 8, 531 }, 532 }, 533 }, 534 })) 535 }) 536 }) 537 538 When("the deliver client returns a status", func() { 539 var ( 540 status common.Status 541 ) 542 543 BeforeEach(func() { 544 // appease the race detector 545 doneC := doneC 546 recvStep := recvStep 547 fakeDeliverClient := fakeDeliverClient 548 549 status = common.Status_SUCCESS 550 fakeDeliverClient.RecvStub = func() (*orderer.DeliverResponse, error) { 551 if fakeDeliverClient.RecvCallCount() == 1 { 552 return &orderer.DeliverResponse{ 553 Type: &orderer.DeliverResponse_Status{ 554 Status: status, 555 }, 556 }, nil 557 } 558 select { 559 case <-recvStep: 560 return nil, fmt.Errorf("fake-recv-step-error") 561 case <-doneC: 562 return nil, nil 563 } 564 } 565 }) 566 567 It("disconnects with an error, and sleeps because the block request is infinite and should never complete", func() { 568 Eventually(fakeSleeper.SleepCallCount).Should(Equal(1)) 569 }) 570 571 When("the status is not successful", func() { 572 BeforeEach(func() { 573 status = common.Status_FORBIDDEN 574 }) 575 576 It("still disconnects with an error", func() { 577 Eventually(fakeSleeper.SleepCallCount).Should(Equal(1)) 578 }) 579 }) 580 }) 581 })