github.com/ethersphere/bee/v2@v2.2.0/pkg/p2p/libp2p/libp2p_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 libp2p_test 6 7 import ( 8 "bytes" 9 "context" 10 "crypto/ecdsa" 11 "sort" 12 "testing" 13 "time" 14 15 "github.com/ethereum/go-ethereum/common" 16 "github.com/ethersphere/bee/v2/pkg/addressbook" 17 "github.com/ethersphere/bee/v2/pkg/crypto" 18 "github.com/ethersphere/bee/v2/pkg/log" 19 "github.com/ethersphere/bee/v2/pkg/p2p" 20 "github.com/ethersphere/bee/v2/pkg/p2p/libp2p" 21 "github.com/ethersphere/bee/v2/pkg/spinlock" 22 "github.com/ethersphere/bee/v2/pkg/statestore/mock" 23 "github.com/ethersphere/bee/v2/pkg/swarm" 24 "github.com/ethersphere/bee/v2/pkg/topology/lightnode" 25 "github.com/ethersphere/bee/v2/pkg/util/testutil" 26 "github.com/multiformats/go-multiaddr" 27 ) 28 29 type libp2pServiceOpts struct { 30 Logger log.Logger 31 Addressbook addressbook.Interface 32 PrivateKey *ecdsa.PrivateKey 33 MockPeerKey *ecdsa.PrivateKey 34 libp2pOpts libp2p.Options 35 lightNodes *lightnode.Container 36 notifier p2p.PickyNotifier 37 } 38 39 // newService constructs a new libp2p service. 40 func newService(t *testing.T, networkID uint64, o libp2pServiceOpts) (s *libp2p.Service, overlay swarm.Address) { 41 t.Helper() 42 43 swarmKey, err := crypto.GenerateSecp256k1Key() 44 if err != nil { 45 t.Fatal(err) 46 } 47 48 nonce := common.HexToHash("0x1").Bytes() 49 50 overlay, err = crypto.NewOverlayAddress(swarmKey.PublicKey, networkID, nonce) 51 if err != nil { 52 t.Fatal(err) 53 } 54 55 addr := ":0" 56 57 if o.Logger == nil { 58 o.Logger = log.Noop 59 } 60 61 statestore := mock.NewStateStore() 62 if o.Addressbook == nil { 63 o.Addressbook = addressbook.New(statestore) 64 } 65 66 if o.PrivateKey == nil { 67 libp2pKey, err := crypto.GenerateSecp256k1Key() 68 if err != nil { 69 t.Fatal(err) 70 } 71 72 o.PrivateKey = libp2pKey 73 } 74 75 ctx, cancel := context.WithCancel(context.Background()) 76 t.Cleanup(cancel) 77 78 if o.lightNodes == nil { 79 o.lightNodes = lightnode.NewContainer(overlay) 80 } 81 opts := o.libp2pOpts 82 opts.Nonce = nonce 83 84 s, err = libp2p.New(ctx, crypto.NewDefaultSigner(swarmKey), networkID, overlay, addr, o.Addressbook, statestore, o.lightNodes, o.Logger, nil, opts) 85 if err != nil { 86 t.Fatal(err) 87 } 88 testutil.CleanupCloser(t, s) 89 90 if o.notifier != nil { 91 s.SetPickyNotifier(o.notifier) 92 } 93 94 _ = s.Ready() 95 96 return s, overlay 97 } 98 99 // expectPeers validates that peers with addresses are connected. 100 func expectPeers(t *testing.T, s *libp2p.Service, addrs ...swarm.Address) { 101 t.Helper() 102 103 peers := s.Peers() 104 105 if len(peers) != len(addrs) { 106 t.Fatalf("got peers %v, want %v", len(peers), len(addrs)) 107 } 108 109 sort.Slice(addrs, func(i, j int) bool { 110 return bytes.Compare(addrs[i].Bytes(), addrs[j].Bytes()) == -1 111 }) 112 sort.Slice(peers, func(i, j int) bool { 113 return bytes.Compare(peers[i].Address.Bytes(), peers[j].Address.Bytes()) == -1 114 }) 115 116 for i, got := range peers { 117 want := addrs[i] 118 if !got.Address.Equal(want) { 119 t.Errorf("got %v peer %s, want %s", i, got.Address, want) 120 } 121 } 122 } 123 124 // expectPeersEventually validates that peers with addresses are connected with 125 // retries. It is supposed to be used to validate asynchronous connecting on the 126 // peer that is connected to. 127 func expectPeersEventually(t *testing.T, s *libp2p.Service, addrs ...swarm.Address) { 128 t.Helper() 129 130 var peers []p2p.Peer 131 err := spinlock.Wait(time.Second, func() bool { 132 peers = s.Peers() 133 return len(peers) == len(addrs) 134 135 }) 136 if err != nil { 137 t.Fatalf("timed out waiting for peers, got %v, want %v", len(peers), len(addrs)) 138 } 139 140 sort.Slice(addrs, func(i, j int) bool { 141 return bytes.Compare(addrs[i].Bytes(), addrs[j].Bytes()) == -1 142 }) 143 sort.Slice(peers, func(i, j int) bool { 144 return bytes.Compare(peers[i].Address.Bytes(), peers[j].Address.Bytes()) == -1 145 }) 146 147 for i, got := range peers { 148 want := addrs[i] 149 if !got.Address.Equal(want) { 150 t.Errorf("got %v peer %s, want %s", i, got.Address, want) 151 } 152 } 153 } 154 155 func serviceUnderlayAddress(t *testing.T, s *libp2p.Service) multiaddr.Multiaddr { 156 t.Helper() 157 158 addrs, err := s.Addresses() 159 if err != nil { 160 t.Fatal(err) 161 } 162 return addrs[0] 163 }