github.com/aergoio/aergo@v1.3.1/p2p/subproto/tx_test.go (about)

     1  /*
     2   * @file
     3   * @copyright defined in aergo/LICENSE.txt
     4   */
     5  package subproto
     6  
     7  import (
     8  	"fmt"
     9  	"github.com/aergoio/aergo-lib/log"
    10  	"github.com/aergoio/aergo/message"
    11  	"github.com/aergoio/aergo/message/messagemock"
    12  	"github.com/aergoio/aergo/p2p/p2pcommon"
    13  	"github.com/aergoio/aergo/p2p/p2pmock"
    14  	"github.com/aergoio/aergo/types"
    15  	"github.com/golang/mock/gomock"
    16  	"github.com/stretchr/testify/assert"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/aergoio/aergo/internal/enc"
    21  	"github.com/aergoio/aergo/p2p/p2putil"
    22  
    23  	"github.com/gofrs/uuid"
    24  )
    25  
    26  func TestTxRequestHandler_handle(t *testing.T) {
    27  	ctrl := gomock.NewController(t)
    28  	defer ctrl.Finish()
    29  
    30  	//var dummyPeerID, _ = types.IDB58Decode("16Uiu2HAmN5YU8V2LnTy9neuuJCLNsxLnd5xVSRZqkjvZUHS3mLoD")
    31  	var sampleMsgID = p2pcommon.NewMsgID()
    32  	var sampleHeader = p2pmock.NewMockMessage(ctrl)
    33  	sampleHeader.EXPECT().ID().Return(sampleMsgID).AnyTimes()
    34  	sampleHeader.EXPECT().Subprotocol().Return(p2pcommon.GetTXsResponse).AnyTimes()
    35  
    36  	var sampleTxsB58 = []string{
    37  		"4H4zAkAyRV253K5SNBJtBxqUgHEbZcXbWFFc6cmQHY45",
    38  		"6xfk39kuyDST7NwCu8tx3wqwFZ5dwKPDjxUS14tU7NZb8",
    39  		"E8dbBGe9Hnuhk35cJoekPjL3VoL4xAxtnRuP47UoxzHd",
    40  		"HB7Hg5GUbHuxwe8Lp5PcYUoAaQ7EZjRNG6RuvS6DnDRf",
    41  		"BxKmDg9VbWHxrWnStEeTzJ2Ze7RF7YK4rpyjcsWSsnxs",
    42  		"DwmGqFU4WgADpYN36FXKsYxMjeppvh9Najg4KxJ8gtX3",
    43  	}
    44  	var sampleTxs = make([][]byte, len(sampleTxsB58))
    45  	var sampleTxHashes = make([]types.TxID, len(sampleTxsB58))
    46  	for i, hashb58 := range sampleTxsB58 {
    47  		hash, _ := enc.ToBytes(hashb58)
    48  		sampleTxs[i] = hash
    49  		copy(sampleTxHashes[i][:], hash)
    50  	}
    51  
    52  	//dummyPeerID2, _ = types.IDB58Decode("16Uiu2HAmFqptXPfcdaCdwipB2fhHATgKGVFVPehDAPZsDKSU7jRm")
    53  	//dummyPeerID3, _ = types.IDB58Decode("16Uiu2HAmU8Wc925gZ5QokM4sGDKjysdPwRCQFoYobvoVnyutccCD")
    54  
    55  	logger := log.NewLogger("test.subproto")
    56  	//dummyMeta := p2pcommon.PeerMeta{ID: dummyPeerID, IPAddress: "192.168.1.2", Port: 4321}
    57  	mockMo := p2pmock.NewMockMsgOrder(ctrl)
    58  	mockMo.EXPECT().GetProtocolID().Return(p2pcommon.GetTXsResponse).AnyTimes()
    59  	mockMo.EXPECT().GetMsgID().Return(sampleMsgID).AnyTimes()
    60  	//mockSigner := p2pmock.NewmockMsgSigner(ctrl)
    61  	//mockSigner.EXPECT().signMsg",gomock.Any()).Return(nil)
    62  	tests := []struct {
    63  		name   string
    64  		setup  func(tt *testing.T, pm *p2pmock.MockPeerManager, actor *p2pmock.MockActorService, msgHelper *messagemock.Helper, mockMF *p2pmock.MockMoFactory, mockRW *p2pmock.MockMsgReadWriter) (p2pcommon.Message, *types.GetTransactionsRequest)
    65  		verify func(tt *testing.T, pm *p2pmock.MockPeerManager, actor *p2pmock.MockActorService, msgHelper *messagemock.Helper, mockMF *p2pmock.MockMoFactory, mockRW *p2pmock.MockMsgReadWriter)
    66  	}{
    67  		// 1. success case (single tx)
    68  		{"TSucc1", func(tt *testing.T, pm *p2pmock.MockPeerManager, actor *p2pmock.MockActorService, msgHelper *messagemock.Helper, mockMF *p2pmock.MockMoFactory, mockRW *p2pmock.MockMsgReadWriter) (p2pcommon.Message, *types.GetTransactionsRequest) {
    69  			// receive request for one tx , query to mempool get send response to remote peer
    70  			dummyTxs := make([]*types.Tx, 1)
    71  			dummyTxs[0] = &types.Tx{Hash: sampleTxs[0]}
    72  			actor.EXPECT().CallRequestDefaultTimeout(message.MemPoolSvc, gomock.AssignableToTypeOf(&message.MemPoolExistEx{})).Return(&message.MemPoolExistExRsp{Txs: dummyTxs}, nil).Times(1)
    73  			msgHelper.EXPECT().ExtractTxsFromResponseAndError(gomock.AssignableToTypeOf(&message.MemPoolExistExRsp{}), nil).Return(dummyTxs, nil).Times(1)
    74  			hashes := sampleTxs[:1]
    75  			mockMF.EXPECT().NewMsgResponseOrder(sampleMsgID, p2pcommon.GetTXsResponse, gomock.AssignableToTypeOf(&types.GetTransactionsResponse{})).Do(func(reqID p2pcommon.MsgID, protocolID p2pcommon.SubProtocol, message p2pcommon.MessageBody) {
    76  				resp := message.(*types.GetTransactionsResponse)
    77  				assert.Equal(tt, types.ResultStatus_OK, resp.Status)
    78  				assert.Equal(tt, 1, len(resp.Hashes))
    79  				assert.Equal(tt, sampleTxs[0], resp.Hashes[0])
    80  			}).Return(mockMo).Times(1)
    81  			return sampleHeader, &types.GetTransactionsRequest{Hashes: hashes}
    82  		}, func(tt *testing.T, pm *p2pmock.MockPeerManager, actor *p2pmock.MockActorService, msgHelper *messagemock.Helper, mockMF *p2pmock.MockMoFactory, mockRW *p2pmock.MockMsgReadWriter) {
    83  			// verification is defined in setup
    84  		}},
    85  		// 1-1 success case2 (multiple tx)
    86  		{"TSucc2", func(tt *testing.T, pm *p2pmock.MockPeerManager, actor *p2pmock.MockActorService, msgHelper *messagemock.Helper, mockMF *p2pmock.MockMoFactory, mockRW *p2pmock.MockMsgReadWriter) (p2pcommon.Message, *types.GetTransactionsRequest) {
    87  			dummyTxs := make([]*types.Tx, len(sampleTxs))
    88  			for i, txHash := range sampleTxs {
    89  				dummyTxs[i] = &types.Tx{Hash: txHash}
    90  			}
    91  			actor.EXPECT().CallRequestDefaultTimeout(message.MemPoolSvc, gomock.AssignableToTypeOf(&message.MemPoolExistEx{})).Return(&message.MemPoolExistExRsp{Txs: dummyTxs}, nil).Times(1)
    92  			msgHelper.EXPECT().ExtractTxsFromResponseAndError(gomock.AssignableToTypeOf(&message.MemPoolExistExRsp{}), nil).Return(dummyTxs, nil).Times(1)
    93  			hashes := sampleTxs
    94  			mockMF.EXPECT().NewMsgResponseOrder(sampleMsgID, p2pcommon.GetTXsResponse, gomock.AssignableToTypeOf(&types.GetTransactionsResponse{})).Do(func(reqID p2pcommon.MsgID, protocolID p2pcommon.SubProtocol, message p2pcommon.MessageBody) {
    95  				resp := message.(*types.GetTransactionsResponse)
    96  				assert.Equal(tt, types.ResultStatus_OK, resp.Status)
    97  				assert.Equal(tt, len(sampleTxs), len(resp.Hashes))
    98  			}).Return(mockMo).Times(1)
    99  			return sampleHeader, &types.GetTransactionsRequest{Hashes: hashes}
   100  		}, func(tt *testing.T, pm *p2pmock.MockPeerManager, actor *p2pmock.MockActorService, msgHelper *messagemock.Helper, mockMF *p2pmock.MockMoFactory, mockRW *p2pmock.MockMsgReadWriter) {
   101  		}},
   102  		// 2. hash not found (partial)
   103  		{"TPartialExist", func(tt *testing.T, pm *p2pmock.MockPeerManager, actor *p2pmock.MockActorService, msgHelper *messagemock.Helper, mockMF *p2pmock.MockMoFactory, mockRW *p2pmock.MockMsgReadWriter) (p2pcommon.Message, *types.GetTransactionsRequest) {
   104  			dummyTxs := make([]*types.Tx, 0, len(sampleTxs))
   105  			hashes := make([][]byte, 0, len(sampleTxs))
   106  			for i, txHash := range sampleTxs {
   107  				if i%2 == 0 {
   108  					dummyTxs = append(dummyTxs, &types.Tx{Hash: txHash})
   109  					hashes = append(hashes, txHash)
   110  				}
   111  			}
   112  			actor.EXPECT().CallRequestDefaultTimeout(message.MemPoolSvc, gomock.AssignableToTypeOf(&message.MemPoolExistEx{})).Return(&message.MemPoolExistExRsp{Txs: dummyTxs}, nil).Times(1)
   113  			msgHelper.EXPECT().ExtractTxsFromResponseAndError(gomock.AssignableToTypeOf(&message.MemPoolExistExRsp{}), nil).Return(dummyTxs, nil).Times(1)
   114  			mockMF.EXPECT().NewMsgResponseOrder(sampleMsgID, p2pcommon.GetTXsResponse, gomock.AssignableToTypeOf(&types.GetTransactionsResponse{})).Do(func(reqID p2pcommon.MsgID, protocolID p2pcommon.SubProtocol, message p2pcommon.MessageBody) {
   115  				resp := message.(*types.GetTransactionsResponse)
   116  				assert.Equal(tt, types.ResultStatus_OK, resp.Status)
   117  				assert.Equal(tt, len(dummyTxs), len(resp.Hashes))
   118  			}).Return(mockMo).Times(1)
   119  			return sampleHeader, &types.GetTransactionsRequest{Hashes: hashes}
   120  		}, func(tt *testing.T, pm *p2pmock.MockPeerManager, actor *p2pmock.MockActorService, msgHelper *messagemock.Helper, mockMF *p2pmock.MockMoFactory, mockRW *p2pmock.MockMsgReadWriter) {
   121  		}},
   122  		// 3. hash not found (all)
   123  		{"TNoExist", func(tt *testing.T, pm *p2pmock.MockPeerManager, actor *p2pmock.MockActorService, msgHelper *messagemock.Helper, mockMF *p2pmock.MockMoFactory, mockRW *p2pmock.MockMsgReadWriter) (p2pcommon.Message, *types.GetTransactionsRequest) {
   124  			//dummyTx := &types.Tx{Hash:nil}
   125  			// emulate second tx is not exists.
   126  			actor.EXPECT().CallRequestDefaultTimeout(message.MemPoolSvc, gomock.AssignableToTypeOf(&message.MemPoolExistEx{})).Return(&message.MemPoolExistExRsp{}, nil).Times(1)
   127  			//msgHelper.EXPECT().ExtractTxsFromResponseAndError", mock.MatchedBy(func(m *message.MemPoolExistExRsp) bool {
   128  			//	if len(m.Txs) == 0 {
   129  			//		return false
   130  			//	}
   131  			//	return true
   132  			//}), nil).Return(dummyTx, nil)
   133  			msgHelper.EXPECT().ExtractTxsFromResponseAndError(&MempoolRspTxCountMatcher{0}, nil).Return(nil, nil).Times(1)
   134  			hashes := sampleTxs
   135  			mockMF.EXPECT().NewMsgResponseOrder(sampleMsgID, p2pcommon.GetTXsResponse, gomock.AssignableToTypeOf(&types.GetTransactionsResponse{})).Do(func(reqID p2pcommon.MsgID, protocolID p2pcommon.SubProtocol, message p2pcommon.MessageBody) {
   136  				resp := message.(*types.GetTransactionsResponse)
   137  				assert.Equal(tt, types.ResultStatus_NOT_FOUND, resp.Status)
   138  				assert.Equal(tt, 0, len(resp.Hashes))
   139  			}).Return(mockMo).Times(1)
   140  			return sampleHeader, &types.GetTransactionsRequest{Hashes: hashes}
   141  		}, func(tt *testing.T, pm *p2pmock.MockPeerManager, actor *p2pmock.MockActorService, msgHelper *messagemock.Helper, mockMF *p2pmock.MockMoFactory, mockRW *p2pmock.MockMsgReadWriter) {
   142  		}},
   143  		// 4. actor failure
   144  		{"TActorError", func(tt *testing.T, pm *p2pmock.MockPeerManager, actor *p2pmock.MockActorService, msgHelper *messagemock.Helper, mockMF *p2pmock.MockMoFactory, mockRW *p2pmock.MockMsgReadWriter) (p2pcommon.Message, *types.GetTransactionsRequest) {
   145  			//dummyTx := &types.Tx{Hash:nil}
   146  			actor.EXPECT().CallRequestDefaultTimeout(message.MemPoolSvc, gomock.AssignableToTypeOf(&message.MemPoolExistEx{})).Return(nil, fmt.Errorf("timeout")).Times(1)
   147  			//msgHelper.EXPECT().ExtractTxsFromResponseAndError", nil, gomock.AssignableToTypeOf("error")).Return(nil, fmt.Errorf("error"))
   148  			msgHelper.EXPECT().ExtractTxsFromResponseAndError(nil, &WantErrMatcher{true}).Return(nil, fmt.Errorf("error")).Times(0)
   149  			hashes := sampleTxs
   150  			mockMF.EXPECT().NewMsgResponseOrder(sampleMsgID, p2pcommon.GetTXsResponse, gomock.AssignableToTypeOf(&types.GetTransactionsResponse{})).Do(func(reqID p2pcommon.MsgID, protocolID p2pcommon.SubProtocol, message p2pcommon.MessageBody) {
   151  				resp := message.(*types.GetTransactionsResponse)
   152  				// TODO check if the changed behavior is fair or not.
   153  				assert.Equal(tt, types.ResultStatus_NOT_FOUND, resp.Status)
   154  			}).Return(mockMo).Times(1)
   155  			return sampleHeader, &types.GetTransactionsRequest{Hashes: hashes}
   156  		}, func(tt *testing.T, pm *p2pmock.MockPeerManager, actor *p2pmock.MockActorService, msgHelper *messagemock.Helper, mockMF *p2pmock.MockMoFactory, mockRW *p2pmock.MockMsgReadWriter) {
   157  			// break at first eval
   158  			// TODO need check that error response was sent
   159  		}},
   160  
   161  		// 5. invalid parameter (no input hash, or etc.)
   162  	}
   163  	for _, test := range tests {
   164  		t.Run(test.name, func(t *testing.T) {
   165  			mockPM := p2pmock.NewMockPeerManager(ctrl)
   166  			mockActor := p2pmock.NewMockActorService(ctrl)
   167  			mockRW := p2pmock.NewMockMsgReadWriter(ctrl)
   168  			mockMF := p2pmock.NewMockMoFactory(ctrl)
   169  			mockMsgHelper := messagemock.NewHelper(ctrl)
   170  			mockPeer := p2pmock.NewMockRemotePeer(ctrl)
   171  			mockPeer.EXPECT().Name().Return("mockPeer").AnyTimes()
   172  			mockPeer.EXPECT().MF().Return(mockMF).AnyTimes()
   173  			mockPeer.EXPECT().SendMessage(mockMo)
   174  
   175  			header, body := test.setup(t, mockPM, mockActor, mockMsgHelper, mockMF, mockRW)
   176  			h := NewTxReqHandler(mockPM, mockPeer, logger, mockActor)
   177  			h.msgHelper = mockMsgHelper
   178  
   179  			//h.Handle(header, body)
   180  			h.handleTxReq(header, body.Hashes)
   181  			// wait for handle finished
   182  			<- h.w
   183  
   184  			test.verify(t, mockPM, mockActor, mockMsgHelper, mockMF, mockRW)
   185  		})
   186  	}
   187  }
   188  
   189  func TestTxRequestHandler_handleBySize(t *testing.T) {
   190  	ctrl := gomock.NewController(t)
   191  	defer ctrl.Finish()
   192  
   193  	logger := log.NewLogger("test.subproto")
   194  	var dummyPeerID, _ = types.IDB58Decode("16Uiu2HAmN5YU8V2LnTy9neuuJCLNsxLnd5xVSRZqkjvZUHS3mLoD")
   195  	var dummyTxHash, _ = enc.ToBytes("4H4zAkAyRV253K5SNBJtBxqUgHEbZcXbWFFc6cmQHY45")
   196  
   197  	bigTxBytes := make([]byte, 2*1024*1024)
   198  	//dummyMO := p2pmock.NewMockMsgOrder(ctrl)
   199  	tests := []struct {
   200  		name              string
   201  		hashCnt           int
   202  		validCallCount    int
   203  		expectedSendCount int
   204  	}{
   205  		{"TSingle", 1, 1, 1},
   206  		{"TNotFounds", 100, 0, 1},
   207  		{"TFound10", 10, 10, 4},
   208  		{"TFoundAll", 20, 100, 7},
   209  	}
   210  	for _, test := range tests {
   211  		t.Run(test.name, func(t *testing.T) {
   212  			mockPM := p2pmock.NewMockPeerManager(ctrl)
   213  			mockMF := &testDoubleMOFactory{}
   214  			mockPeer := p2pmock.NewMockRemotePeer(ctrl)
   215  			mockActor := p2pmock.NewMockActorService(ctrl)
   216  			mockPeer.EXPECT().MF().Return(mockMF).AnyTimes()
   217  			mockPeer.EXPECT().ID().Return(dummyPeerID).AnyTimes()
   218  			mockPeer.EXPECT().Name().Return("16..aadecf@1").AnyTimes()
   219  			mockPeer.EXPECT().SendMessage(gomock.Any()).Times(test.expectedSendCount)
   220  
   221  			validBigMempoolRsp := &message.MemPoolExistExRsp{}
   222  			txs := make([]*types.Tx, 0, test.hashCnt)
   223  			for i := 0; i < test.hashCnt; i++ {
   224  				if i >= test.validCallCount {
   225  					break
   226  				}
   227  				txs = append(txs, &types.Tx{Hash: dummyTxHash, Body: &types.TxBody{Payload: bigTxBytes}})
   228  			}
   229  			validBigMempoolRsp.Txs = txs
   230  
   231  			mockActor.EXPECT().CallRequestDefaultTimeout(message.MemPoolSvc, gomock.AssignableToTypeOf(&message.MemPoolExistEx{})).Return(validBigMempoolRsp, nil)
   232  
   233  			h := NewTxReqHandler(mockPM, mockPeer, logger, mockActor)
   234  			dummyMsg := &testMessage{subProtocol: p2pcommon.GetTXsRequest, id:p2pcommon.NewMsgID()}
   235  			msgBody := &types.GetTransactionsRequest{Hashes: make([][]byte, test.hashCnt)}
   236  			//h.Handle(dummyMsg, msgBody)
   237  			h.handleTxReq(dummyMsg, msgBody.Hashes)
   238  			// wait for handle finished
   239  			<- h.w
   240  
   241  		})
   242  	}
   243  }
   244  
   245  func TestNewTxNoticeHandler_handle(t *testing.T) {
   246  	ctrl := gomock.NewController(t)
   247  	defer ctrl.Finish()
   248  
   249  	logger := log.NewLogger("test.subproto")
   250  	var dummyPeerID, _ = types.IDB58Decode("16Uiu2HAmN5YU8V2LnTy9neuuJCLNsxLnd5xVSRZqkjvZUHS3mLoD")
   251  	var dummyTxHash, _ = enc.ToBytes("4H4zAkAyRV253K5SNBJtBxqUgHEbZcXbWFFc6cmQHY45")
   252  	sampleMeta := p2pcommon.PeerMeta{ID: dummyPeerID, IPAddress: "192.168.1.2", Port: 4321}
   253  	sampleHeader := &testMessage{id:p2pcommon.NewMsgID()}
   254  
   255  	var filledArrs = make([]types.TxID, 1)
   256  	filledArrs[0] = types.ToTxID(dummyTxHash)
   257  	var emptyArrs = make([]types.TxID, 0)
   258  
   259  	var sampleTxsB58 = []string{
   260  		"4H4zAkAyRV253K5SNBJtBxqUgHEbZcXbWFFc6cmQHY45",
   261  		"6xfk39kuyDST7NwCu8tx3wqwFZ5dwKPDjxUS14tU7NZb8",
   262  		"E8dbBGe9Hnuhk35cJoekPjL3VoL4xAxtnRuP47UoxzHd",
   263  		"HB7Hg5GUbHuxwe8Lp5PcYUoAaQ7EZjRNG6RuvS6DnDRf",
   264  		"BxKmDg9VbWHxrWnStEeTzJ2Ze7RF7YK4rpyjcsWSsnxs",
   265  		"DwmGqFU4WgADpYN36FXKsYxMjeppvh9Najg4KxJ8gtX3",
   266  	}
   267  	sampleTxs := make([][]byte, len(sampleTxsB58))
   268  	sampleTxHashes := make([]types.TxID, len(sampleTxsB58))
   269  	for i, hashb58 := range sampleTxsB58 {
   270  		hash, _ := enc.ToBytes(hashb58)
   271  		sampleTxs[i] = hash
   272  		copy(sampleTxHashes[i][:], hash)
   273  	}
   274  
   275  	tests := []struct {
   276  		name string
   277  		//hashes [][]byte
   278  		//calledUpdataCache bool
   279  		//passedToSM bool
   280  		setup  func(tt *testing.T, pm *p2pmock.MockPeerManager, mockPeer *p2pmock.MockRemotePeer, mockSM *p2pmock.MockSyncManager) (p2pcommon.Message, *types.NewTransactionsNotice)
   281  		verify func(tt *testing.T, pm *p2pmock.MockPeerManager, mockPeer *p2pmock.MockRemotePeer, mockSM *p2pmock.MockSyncManager)
   282  	}{
   283  		// 1. success case (single tx)
   284  		{"TSuccSingle", func(tt *testing.T, pm *p2pmock.MockPeerManager, mockPeer *p2pmock.MockRemotePeer, mockSM *p2pmock.MockSyncManager) (p2pcommon.Message, *types.NewTransactionsNotice) {
   285  			hashes := sampleTxs[:1]
   286  			mockPeer.EXPECT().UpdateTxCache(&TxIDCntMatcher{1}).Return(filledArrs).MinTimes(1)
   287  			//mockPeer.EXPECT().UpdateTxCache(gomock.Any()).Return(filledArrs).AnyTimes()
   288  			mockSM.EXPECT().HandleNewTxNotice(mockPeer, filledArrs, gomock.AssignableToTypeOf(&types.NewTransactionsNotice{})).MinTimes(1)
   289  			return sampleHeader, &types.NewTransactionsNotice{TxHashes: hashes}
   290  		}, func(tt *testing.T, pm *p2pmock.MockPeerManager, mockPeer *p2pmock.MockRemotePeer, mockSM *p2pmock.MockSyncManager) {
   291  		}},
   292  		// 1-1 success case2 (multiple tx)
   293  		{"TSuccMultiHash", func(tt *testing.T, pm *p2pmock.MockPeerManager, mockPeer *p2pmock.MockRemotePeer, mockSM *p2pmock.MockSyncManager) (p2pcommon.Message, *types.NewTransactionsNotice) {
   294  			hashes := sampleTxs
   295  			mockPeer.EXPECT().UpdateTxCache(&TxIDCntMatcher{len(sampleTxs)}).Return(filledArrs).MinTimes(1)
   296  			//mockPeer.EXPECT().UpdateTxCache(gomock.Any()).Return(filledArrs)
   297  			mockSM.EXPECT().HandleNewTxNotice(gomock.Any(), filledArrs, gomock.AssignableToTypeOf(&types.NewTransactionsNotice{})).MinTimes(1)
   298  			return sampleHeader, &types.NewTransactionsNotice{TxHashes: hashes}
   299  		}, func(tt *testing.T, pm *p2pmock.MockPeerManager, mockPeer *p2pmock.MockRemotePeer, mockSM *p2pmock.MockSyncManager) {
   300  		}},
   301  		//// 2. All hashes already exist
   302  		{"TSuccAlreadyExists", func(tt *testing.T, pm *p2pmock.MockPeerManager, mockPeer *p2pmock.MockRemotePeer, mockSM *p2pmock.MockSyncManager) (p2pcommon.Message, *types.NewTransactionsNotice) {
   303  			hashes := sampleTxs
   304  			mockPeer.EXPECT().UpdateTxCache(gomock.Any()).Return(emptyArrs)
   305  			mockSM.EXPECT().HandleNewTxNotice(gomock.Any(), gomock.Any(), gomock.Any()).Times(0)
   306  			return sampleHeader, &types.NewTransactionsNotice{TxHashes: hashes}
   307  		}, func(tt *testing.T, pm *p2pmock.MockPeerManager, mockPeer *p2pmock.MockRemotePeer, mockSM *p2pmock.MockSyncManager) {
   308  		}},
   309  	}
   310  	for _, test := range tests {
   311  		t.Run(test.name, func(t *testing.T) {
   312  			mockPM := p2pmock.NewMockPeerManager(ctrl)
   313  			mockActor := p2pmock.NewMockActorService(ctrl)
   314  			mockPeer := p2pmock.NewMockRemotePeer(ctrl)
   315  			mockPeer.EXPECT().Meta().Return(sampleMeta).AnyTimes()
   316  			mockPeer.EXPECT().ID().Return(sampleMeta.ID).AnyTimes()
   317  			mockPeer.EXPECT().Name().Return(p2putil.ShortForm(sampleMeta.ID) + "#1").AnyTimes()
   318  			mockSM := p2pmock.NewMockSyncManager(ctrl)
   319  
   320  			header, body := test.setup(t, mockPM, mockPeer, mockSM)
   321  
   322  			target := NewNewTxNoticeHandler(mockPM, mockPeer, logger, mockActor, mockSM)
   323  			target.Handle(header, body)
   324  
   325  			test.verify(t, mockPM, mockPeer, mockSM)
   326  		})
   327  	}
   328  }
   329  
   330  
   331  func BenchmarkArrayKey(b *testing.B) {
   332  	size := 100000
   333  	const hashSize = 32
   334  	var samples = make([]([hashSize]byte), size)
   335  	for i := 0; i < size; i++ {
   336  		copy(samples[i][:], uuid.Must(uuid.NewV4()).Bytes())
   337  		copy(samples[i][16:], uuid.Must(uuid.NewV4()).Bytes())
   338  	}
   339  
   340  	b.Run("BArray", func(b *testing.B) {
   341  		var keyArr [hashSize]byte
   342  		startTime := time.Now()
   343  		fmt.Printf("P1 in byte array\n")
   344  		target := make(map[[hashSize]byte]int)
   345  		for i := 0; i < size; i++ {
   346  			copy(keyArr[:], samples[i][:])
   347  			target[keyArr] = i
   348  		}
   349  		endTime := time.Now()
   350  		fmt.Printf("Takes %f sec \n", endTime.Sub(startTime).Seconds())
   351  	})
   352  
   353  	b.Run("Bbase64", func(b *testing.B) {
   354  		startTime := time.Now()
   355  		fmt.Printf("P2 in base64\n")
   356  		target2 := make(map[string]int)
   357  		for i := 0; i < size; i++ {
   358  			target2[enc.ToString(samples[i][:])] = i
   359  		}
   360  		endTime := time.Now()
   361  		fmt.Printf("Takes %f sec\n", endTime.Sub(startTime).Seconds())
   362  
   363  	})
   364  
   365  }
   366  
   367  type MempoolRspTxCountMatcher struct {
   368  	matchCnt int
   369  }
   370  
   371  func (tcm MempoolRspTxCountMatcher) Matches(x interface{}) bool {
   372  	m, ok := x.(*message.MemPoolExistExRsp)
   373  	if !ok {
   374  		return false
   375  	}
   376  	return tcm.matchCnt == len(m.Txs)
   377  }
   378  
   379  func (tcm MempoolRspTxCountMatcher) String() string {
   380  	return fmt.Sprintf("tx count = %d",tcm.matchCnt)
   381  }
   382  
   383  type TxIDCntMatcher struct {
   384  	matchCnt int
   385  }
   386  
   387  func (scm TxIDCntMatcher) Matches(x interface{}) bool {
   388  	m, ok := x.([]types.TxID)
   389  	if !ok {
   390  		return false
   391  	}
   392  	return scm.matchCnt == len(m)
   393  }
   394  
   395  func (scm TxIDCntMatcher) String() string {
   396  	return fmt.Sprintf("len(slice) = %d",scm.matchCnt)
   397  }
   398  
   399  type WantErrMatcher struct {
   400  	wantErr bool
   401  }
   402  
   403  func (tcm WantErrMatcher) Matches(x interface{}) bool {
   404  	m, ok := x.(*error)
   405  	if !ok {
   406  		return false
   407  	}
   408  	return tcm.wantErr == (m != nil)
   409  }
   410  
   411  func (tcm WantErrMatcher) String() string {
   412  	return fmt.Sprintf("want error = %v",tcm.wantErr)
   413  }
   414