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) }