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 }