github.com/aergoio/aergo@v1.3.1/p2p/waitpeermanager_test.go (about) 1 /* 2 * @file 3 * @copyright defined in aergo/LICENSE.txt 4 */ 5 6 package p2p 7 8 import ( 9 "errors" 10 "github.com/aergoio/aergo/p2p/list" 11 "github.com/aergoio/aergo/p2p/p2putil" 12 "testing" 13 "time" 14 15 "github.com/aergoio/aergo-lib/log" 16 "github.com/aergoio/aergo/p2p/p2pcommon" 17 "github.com/aergoio/aergo/p2p/p2pmock" 18 "github.com/aergoio/aergo/types" 19 "github.com/golang/mock/gomock" 20 "github.com/libp2p/go-libp2p-core/network" 21 ) 22 23 const ( 24 OneDay = time.Hour * 24 25 ) 26 27 func Test_staticWPManager_OnDiscoveredPeers(t *testing.T) { 28 ctrl := gomock.NewController(t) 29 defer ctrl.Finish() 30 31 type args struct { 32 metas []p2pcommon.PeerMeta 33 } 34 tests := []struct { 35 name string 36 args args 37 wantCount int 38 }{ 39 {"TSingleDesign", args{desigPeers[:1]}, 0}, 40 {"TAllDesign", args{desigPeers}, 0}, 41 {"TNewID", args{unknownPeers}, 0}, 42 {"TMixedIDs", args{append(unknownPeers[:5], desigPeers[:5]...)}, 0}, 43 } 44 for _, tt := range tests { 45 t.Run(tt.name, func(t *testing.T) { 46 dummyPM := createDummyPM() 47 mockLM := p2pmock.NewMockListManager(ctrl) 48 49 dp := NewWaitingPeerManager(logger, dummyPM, mockLM, 10, false).(*staticWPManager) 50 51 dp.OnDiscoveredPeers(tt.args.metas) 52 if len(dummyPM.waitingPeers) != tt.wantCount { 53 t.Errorf("count waitingPeer %v, want %v", len(dummyPM.waitingPeers), tt.wantCount) 54 } 55 }) 56 } 57 } 58 59 func Test_dynamicWPManager_OnDiscoveredPeers(t *testing.T) { 60 ctrl := gomock.NewController(t) 61 defer ctrl.Finish() 62 63 type args struct { 64 preConnected []types.PeerID 65 metas []p2pcommon.PeerMeta 66 } 67 tests := []struct { 68 name string 69 args args 70 wantCount int 71 }{ 72 {"TAllNew", args{nil, desigPeers[:1]}, 1}, 73 {"TAllExist", args{desigIDs, desigPeers[:5]}, 0}, 74 {"TMixedIDs", args{desigIDs, append(unknownPeers[:5], desigPeers[:5]...)}, 5}, 75 } 76 for _, tt := range tests { 77 t.Run(tt.name, func(t *testing.T) { 78 dummyPM := createDummyPM() 79 mockLM := p2pmock.NewMockListManager(ctrl) 80 81 dp := NewWaitingPeerManager(logger, dummyPM, mockLM, 10, true) 82 for _, id := range tt.args.preConnected { 83 dummyPM.remotePeers[id] = &remotePeerImpl{} 84 dp.OnPeerConnect(id) 85 } 86 87 dp.OnDiscoveredPeers(tt.args.metas) 88 if len(dummyPM.waitingPeers) != tt.wantCount { 89 t.Errorf("count waitingPeer %v, want %v", len(dummyPM.waitingPeers), tt.wantCount) 90 } 91 }) 92 } 93 } 94 95 func Test_setNextTrial(t *testing.T) { 96 dummyDesignated := p2pcommon.PeerMeta{Designated: true} 97 98 type args struct { 99 wp *p2pcommon.WaitingPeer 100 setCnt int 101 } 102 tests := []struct { 103 name string 104 args args 105 want bool 106 }{ 107 {"TDesig1", args{&p2pcommon.WaitingPeer{Meta: dummyDesignated}, 1}, true}, 108 {"TDesigSome", args{&p2pcommon.WaitingPeer{Meta: dummyDesignated}, 5}, true}, 109 {"TDesigMany", args{&p2pcommon.WaitingPeer{Meta: dummyDesignated}, 30}, true}, 110 111 {"TUnknown1", args{&p2pcommon.WaitingPeer{Meta: dummyMeta}, 1}, false}, 112 {"TUnknownSome", args{&p2pcommon.WaitingPeer{Meta: dummyMeta}, 5}, false}, 113 {"TUnknownMany", args{&p2pcommon.WaitingPeer{Meta: dummyMeta}, 30}, false}, 114 } 115 for _, tt := range tests { 116 t.Run(tt.name, func(t *testing.T) { 117 lastResult := false 118 prevDuration := time.Duration(0) 119 for i := 0; i < tt.args.setCnt; i++ { 120 now := time.Now() 121 lastResult = setNextTrial(tt.args.wp) 122 gotDuration := tt.args.wp.NextTrial.Sub(now) 123 // nextTrial time will be increased exponentially and clipped when trial count is bigger than internal count 124 // the clipped 125 if lastResult && 126 (gotDuration < prevDuration && gotDuration < OneDay) { 127 t.Errorf("smaller duration %v, want at least %v", gotDuration, prevDuration) 128 } 129 prevDuration = gotDuration 130 } 131 132 if lastResult != tt.want { 133 t.Errorf("setNextTrial() = %v, want %v", lastResult, tt.want) 134 } 135 }) 136 } 137 } 138 139 func Test_basePeerManager_tryAddPeer(t *testing.T) { 140 ctrl := gomock.NewController(t) 141 defer ctrl.Finish() 142 143 // tests for add peer 144 type args struct { 145 outbound bool 146 meta p2pcommon.PeerMeta 147 } 148 149 tests := []struct { 150 name string 151 args args 152 153 hsRet *types.Status 154 hsErr error 155 156 wantDesign bool 157 wantHidden bool 158 wantID types.PeerID 159 wantSucc bool 160 }{ 161 // add inbound peer 162 {"TIn", args{false, p2pcommon.PeerMeta{ID: dummyPeerID}}, 163 dummyStatus(dummyPeerID, false), nil, false, false, dummyPeerID, true}, 164 165 // add outbound peer 166 {"TOut", args{true, p2pcommon.PeerMeta{ID: dummyPeerID}}, 167 dummyStatus(dummyPeerID, false), nil, false, false, dummyPeerID, true}, 168 169 // failed to handshake 170 {"TErrHandshake", args{false, p2pcommon.PeerMeta{ID: dummyPeerID}}, 171 nil, errors.New("handshake err"), false, false, dummyPeerID, false}, 172 } 173 for _, tt := range tests { 174 t.Run(tt.name, func(t *testing.T) { 175 mockStream := p2pmock.NewMockStream(ctrl) 176 mockHSFactory := p2pmock.NewMockHSHandlerFactory(ctrl) 177 mockHSHandler := p2pmock.NewMockHSHandler(ctrl) 178 mockRW := p2pmock.NewMockMsgReadWriter(ctrl) 179 //mockHSFactory.EXPECT().CreateHSHandler(gomock.Any(), tt.args.outbound, tt.args.meta.ID).Return(mockHSHandler) 180 mockHSHandler.EXPECT().Handle(gomock.Any(), gomock.Any()).Return(mockRW, tt.hsRet, tt.hsErr) 181 //mockHandlerFactory := p2pmock.NewMockHSHandlerFactory(ctrl) 182 //mockHandlerFactory.EXPECT().InsertHandlers(gomock.AssignableToTypeOf(&remotePeerImpl{})).MaxTimes(1) 183 184 // in cases of handshake error 185 mockMF := p2pmock.NewMockMoFactory(ctrl) 186 mockMF.EXPECT().NewMsgRequestOrder(false, p2pcommon.GoAway, gomock.Any()).Return(&pbRequestOrder{}).MaxTimes(1) 187 mockRW.EXPECT().WriteMsg(gomock.Any()).MaxTimes(1) 188 189 pm := &peerManager{ 190 hsFactory: mockHSFactory, 191 peerHandshaked: make(chan handshakeResult, 10), 192 } 193 dpm := &basePeerManager{ 194 pm: pm, 195 logger: logger, 196 } 197 got, got1 := dpm.tryAddPeer(tt.args.outbound, tt.args.meta, mockStream, mockHSHandler) 198 if got1 != tt.wantSucc { 199 t.Errorf("basePeerManager.tryAddPeer() got1 = %v, want %v", got1, tt.wantSucc) 200 } 201 if tt.wantSucc { 202 if got.ID != tt.wantID { 203 t.Errorf("basePeerManager.tryAddPeer() got ID = %v, want %v", got.ID, tt.wantID) 204 } 205 if got.Outbound != tt.args.outbound { 206 t.Errorf("basePeerManager.tryAddPeer() got bound = %v, want %v", got.Outbound, tt.args.outbound) 207 } 208 if got.Designated != tt.wantDesign { 209 t.Errorf("basePeerManager.tryAddPeer() got Designated = %v, want %v", got.Designated, tt.wantDesign) 210 } 211 if got.Hidden != tt.wantHidden { 212 t.Errorf("basePeerManager.tryAddPeer() got Hidden = %v, want %v", got.Hidden, tt.wantHidden) 213 } 214 } 215 216 }) 217 } 218 } 219 220 func dummyStatus(id types.PeerID, noexpose bool) *types.Status { 221 return &types.Status{Sender: &types.PeerAddress{PeerID: []byte(id)}, NoExpose: noexpose} 222 } 223 224 func Test_basePeerManager_CheckAndConnect(t *testing.T) { 225 type fields struct { 226 pm *peerManager 227 lm p2pcommon.ListManager 228 logger *log.Logger 229 workingJobs map[types.PeerID]ConnWork 230 } 231 tests := []struct { 232 name string 233 fields fields 234 }{ 235 // TODO: Add test cases. 236 } 237 for _, tt := range tests { 238 t.Run(tt.name, func(t *testing.T) { 239 dpm := &basePeerManager{ 240 pm: tt.fields.pm, 241 lm: tt.fields.lm, 242 logger: tt.fields.logger, 243 workingJobs: tt.fields.workingJobs, 244 } 245 dpm.CheckAndConnect() 246 }) 247 } 248 } 249 250 func Test_dynamicWPManager_CheckAndConnect(t *testing.T) { 251 ctrl := gomock.NewController(t) 252 defer ctrl.Finish() 253 254 type args struct { 255 preConnected []types.PeerID 256 metas []p2pcommon.PeerMeta 257 } 258 tests := []struct { 259 name string 260 args args 261 wantCount int 262 }{ 263 {"TAllNew", args{nil, desigPeers[:1]}, 1}, 264 {"TAllExist", args{desigIDs, desigPeers[:5]}, 0}, 265 {"TMixedIDs", args{desigIDs, append(unknownPeers[:5], desigPeers[:5]...)}, 5}, 266 } 267 for _, tt := range tests { 268 t.Run(tt.name, func(t *testing.T) { 269 dummyPM := createDummyPM() 270 mockLM := p2pmock.NewMockListManager(ctrl) 271 272 dp := NewWaitingPeerManager(logger, dummyPM, mockLM, 10, true) 273 for _, id := range tt.args.preConnected { 274 dummyPM.remotePeers[id] = &remotePeerImpl{} 275 dp.OnPeerConnect(id) 276 } 277 278 dp.OnDiscoveredPeers(tt.args.metas) 279 if len(dummyPM.waitingPeers) != tt.wantCount { 280 t.Errorf("count waitingPeer %v, want %v", len(dummyPM.waitingPeers), tt.wantCount) 281 } 282 }) 283 } 284 } 285 286 func Test_basePeerManager_connectWaitingPeers(t *testing.T) { 287 ctrl := gomock.NewController(t) 288 defer ctrl.Finish() 289 290 c := []*p2pcommon.WaitingPeer{} 291 for i := 0 ; i < 5 ; i++ { 292 meta := p2pcommon.PeerMeta{ID:p2putil.RandomPeerID()} 293 wp := &p2pcommon.WaitingPeer{Meta:meta, NextTrial:time.Now()} 294 c = append(c, wp) 295 } 296 n := []*p2pcommon.WaitingPeer{} 297 for i := 0 ; i < 5 ; i++ { 298 meta := p2pcommon.PeerMeta{ID:p2putil.RandomPeerID()} 299 wp := &p2pcommon.WaitingPeer{Meta:meta, NextTrial:time.Now().Add(time.Hour*100)} 300 n = append(n, wp) 301 } 302 type args struct { 303 maxJob int 304 } 305 tests := []struct { 306 name string 307 wjs []*p2pcommon.WaitingPeer 308 args args 309 310 wantCnt int 311 }{ 312 {"TEmptyJob", nil, args{4}, 0}, 313 {"TFewer", c[:2], args{4}, 2}, 314 {"TLarger", c, args{4}, 4}, 315 {"TWithNotConn", append(nc(),c[0],n[0],n[1],c[1],n[4],c[4]), args{4}, 3}, 316 317 } 318 for _, tt := range tests { 319 t.Run(tt.name, func(t *testing.T) { 320 mockLM := p2pmock.NewMockListManager(ctrl) 321 mockNT := p2pmock.NewMockNetworkTransport(ctrl) 322 wpMap := make(map[types.PeerID]*p2pcommon.WaitingPeer) 323 for _, w := range tt.wjs { 324 wpMap[w.Meta.ID] = w 325 } 326 327 dummyPM := &peerManager{nt: mockNT, waitingPeers:wpMap, workDoneChannel: make(chan p2pcommon.ConnWorkResult,10)} 328 329 dpm := &basePeerManager{ 330 pm: dummyPM, 331 lm: mockLM, 332 logger: logger, 333 workingJobs: make(map[types.PeerID]ConnWork), 334 } 335 336 mockNT.EXPECT().GetOrCreateStream(gomock.Any(), gomock.Any()).Return(nil, errors.New("stream failed")).Times(tt.wantCnt) 337 mockLM.EXPECT().IsBanned(gomock.Any(), gomock.Any()).Return(false, list.FarawayFuture).AnyTimes() 338 339 dpm.connectWaitingPeers(tt.args.maxJob) 340 341 doneCnt := 0 342 expire := time.NewTimer(time.Millisecond * 500) 343 WAITLOOP: 344 for doneCnt < tt.wantCnt { 345 select { 346 case <-dummyPM.workDoneChannel: 347 doneCnt++ 348 case <-expire.C: 349 t.Errorf("connectWaitingPeers() job cnt %v, want %v", doneCnt, tt.wantCnt) 350 break WAITLOOP 351 } 352 } 353 }) 354 } 355 } 356 357 func nc() []*p2pcommon.WaitingPeer { 358 return nil 359 } 360 func Test_basePeerManager_OnInboundConn(t *testing.T) { 361 ctrl := gomock.NewController(t) 362 defer ctrl.Finish() 363 364 type fields struct { 365 workingJobs map[types.PeerID]ConnWork 366 } 367 type args struct { 368 s network.Stream 369 } 370 tests := []struct { 371 name string 372 fields fields 373 args args 374 }{ 375 // TODO: Add test cases. 376 } 377 for _, tt := range tests { 378 t.Run(tt.name, func(t *testing.T) { 379 dummyPM := &peerManager{} 380 mockLM := p2pmock.NewMockListManager(ctrl) 381 382 mockStream := p2pmock.NewMockStream(ctrl) 383 384 dpm := &basePeerManager{ 385 pm: dummyPM, 386 lm: mockLM, 387 logger: logger, 388 workingJobs: tt.fields.workingJobs, 389 } 390 dpm.OnInboundConn(mockStream) 391 }) 392 } 393 }