github.com/true-sqn/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  })