github.com/lzy4123/fabric@v2.1.1+incompatible/core/peer/deliverevents_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package peer
     8  
     9  import (
    10  	"context"
    11  	"fmt"
    12  	"io"
    13  	"strings"
    14  	"sync"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/golang/protobuf/proto"
    19  	"github.com/hyperledger/fabric-protos-go/common"
    20  	"github.com/hyperledger/fabric-protos-go/orderer"
    21  	"github.com/hyperledger/fabric-protos-go/peer"
    22  	"github.com/hyperledger/fabric/common/deliver"
    23  	"github.com/hyperledger/fabric/common/ledger/blockledger"
    24  	"github.com/hyperledger/fabric/common/metrics/disabled"
    25  	"github.com/hyperledger/fabric/common/policies"
    26  	"github.com/hyperledger/fabric/common/util"
    27  	"github.com/hyperledger/fabric/core/ledger"
    28  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
    29  	fake "github.com/hyperledger/fabric/core/peer/mock"
    30  	"github.com/hyperledger/fabric/protoutil"
    31  	"github.com/stretchr/testify/assert"
    32  	"github.com/stretchr/testify/mock"
    33  	"google.golang.org/grpc/metadata"
    34  	peer2 "google.golang.org/grpc/peer"
    35  )
    36  
    37  // defaultPolicyCheckerProvider policy checker provider used by default,
    38  // generates policy checker which always accepts regardless of arguments
    39  // passed in
    40  var defaultPolicyCheckerProvider = func(_ string) deliver.PolicyCheckerFunc {
    41  	return func(_ *common.Envelope, _ string) error {
    42  		return nil
    43  	}
    44  }
    45  
    46  //go:generate counterfeiter -o mock/peer_ledger.go -fake-name PeerLedger . peerLedger
    47  
    48  type peerLedger interface {
    49  	ledger.PeerLedger
    50  }
    51  
    52  //go:generate counterfeiter -o mock/identity_deserializer_manager.go -fake-name IdentityDeserializerManager . identityDeserializerManager
    53  
    54  type identityDeserializerManager interface {
    55  	IdentityDeserializerManager
    56  }
    57  
    58  //go:generate counterfeiter -o mock/collection_policy_checker.go -fake-name CollectionPolicyChecker . collectionPolicyChecker
    59  
    60  type collectionPolicyChecker interface {
    61  	CollectionPolicyChecker
    62  }
    63  
    64  // mockIterator mock structure implementing
    65  // the blockledger.Iterator interface
    66  type mockIterator struct {
    67  	mock.Mock
    68  }
    69  
    70  func (m *mockIterator) Next() (*common.Block, common.Status) {
    71  	args := m.Called()
    72  	return args.Get(0).(*common.Block), args.Get(1).(common.Status)
    73  }
    74  
    75  func (m *mockIterator) ReadyChan() <-chan struct{} {
    76  	panic("implement me")
    77  }
    78  
    79  func (m *mockIterator) Close() {
    80  
    81  }
    82  
    83  // mockReader mock structure implementing
    84  // the blockledger.Reader interface
    85  type mockReader struct {
    86  	mock.Mock
    87  }
    88  
    89  func (m *mockReader) Iterator(startType *orderer.SeekPosition) (blockledger.Iterator, uint64) {
    90  	args := m.Called(startType)
    91  	return args.Get(0).(blockledger.Iterator), args.Get(1).(uint64)
    92  }
    93  
    94  func (m *mockReader) Height() uint64 {
    95  	args := m.Called()
    96  	return args.Get(0).(uint64)
    97  }
    98  
    99  // mockChainSupport
   100  type mockChainSupport struct {
   101  	mock.Mock
   102  }
   103  
   104  func (m *mockChainSupport) Sequence() uint64 {
   105  	return m.Called().Get(0).(uint64)
   106  }
   107  
   108  func (m *mockChainSupport) Ledger() ledger.PeerLedger {
   109  	return m.Called().Get(0).(ledger.PeerLedger)
   110  }
   111  
   112  func (m *mockChainSupport) PolicyManager() policies.Manager {
   113  	panic("implement me")
   114  }
   115  
   116  func (m *mockChainSupport) Reader() blockledger.Reader {
   117  	return m.Called().Get(0).(blockledger.Reader)
   118  }
   119  
   120  func (*mockChainSupport) Errored() <-chan struct{} {
   121  	return make(chan struct{})
   122  }
   123  
   124  // mockChainManager mock implementation of the ChainManager interface
   125  type mockChainManager struct {
   126  	mock.Mock
   127  }
   128  
   129  func (m *mockChainManager) GetChain(chainID string) deliver.Chain {
   130  	args := m.Called(chainID)
   131  	return args.Get(0).(deliver.Chain)
   132  }
   133  
   134  // mockDeliverServer mock implementation of the Deliver_DeliverServer
   135  type mockDeliverServer struct {
   136  	mock.Mock
   137  }
   138  
   139  func (m *mockDeliverServer) Context() context.Context {
   140  	return m.Called().Get(0).(context.Context)
   141  }
   142  
   143  func (m *mockDeliverServer) Recv() (*common.Envelope, error) {
   144  	args := m.Called()
   145  	if args.Get(0) == nil {
   146  		return nil, args.Error(1)
   147  	}
   148  	return args.Get(0).(*common.Envelope), args.Error(1)
   149  }
   150  
   151  func (m *mockDeliverServer) Send(response *peer.DeliverResponse) error {
   152  	args := m.Called(response)
   153  	return args.Error(0)
   154  }
   155  
   156  func (*mockDeliverServer) RecvMsg(m interface{}) error {
   157  	panic("implement me")
   158  }
   159  
   160  func (*mockDeliverServer) SendHeader(metadata.MD) error {
   161  	panic("implement me")
   162  }
   163  
   164  func (*mockDeliverServer) SendMsg(m interface{}) error {
   165  	panic("implement me")
   166  }
   167  
   168  func (*mockDeliverServer) SetHeader(metadata.MD) error {
   169  	panic("implement me")
   170  }
   171  
   172  func (*mockDeliverServer) SetTrailer(metadata.MD) {
   173  	panic("implement me")
   174  }
   175  
   176  type testConfig struct {
   177  	channelID     string
   178  	eventName     string
   179  	chaincodeName string
   180  	txID          string
   181  	payload       *common.Payload
   182  	*assert.Assertions
   183  }
   184  
   185  type testCase struct {
   186  	name    string
   187  	prepare func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer)
   188  }
   189  
   190  func TestFilteredBlockResponseSenderIsFiltered(t *testing.T) {
   191  	var fbrs interface{} = &filteredBlockResponseSender{}
   192  	filtered, ok := fbrs.(deliver.Filtered)
   193  	assert.True(t, ok, "should be filtered")
   194  	assert.True(t, filtered.IsFiltered(), "should return true from IsFiltered")
   195  }
   196  
   197  func TestEventsServer_DeliverFiltered(t *testing.T) {
   198  	tests := []testCase{
   199  		{
   200  			name: "Testing deliver of the filtered block events",
   201  			prepare: func(config testConfig) func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
   202  				return func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
   203  					wg.Add(2)
   204  					p := &peer2.Peer{}
   205  					chaincodeActionPayload, err := createChaincodeAction(config.chaincodeName, config.eventName, config.txID)
   206  					config.NoError(err)
   207  
   208  					chainManager := createDefaultSupportMamangerMock(config, chaincodeActionPayload, nil)
   209  					// setup mock deliver server
   210  					deliverServer := &mockDeliverServer{}
   211  					deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
   212  
   213  					deliverServer.On("Recv").Return(&common.Envelope{
   214  						Payload: protoutil.MarshalOrPanic(config.payload),
   215  					}, nil).Run(func(_ mock.Arguments) {
   216  						// once we are getting new message we need to mock
   217  						// Recv call to get io.EOF to stop the looping for
   218  						// next message and we can assert for the DeliverResponse
   219  						// value we are getting from the deliver server
   220  						deliverServer.Mock = mock.Mock{}
   221  						deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
   222  						deliverServer.On("Recv").Return(&common.Envelope{}, io.EOF)
   223  						deliverServer.On("Send", mock.Anything).Run(func(args mock.Arguments) {
   224  							defer wg.Done()
   225  							response := args.Get(0).(*peer.DeliverResponse)
   226  							switch response.Type.(type) {
   227  							case *peer.DeliverResponse_Status:
   228  								config.Equal(common.Status_SUCCESS, response.GetStatus())
   229  							case *peer.DeliverResponse_FilteredBlock:
   230  								block := response.GetFilteredBlock()
   231  								config.Equal(uint64(0), block.Number)
   232  								config.Equal(config.channelID, block.ChannelId)
   233  								config.Equal(1, len(block.FilteredTransactions))
   234  								tx := block.FilteredTransactions[0]
   235  								config.Equal(config.txID, tx.Txid)
   236  								config.Equal(peer.TxValidationCode_VALID, tx.TxValidationCode)
   237  								config.Equal(common.HeaderType_ENDORSER_TRANSACTION, tx.Type)
   238  								transactionActions := tx.GetTransactionActions()
   239  								config.NotNil(transactionActions)
   240  								chaincodeActions := transactionActions.ChaincodeActions
   241  								config.Equal(1, len(chaincodeActions))
   242  								config.Equal(config.eventName, chaincodeActions[0].ChaincodeEvent.EventName)
   243  								config.Equal(config.txID, chaincodeActions[0].ChaincodeEvent.TxId)
   244  								config.Equal(config.chaincodeName, chaincodeActions[0].ChaincodeEvent.ChaincodeId)
   245  							default:
   246  								config.FailNow("Unexpected response type")
   247  							}
   248  						}).Return(nil)
   249  					})
   250  
   251  					return chainManager, deliverServer
   252  				}
   253  			}(testConfig{
   254  				channelID:     "testChainID",
   255  				eventName:     "testEvent",
   256  				chaincodeName: "mycc",
   257  				txID:          "testID",
   258  				payload: &common.Payload{
   259  					Header: &common.Header{
   260  						ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{
   261  							ChannelId: "testChainID",
   262  							Timestamp: util.CreateUtcTimestamp(),
   263  						}),
   264  						SignatureHeader: protoutil.MarshalOrPanic(&common.SignatureHeader{}),
   265  					},
   266  					Data: protoutil.MarshalOrPanic(&orderer.SeekInfo{
   267  						Start:    &orderer.SeekPosition{Type: &orderer.SeekPosition_Specified{Specified: &orderer.SeekSpecified{Number: 0}}},
   268  						Stop:     &orderer.SeekPosition{Type: &orderer.SeekPosition_Newest{Newest: &orderer.SeekNewest{}}},
   269  						Behavior: orderer.SeekInfo_BLOCK_UNTIL_READY,
   270  					}),
   271  				},
   272  				Assertions: assert.New(t),
   273  			}),
   274  		},
   275  		{
   276  			name: "Testing deliver of the filtered block events with nil chaincode action payload",
   277  			prepare: func(config testConfig) func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
   278  				return func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
   279  					wg.Add(2)
   280  					p := &peer2.Peer{}
   281  					chainManager := createDefaultSupportMamangerMock(config, nil, nil)
   282  
   283  					// setup mock deliver server
   284  					deliverServer := &mockDeliverServer{}
   285  					deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
   286  
   287  					deliverServer.On("Recv").Return(&common.Envelope{
   288  						Payload: protoutil.MarshalOrPanic(config.payload),
   289  					}, nil).Run(func(_ mock.Arguments) {
   290  						// once we are getting new message we need to mock
   291  						// Recv call to get io.EOF to stop the looping for
   292  						// next message and we can assert for the DeliverResponse
   293  						// value we are getting from the deliver server
   294  						deliverServer.Mock = mock.Mock{}
   295  						deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
   296  						deliverServer.On("Recv").Return(&common.Envelope{}, io.EOF)
   297  						deliverServer.On("Send", mock.Anything).Run(func(args mock.Arguments) {
   298  							defer wg.Done()
   299  							response := args.Get(0).(*peer.DeliverResponse)
   300  							switch response.Type.(type) {
   301  							case *peer.DeliverResponse_Status:
   302  								config.Equal(common.Status_SUCCESS, response.GetStatus())
   303  							case *peer.DeliverResponse_FilteredBlock:
   304  								block := response.GetFilteredBlock()
   305  								config.Equal(uint64(0), block.Number)
   306  								config.Equal(config.channelID, block.ChannelId)
   307  								config.Equal(1, len(block.FilteredTransactions))
   308  								tx := block.FilteredTransactions[0]
   309  								config.Equal(config.txID, tx.Txid)
   310  								config.Equal(peer.TxValidationCode_VALID, tx.TxValidationCode)
   311  								config.Equal(common.HeaderType_ENDORSER_TRANSACTION, tx.Type)
   312  								transactionActions := tx.GetTransactionActions()
   313  								config.NotNil(transactionActions)
   314  								chaincodeActions := transactionActions.ChaincodeActions
   315  								// we expecting to get zero chaincode action,
   316  								// since provided nil payload
   317  								config.Equal(0, len(chaincodeActions))
   318  							default:
   319  								config.FailNow("Unexpected response type")
   320  							}
   321  						}).Return(nil)
   322  					})
   323  
   324  					return chainManager, deliverServer
   325  				}
   326  			}(testConfig{
   327  				channelID:     "testChainID",
   328  				eventName:     "testEvent",
   329  				chaincodeName: "mycc",
   330  				txID:          "testID",
   331  				payload: &common.Payload{
   332  					Header: &common.Header{
   333  						ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{
   334  							ChannelId: "testChainID",
   335  							Timestamp: util.CreateUtcTimestamp(),
   336  						}),
   337  						SignatureHeader: protoutil.MarshalOrPanic(&common.SignatureHeader{}),
   338  					},
   339  					Data: protoutil.MarshalOrPanic(&orderer.SeekInfo{
   340  						Start:    &orderer.SeekPosition{Type: &orderer.SeekPosition_Specified{Specified: &orderer.SeekSpecified{Number: 0}}},
   341  						Stop:     &orderer.SeekPosition{Type: &orderer.SeekPosition_Newest{Newest: &orderer.SeekNewest{}}},
   342  						Behavior: orderer.SeekInfo_BLOCK_UNTIL_READY,
   343  					}),
   344  				},
   345  				Assertions: assert.New(t),
   346  			}),
   347  		},
   348  		{
   349  			name: "Testing deliver of the filtered block events with nil payload header",
   350  			prepare: func(config testConfig) func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
   351  				return func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
   352  					wg.Add(1)
   353  					p := &peer2.Peer{}
   354  					chainManager := createDefaultSupportMamangerMock(config, nil, nil)
   355  
   356  					// setup mock deliver server
   357  					deliverServer := &mockDeliverServer{}
   358  					deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
   359  
   360  					deliverServer.On("Recv").Return(&common.Envelope{
   361  						Payload: protoutil.MarshalOrPanic(config.payload),
   362  					}, nil).Run(func(_ mock.Arguments) {
   363  						// once we are getting new message we need to mock
   364  						// Recv call to get io.EOF to stop the looping for
   365  						// next message and we can assert for the DeliverResponse
   366  						// value we are getting from the deliver server
   367  						deliverServer.Mock = mock.Mock{}
   368  						deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
   369  						deliverServer.On("Recv").Return(&common.Envelope{}, io.EOF)
   370  						deliverServer.On("Send", mock.Anything).Run(func(args mock.Arguments) {
   371  							defer wg.Done()
   372  							response := args.Get(0).(*peer.DeliverResponse)
   373  							switch response.Type.(type) {
   374  							case *peer.DeliverResponse_Status:
   375  								config.Equal(common.Status_BAD_REQUEST, response.GetStatus())
   376  							case *peer.DeliverResponse_FilteredBlock:
   377  								config.FailNow("Unexpected response type")
   378  							default:
   379  								config.FailNow("Unexpected response type")
   380  							}
   381  						}).Return(nil)
   382  					})
   383  
   384  					return chainManager, deliverServer
   385  				}
   386  			}(testConfig{
   387  				channelID:     "testChainID",
   388  				eventName:     "testEvent",
   389  				chaincodeName: "mycc",
   390  				txID:          "testID",
   391  				payload: &common.Payload{
   392  					Header: nil,
   393  					Data: protoutil.MarshalOrPanic(&orderer.SeekInfo{
   394  						Start:    &orderer.SeekPosition{Type: &orderer.SeekPosition_Specified{Specified: &orderer.SeekSpecified{Number: 0}}},
   395  						Stop:     &orderer.SeekPosition{Type: &orderer.SeekPosition_Newest{Newest: &orderer.SeekNewest{}}},
   396  						Behavior: orderer.SeekInfo_BLOCK_UNTIL_READY,
   397  					}),
   398  				},
   399  				Assertions: assert.New(t),
   400  			}),
   401  		},
   402  	}
   403  	for _, test := range tests {
   404  		t.Run(test.name, func(t *testing.T) {
   405  			wg := &sync.WaitGroup{}
   406  			chainManager, deliverServer := test.prepare(wg)
   407  
   408  			metrics := deliver.NewMetrics(&disabled.Provider{})
   409  			server := &DeliverServer{
   410  				DeliverHandler:        deliver.NewHandler(chainManager, time.Second, false, metrics, false),
   411  				PolicyCheckerProvider: defaultPolicyCheckerProvider,
   412  			}
   413  
   414  			err := server.DeliverFiltered(deliverServer)
   415  			wg.Wait()
   416  			// no error expected
   417  			assert.NoError(t, err)
   418  		})
   419  	}
   420  }
   421  
   422  func TestEventsServer_DeliverWithPrivateData(t *testing.T) {
   423  	fakeDeserializerMgr := &fake.IdentityDeserializerManager{}
   424  	fakeDeserializerMgr.DeserializerReturns(nil, nil)
   425  	fakeCollPolicyChecker := &fake.CollectionPolicyChecker{}
   426  	fakeCollPolicyChecker.CheckCollectionPolicyReturns(true, nil)
   427  	tests := []testCase{
   428  		{
   429  			name: "Testing deliver block with private data events",
   430  			prepare: func(config testConfig) func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
   431  				return func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
   432  					wg.Add(2)
   433  					p := &peer2.Peer{}
   434  					chaincodeActionPayload, err := createChaincodeAction(config.chaincodeName, config.eventName, config.txID)
   435  					config.NoError(err)
   436  
   437  					pvtData := []*ledger.TxPvtData{
   438  						produceSamplePvtdataOrPanic(0, []string{"ns-0:coll-0", "ns-2:coll-20", "ns-2:coll-21"}),
   439  					}
   440  					chainManager := createDefaultSupportMamangerMock(config, chaincodeActionPayload, pvtData)
   441  
   442  					deliverServer := &mockDeliverServer{}
   443  					deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
   444  					deliverServer.On("Recv").Return(&common.Envelope{
   445  						Payload: protoutil.MarshalOrPanic(config.payload),
   446  					}, nil).Run(func(_ mock.Arguments) {
   447  						// mock Recv calls to get io.EOF to stop the looping for next message
   448  						deliverServer.Mock = mock.Mock{}
   449  						deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
   450  						deliverServer.On("Recv").Return(&common.Envelope{}, io.EOF)
   451  						deliverServer.On("Send", mock.Anything).Run(func(args mock.Arguments) {
   452  							defer wg.Done()
   453  							response := args.Get(0).(*peer.DeliverResponse)
   454  							switch response.Type.(type) {
   455  							case *peer.DeliverResponse_Status:
   456  								config.Equal(common.Status_SUCCESS, response.GetStatus())
   457  							case *peer.DeliverResponse_BlockAndPrivateData:
   458  								blockAndPvtData := response.GetBlockAndPrivateData()
   459  								block := blockAndPvtData.Block
   460  								config.Equal(uint64(0), block.Header.Number)
   461  								config.Equal(1, len(blockAndPvtData.PrivateDataMap))
   462  								config.NotNil(blockAndPvtData.PrivateDataMap[uint64(0)])
   463  								txPvtRwset := blockAndPvtData.PrivateDataMap[uint64(0)]
   464  								// expect to have 2 NsPvtRwset (i.e., 2 namespaces)
   465  								config.Equal(2, len(txPvtRwset.NsPvtRwset))
   466  								// check namespace because the index may be out of order
   467  								for _, nsPvtRwset := range txPvtRwset.NsPvtRwset {
   468  									switch nsPvtRwset.Namespace {
   469  									case "ns-0":
   470  										config.Equal(1, len(nsPvtRwset.CollectionPvtRwset))
   471  										config.Equal("coll-0", nsPvtRwset.CollectionPvtRwset[0].CollectionName)
   472  									case "ns-2":
   473  										config.Equal(2, len(nsPvtRwset.CollectionPvtRwset))
   474  										config.Equal("coll-20", nsPvtRwset.CollectionPvtRwset[0].CollectionName)
   475  										config.Equal("coll-21", nsPvtRwset.CollectionPvtRwset[1].CollectionName)
   476  									default:
   477  										config.FailNow("Wrong namespace " + nsPvtRwset.Namespace)
   478  									}
   479  								}
   480  							default:
   481  								config.FailNow("Unexpected response type")
   482  							}
   483  						}).Return(nil)
   484  					})
   485  
   486  					return chainManager, deliverServer
   487  				}
   488  			}(testConfig{
   489  				channelID:     "testChainID",
   490  				eventName:     "testEvent",
   491  				chaincodeName: "mycc",
   492  				txID:          "testID",
   493  				payload: &common.Payload{
   494  					Header: &common.Header{
   495  						ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{
   496  							ChannelId: "testChainID",
   497  							Timestamp: util.CreateUtcTimestamp(),
   498  						}),
   499  						SignatureHeader: protoutil.MarshalOrPanic(&common.SignatureHeader{}),
   500  					},
   501  					Data: protoutil.MarshalOrPanic(&orderer.SeekInfo{
   502  						Start:    &orderer.SeekPosition{Type: &orderer.SeekPosition_Specified{Specified: &orderer.SeekSpecified{Number: 0}}},
   503  						Stop:     &orderer.SeekPosition{Type: &orderer.SeekPosition_Newest{Newest: &orderer.SeekNewest{}}},
   504  						Behavior: orderer.SeekInfo_BLOCK_UNTIL_READY,
   505  					}),
   506  				},
   507  				Assertions: assert.New(t),
   508  			}),
   509  		},
   510  		{
   511  			name: "Testing deliver of block with private data events with nil header",
   512  			prepare: func(config testConfig) func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
   513  				return func(wg *sync.WaitGroup) (deliver.ChainManager, peer.Deliver_DeliverServer) {
   514  					wg.Add(1)
   515  					p := &peer2.Peer{}
   516  					chainManager := createDefaultSupportMamangerMock(config, nil, nil)
   517  
   518  					deliverServer := &mockDeliverServer{}
   519  					deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
   520  					deliverServer.On("Recv").Return(&common.Envelope{
   521  						Payload: protoutil.MarshalOrPanic(config.payload),
   522  					}, nil).Run(func(_ mock.Arguments) {
   523  						// mock Recv calls to get io.EOF to stop the looping for next message
   524  						deliverServer.Mock = mock.Mock{}
   525  						deliverServer.On("Context").Return(peer2.NewContext(context.TODO(), p))
   526  						deliverServer.On("Recv").Return(&common.Envelope{}, io.EOF)
   527  						deliverServer.On("Send", mock.Anything).Run(func(args mock.Arguments) {
   528  							defer wg.Done()
   529  							response := args.Get(0).(*peer.DeliverResponse)
   530  							switch response.Type.(type) {
   531  							case *peer.DeliverResponse_Status:
   532  								config.Equal(common.Status_BAD_REQUEST, response.GetStatus())
   533  							case *peer.DeliverResponse_BlockAndPrivateData:
   534  								config.FailNow("Unexpected response type")
   535  							default:
   536  								config.FailNow("Unexpected response type")
   537  							}
   538  						}).Return(nil)
   539  					})
   540  
   541  					return chainManager, deliverServer
   542  				}
   543  			}(testConfig{
   544  				channelID:     "testChainID",
   545  				eventName:     "testEvent",
   546  				chaincodeName: "mycc",
   547  				txID:          "testID",
   548  				payload: &common.Payload{
   549  					Header: nil,
   550  					Data: protoutil.MarshalOrPanic(&orderer.SeekInfo{
   551  						Start:    &orderer.SeekPosition{Type: &orderer.SeekPosition_Specified{Specified: &orderer.SeekSpecified{Number: 0}}},
   552  						Stop:     &orderer.SeekPosition{Type: &orderer.SeekPosition_Newest{Newest: &orderer.SeekNewest{}}},
   553  						Behavior: orderer.SeekInfo_BLOCK_UNTIL_READY,
   554  					}),
   555  				},
   556  				Assertions: assert.New(t),
   557  			}),
   558  		},
   559  	}
   560  	for _, test := range tests {
   561  		t.Run(test.name, func(t *testing.T) {
   562  			wg := &sync.WaitGroup{}
   563  			chainManager, deliverServer := test.prepare(wg)
   564  
   565  			metrics := deliver.NewMetrics(&disabled.Provider{})
   566  			handler := deliver.NewHandler(chainManager, time.Second, false, metrics, false)
   567  			server := &DeliverServer{
   568  				DeliverHandler:          handler,
   569  				PolicyCheckerProvider:   defaultPolicyCheckerProvider,
   570  				CollectionPolicyChecker: fakeCollPolicyChecker,
   571  				IdentityDeserializerMgr: fakeDeserializerMgr,
   572  			}
   573  
   574  			err := server.DeliverWithPrivateData(deliverServer)
   575  			wg.Wait()
   576  			// no error expected
   577  			assert.NoError(t, err)
   578  		})
   579  	}
   580  }
   581  
   582  func createDefaultSupportMamangerMock(config testConfig, chaincodeActionPayload *peer.ChaincodeActionPayload, pvtData []*ledger.TxPvtData) *mockChainManager {
   583  	chainManager := &mockChainManager{}
   584  	iter := &mockIterator{}
   585  	reader := &mockReader{}
   586  	chain := &mockChainSupport{}
   587  	ldgr := &fake.PeerLedger{}
   588  
   589  	payload, err := createEndorsement(config.channelID, config.txID, chaincodeActionPayload)
   590  	config.NoError(err)
   591  
   592  	payloadBytes, err := proto.Marshal(payload)
   593  	config.NoError(err)
   594  
   595  	block, err := createTestBlock([]*common.Envelope{{
   596  		Payload:   payloadBytes,
   597  		Signature: []byte{}}})
   598  	config.NoError(err)
   599  
   600  	iter.On("Next").Return(block, common.Status_SUCCESS)
   601  	reader.On("Iterator", mock.Anything).Return(iter, uint64(1))
   602  	reader.On("Height").Return(uint64(1))
   603  	chain.On("Sequence").Return(uint64(0))
   604  	chain.On("Reader").Return(reader)
   605  	chain.On("Ledger").Return(ldgr)
   606  	chainManager.On("GetChain", config.channelID).Return(chain, true)
   607  
   608  	ldgr.GetPvtDataByNumReturns(pvtData, nil)
   609  
   610  	return chainManager
   611  }
   612  
   613  func createEndorsement(channelID string, txID string, chaincodeActionPayload *peer.ChaincodeActionPayload) (*common.Payload, error) {
   614  	var chActionBytes []byte
   615  	var err error
   616  	if chaincodeActionPayload != nil {
   617  		chActionBytes, err = proto.Marshal(chaincodeActionPayload)
   618  		if err != nil {
   619  			return nil, err
   620  		}
   621  	}
   622  
   623  	// the transaction
   624  	txBytes, err := proto.Marshal(&peer.Transaction{
   625  		Actions: []*peer.TransactionAction{
   626  			{
   627  				Payload: chActionBytes,
   628  			},
   629  		},
   630  	})
   631  	if err != nil {
   632  		return nil, err
   633  	}
   634  	// channel header
   635  	chdrBytes, err := proto.Marshal(&common.ChannelHeader{
   636  		ChannelId: channelID,
   637  		TxId:      txID,
   638  		Type:      int32(common.HeaderType_ENDORSER_TRANSACTION),
   639  	})
   640  	if err != nil {
   641  		return nil, err
   642  	}
   643  
   644  	// the payload
   645  	payload := &common.Payload{
   646  		Header: &common.Header{
   647  			ChannelHeader: chdrBytes,
   648  		},
   649  		Data: txBytes,
   650  	}
   651  	return payload, nil
   652  }
   653  
   654  func createChaincodeAction(chaincodeName string, eventName string, txID string) (*peer.ChaincodeActionPayload, error) {
   655  	// chaincode events
   656  	eventsBytes, err := proto.Marshal(&peer.ChaincodeEvent{
   657  		ChaincodeId: chaincodeName,
   658  		EventName:   eventName,
   659  		TxId:        txID,
   660  	})
   661  	if err != nil {
   662  		return nil, err
   663  	}
   664  
   665  	// chaincode action
   666  	actionBytes, err := proto.Marshal(&peer.ChaincodeAction{
   667  		ChaincodeId: &peer.ChaincodeID{
   668  			Name: chaincodeName,
   669  		},
   670  		Events: eventsBytes,
   671  	})
   672  	if err != nil {
   673  		return nil, err
   674  	}
   675  
   676  	// proposal response
   677  	proposalResBytes, err := proto.Marshal(&peer.ProposalResponsePayload{
   678  		Extension: actionBytes,
   679  	})
   680  	if err != nil {
   681  		return nil, err
   682  	}
   683  
   684  	// chaincode action
   685  	chaincodeActionPayload := &peer.ChaincodeActionPayload{
   686  		Action: &peer.ChaincodeEndorsedAction{
   687  			ProposalResponsePayload: proposalResBytes,
   688  			Endorsements:            []*peer.Endorsement{},
   689  		},
   690  	}
   691  	return chaincodeActionPayload, err
   692  }
   693  
   694  func createTestBlock(data []*common.Envelope) (*common.Block, error) {
   695  	// block
   696  	block := &common.Block{
   697  		Header: &common.BlockHeader{
   698  			Number:   0,
   699  			DataHash: []byte{},
   700  		},
   701  		Data:     &common.BlockData{},
   702  		Metadata: &common.BlockMetadata{},
   703  	}
   704  	for _, d := range data {
   705  		envBytes, err := proto.Marshal(d)
   706  		if err != nil {
   707  			return nil, err
   708  		}
   709  
   710  		block.Data.Data = append(block.Data.Data, envBytes)
   711  	}
   712  	// making up metadata
   713  	block.Metadata.Metadata = make([][]byte, 4)
   714  	block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = make([]byte, len(data))
   715  	return block, nil
   716  }
   717  
   718  func produceSamplePvtdataOrPanic(txNum uint64, nsColls []string) *ledger.TxPvtData {
   719  	builder := rwsetutil.NewRWSetBuilder()
   720  	for _, nsColl := range nsColls {
   721  		nsCollSplit := strings.Split(nsColl, ":")
   722  		ns := nsCollSplit[0]
   723  		coll := nsCollSplit[1]
   724  		builder.AddToPvtAndHashedWriteSet(ns, coll, fmt.Sprintf("key-%s-%s", ns, coll), []byte(fmt.Sprintf("value-%s-%s", ns, coll)))
   725  	}
   726  	simRes, err := builder.GetTxSimulationResults()
   727  	if err != nil {
   728  		panic(err)
   729  	}
   730  	return &ledger.TxPvtData{SeqInBlock: txNum, WriteSet: simRes.PvtSimulationResults}
   731  }