github.com/ethersphere/bee/v2@v2.2.0/pkg/pullsync/mock/pullsync.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 mock 6 7 import ( 8 "context" 9 "fmt" 10 "sync" 11 12 "github.com/ethersphere/bee/v2/pkg/pullsync" 13 "github.com/ethersphere/bee/v2/pkg/swarm" 14 ) 15 16 var _ pullsync.Interface = (*PullSyncMock)(nil) 17 18 func WithSyncError(err error) Option { 19 return optionFunc(func(p *PullSyncMock) { 20 p.syncErr = err 21 }) 22 } 23 24 func WithCursors(v []uint64, e uint64) Option { 25 return optionFunc(func(p *PullSyncMock) { 26 p.cursors = v 27 p.epoch = e 28 }) 29 } 30 31 func WithReplies(replies ...SyncReply) Option { 32 return optionFunc(func(p *PullSyncMock) { 33 for _, r := range replies { 34 p.replies[toID(r.Peer, r.Bin, r.Start)] = append(p.replies[toID(r.Peer, r.Bin, r.Start)], r) 35 } 36 }) 37 } 38 39 func toID(a swarm.Address, bin uint8, start uint64) string { 40 return fmt.Sprintf("%s-%d-%d", a, bin, start) 41 } 42 43 type SyncReply struct { 44 Peer swarm.Address 45 Bin uint8 46 Start uint64 47 Topmost uint64 48 Count int 49 } 50 51 type PullSyncMock struct { 52 mtx sync.Mutex 53 syncCalls []SyncReply 54 syncErr error 55 cursors []uint64 56 epoch uint64 57 getCursorsPeers []swarm.Address 58 replies map[string][]SyncReply 59 60 quit chan struct{} 61 } 62 63 func NewPullSync(opts ...Option) *PullSyncMock { 64 s := &PullSyncMock{ 65 quit: make(chan struct{}), 66 replies: make(map[string][]SyncReply), 67 } 68 for _, v := range opts { 69 v.apply(s) 70 } 71 return s 72 } 73 74 func (p *PullSyncMock) Sync(ctx context.Context, peer swarm.Address, bin uint8, start uint64) (topmost uint64, count int, err error) { 75 76 p.mtx.Lock() 77 78 id := toID(peer, bin, start) 79 replies := p.replies[id] 80 81 if len(replies) > 0 { 82 reply := replies[0] 83 p.replies[id] = p.replies[id][1:] 84 p.syncCalls = append(p.syncCalls, reply) 85 p.mtx.Unlock() 86 return reply.Topmost, reply.Count, p.syncErr 87 } 88 p.mtx.Unlock() 89 <-ctx.Done() 90 return 0, 0, ctx.Err() 91 } 92 93 func (p *PullSyncMock) GetCursors(_ context.Context, peer swarm.Address) ([]uint64, uint64, error) { 94 p.mtx.Lock() 95 defer p.mtx.Unlock() 96 p.getCursorsPeers = append(p.getCursorsPeers, peer) 97 return p.cursors, p.epoch, nil 98 } 99 100 func (p *PullSyncMock) ResetCalls(peer swarm.Address) { 101 p.mtx.Lock() 102 defer p.mtx.Unlock() 103 p.syncCalls = nil 104 } 105 106 func (p *PullSyncMock) SyncCalls(peer swarm.Address) (res []SyncReply) { 107 p.mtx.Lock() 108 defer p.mtx.Unlock() 109 110 for _, v := range p.syncCalls { 111 if v.Peer.Equal(peer) { 112 res = append(res, v) 113 } 114 } 115 return res 116 } 117 118 func (p *PullSyncMock) CursorsCalls(peer swarm.Address) bool { 119 p.mtx.Lock() 120 defer p.mtx.Unlock() 121 return swarm.ContainsAddress(p.getCursorsPeers, peer) 122 } 123 124 func (p *PullSyncMock) SetEpoch(epoch uint64) { 125 p.mtx.Lock() 126 defer p.mtx.Unlock() 127 p.epoch = epoch 128 } 129 130 type Option interface { 131 apply(*PullSyncMock) 132 } 133 type optionFunc func(*PullSyncMock) 134 135 func (f optionFunc) apply(r *PullSyncMock) { f(r) }