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

     1  /**
     2   *  @file
     3   *  @copyright defined in aergo/LICENSE.txt
     4   */
     5  
     6  package p2p
     7  
     8  import (
     9  	"fmt"
    10  	"math/rand"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/aergoio/aergo/p2p/p2pcommon"
    15  	"github.com/aergoio/aergo/p2p/p2pmock"
    16  	"github.com/golang/mock/gomock"
    17  
    18  	"github.com/aergoio/aergo/types"
    19  	"github.com/stretchr/testify/assert"
    20  )
    21  
    22  func Test_pbRequestOrder_SendTo(t *testing.T) {
    23  	ctrl := gomock.NewController(t)
    24  	defer ctrl.Finish()
    25  	mockTNT := p2pmock.NewMockTxNoticeTracer(ctrl)
    26  	factory := &baseMOFactory{tnt:mockTNT}
    27  
    28  	sampleMeta := p2pcommon.PeerMeta{ID: samplePeerID, IPAddress: "192.168.1.2", Port: 7845}
    29  
    30  
    31  	tests := []struct {
    32  		name     string
    33  		writeErr error
    34  		wantErr  bool
    35  	}{
    36  		// new request fill cache of peer
    37  		{"TSucc", nil, false},
    38  		// when failed in send
    39  		{"TWriteFail", fmt.Errorf("writeFail"), true},
    40  	}
    41  	for _, tt := range tests {
    42  		t.Run(tt.name, func(t *testing.T) {
    43  
    44  			mockActorServ := p2pmock.NewMockActorService(ctrl)
    45  			mockPeerManager := p2pmock.NewMockPeerManager(ctrl)
    46  			mockRW := p2pmock.NewMockMsgReadWriter(ctrl)
    47  
    48  			mockRW.EXPECT().WriteMsg(gomock.Any()).Return(tt.writeErr)
    49  
    50  			peer := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActorServ, logger, factory, &dummySigner{}, mockRW)
    51  			pr := factory.NewMsgRequestOrder(true, p2pcommon.PingRequest, &types.Ping{})
    52  			prevCacheSize := len(peer.requests)
    53  			msgID := pr.GetMsgID()
    54  
    55  			if err := pr.SendTo(peer); (err != nil) != tt.wantErr {
    56  				t.Errorf("pbRequestOrder.SendTo() error = %v, wantErr %v", err, tt.wantErr)
    57  			}
    58  
    59  			if !tt.wantErr {
    60  				assert.Equal(t, prevCacheSize+1, len(peer.requests))
    61  				actualMo, ok := peer.requests[msgID]
    62  				assert.True(t, ok)
    63  				assert.Equal(t, pr, actualMo.reqMO)
    64  			} else {
    65  				assert.Equal(t, prevCacheSize, len(peer.requests))
    66  			}
    67  		})
    68  	}
    69  }
    70  
    71  func Test_pbMessageOrder_SendTo(t *testing.T) {
    72  	ctrl := gomock.NewController(t)
    73  	defer ctrl.Finish()
    74  	mockTNT := p2pmock.NewMockTxNoticeTracer(ctrl)
    75  	factory := &baseMOFactory{tnt:mockTNT}
    76  
    77  	sampleMeta := p2pcommon.PeerMeta{ID: samplePeerID, IPAddress: "192.168.1.2", Port: 7845}
    78  
    79  	tests := []struct {
    80  		name     string
    81  		writeErr error
    82  		wantErr  bool
    83  	}{
    84  		{"TSucc", nil, false},
    85  		// when failed in send
    86  		{"TWriteFail", fmt.Errorf("writeFail"), true},
    87  	}
    88  	for _, tt := range tests {
    89  		t.Run(tt.name, func(t *testing.T) {
    90  			mockActorServ := p2pmock.NewMockActorService(ctrl)
    91  			mockPeerManager := p2pmock.NewMockPeerManager(ctrl)
    92  			mockRW := p2pmock.NewMockMsgReadWriter(ctrl)
    93  
    94  			mockRW.EXPECT().WriteMsg(gomock.Any()).Return(tt.writeErr)
    95  
    96  			peer := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActorServ, logger, factory, &dummySigner{}, mockRW)
    97  			pr := factory.NewMsgResponseOrder(p2pcommon.NewMsgID(), p2pcommon.PingResponse, &types.Pong{})
    98  			msgID := pr.GetMsgID()
    99  			// put dummy request information in cache
   100  			peer.requests[msgID] = &requestInfo{reqMO: &pbRequestOrder{}}
   101  			prevCacheSize := len(peer.requests)
   102  
   103  			if err := pr.SendTo(peer); (err != nil) != tt.wantErr {
   104  				t.Errorf("pbMessageOrder.SendTo() error = %v, wantErr %v", err, tt.wantErr)
   105  			}
   106  			// not affect any cache
   107  			assert.Equal(t, prevCacheSize, len(peer.requests))
   108  			_, ok := peer.requests[msgID]
   109  			assert.True(t, ok)
   110  		})
   111  	}
   112  }
   113  
   114  func Test_pbBlkNoticeOrder_SendTo(t *testing.T) {
   115  	ctrl := gomock.NewController(t)
   116  	defer ctrl.Finish()
   117  	mockTNT := p2pmock.NewMockTxNoticeTracer(ctrl)
   118  	factory := &baseMOFactory{tnt:mockTNT}
   119  
   120  	sampleMeta := p2pcommon.PeerMeta{ID: samplePeerID, IPAddress: "192.168.1.2", Port: 7845}
   121  
   122  	tests := []struct {
   123  		name     string
   124  		writeErr error
   125  		keyExist bool
   126  		wantErr  bool
   127  	}{
   128  		{"TSucc", nil, false, false},
   129  		// when failed in send
   130  		{"TWriteFail", fmt.Errorf("writeFail"), false, true},
   131  		{"TExist", nil, true, false},
   132  		// no write happen.
   133  		{"TExistWriteFail", fmt.Errorf("writeFail"), true, false},
   134  	}
   135  	for _, tt := range tests {
   136  		t.Run(tt.name, func(t *testing.T) {
   137  			mockActorServ := p2pmock.NewMockActorService(ctrl)
   138  			mockPeerManager := p2pmock.NewMockPeerManager(ctrl)
   139  			mockRW := p2pmock.NewMockMsgReadWriter(ctrl)
   140  
   141  			if tt.keyExist {
   142  				mockRW.EXPECT().WriteMsg(gomock.Any()).Return(tt.writeErr).Times(0)
   143  			} else {
   144  				mockRW.EXPECT().WriteMsg(gomock.Any()).Return(tt.writeErr).Times(1)
   145  			}
   146  			peer := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActorServ, logger, factory, &dummySigner{}, mockRW)
   147  			peer.lastStatus = &types.LastBlockStatus{}
   148  
   149  			target := factory.NewMsgBlkBroadcastOrder(&types.NewBlockNotice{BlockHash: dummyBlockHash, BlockNo:1})
   150  			msgID := sampleMsgID
   151  			// notice broadcast is affected by cache
   152  			// put dummy request information in cache
   153  			peer.requests[msgID] = &requestInfo{reqMO: &pbRequestOrder{}}
   154  			prevCacheSize := len(peer.requests)
   155  			if tt.keyExist {
   156  				hashKey := types.ToBlockID(dummyBlockHash)
   157  				peer.blkHashCache.Add(hashKey, true)
   158  			}
   159  			if err := target.SendTo(peer); (err != nil) != tt.wantErr {
   160  				t.Errorf("pbMessageOrder.SendTo() error = %v, wantErr %v", err, tt.wantErr)
   161  			}
   162  			// not affect any cache
   163  			assert.Equal(t, prevCacheSize, len(peer.requests))
   164  			_, ok := peer.requests[msgID]
   165  			assert.True(t, ok)
   166  		})
   167  	}
   168  }
   169  
   170  func Test_pbBlkNoticeOrder_SendTo_SkipByHeight(t *testing.T) {
   171  	allSendCnt := 3
   172  	hashes := make([][]byte,allSendCnt)
   173  	for i:=0 ; i<allSendCnt; i++ {
   174  		token := make([]byte, 32)
   175  		rand.Read(token)
   176  		hashes[i] = token
   177  	}
   178  
   179  	ctrl := gomock.NewController(t)
   180  	defer ctrl.Finish()
   181  	mockTNT := p2pmock.NewMockTxNoticeTracer(ctrl)
   182  	factory := &baseMOFactory{tnt:mockTNT}
   183  	sampleMeta := p2pcommon.PeerMeta{ID: samplePeerID, IPAddress: "192.168.1.2", Port: 7845}
   184  
   185  	tests := []struct {
   186  		name         string
   187  		noDiff       int
   188  		tryCnt       int
   189  		sendInterval time.Duration
   190  		wantSentLow  int   // inclusive
   191  		wantSentHigh int  // exclusive
   192  		//wantMinSkip int
   193  	}{
   194  		// send all if remote peer is low
   195  		{"TAllLowPeer", -1000, 3, time.Second>>1, 3,4},
   196  		//// skip same or higher peer
   197  		//// the first notice is same and skip but seconds will be sent
   198  		{"TSamePeer", 0, 3, time.Second>>2, 2,3},
   199  		{"TPartialHigh", 900, 3, time.Second>>2, 0,1},
   200  		{"THighPeer", 10000, 3, time.Second>>2, 0,1},
   201  		{"TVeryHighPeer", 100000, 3, time.Second>>2, 0,1},
   202  	}
   203  	for _, tt := range tests {
   204  		t.Run(tt.name, func(t *testing.T) {
   205  			mockActorServ := p2pmock.NewMockActorService(ctrl)
   206  			mockPeerManager := p2pmock.NewMockPeerManager(ctrl)
   207  			mockRW := p2pmock.NewMockMsgReadWriter(ctrl)
   208  
   209  			writeCnt := 0
   210  			mockRW.EXPECT().WriteMsg(gomock.Any()).Do(func(arg interface{}) {
   211  				writeCnt++
   212  			}).MinTimes(tt.wantSentLow)
   213  
   214  			notiNo := uint64(99999)
   215  			peerBlkNo := uint64(int64(notiNo)+int64(tt.noDiff))
   216  			peer := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActorServ, logger, factory, &dummySigner{}, mockRW)
   217  			peer.lastStatus = &types.LastBlockStatus{BlockNumber:peerBlkNo}
   218  
   219  			skipMax := int32(0)
   220  			for i:=0; i<tt.tryCnt; i++ {
   221  				target := factory.NewMsgBlkBroadcastOrder(&types.NewBlockNotice{BlockHash: hashes[i], BlockNo:notiNo+uint64(i)})
   222  				msgID := sampleMsgID
   223  				// notice broadcast is affected by cache
   224  				// put dummy request information in cache
   225  				peer.requests[msgID] = &requestInfo{reqMO: &pbRequestOrder{}}
   226  
   227  				if err := target.SendTo(peer); err != nil {
   228  					t.Errorf("pbMessageOrder.SendTo() error = %v, want nil", err)
   229  				}
   230  				if skipMax < peer.skipCnt {
   231  					skipMax = peer.skipCnt
   232  				}
   233  				time.Sleep(tt.sendInterval)
   234  			}
   235  			fmt.Printf("%v : Max skipCnt %v \n",tt.name, skipMax)
   236  
   237  			// verification
   238  			if !(tt.wantSentLow<=writeCnt && writeCnt<tt.wantSentHigh) {
   239  				t.Errorf("Sent count %v, want %v:%v", writeCnt, tt.wantSentLow, tt.wantSentHigh)
   240  			}
   241  		})
   242  	}
   243  }
   244  
   245  func Test_pbBlkNoticeOrder_SendTo_SkipByTime(t *testing.T) {
   246  	//t.Skip("This test is varied by machine power or load state.")
   247  	allSendCnt := 1000
   248  	hashes := make([][]byte,allSendCnt)
   249  	for i:=0 ; i<allSendCnt; i++ {
   250  		token := make([]byte, 32)
   251  		rand.Read(token)
   252  		hashes[i] = token
   253  	}
   254  
   255  	ctrl := gomock.NewController(t)
   256  	defer ctrl.Finish()
   257  	mockTNT := p2pmock.NewMockTxNoticeTracer(ctrl)
   258  	factory := &baseMOFactory{tnt:mockTNT}
   259  	sampleMeta := p2pcommon.PeerMeta{ID: samplePeerID, IPAddress: "192.168.1.2", Port: 7845}
   260  
   261  	tests := []struct {
   262  		name     string
   263  		noDiff   int
   264  		tryCnt   int
   265  		wantSent int // inclusive
   266  		//wantMinSkip int
   267  	}{
   268  		{"TLow", -1000, allSendCnt, 4},
   269  		{"TSame", 0, allSendCnt, 4},
   270  		// sent a notice for every 300 times skip
   271  		{"TPartialHigh", 900, allSendCnt, 3},
   272  		// sent a notice for every 3600 times skip
   273  		{"THighAbout1Hour", 4500, allSendCnt, 1},
   274  		// sent a notice for every 3600 times skip, but total try was only 1000, so no send
   275  		{"TVeryHigh", 100000, allSendCnt, 0},
   276  	}
   277  	for _, tt := range tests {
   278  		t.Run(tt.name, func(t *testing.T) {
   279  			mockActorServ := p2pmock.NewMockActorService(ctrl)
   280  			mockPeerManager := p2pmock.NewMockPeerManager(ctrl)
   281  			mockRW := p2pmock.NewMockMsgReadWriter(ctrl)
   282  
   283  			writeCnt := 0
   284  			mockRW.EXPECT().WriteMsg(gomock.Any()).Do(func(arg interface{}) {
   285  				writeCnt++
   286  			}).Times(tt.wantSent)
   287  
   288  			notiNo := uint64(99999)
   289  			peerBlkNo := uint64(int64(notiNo)+int64(tt.noDiff))
   290  			peer := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActorServ, logger, factory, &dummySigner{}, mockRW)
   291  			peer.lastStatus = &types.LastBlockStatus{BlockNumber:peerBlkNo}
   292  
   293  			skipMax := int32(0)
   294  			for i:=0; i<tt.tryCnt; i++ {
   295  				target := factory.NewMsgBlkBroadcastOrder(&types.NewBlockNotice{BlockHash: hashes[i], BlockNo:notiNo+uint64(i)})
   296  				msgID := sampleMsgID
   297  				// notice broadcast is affected by cache
   298  				// put dummy request information in cache
   299  				peer.requests[msgID] = &requestInfo{reqMO: &pbRequestOrder{}}
   300  
   301  				if err := target.SendTo(peer); err != nil {
   302  					t.Errorf("pbMessageOrder.SendTo() error = %v, want nil", err)
   303  				}
   304  				if skipMax < peer.skipCnt {
   305  					skipMax = peer.skipCnt
   306  				}
   307  				if i&0x0ff == 0 && i>0 {
   308  					// sleep tree times
   309  					time.Sleep(time.Second >> 2 )
   310  				}
   311  			}
   312  			fmt.Printf("%v : Max skipCnt %v \n",tt.name, skipMax)
   313  
   314  		})
   315  	}
   316  }
   317  
   318  func Test_pbTxNoticeOrder_SendTo(t *testing.T) {
   319  	sampleMeta := p2pcommon.PeerMeta{ID: samplePeerID, IPAddress: "192.168.1.2", Port: 7845}
   320  
   321  	sampleHashes := make([][]byte, 10)
   322  	for i := 0; i < 10; i++ {
   323  		sampleHashes[i] = []byte(fmt.Sprint("tx_000", i))
   324  	}
   325  	tests := []struct {
   326  		name     string
   327  		writeErr error
   328  		keyExist int
   329  		wantErr  bool
   330  		wantRType p2pcommon.ReportType
   331  	}{
   332  		{"TSucc", nil, 0, false, p2pcommon.Send},
   333  		{"TWriteFail", fmt.Errorf("writeFail"), 0, true, p2pcommon.Fail},
   334  	}
   335  	for _, tt := range tests {
   336  		t.Run(tt.name, func(t *testing.T) {
   337  			ctrl := gomock.NewController(t)
   338  			defer ctrl.Finish()
   339  			mockTNT := p2pmock.NewMockTxNoticeTracer(ctrl)
   340  			factory := &baseMOFactory{tnt:mockTNT}
   341  			mockActorServ := p2pmock.NewMockActorService(ctrl)
   342  			mockPeerManager := p2pmock.NewMockPeerManager(ctrl)
   343  			mockRW := p2pmock.NewMockMsgReadWriter(ctrl)
   344  
   345  			if tt.keyExist == len(sampleHashes) {
   346  				mockRW.EXPECT().WriteMsg(gomock.Any()).Return(tt.writeErr).Times(0)
   347  			} else {
   348  				mockRW.EXPECT().WriteMsg(gomock.Any()).Return(tt.writeErr).Times(1)
   349  			}
   350  			if tt.wantRType == p2pcommon.Send {
   351  				mockTNT.EXPECT().ReportSend(gomock.Any(), samplePeerID).Times(1)
   352  			} else {
   353  				mockTNT.EXPECT().ReportNotSend(gomock.Any(), 1).Times(1)
   354  			}
   355  
   356  			peer := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActorServ, logger, factory, &dummySigner{}, mockRW)
   357  
   358  			pr := factory.NewMsgTxBroadcastOrder(&types.NewTransactionsNotice{TxHashes: sampleHashes})
   359  			msgID := pr.GetMsgID()
   360  			// notice broadcast is affected by cache
   361  			// put dummy request information in cache
   362  			peer.requests[msgID] = &requestInfo{reqMO: &pbRequestOrder{}}
   363  			prevCacheSize := len(peer.requests)
   364  			var hashKey types.TxID
   365  			for i := 0; i < tt.keyExist; i++ {
   366  				hashKey = types.ToTxID(sampleHashes[i])
   367  				peer.txHashCache.Add(hashKey, true)
   368  			}
   369  
   370  			if err := pr.SendTo(peer); (err != nil) != tt.wantErr {
   371  				t.Errorf("pbRequestOrder.SendTo() error = %v, wantErr %v", err, tt.wantErr)
   372  			}
   373  			// not affect any cache
   374  			assert.Equal(t, prevCacheSize, len(peer.requests))
   375  			_, ok := peer.requests[msgID]
   376  			assert.True(t, ok)
   377  		})
   378  	}
   379  }