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

     1  /*
     2   * @file
     3   * @copyright defined in aergo/LICENSE.txt
     4   */
     5  
     6  package p2p
     7  
     8  import (
     9  	"github.com/aergoio/aergo/chain"
    10  	"github.com/aergoio/aergo/p2p/p2pcommon"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/aergoio/aergo/message"
    15  	"github.com/aergoio/aergo/p2p/p2pmock"
    16  	"github.com/aergoio/aergo/types"
    17  	"github.com/golang/mock/gomock"
    18  	"github.com/stretchr/testify/assert"
    19  )
    20  
    21  func TestBlocksChunkReceiver_StartGet(t *testing.T) {
    22  	ctrl := gomock.NewController(t)
    23  	defer ctrl.Finish()
    24  
    25  	inputHashes := make([]message.BlockHash, len(sampleBlks))
    26  	for i, hash := range sampleBlks {
    27  		inputHashes[i] = hash
    28  	}
    29  	tests := []struct {
    30  		name  string
    31  		input []message.BlockHash
    32  		ttl   time.Duration
    33  	}{
    34  		{"TSimple", inputHashes, time.Millisecond * 10},
    35  		// TODO: test cases
    36  	}
    37  	for _, test := range tests {
    38  		t.Run(test.name, func(t *testing.T) {
    39  			//mockContext := new(mockContext)
    40  			mockActor := p2pmock.NewMockActorService(ctrl)
    41  			//mockActor.On("SendRequest", message.P2PSvc, mock.AnythingOfType("*types.GetBlock"))
    42  			//mockActor.On("TellRequest", message.SyncerSvc, mock.AnythingOfType("*types.GetBlock"))
    43  			mockMF := p2pmock.NewMockMoFactory(ctrl)
    44  			mockMo := createDummyMo(ctrl)
    45  			mockMF.EXPECT().NewMsgBlockRequestOrder(gomock.Any(), gomock.Any(), gomock.Any()).Return(mockMo)
    46  			mockPeer := p2pmock.NewMockRemotePeer(ctrl)
    47  			mockPeer.EXPECT().MF().Return(mockMF)
    48  			mockPeer.EXPECT().SendMessage(mockMo).Times(1)
    49  
    50  			expire := time.Now().Add(test.ttl)
    51  			br := NewBlockReceiver(mockActor, mockPeer, 0, test.input, test.ttl)
    52  
    53  			br.StartGet()
    54  
    55  			assert.Equal(t, len(test.input), len(br.blockHashes))
    56  			assert.False(t, expire.After(br.timeout))
    57  		})
    58  	}
    59  }
    60  
    61  func TestBlocksChunkReceiver_ReceiveResp(t *testing.T) {
    62  	ctrl := gomock.NewController(t)
    63  	defer ctrl.Finish()
    64  	chain.Init(1<<20 , "", false, 1, 1 )
    65  
    66  	seqNo := uint64(8723)
    67  	blkNo := uint64(100)
    68  	prevHash := dummyBlockHash
    69  	inputHashes := make([]message.BlockHash, len(sampleBlks))
    70  	inputBlocks := make([]*types.Block, len(sampleBlks))
    71  	for i, hash := range sampleBlks {
    72  		inputHashes[i] = hash
    73  		inputBlocks[i] = &types.Block{Hash: hash, Header: &types.BlockHeader{PrevBlockHash: prevHash, BlockNo: blkNo}}
    74  		blkNo++
    75  		prevHash = hash
    76  	}
    77  	tests := []struct {
    78  		name        string
    79  		input       []message.BlockHash
    80  		blkInput    [][]*types.Block
    81  
    82  		// to verify
    83  		consumed  int
    84  		respError bool
    85  	}{
    86  		{"TSingleResp", inputHashes,  [][]*types.Block{inputBlocks}, 1,  false},
    87  		{"TMultiResp", inputHashes, [][]*types.Block{inputBlocks[:1], inputBlocks[1:3], inputBlocks[3:]}, 1,  false},
    88  		// Fail1 remote err
    89  		{"TRemoteFail", inputHashes, [][]*types.Block{inputBlocks[:0]}, 1,  true},
    90  		// server didn't sent last parts. and it is very similar to timeout
    91  		//{"TNotComplete", inputHashes, time.Minute,0,[][]*types.Block{inputBlocks[:2]},1,0, false},
    92  		// Fail2 missing some blocks in the middle
    93  		{"TMissingBlk", inputHashes, [][]*types.Block{inputBlocks[:1],inputBlocks[2:3],inputBlocks[3:]},0, true},
    94  		// Fail2-1 missing some blocks in last
    95  		{"TMissingBlkLast", inputHashes, [][]*types.Block{inputBlocks[:1],inputBlocks[1:2],inputBlocks[3:]},1, true},
    96  		// Fail3 unexpected block
    97  		{"TDupBlock", inputHashes, [][]*types.Block{inputBlocks[:2],inputBlocks[1:3],inputBlocks[3:]},0, true},
    98  		{"TTooManyBlks", inputHashes[:4], [][]*types.Block{inputBlocks[:1],inputBlocks[1:3],inputBlocks[3:]},1, true},
    99  		{"TTooManyBlksMiddle", inputHashes[:2], [][]*types.Block{inputBlocks[:1],inputBlocks[1:3],inputBlocks[3:]},0, true},
   100  	}
   101  	for _, test := range tests {
   102  		t.Run(test.name, func(t *testing.T) {
   103  			//mockContext := new(mockContext)
   104  			mockActor := p2pmock.NewMockActorService(ctrl)
   105  			mockActor.EXPECT().TellRequest(message.SyncerSvc, gomock.Any()).
   106  				DoAndReturn(func(a string, arg *message.GetBlockChunksRsp) {
   107  					if !((arg.Err != nil) == test.respError) {
   108  						t.Fatalf("Wrong error (have %v)\n", arg.Err)
   109  					}
   110  					if arg.Seq != seqNo {
   111  						t.Fatalf("Wrong seqNo %d, want %d)\n", arg.Seq, seqNo)
   112  					}
   113  				}).Times(1)
   114  
   115  			mockMF := p2pmock.NewMockMoFactory(ctrl)
   116  			mockMo := createDummyMo(ctrl)
   117  			mockMF.EXPECT().NewMsgBlockRequestOrder(gomock.Any(), gomock.Any(), gomock.Any()).Return(mockMo)
   118  			mockPeer := p2pmock.NewMockRemotePeer(ctrl)
   119  			mockPeer.EXPECT().ID().Return(dummyPeerID).AnyTimes()
   120  			mockPeer.EXPECT().MF().Return(mockMF)
   121  			mockPeer.EXPECT().SendMessage(gomock.Any()).Times(1)
   122  			if test.consumed > 0 {
   123  				mockPeer.EXPECT().ConsumeRequest(gomock.Any()).Times(test.consumed)
   124  			}
   125  
   126  			//expire := time.Now().Add(test.ttl)
   127  			br := NewBlockReceiver(mockActor, mockPeer, seqNo, test.input, time.Minute<<2)
   128  			br.StartGet()
   129  
   130  			msg := p2pcommon.NewSimpleMsgVal(p2pcommon.GetBlocksResponse, sampleMsgID)
   131  			for i, blks := range test.blkInput {
   132  				body := &types.GetBlockResponse{Blocks: blks, HasNext: i < len(test.blkInput)-1}
   133  				br.ReceiveResp(msg, body)
   134  				if br.status == receiverStatusFinished {
   135  					break
   136  				}
   137  			}
   138  
   139  		})
   140  	}
   141  }
   142  
   143  
   144  func TestBlocksChunkReceiver_ReceiveRespTimeout(t *testing.T) {
   145  	ctrl := gomock.NewController(t)
   146  	defer ctrl.Finish()
   147  	chain.Init(1<<20 , "", false, 1, 1 )
   148  
   149  	seqNo := uint64(8723)
   150  	blkNo := uint64(100)
   151  	prevHash := dummyBlockHash
   152  	inputHashes := make([]message.BlockHash, len(sampleBlks))
   153  	inputBlocks := make([]*types.Block, len(sampleBlks))
   154  	for i, hash := range sampleBlks {
   155  		inputHashes[i] = hash
   156  		inputBlocks[i] = &types.Block{Hash: hash, Header: &types.BlockHeader{PrevBlockHash: prevHash, BlockNo: blkNo}}
   157  		blkNo++
   158  		prevHash = hash
   159  	}
   160  	tests := []struct {
   161  		name        string
   162  		input       []message.BlockHash
   163  		ttl         time.Duration
   164  		blkInterval time.Duration
   165  		blkInput    [][]*types.Block
   166  
   167  		// to verify
   168  		consumed  int
   169  		sentResp  int
   170  	}{
   171  		// Fail4 response sent after timeout
   172  		{"TBefore", inputHashes, time.Millisecond * 40, time.Millisecond * 100, [][]*types.Block{inputBlocks[:1], inputBlocks[1:3], inputBlocks[3:]}, 1, 0},
   173  	}
   174  	for _, test := range tests {
   175  		t.Run(test.name, func(t *testing.T) {
   176  			//mockContext := new(mockContext)
   177  			mockActor := p2pmock.NewMockActorService(ctrl)
   178  			if test.sentResp > 0 {
   179  				mockActor.EXPECT().TellRequest(message.SyncerSvc, gomock.Any()).
   180  					DoAndReturn(func(a string, arg *message.GetBlockChunksRsp) {
   181  						// timeout should resp with timeout error or not send response
   182  						if arg.Err == nil {
   183  							t.Fatalf("Wrong error (have %v)\n", arg.Err)
   184  						}
   185  						if arg.Seq != seqNo {
   186  							t.Fatalf("Wrong seqNo %d, want %d)\n", arg.Seq, seqNo)
   187  						}
   188  					}).Times(test.sentResp)
   189  			}
   190  
   191  			mockMF := p2pmock.NewMockMoFactory(ctrl)
   192  			mockMo := createDummyMo(ctrl)
   193  			mockMF.EXPECT().NewMsgBlockRequestOrder(gomock.Any(), gomock.Any(), gomock.Any()).Return(mockMo)
   194  			mockPeer := p2pmock.NewMockRemotePeer(ctrl)
   195  			mockPeer.EXPECT().ID().Return(dummyPeerID).AnyTimes()
   196  			mockPeer.EXPECT().MF().Return(mockMF)
   197  			mockPeer.EXPECT().SendMessage(gomock.Any()).Times(1)
   198  			if test.consumed > 0 {
   199  				mockPeer.EXPECT().ConsumeRequest(gomock.Any()).MinTimes(test.consumed)
   200  			}
   201  
   202  			//expire := time.Now().Add(test.ttl)
   203  			br := NewBlockReceiver(mockActor, mockPeer, seqNo, test.input, test.ttl)
   204  			br.StartGet()
   205  
   206  			msg := p2pcommon.NewSimpleMsgVal(p2pcommon.GetBlocksResponse, sampleMsgID)
   207  			for i, blks := range test.blkInput {
   208  				time.Sleep(test.blkInterval)
   209  
   210  				body := &types.GetBlockResponse{Blocks: blks, HasNext: i < len(test.blkInput)-1}
   211  				br.ReceiveResp(msg, body)
   212  				if br.status == receiverStatusFinished {
   213  					break
   214  				}
   215  			}
   216  
   217  		})
   218  	}
   219  }