github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/internal/pkg/peer/blocksprovider/blocksprovider_test.go (about)

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