github.com/ethersphere/bee/v2@v2.2.0/pkg/puller/puller_test.go (about) 1 // Copyright 2020 The Swarm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package puller_test 6 7 import ( 8 "context" 9 "errors" 10 "fmt" 11 "testing" 12 "time" 13 14 "github.com/ethersphere/bee/v2/pkg/log" 15 "github.com/ethersphere/bee/v2/pkg/puller" 16 "github.com/ethersphere/bee/v2/pkg/puller/intervalstore" 17 mockps "github.com/ethersphere/bee/v2/pkg/pullsync/mock" 18 "github.com/ethersphere/bee/v2/pkg/spinlock" 19 "github.com/ethersphere/bee/v2/pkg/statestore/leveldb" 20 "github.com/ethersphere/bee/v2/pkg/statestore/mock" 21 "github.com/ethersphere/bee/v2/pkg/storage" 22 resMock "github.com/ethersphere/bee/v2/pkg/storer/mock" 23 "github.com/ethersphere/bee/v2/pkg/swarm" 24 kadMock "github.com/ethersphere/bee/v2/pkg/topology/kademlia/mock" 25 "github.com/ethersphere/bee/v2/pkg/util/testutil" 26 "github.com/google/go-cmp/cmp" 27 ) 28 29 // test that adding one peer starts syncing 30 func TestOneSync(t *testing.T) { 31 t.Parallel() 32 33 var ( 34 addr = swarm.RandAddress(t) 35 cursors = []uint64{1000, 1000, 1000} 36 replies = []mockps.SyncReply{ 37 {Bin: 1, Start: 1, Topmost: 1000, Peer: addr}, 38 {Bin: 2, Start: 1, Topmost: 1001, Peer: addr}} 39 ) 40 41 _, _, kad, pullsync := newPuller(t, opts{ 42 kad: []kadMock.Option{ 43 kadMock.WithEachPeerRevCalls( 44 kadMock.AddrTuple{Addr: addr, PO: 1}, 45 ), 46 }, 47 pullSync: []mockps.Option{mockps.WithCursors(cursors, 0), mockps.WithReplies(replies...)}, 48 bins: 3, 49 rs: resMock.NewReserve(resMock.WithRadius(1)), 50 }) 51 time.Sleep(100 * time.Millisecond) 52 53 kad.Trigger() 54 55 waitCursorsCalled(t, pullsync, addr) 56 waitSyncCalledBins(t, pullsync, addr, 1, 2) 57 } 58 59 func TestSyncOutsideDepth(t *testing.T) { 60 t.Parallel() 61 62 var ( 63 addr = swarm.RandAddress(t) 64 addr2 = swarm.RandAddress(t) 65 cursors = []uint64{1000, 1000, 1000, 1000} 66 replies = []mockps.SyncReply{ 67 {Bin: 0, Start: 1, Topmost: 1000, Peer: addr2}, 68 {Bin: 2, Start: 1, Topmost: 1000, Peer: addr}, 69 {Bin: 3, Start: 1, Topmost: 1000, Peer: addr}} 70 ) 71 72 _, _, kad, pullsync := newPuller(t, opts{ 73 kad: []kadMock.Option{ 74 kadMock.WithEachPeerRevCalls( 75 kadMock.AddrTuple{Addr: addr, PO: 2}, 76 kadMock.AddrTuple{Addr: addr2, PO: 0}, 77 ), 78 }, 79 pullSync: []mockps.Option{mockps.WithCursors(cursors, 0), mockps.WithReplies(replies...)}, 80 bins: 4, 81 rs: resMock.NewReserve(resMock.WithRadius(2)), 82 }) 83 84 time.Sleep(100 * time.Millisecond) 85 kad.Trigger() 86 87 waitCursorsCalled(t, pullsync, addr) 88 waitCursorsCalled(t, pullsync, addr2) 89 90 waitSyncCalledBins(t, pullsync, addr, 2, 3) 91 waitSyncCalledBins(t, pullsync, addr2, 0) 92 } 93 94 func TestSyncIntervals(t *testing.T) { 95 t.Parallel() 96 97 addr := swarm.RandAddress(t) 98 99 for _, tc := range []struct { 100 name string // name of test 101 cursors []uint64 // mocked cursors to be exchanged from peer 102 replies []mockps.SyncReply 103 intervals string // expected intervals on pivot 104 }{ 105 { 106 name: "0, 1 chunk on live", 107 cursors: []uint64{0, 0}, 108 intervals: "[[1 1]]", 109 replies: []mockps.SyncReply{ 110 {Bin: 1, Start: 1, Topmost: 1, Peer: addr}, 111 {Bin: 1, Start: 1, Topmost: 1, Peer: addr}, 112 }, 113 }, 114 { 115 name: "0 - calls 1-1, 2-5, 6-10", 116 cursors: []uint64{0, 0}, 117 intervals: "[[1 10]]", 118 replies: []mockps.SyncReply{ 119 {Bin: 1, Start: 1, Topmost: 1, Peer: addr}, 120 {Bin: 1, Start: 2, Topmost: 5, Peer: addr}, 121 {Bin: 1, Start: 6, Topmost: 10, Peer: addr}, 122 }, 123 }, 124 { 125 name: "0, 1 - calls 1-1", 126 cursors: []uint64{0, 1}, 127 intervals: "[[1 1]]", 128 replies: []mockps.SyncReply{ 129 {Bin: 1, Start: 1, Topmost: 1, Peer: addr}, 130 {Bin: 1, Start: 1, Topmost: 1, Peer: addr}, 131 }, 132 }, 133 { 134 name: "0, 10 - calls 1-10", 135 cursors: []uint64{0, 10}, 136 intervals: "[[1 11]]", 137 replies: []mockps.SyncReply{ 138 {Bin: 1, Start: 1, Topmost: 10, Peer: addr}, 139 {Bin: 1, Start: 11, Topmost: 11, Peer: addr}, 140 }, 141 }, 142 { 143 name: "0, 50 - 1 call", 144 cursors: []uint64{0, 50}, 145 intervals: "[[1 50]]", 146 replies: []mockps.SyncReply{ 147 {Bin: 1, Start: 1, Topmost: 50, Peer: addr}, 148 }, 149 }, 150 { 151 name: "0, 50 - 2 calls", 152 cursors: []uint64{0, 50}, 153 intervals: "[[1 51]]", 154 replies: []mockps.SyncReply{ 155 {Bin: 1, Start: 1, Topmost: 50, Peer: addr}, 156 {Bin: 1, Start: 51, Topmost: 51, Peer: addr}, 157 }, 158 }, 159 { 160 name: "1,100 - 2 calls", 161 cursors: []uint64{130, 100}, 162 intervals: "[[1 100]]", 163 replies: []mockps.SyncReply{ 164 {Bin: 1, Start: 1, Topmost: 50, Peer: addr}, 165 {Bin: 1, Start: 51, Topmost: 100, Peer: addr}, 166 }, 167 }, 168 { 169 name: "1,200 - 4 calls", 170 cursors: []uint64{200, 200}, 171 intervals: "[[1 200]]", 172 replies: []mockps.SyncReply{ 173 {Bin: 1, Start: 1, Topmost: 1, Peer: addr}, 174 {Bin: 1, Start: 2, Topmost: 100, Peer: addr}, 175 {Bin: 1, Start: 101, Topmost: 150, Peer: addr}, 176 {Bin: 1, Start: 151, Topmost: 200, Peer: addr}, 177 }, 178 }, 179 } { 180 tc := tc 181 t.Run(tc.name, func(t *testing.T) { 182 t.Parallel() 183 184 _, st, kad, pullsync := newPuller(t, opts{ 185 kad: []kadMock.Option{ 186 kadMock.WithEachPeerRevCalls( 187 kadMock.AddrTuple{Addr: addr, PO: 1}, 188 ), 189 }, 190 pullSync: []mockps.Option{mockps.WithCursors(tc.cursors, 0), mockps.WithReplies(tc.replies...)}, 191 bins: 2, 192 rs: resMock.NewReserve(resMock.WithRadius(1)), 193 }) 194 195 time.Sleep(100 * time.Millisecond) 196 kad.Trigger() 197 waitSyncCalledBins(t, pullsync, addr, 1) 198 waitSyncStart(t, pullsync, addr, tc.replies[len(tc.replies)-1].Start) 199 time.Sleep(100 * time.Millisecond) 200 checkIntervals(t, st, addr, tc.intervals, 1) 201 }) 202 } 203 } 204 205 func TestPeerDisconnected(t *testing.T) { 206 t.Parallel() 207 208 cursors := []uint64{0, 0, 0, 0, 0} 209 addr := swarm.RandAddress(t) 210 211 p, _, kad, pullsync := newPuller(t, opts{ 212 kad: []kadMock.Option{ 213 kadMock.WithEachPeerRevCalls( 214 kadMock.AddrTuple{Addr: addr, PO: 1}, 215 ), 216 }, 217 pullSync: []mockps.Option{mockps.WithCursors(cursors, 0)}, 218 bins: 5, 219 rs: resMock.NewReserve(resMock.WithRadius(2)), 220 }) 221 222 time.Sleep(100 * time.Millisecond) 223 kad.Trigger() 224 waitCursorsCalled(t, pullsync, addr) 225 if !p.IsSyncing(addr) { 226 t.Fatalf("peer is not syncing but should") 227 } 228 kad.ResetPeers() 229 kad.Trigger() 230 time.Sleep(50 * time.Millisecond) 231 if p.IsSyncing(addr) { 232 t.Fatalf("peer is syncing but shouldn't") 233 } 234 } 235 236 func TestEpochReset(t *testing.T) { 237 t.Parallel() 238 239 cursors := []uint64{0, 50} 240 241 beforeEpoch := 900 242 afterEpoch := 1000 243 244 addr := swarm.RandAddress(t) 245 s := mock.NewStateStore() 246 247 replies := []mockps.SyncReply{ 248 {Bin: 1, Start: 1, Topmost: 50, Peer: addr}, 249 {Bin: 1, Start: 1, Topmost: 50, Peer: addr}, 250 } 251 252 peer := kadMock.AddrTuple{Addr: addr, PO: 1} 253 254 p, kad, pullsync := newPullerWithState(t, s, opts{ 255 kad: []kadMock.Option{kadMock.WithEachPeerRevCalls(peer)}, 256 pullSync: []mockps.Option{mockps.WithCursors(cursors, uint64(beforeEpoch)), mockps.WithReplies(replies...)}, 257 bins: 2, 258 rs: resMock.NewReserve(resMock.WithRadius(1)), 259 }) 260 261 time.Sleep(100 * time.Millisecond) 262 kad.Trigger() 263 waitSync(t, pullsync, addr) 264 if !p.IsSyncing(addr) { 265 t.Fatalf("peer is not syncing but should") 266 } 267 kad.ResetPeers() 268 kad.Trigger() 269 time.Sleep(100 * time.Millisecond) 270 if p.IsSyncing(addr) { 271 t.Fatalf("peer is syncing but shouldn't") 272 } 273 274 beforeCalls := pullsync.SyncCalls(addr) 275 276 pullsync.SetEpoch(uint64(afterEpoch)) 277 pullsync.ResetCalls(addr) 278 279 kad.AddRevPeers(peer) 280 kad.Trigger() 281 waitSync(t, pullsync, addr) 282 283 afterCalls := pullsync.SyncCalls(addr) 284 285 // after resetting the epoch, the peer will resync all intervals again. 286 // Hence why the sync calls from before and now should be the same. 287 if diff := cmp.Diff(beforeCalls, afterCalls); diff != "" { 288 t.Fatalf("invalid calls (+want -have):\n%s", diff) 289 } 290 } 291 292 func TestBinReset(t *testing.T) { 293 t.Parallel() 294 295 var ( 296 addr = swarm.RandAddress(t) 297 cursors = []uint64{1000, 1000, 1000} 298 ) 299 300 _, s, kad, pullsync := newPuller(t, opts{ 301 kad: []kadMock.Option{ 302 kadMock.WithEachPeerRevCalls( 303 kadMock.AddrTuple{Addr: addr, PO: 1}, 304 ), 305 }, 306 pullSync: []mockps.Option{mockps.WithCursors(cursors, 0), mockps.WithReplies(mockps.SyncReply{Bin: 1, Start: 1, Topmost: 1, Peer: addr})}, 307 bins: 3, 308 rs: resMock.NewReserve(resMock.WithRadius(2)), 309 }) 310 311 time.Sleep(100 * time.Millisecond) 312 313 kad.Trigger() 314 315 waitCursorsCalled(t, pullsync, addr) 316 waitSync(t, pullsync, addr) 317 318 kad.ResetPeers() 319 kad.Trigger() 320 time.Sleep(100 * time.Millisecond) 321 322 if err := s.Get(fmt.Sprintf("sync|001|%s", addr.ByteString()), nil); !errors.Is(err, storage.ErrNotFound) { 323 t.Fatalf("got error %v, want %v", err, storage.ErrNotFound) 324 } 325 326 if err := s.Get(fmt.Sprintf("sync|000|%s", addr.ByteString()), nil); !errors.Is(err, storage.ErrNotFound) { 327 t.Fatalf("got error %v, want %v", err, storage.ErrNotFound) 328 } 329 } 330 331 func TestRadiusDecreaseNeighbor(t *testing.T) { 332 t.Parallel() 333 334 base := swarm.RandAddress(t) 335 peerAddr := swarm.RandAddressAt(t, base, 2) 336 337 var ( 338 cursors = []uint64{1000, 1000, 1000, 1000} 339 replies = []mockps.SyncReply{ 340 {Bin: 0, Start: 1, Topmost: 1000, Peer: peerAddr}, 341 {Bin: 1, Start: 1, Topmost: 1000, Peer: peerAddr}, 342 {Bin: 2, Start: 1, Topmost: 1000, Peer: peerAddr}, 343 {Bin: 3, Start: 1, Topmost: 1000, Peer: peerAddr}, 344 {Bin: 0, Start: 1, Topmost: 1000, Peer: peerAddr}, 345 {Bin: 1, Start: 1, Topmost: 1000, Peer: peerAddr}, 346 } 347 ) 348 349 // at first, sync all bins 350 rs := resMock.NewReserve(resMock.WithRadius(0)) 351 352 _, _, kad, pullsync := newPulleAddr(t, base, opts{ 353 kad: []kadMock.Option{ 354 kadMock.WithEachPeerRevCalls( 355 kadMock.AddrTuple{Addr: peerAddr, PO: 2}, 356 ), 357 }, 358 pullSync: []mockps.Option{mockps.WithCursors(cursors, 0), mockps.WithReplies(replies...)}, 359 bins: 4, 360 rs: rs, 361 }) 362 363 waitSyncCalledBins(t, pullsync, peerAddr, 0, 1, 2, 3) 364 365 // sync all bins >= 2, as this peer is still within depth 366 rs.SetStorageRadius(2) 367 kad.Trigger() 368 time.Sleep(time.Millisecond * 250) 369 370 // peer is still within depth, resync bins < 2 371 pullsync.ResetCalls(swarm.ZeroAddress) 372 rs.SetStorageRadius(0) 373 kad.Trigger() 374 time.Sleep(time.Millisecond * 250) 375 376 waitSyncCalledBins(t, pullsync, peerAddr, 0, 1) 377 } 378 379 func TestRadiusDecreaseNonNeighbor(t *testing.T) { 380 t.Parallel() 381 382 base := swarm.RandAddress(t) 383 peerAddr := swarm.RandAddressAt(t, base, 1) 384 385 var ( 386 cursors = []uint64{1000, 1000, 1000, 1000} 387 replies = []mockps.SyncReply{ 388 {Bin: 0, Start: 1, Topmost: 1000, Peer: peerAddr}, 389 {Bin: 1, Start: 1, Topmost: 1000, Peer: peerAddr}, 390 {Bin: 2, Start: 1, Topmost: 1000, Peer: peerAddr}, 391 {Bin: 3, Start: 1, Topmost: 1000, Peer: peerAddr}, 392 {Bin: 0, Start: 1, Topmost: 1000, Peer: peerAddr}, 393 {Bin: 1, Start: 1, Topmost: 1000, Peer: peerAddr}, 394 {Bin: 2, Start: 1, Topmost: 1000, Peer: peerAddr}, 395 {Bin: 3, Start: 1, Topmost: 1000, Peer: peerAddr}, 396 } 397 ) 398 399 // at first, sync all bins 400 rs := resMock.NewReserve(resMock.WithRadius(0)) 401 402 _, _, kad, pullsync := newPulleAddr(t, base, opts{ 403 kad: []kadMock.Option{ 404 kadMock.WithEachPeerRevCalls( 405 kadMock.AddrTuple{Addr: peerAddr, PO: 2}, 406 ), 407 }, 408 pullSync: []mockps.Option{mockps.WithCursors(cursors, 0), mockps.WithReplies(replies...)}, 409 bins: 4, 410 rs: rs, 411 }) 412 413 waitSyncCalledBins(t, pullsync, peerAddr, 0, 1, 2, 3) 414 415 // syncs bin 2 only as this peer is out of depth 416 rs.SetStorageRadius(3) 417 kad.Trigger() 418 time.Sleep(time.Millisecond * 250) 419 420 // peer is now within depth, resync all bins 421 pullsync.ResetCalls(swarm.ZeroAddress) 422 rs.SetStorageRadius(0) 423 kad.Trigger() 424 time.Sleep(time.Millisecond * 250) 425 426 waitSyncCalledBins(t, pullsync, peerAddr, 0, 1, 2, 3) 427 } 428 429 func TestRadiusIncrease(t *testing.T) { 430 t.Parallel() 431 432 var ( 433 addr = swarm.RandAddress(t) 434 cursors = []uint64{1000, 1000, 1000, 1000} 435 replies = []mockps.SyncReply{ 436 {Bin: 1, Start: 1, Topmost: 1000, Peer: addr}, 437 {Bin: 2, Start: 1, Topmost: 1000, Peer: addr}, 438 {Bin: 3, Start: 1, Topmost: 1000, Peer: addr}, 439 {Bin: 1, Start: 1, Topmost: 1000, Peer: addr}, 440 } 441 ) 442 443 rs := resMock.NewReserve(resMock.WithRadius(1)) 444 445 p, _, kad, pullsync := newPuller(t, opts{ 446 kad: []kadMock.Option{ 447 kadMock.WithEachPeerRevCalls( 448 kadMock.AddrTuple{Addr: addr, PO: 1}, 449 ), 450 }, 451 pullSync: []mockps.Option{mockps.WithCursors(cursors, 0), mockps.WithReplies(replies...)}, 452 bins: 4, 453 rs: rs, 454 }) 455 456 time.Sleep(100 * time.Millisecond) 457 kad.Trigger() 458 waitSyncCalledBins(t, pullsync, addr, 2, 3) 459 460 pullsync.ResetCalls(swarm.ZeroAddress) 461 rs.SetStorageRadius(2) 462 kad.Trigger() 463 time.Sleep(100 * time.Millisecond) 464 if !p.IsBinSyncing(addr, 1) { 465 t.Fatalf("peer is not syncing but should") 466 } 467 if p.IsBinSyncing(addr, 2) { 468 t.Fatalf("peer is syncing but shouldn't") 469 } 470 } 471 472 // TestContinueSyncing adds a single peer with PO 0 to hist and live sync only a peer 473 // to test that when Sync returns an error, the syncing does not terminate. 474 func TestContinueSyncing(t *testing.T) { 475 t.Parallel() 476 477 var ( 478 addr = swarm.RandAddress(t) 479 ) 480 481 _, _, kad, pullsync := newPuller(t, opts{ 482 kad: []kadMock.Option{ 483 kadMock.WithEachPeerRevCalls(kadMock.AddrTuple{Addr: addr, PO: 0}), 484 }, 485 pullSync: []mockps.Option{ 486 mockps.WithCursors([]uint64{1}, 0), 487 mockps.WithSyncError(errors.New("sync error")), 488 mockps.WithReplies( 489 mockps.SyncReply{Start: 1, Topmost: 2, Peer: addr}, 490 mockps.SyncReply{Start: 1, Topmost: 2, Peer: addr}, 491 mockps.SyncReply{Start: 1, Topmost: 2, Peer: addr}, 492 ), 493 }, 494 bins: 1, 495 rs: resMock.NewReserve(resMock.WithRadius(0)), 496 497 syncSleepDur: time.Millisecond * 10, 498 }) 499 500 time.Sleep(100 * time.Millisecond) 501 kad.Trigger() 502 503 err := spinlock.Wait(time.Second, func() bool { 504 return len(pullsync.SyncCalls(addr)) == 1 505 }) 506 if err != nil { 507 t.Fatal(err) 508 } 509 } 510 511 func TestPeerGone(t *testing.T) { 512 t.Parallel() 513 514 var ( 515 addr = swarm.RandAddress(t) 516 replies = []mockps.SyncReply{ 517 {Bin: 0, Start: 1, Topmost: 1001, Peer: addr}, 518 {Bin: 1, Start: 1, Topmost: 1001, Peer: addr}} 519 ) 520 521 p, _, kad, pullsync := newPuller(t, opts{ 522 kad: []kadMock.Option{ 523 kadMock.WithEachPeerRevCalls(kadMock.AddrTuple{Addr: addr, PO: 1}), 524 }, 525 pullSync: []mockps.Option{ 526 mockps.WithCursors([]uint64{1, 1}, 0), 527 mockps.WithReplies(replies...), 528 }, 529 bins: 2, 530 rs: resMock.NewReserve(resMock.WithRadius(1)), 531 532 syncSleepDur: time.Millisecond * 10, 533 }) 534 535 time.Sleep(100 * time.Millisecond) 536 kad.Trigger() 537 time.Sleep(100 * time.Millisecond) 538 539 beforeCalls := pullsync.SyncCalls(addr) 540 541 if len(beforeCalls) != 1 { 542 t.Fatalf("unexpected amount of calls, got %d, want 1", len(beforeCalls)) 543 } 544 545 kad.ResetPeers() 546 kad.Trigger() 547 time.Sleep(100 * time.Millisecond) 548 549 afterCalls := pullsync.SyncCalls(addr) 550 551 if len(beforeCalls) != len(afterCalls) { 552 t.Fatalf("unexpected new calls to sync interval, expected 0, got %d", len(afterCalls)-len(beforeCalls)) 553 } 554 555 if p.IsSyncing(addr) { 556 t.Fatalf("peer is syncing but shouldn't") 557 } 558 } 559 560 func checkIntervals(t *testing.T, s storage.StateStorer, addr swarm.Address, expInterval string, bin uint8) { 561 t.Helper() 562 key := puller.PeerIntervalKey(addr, bin) 563 i := &intervalstore.Intervals{} 564 err := s.Get(key, i) 565 if err != nil { 566 t.Fatalf("error getting interval for bin %d: %v", bin, err) 567 } 568 if v := i.String(); v != expInterval { 569 t.Fatalf("got unexpected interval: %s, want %s bin %d", v, expInterval, bin) 570 } 571 } 572 573 // waitCursorsCalled waits until GetCursors are called on the given address. 574 func waitCursorsCalled(t *testing.T, ps *mockps.PullSyncMock, addr swarm.Address) { 575 t.Helper() 576 577 err := spinlock.Wait(time.Second, func() bool { 578 return ps.CursorsCalls(addr) 579 }) 580 if err != nil { 581 t.Fatal("timed out waiting for cursors") 582 } 583 } 584 585 // waitSync waits until SyncInterval is called on the address given. 586 func waitSync(t *testing.T, ps *mockps.PullSyncMock, addr swarm.Address) { 587 t.Helper() 588 589 err := spinlock.Wait(time.Second, func() bool { 590 v := ps.SyncCalls(addr) 591 return len(v) > 0 592 }) 593 if err != nil { 594 t.Fatal("timed out waiting for sync") 595 } 596 } 597 598 // waitSyncCalled waits until SyncInterval is called on the address given. 599 func waitSyncStart(t *testing.T, ps *mockps.PullSyncMock, addr swarm.Address, start uint64) { 600 t.Helper() 601 602 err := spinlock.Wait(time.Second, func() bool { 603 calls := ps.SyncCalls(addr) 604 for _, c := range calls { 605 if c.Start == start { 606 return true 607 } 608 } 609 return false 610 }) 611 if err != nil { 612 t.Fatal("timed out waiting for sync") 613 } 614 } 615 616 func waitSyncCalledBins(t *testing.T, ps *mockps.PullSyncMock, addr swarm.Address, bins ...uint8) { 617 t.Helper() 618 619 err := spinlock.Wait(time.Second, func() bool { 620 calls := ps.SyncCalls(addr) 621 nextCall: 622 for _, b := range bins { 623 for _, c := range calls { 624 if c.Bin == b { 625 continue nextCall 626 } 627 } 628 return false 629 } 630 return true 631 }) 632 if err != nil { 633 t.Fatal("timed out waiting for sync") 634 } 635 } 636 637 type opts struct { 638 pullSync []mockps.Option 639 kad []kadMock.Option 640 rs *resMock.ReserveStore 641 bins uint8 642 syncSleepDur time.Duration 643 } 644 645 func newPuller(t *testing.T, ops opts) (*puller.Puller, storage.StateStorer, *kadMock.Mock, *mockps.PullSyncMock) { 646 t.Helper() 647 648 logger := log.Noop 649 650 s, err := leveldb.NewStateStore(t.TempDir(), logger) 651 if err != nil { 652 t.Fatal(err) 653 } 654 655 ps := mockps.NewPullSync(ops.pullSync...) 656 kad := kadMock.NewMockKademlia(ops.kad...) 657 658 o := puller.Options{ 659 Bins: ops.bins, 660 } 661 p := puller.New(swarm.RandAddress(t), s, kad, ops.rs, ps, nil, logger, o) 662 p.Start(context.Background()) 663 664 testutil.CleanupCloser(t, p, s) 665 666 return p, s, kad, ps 667 } 668 669 func newPulleAddr(t *testing.T, addr swarm.Address, ops opts) (*puller.Puller, storage.StateStorer, *kadMock.Mock, *mockps.PullSyncMock) { 670 t.Helper() 671 672 logger := log.Noop 673 674 s, err := leveldb.NewStateStore(t.TempDir(), logger) 675 if err != nil { 676 t.Fatal(err) 677 } 678 679 ps := mockps.NewPullSync(ops.pullSync...) 680 kad := kadMock.NewMockKademlia(ops.kad...) 681 682 o := puller.Options{ 683 Bins: ops.bins, 684 } 685 p := puller.New(addr, s, kad, ops.rs, ps, nil, logger, o) 686 p.Start(context.Background()) 687 688 testutil.CleanupCloser(t, p, s) 689 690 return p, s, kad, ps 691 } 692 693 func newPullerWithState(t *testing.T, s storage.StateStorer, ops opts) (*puller.Puller, *kadMock.Mock, *mockps.PullSyncMock) { 694 t.Helper() 695 696 ps := mockps.NewPullSync(ops.pullSync...) 697 kad := kadMock.NewMockKademlia(ops.kad...) 698 logger := log.Noop 699 700 o := puller.Options{ 701 Bins: ops.bins, 702 } 703 p := puller.New(swarm.RandAddress(t), s, kad, ops.rs, ps, nil, logger, o) 704 p.Start(context.Background()) 705 706 testutil.CleanupCloser(t, p) 707 708 return p, kad, ps 709 }