github.com/aergoio/aergo@v1.3.1/p2p/remotepeer_test.go (about) 1 /* 2 * @file 3 * @copyright defined in aergo/LICENSE.txt 4 */ 5 6 package p2p 7 8 import ( 9 "bytes" 10 "encoding/binary" 11 "testing" 12 "time" 13 14 "github.com/aergoio/aergo/p2p/p2pcommon" 15 "github.com/aergoio/aergo/p2p/p2pmock" 16 "github.com/aergoio/aergo/p2p/p2putil" 17 "github.com/aergoio/aergo/types" 18 "github.com/gofrs/uuid" 19 "github.com/golang/mock/gomock" 20 "github.com/stretchr/testify/assert" 21 ) 22 23 //const testDuration = time.Second >> 1 24 25 // TODO refactor rw and modify this test 26 /* 27 func TestAergoPeer_RunPeer(t *testing.T) { 28 //t.SkipNow() 29 30 ctrl := gomock.NewController(t) 31 defer ctrl.Finish() 32 33 //mockActorServ := new(p2pmock.MockActorService) 34 mockActorServ := p2pmock.NewMockActorService(ctrl) 35 dummyP2PServ := new(p2pmock.MockPeerManager) 36 mockMF := new(p2pmock.MockMoFactory) 37 dummyRW := new(p2pmock.MockMsgReadWriter) 38 target := newRemotePeer(p2pcommon.PeerMeta{ID: types.PeerID("ddddd")}, 0, dummyP2PServ, mockActorServ, logger, mockMF, nil, nil, dummyRW) 39 40 target.pingDuration = time.Second * 10 41 dummyBestBlock := types.Block{Hash: []byte("testHash"), Header: &types.BlockHeader{BlockNo: 1234}} 42 43 mockActorServ.On("requestSync", mock.Anything, mock.AnythingOfType("message.GetBlockRsp")).Return(dummyBestBlock, true) 44 45 mockActorServ.EXPECT(). 46 go target.RunPeer() 47 48 time.Sleep(testDuration) 49 target.Stop() 50 } 51 52 func TestRemotePeer_sendPing(t *testing.T) { 53 t.Skip("Send ping is not used for now, and will be reused after") 54 selfPeerID, _ := types.IDB58Decode("16Uiu2HAmFqptXPfcdaCdwipB2fhHATgKGVFVPehDAPZsDKSU7jRm") 55 sampleSelf := p2pcommon.PeerMeta{ID: selfPeerID, IPAddress: "192.168.1.1", Port: 6845} 56 57 dummyBestBlockRsp := message.GetBestBlockRsp{Block: &types.Block{Header: &types.BlockHeader{}}} 58 type wants struct { 59 wantWrite bool 60 } 61 tests := []struct { 62 name string 63 getBlockErr error 64 wants wants 65 }{ 66 {"TSucc", nil, wants{wantWrite: true}}, 67 // TODO: Add test cases. 68 } 69 for _, tt := range tests { 70 t.Run(tt.name, func(t *testing.T) { 71 mockActorServ := new(p2pmock.MockActorService) 72 mockPeerManager := new(p2pmock.MockPeerManager) 73 mockMF := new(p2pmock.MockMoFactory) 74 75 mockActorServ.On("CallRequest", message.ChainSvc, mock.AnythingOfType("*message.GetBestBlock")).Return(dummyBestBlockRsp, tt.getBlockErr) 76 mockPeerManager.On("SelfMeta").Return(sampleSelf) 77 mockMF.On("signMsg", mock.AnythingOfType("*types.P2PMessage")).Return(nil) 78 p := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActorServ, logger, mockMF, nil, nil, nil) 79 p.state.SetAndGet(types.RUNNING) 80 81 go p.sendPing() 82 83 time.Sleep(200 * time.Millisecond) 84 85 actualWrite := false 86 select { 87 case msg := <-p.dWrite: 88 assert.Equal(t, PingRequest, msg.(msgOrder).GetProtocolID()) 89 actualWrite = true 90 default: 91 } 92 assert.Equal(t, tt.wants.wantWrite, actualWrite) 93 mockPeerManager.AssertNotCalled(t, "SelfMeta") 94 // ping request does not contain best block information anymore. 95 mockActorServ.AssertNotCalled(t, "CallRequest") 96 }) 97 } 98 } 99 100 func TestRemotePeer_pruneRequests(t *testing.T) { 101 tests := []struct { 102 name string 103 loglevel string 104 }{ 105 {"T1", "info"}, 106 // {"T2", "debug"}, 107 // TODO: Add test cases. 108 } 109 // prevLevel := logger.Level() 110 // defer logger.SetLevel(prevLevel) 111 for _, tt := range tests { 112 // logger.SetLevel(tt.loglevel) 113 mockActorServ := new(p2pmock.MockActorService) 114 mockPeerManager := new(p2pmock.MockPeerManager) 115 mockStream := new(p2pmock.MockStream) 116 mockStream.On("Close").Return(nil) 117 118 p := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActorServ, logger, nil, nil, mockStream, nil) 119 t.Run(tt.name, func(t *testing.T) { 120 mid1, mid2, midn := p2pcommon.NewMsgID(), p2pcommon.NewMsgID(), p2pcommon.NewMsgID() 121 p.requests[mid1] = &requestInfo{cTime: time.Now().Add(time.Minute * -61), reqMO: &pbRequestOrder{pbMessageOrder{message: &MessageValue{id: mid1}}, nil}} 122 p.requests[mid2] = &requestInfo{cTime: time.Now().Add(time.Minute * -60).Add(time.Second * -1), reqMO: &pbRequestOrder{pbMessageOrder{message: &MessageValue{id: mid2}}, nil}} 123 p.requests[midn] = &requestInfo{cTime: time.Now().Add(time.Minute * -59), reqMO: &pbRequestOrder{pbMessageOrder{message: &MessageValue{id: midn}}, nil}} 124 p.pruneRequests() 125 126 assert.Equal(t, 1, len(p.requests)) 127 }) 128 } 129 } 130 131 func TestRemotePeer_sendMessage(t *testing.T) { 132 133 type args struct { 134 msgID p2pcommon.MsgID 135 protocol protocol.ID 136 timeout time.Duration 137 } 138 tests := []struct { 139 name string 140 args args 141 timeout bool 142 }{ 143 {"TSucc", args{p2pcommon.NewMsgID(), "p1", time.Millisecond * 100}, false}, 144 {"TTimeout", args{p2pcommon.NewMsgID(), "p1", time.Millisecond * 100}, true}, 145 // TODO: Add test cases. 146 } 147 for _, tt := range tests { 148 mockActorServ := new(p2pmock.MockActorService) 149 mockPeerManager := new(p2pmock.MockPeerManager) 150 mockMsg := new(p2pmock.MockMsgOrder) 151 mockMsg.On("GetMsgID").Return(tt.args.msgID) 152 mockMsg.On("GetProtocolID").Return(NewBlockNotice) 153 154 writeCnt := int32(0) 155 t.Run(tt.name, func(t *testing.T) { 156 finishTest := make(chan interface{}, 1) 157 wg := &sync.WaitGroup{} 158 wg.Add(1) 159 wg2 := &sync.WaitGroup{} 160 wg2.Add(1) 161 p := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActorServ, logger, nil, nil, nil, nil) 162 p.state.SetAndGet(types.RUNNING) 163 164 if !tt.timeout { 165 go func() { 166 wg.Wait() 167 for { 168 select { 169 case mo := <-p.dWrite: 170 p.logger.Info().Msgf("Got order from chan %v", mo) 171 msg := mo.(msgOrder) 172 p.logger.Info().Str(LogMsgID, msg.GetMsgID().String()).Msg("Got order") 173 atomic.AddInt32(&writeCnt, 1) 174 wg2.Done() 175 continue 176 case <-finishTest: 177 return 178 } 179 } 180 }() 181 } else { 182 wg2.Done() 183 } 184 wg.Done() 185 p.sendMessage(mockMsg) 186 wg2.Wait() 187 if !tt.timeout { 188 assert.Equal(t, int32(1), atomic.LoadInt32(&writeCnt)) 189 } 190 finishTest <- struct{}{} 191 }) 192 } 193 } 194 195 func TestRemotePeer_handleMsg(t *testing.T) { 196 sampleMsgID := p2pcommon.NewMsgID() 197 mockMO := new(p2pmock.MockMsgOrder) 198 mockMO.On("GetMsgID").Return(sampleMsgID) 199 mockMO.On("Subprotocol").Return(PingRequest) 200 201 type args struct { 202 nohandler bool 203 parerr error 204 autherr error 205 } 206 tests := []struct { 207 name string 208 args args 209 wantErr bool 210 }{ 211 {"TSucc", args{false, nil, nil}, false}, 212 {"Tnopro", args{true, nil, nil}, true}, 213 {"Tparcefail", args{false, fmt.Errorf("not proto"), nil}, true}, 214 {"Tauthfail", args{false, nil, fmt.Errorf("no permission")}, true}, 215 216 // TODO: make later use 217 //{"TTimeout", args{false, nil, fmt.Errorf("no permission")}, true}, 218 } 219 for _, tt := range tests { 220 mockActorServ := new(p2pmock.MockActorService) 221 mockPeerManager := new(p2pmock.MockPeerManager) 222 mockMsgHandler := new(p2pmock.MockMessageHandler) 223 mockSigner := new(p2pmock.MockMsgSigner) 224 mockMF := new(p2pmock.MockMoFactory) 225 t.Run(tt.name, func(t *testing.T) { 226 msg := new(p2pmock.MockMessage) 227 if tt.args.nohandler { 228 msg.On("Subprotocol").Return(p2pcommon.SubProtocol(3999999999)) 229 } else { 230 msg.On("Subprotocol").Return(PingRequest) 231 } 232 bodyStub := &types.Ping{} 233 bytes, _ := proto.Marshal(bodyStub) 234 msg.On("ID").Return(sampleMsgID) 235 msg.On("Payload").Return(bytes) 236 mockMsgHandler.On("parsePayload", mock.AnythingOfType("[]uint8")).Return(bodyStub, tt.args.parerr) 237 mockMsgHandler.On("checkAuth", mock.Anything, mock.Anything).Return(tt.args.autherr) 238 mockMsgHandler.On("handle", mock.Anything, mock.Anything) 239 mockSigner.On("verifyMsg", mock.Anything, mock.Anything).Return(nil) 240 241 target := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActorServ, logger, mockMF, mockSigner, nil, nil) 242 target.handlers[PingRequest] = mockMsgHandler 243 244 if err := target.handleMsg(msg); (err != nil) != tt.wantErr { 245 t.Errorf("remotePeerImpl.handleMsg() error = %v, wantErr %v", err, tt.wantErr) 246 } 247 if tt.args.nohandler { 248 mockMsgHandler.AssertNotCalled(t, "parsePayload", mock.AnythingOfType("[]uint8")) 249 } else { 250 mockMsgHandler.AssertCalled(t, "parsePayload", mock.AnythingOfType("[]uint8")) 251 } 252 if tt.args.nohandler || tt.args.parerr != nil { 253 mockMsgHandler.AssertNotCalled(t, "checkAuth", mock.Anything, mock.Anything) 254 } else { 255 mockMsgHandler.AssertCalled(t, "checkAuth", msg, bodyStub) 256 } 257 if tt.args.nohandler || tt.args.parerr != nil || tt.args.autherr != nil { 258 mockMsgHandler.AssertNotCalled(t, "handle", mock.Anything, mock.Anything) 259 } else { 260 mockMsgHandler.AssertCalled(t, "handle", msg, bodyStub) 261 } 262 }) 263 } 264 } 265 266 func TestRemotePeer_sendTxNotices(t *testing.T) { 267 t.Skip("meaningless after 20181030 refactoring") 268 sampleSize := DefaultPeerTxQueueSize << 1 269 sampleHashes := make([]types.TxID, sampleSize) 270 maxTxHashSize := 100 271 for i := 0; i < sampleSize; i++ { 272 sampleHashes[i] = generateHash(uint64(i)) 273 } 274 tests := []struct { 275 name string 276 initCnt int 277 moCnt int 278 }{ 279 {"TZero", 0, 0}, 280 {"TSingle", 1, 1}, 281 {"TSmall", 100, 1}, 282 {"TBig", 1001, 1}, 283 } 284 for _, test := range tests { 285 t.Run(test.name, func(t *testing.T) { 286 mockActorServ := new(p2pmock.MockActorService) 287 mockPeerManager := new(p2pmock.MockPeerManager) 288 mockSigner := new(p2pmock.MockMsgSigner) 289 mockMF := new(p2pmock.MockMoFactory) 290 mockOrder := new(p2pmock.MockMsgOrder) 291 mockOrder.On("IsNeedSign").Return(true) 292 mockOrder.On("GetProtocolID").Return(NewTxNotice) 293 mockOrder.On("GetMsgID").Return(p2pcommon.NewMsgID()) 294 295 mockMF.On("newMsgTxBroadcastOrder", mock.AnythingOfType("*types.NewTransactionsNotice")).Return(mockOrder) 296 297 target := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActorServ, logger, mockMF, mockSigner, nil, nil) 298 target.maxTxNoticeHashSize = maxTxHashSize 299 300 for i := 0; i < test.initCnt; i++ { 301 target.txNoticeQueue.Press(sampleHashes[i]) 302 } 303 target.sendTxNotices() 304 mockMF.AssertNumberOfCalls(t, "newMsgTxBroadcastOrder", test.moCnt) 305 }) 306 } 307 } 308 309 */ 310 311 func generateHash(i uint64) types.TxID { 312 bs := types.TxID{} 313 binary.LittleEndian.PutUint64(bs[:], i) 314 return bs 315 } 316 317 func TestRemotePeerImpl_UpdateBlkCache(t *testing.T) { 318 319 tests := []struct { 320 name string 321 hash types.BlockID 322 inCache []types.BlockID 323 prevLastBlk types.BlockID 324 expected bool 325 }{ 326 {"TAllNew", sampleBlksHashes[0], sampleBlksHashes[2:], sampleBlksHashes[2], false}, 327 {"TAllExist", sampleBlksHashes[0], sampleBlksHashes, sampleBlksHashes[1], true}, 328 // TODO: test cases 329 } 330 for _, test := range tests { 331 t.Run(test.name, func(t *testing.T) { 332 mockActor := new(p2pmock.MockActorService) 333 mockPeerManager := new(p2pmock.MockPeerManager) 334 mockSigner := new(p2pmock.MockMsgSigner) 335 mockMF := new(p2pmock.MockMoFactory) 336 337 target := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActor, logger, mockMF, mockSigner, nil) 338 for _, hash := range test.inCache { 339 target.blkHashCache.Add(hash, true) 340 } 341 target.lastStatus = &types.LastBlockStatus{BlockHash: test.prevLastBlk[:], BlockNumber: 0, CheckTime: time.Now()} 342 actual := target.UpdateBlkCache(test.hash[:], 0) 343 assert.Equal(t, test.expected, actual) 344 assert.True(t, bytes.Equal(test.hash[:], target.LastStatus().BlockHash)) 345 }) 346 } 347 } 348 349 func TestRemotePeerImpl_UpdateTxCache(t *testing.T) { 350 tests := []struct { 351 name string 352 hashes []types.TxID 353 inCache []types.TxID 354 expected []types.TxID 355 }{ 356 {"TAllNew", sampleTxHashes, sampleTxHashes[:0], sampleTxHashes}, 357 {"TPartial", sampleTxHashes, sampleTxHashes[2:], sampleTxHashes[:2]}, 358 {"TAllExist", sampleTxHashes, sampleTxHashes, make([]types.TxID, 0)}, 359 // TODO: test cases 360 } 361 for _, test := range tests { 362 t.Run(test.name, func(t *testing.T) { 363 mockActor := new(p2pmock.MockActorService) 364 mockPeerManager := new(p2pmock.MockPeerManager) 365 mockSigner := new(p2pmock.MockMsgSigner) 366 mockMF := new(p2pmock.MockMoFactory) 367 368 target := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActor, logger, mockMF, mockSigner, nil) 369 for _, hash := range test.inCache { 370 target.txHashCache.Add(hash, true) 371 } 372 actual := target.UpdateTxCache(test.hashes) 373 374 assert.Equal(t, test.expected, actual) 375 }) 376 } 377 } 378 379 func TestRemotePeerImpl_GetReceiver(t *testing.T) { 380 idSize := 10 381 idList := make([]p2pcommon.MsgID, idSize) 382 recvList := make(map[p2pcommon.MsgID]p2pcommon.ResponseReceiver) 383 // first 5 have receiver, but lattes don't 384 for i := 0; i < idSize; i++ { 385 idList[i] = p2pcommon.NewMsgID() 386 if i < 5 { 387 recvList[idList[i]] = func(msg p2pcommon.Message, msgBody p2pcommon.MessageBody) bool { 388 logger.Debug().Int("seq", i).Msg("receiver called") 389 return true 390 } 391 } 392 } 393 // GetReceiver should not return nil and consumeRequest must be thread-safe 394 tests := []struct { 395 name string 396 toAdd []p2pcommon.MsgID 397 inID p2pcommon.MsgID 398 399 receiverReturn bool 400 }{ 401 // 1. not anything 402 {"TEmpty", idList[1:10], idList[0], true}, 403 // 2. have request history but no receiver 404 {"TNOReceiver", idList[1:10], idList[5], false}, 405 // 3. have request history with receiver 406 {"THave", idList[1:10], idList[1], true}, 407 // 4. have multiple receivers 408 // TODO maybe to make separate test 409 } 410 for _, test := range tests { 411 t.Run(test.name, func(t *testing.T) { 412 mockActor := new(p2pmock.MockActorService) 413 mockPeerManager := new(p2pmock.MockPeerManager) 414 mockSigner := new(p2pmock.MockMsgSigner) 415 mockMF := new(p2pmock.MockMoFactory) 416 p := newRemotePeer(sampleMeta, 0, mockPeerManager, mockActor, logger, mockMF, mockSigner, nil) 417 for _, add := range test.toAdd { 418 p.requests[add] = &requestInfo{receiver: recvList[add]} 419 } 420 actual := p.GetReceiver(test.inID) 421 assert.NotNil(t, actual) 422 dummyMsg := p2pcommon.NewSimpleRespMsgVal(p2pcommon.AddressesResponse, p2pcommon.NewMsgID(), test.inID) 423 assert.Equal(t, test.receiverReturn, actual(dummyMsg, nil)) 424 425 // after consuming request, GetReceiver always return requestIDNotFoundReceiver, which always return true 426 p.ConsumeRequest(test.inID) 427 actual2 := p.GetReceiver(test.inID) 428 assert.NotNil(t, actual2) 429 assert.Equal(t, true, actual2(dummyMsg, nil)) 430 }) 431 } 432 } 433 434 func TestRemotePeerImpl_pushTxsNotice(t *testing.T) { 435 ctrl := gomock.NewController(t) 436 defer ctrl.Finish() 437 sampleSize := 100 438 sampleHashes := make([]types.TxID, sampleSize) 439 maxTxHashSize := 10 440 for i := 0; i < sampleSize; i++ { 441 sampleHashes[i] = generateHash(uint64(i)) 442 } 443 tests := []struct { 444 name string 445 in []types.TxID 446 expectSend int 447 }{ 448 // 1. single tx 449 {"TSingle", sampleHashes[:1], 0}, 450 // 2, multiple tx less than capacity 451 {"TSmall", sampleHashes[:maxTxHashSize], 0}, 452 // 3. multiple tx more than capacity. last one is not sent but just queued. 453 {"TLarge", sampleHashes[:maxTxHashSize*3+1], 3}, 454 } 455 for _, test := range tests { 456 t.Run(test.name, func(t *testing.T) { 457 mockMO := p2pmock.NewMockMsgOrder(ctrl) 458 mockPeerManager := p2pmock.NewMockPeerManager(ctrl) 459 mockMF := p2pmock.NewMockMoFactory(ctrl) 460 mockSigner := new(p2pmock.MockMsgSigner) 461 462 mockMO.EXPECT().GetMsgID().Return(p2pcommon.NewMsgID()).AnyTimes() 463 mockMF.EXPECT().NewMsgTxBroadcastOrder(gomock.Any()).Return(mockMO). 464 Times(test.expectSend) 465 466 p := newRemotePeer(sampleMeta, 0, mockPeerManager, nil, logger, mockMF, mockSigner, nil) 467 p.txNoticeQueue = p2putil.NewPressableQueue(maxTxHashSize) 468 p.maxTxNoticeHashSize = maxTxHashSize 469 470 p.PushTxsNotice(test.in) 471 }) 472 } 473 } 474 func TestRemotePeer_writeToPeer(t *testing.T) { 475 ctrl := gomock.NewController(t) 476 defer ctrl.Finish() 477 478 rand := uuid.Must(uuid.NewV4()) 479 var sampleMsgID p2pcommon.MsgID 480 copy(sampleMsgID[:], rand[:]) 481 type args struct { 482 StreamResult error 483 signErr error 484 needResponse bool 485 sendErr error 486 } 487 type wants struct { 488 sendCnt int 489 expReqCnt int 490 } 491 tests := []struct { 492 name string 493 args args 494 wants wants 495 }{ 496 {"TNReq1", args{}, wants{1, 0}}, 497 // {"TNReqWResp1", args{needResponse: true}, wants{1, 1}}, 498 499 // error while signing 500 // error while get stream 501 // TODO this case is evaluated in pbMsgOrder tests 502 // {"TFSend1", args{needResponse: true, sendErr: sampleErr}, wants{1, 0}}, 503 } 504 for _, tt := range tests { 505 t.Run(tt.name, func(t *testing.T) { 506 mockPeerManager := p2pmock.NewMockPeerManager(ctrl) 507 mockMO := p2pmock.NewMockMsgOrder(ctrl) 508 mockStream := p2pmock.NewMockStream(ctrl) 509 dummyRW := p2pmock.NewMockMsgReadWriter(ctrl) 510 dummyRW.EXPECT().Close().AnyTimes() 511 512 mockStream.EXPECT().Close().Return(nil).AnyTimes() 513 mockMO.EXPECT().IsNeedSign().Return(true).AnyTimes() 514 mockMO.EXPECT().SendTo(gomock.Any()).Return(tt.args.sendErr) 515 mockMO.EXPECT().GetProtocolID().Return(p2pcommon.PingRequest).AnyTimes() 516 mockMO.EXPECT().GetMsgID().Return(sampleMsgID).AnyTimes() 517 518 p := newRemotePeer(sampleMeta, 0, mockPeerManager, nil, logger, nil, nil, dummyRW) 519 p.state.SetAndGet(types.RUNNING) 520 go p.runWrite() 521 p.state.SetAndGet(types.RUNNING) 522 523 p.writeToPeer(mockMO) 524 525 // FIXME wait in more reliable way 526 time.Sleep(50 * time.Millisecond) 527 close(p.closeWrite) 528 //mockOrder.AssertNumberOfCalls(t, "SendTo", tt.wants.sendCnt) 529 //assert.Equal(t, tt.wants.expReqCnt, len(p.requests)) 530 }) 531 } 532 } 533 534 func Test_remotePeerImpl_handleMsg_InPanic(t *testing.T) { 535 ctrl := gomock.NewController(t) 536 defer ctrl.Finish() 537 538 msg := p2pmock.NewMockMessage(ctrl) 539 msg.EXPECT().Subprotocol().Return(p2pcommon.PingRequest).MaxTimes(1) 540 msg.EXPECT().ID().Return(p2pcommon.NewMsgID()).AnyTimes() 541 msg.EXPECT().Payload().DoAndReturn(func() []byte { 542 panic("for test") 543 return nil 544 }) 545 mockHandler := p2pmock.NewMockMessageHandler(ctrl) 546 mockHandler.EXPECT().PreHandle().AnyTimes() 547 548 p := &remotePeerImpl{ 549 logger: logger, 550 handlers:make(map[p2pcommon.SubProtocol]p2pcommon.MessageHandler), 551 } 552 p.handlers[p2pcommon.PingRequest] = mockHandler 553 554 if err := p.handleMsg(msg); err == nil { 555 t.Errorf("remotePeerImpl.handleMsg() no error, err by panic") 556 } else { 557 t.Logf("expected error %v", err) 558 } 559 }