github.com/ethersphere/bee/v2@v2.2.0/pkg/topology/mock/mock.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  	"maps"
    10  	"sync"
    11  	"time"
    12  
    13  	"github.com/ethersphere/bee/v2/pkg/p2p"
    14  	"github.com/ethersphere/bee/v2/pkg/swarm"
    15  	"github.com/ethersphere/bee/v2/pkg/topology"
    16  )
    17  
    18  type mock struct {
    19  	peers           []swarm.Address
    20  	depth           uint8
    21  	closestPeer     swarm.Address
    22  	closestPeerErr  error
    23  	peersErr        error
    24  	addPeersErr     error
    25  	isWithinFunc    func(c swarm.Address) bool
    26  	marshalJSONFunc func() ([]byte, error)
    27  	mtx             sync.Mutex
    28  	health          map[string]bool
    29  }
    30  
    31  var _ topology.Driver = (*mock)(nil)
    32  
    33  func WithPeers(peers ...swarm.Address) Option {
    34  	return optionFunc(func(d *mock) {
    35  		d.peers = peers
    36  	})
    37  }
    38  
    39  func WithAddPeersErr(err error) Option {
    40  	return optionFunc(func(d *mock) {
    41  		d.addPeersErr = err
    42  	})
    43  }
    44  
    45  func WithNeighborhoodDepth(dd uint8) Option {
    46  	return optionFunc(func(d *mock) {
    47  		d.depth = dd
    48  	})
    49  }
    50  
    51  func WithClosestPeer(addr swarm.Address) Option {
    52  	return optionFunc(func(d *mock) {
    53  		d.closestPeer = addr
    54  	})
    55  }
    56  
    57  func WithClosestPeerErr(err error) Option {
    58  	return optionFunc(func(d *mock) {
    59  		d.closestPeerErr = err
    60  	})
    61  }
    62  
    63  func WithMarshalJSONFunc(f func() ([]byte, error)) Option {
    64  	return optionFunc(func(d *mock) {
    65  		d.marshalJSONFunc = f
    66  	})
    67  }
    68  
    69  func WithIsWithinFunc(f func(swarm.Address) bool) Option {
    70  	return optionFunc(func(d *mock) {
    71  		d.isWithinFunc = f
    72  	})
    73  }
    74  
    75  func NewTopologyDriver(opts ...Option) *mock {
    76  	d := new(mock)
    77  	for _, o := range opts {
    78  		o.apply(d)
    79  	}
    80  
    81  	d.health = map[string]bool{}
    82  
    83  	return d
    84  }
    85  
    86  func (d *mock) AddPeers(addrs ...swarm.Address) {
    87  	d.mtx.Lock()
    88  	defer d.mtx.Unlock()
    89  
    90  	d.peers = append(d.peers, addrs...)
    91  }
    92  
    93  func (d *mock) Connected(ctx context.Context, peer p2p.Peer, _ bool) error {
    94  	d.AddPeers(peer.Address)
    95  	return nil
    96  }
    97  
    98  func (d *mock) Disconnected(peer p2p.Peer) {
    99  	d.mtx.Lock()
   100  	defer d.mtx.Unlock()
   101  
   102  	d.peers = swarm.RemoveAddress(d.peers, peer.Address)
   103  }
   104  
   105  func (d *mock) Announce(_ context.Context, _ swarm.Address, _ bool) error {
   106  	return nil
   107  }
   108  
   109  func (d *mock) AnnounceTo(_ context.Context, _, _ swarm.Address, _ bool) error {
   110  	return nil
   111  }
   112  
   113  func (d *mock) UpdatePeerHealth(peer swarm.Address, health bool, pingDur time.Duration) {
   114  	d.mtx.Lock()
   115  	defer d.mtx.Unlock()
   116  	d.health[peer.ByteString()] = health
   117  }
   118  
   119  func (d *mock) PeersHealth() map[string]bool {
   120  	d.mtx.Lock()
   121  	defer d.mtx.Unlock()
   122  	return maps.Clone(d.health)
   123  }
   124  
   125  func (d *mock) Peers() []swarm.Address {
   126  	return d.peers
   127  }
   128  
   129  func (d *mock) ClosestPeer(addr swarm.Address, wantSelf bool, _ topology.Select, skipPeers ...swarm.Address) (peerAddr swarm.Address, err error) {
   130  	if len(skipPeers) == 0 {
   131  		if d.closestPeerErr != nil {
   132  			return d.closestPeer, d.closestPeerErr
   133  		}
   134  		if !d.closestPeer.Equal(swarm.ZeroAddress) {
   135  			return d.closestPeer, nil
   136  		}
   137  	}
   138  
   139  	d.mtx.Lock()
   140  	defer d.mtx.Unlock()
   141  
   142  	if len(d.peers) == 0 {
   143  		return peerAddr, topology.ErrNotFound
   144  	}
   145  
   146  	skipPeer := false
   147  	for _, p := range d.peers {
   148  		for _, a := range skipPeers {
   149  			if a.Equal(p) {
   150  				skipPeer = true
   151  				break
   152  			}
   153  		}
   154  		if skipPeer {
   155  			skipPeer = false
   156  			continue
   157  		}
   158  
   159  		if peerAddr.IsZero() {
   160  			peerAddr = p
   161  		}
   162  
   163  		if closer, _ := p.Closer(addr, peerAddr); closer {
   164  			peerAddr = p
   165  		}
   166  	}
   167  
   168  	if peerAddr.IsZero() {
   169  		if wantSelf {
   170  			return peerAddr, topology.ErrWantSelf
   171  		} else {
   172  			return peerAddr, topology.ErrNotFound
   173  		}
   174  	}
   175  
   176  	return peerAddr, nil
   177  }
   178  
   179  func (m *mock) IsReachable() bool {
   180  	return true
   181  }
   182  
   183  func (d *mock) SubscribeTopologyChange() (c <-chan struct{}, unsubscribe func()) {
   184  	return c, unsubscribe
   185  }
   186  
   187  func (m *mock) NeighborhoodDepth() uint8 {
   188  	return m.depth
   189  }
   190  
   191  func (m *mock) SetStorageRadius(uint8) {}
   192  
   193  // EachConnectedPeer implements topology.PeerIterator interface.
   194  func (d *mock) EachConnectedPeer(f topology.EachPeerFunc, _ topology.Select) (err error) {
   195  	d.mtx.Lock()
   196  	defer d.mtx.Unlock()
   197  
   198  	if d.peersErr != nil {
   199  		return d.peersErr
   200  	}
   201  
   202  	for i, p := range d.peers {
   203  		_, _, err = f(p, uint8(i))
   204  		if err != nil {
   205  			return
   206  		}
   207  	}
   208  
   209  	return nil
   210  }
   211  
   212  // EachConnectedPeerRev implements topology.PeerIterator interface.
   213  func (d *mock) EachConnectedPeerRev(f topology.EachPeerFunc, _ topology.Select) (err error) {
   214  	d.mtx.Lock()
   215  	defer d.mtx.Unlock()
   216  
   217  	for i := len(d.peers) - 1; i >= 0; i-- {
   218  		_, _, err = f(d.peers[i], uint8(i))
   219  		if err != nil {
   220  			return
   221  		}
   222  	}
   223  
   224  	return nil
   225  }
   226  
   227  func (d *mock) Snapshot() *topology.KadParams {
   228  	return new(topology.KadParams)
   229  }
   230  
   231  func (d *mock) Halt()        {}
   232  func (d *mock) Close() error { return nil }
   233  
   234  type Option interface {
   235  	apply(*mock)
   236  }
   237  
   238  type optionFunc func(*mock)
   239  
   240  func (f optionFunc) apply(r *mock) { f(r) }