libp2p_test.go 4.12 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package libp2p_test

import (
8
	"bytes"
9
	"context"
10
	"crypto/ecdsa"
11
	"io/ioutil"
12
	"sort"
13
	"testing"
14
	"time"
15

16
	"github.com/ethereum/go-ethereum/common"
17
	"github.com/ethersphere/bee/pkg/addressbook"
18 19 20 21
	"github.com/ethersphere/bee/pkg/crypto"
	"github.com/ethersphere/bee/pkg/logging"
	"github.com/ethersphere/bee/pkg/p2p"
	"github.com/ethersphere/bee/pkg/p2p/libp2p"
22
	"github.com/ethersphere/bee/pkg/statestore/mock"
23
	"github.com/ethersphere/bee/pkg/swarm"
24
	"github.com/ethersphere/bee/pkg/topology/lightnode"
Janos Guljas's avatar
Janos Guljas committed
25
	"github.com/multiformats/go-multiaddr"
26 27
)

28 29 30 31
type libp2pServiceOpts struct {
	Logger      logging.Logger
	Addressbook addressbook.Interface
	PrivateKey  *ecdsa.PrivateKey
32
	MockPeerKey *ecdsa.PrivateKey
33
	libp2pOpts  libp2p.Options
34
	lightNodes  *lightnode.Container
35 36
}

37
// newService constructs a new libp2p service.
38
func newService(t *testing.T, networkID uint64, o libp2pServiceOpts) (s *libp2p.Service, overlay swarm.Address) {
39 40
	t.Helper()

41
	swarmKey, err := crypto.GenerateSecp256k1Key()
42 43
	if err != nil {
		t.Fatal(err)
44 45
	}

46 47 48 49
	trx := common.HexToHash("0x1").Bytes()
	blockHash := common.HexToHash("0x2").Bytes()

	overlay, err = crypto.NewOverlayAddress(swarmKey.PublicKey, networkID, blockHash)
50 51 52
	if err != nil {
		t.Fatal(err)
	}
53 54

	addr := ":0"
55 56 57 58 59

	if o.Logger == nil {
		o.Logger = logging.New(ioutil.Discard, 0)
	}

60
	statestore := mock.NewStateStore()
61
	if o.Addressbook == nil {
62
		o.Addressbook = addressbook.New(statestore)
acud's avatar
acud committed
63
	}
64

65 66 67 68 69 70 71 72 73
	if o.PrivateKey == nil {
		libp2pKey, err := crypto.GenerateSecp256k1Key()
		if err != nil {
			t.Fatal(err)
		}

		o.PrivateKey = libp2pKey
	}

74
	ctx, cancel := context.WithCancel(context.Background())
75

76 77 78
	if o.lightNodes == nil {
		o.lightNodes = lightnode.NewContainer(overlay)
	}
79
	opts := o.libp2pOpts
80
	opts.Transaction = trx
81

82 83 84
	senderMatcher := &MockSenderMatcher{
		BlockHash: blockHash,
	}
85

86
	s, err = libp2p.New(ctx, crypto.NewDefaultSigner(swarmKey), networkID, overlay, addr, o.Addressbook, statestore, o.lightNodes, senderMatcher, o.Logger, nil, opts)
87 88 89
	if err != nil {
		t.Fatal(err)
	}
90
	s.Ready()
91

92
	t.Cleanup(func() {
93 94
		cancel()
		s.Close()
95 96
	})
	return s, overlay
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
}

// expectPeers validates that peers with addresses are connected.
func expectPeers(t *testing.T, s *libp2p.Service, addrs ...swarm.Address) {
	t.Helper()

	peers := s.Peers()

	if len(peers) != len(addrs) {
		t.Fatalf("got peers %v, want %v", len(peers), len(addrs))
	}

	sort.Slice(addrs, func(i, j int) bool {
		return bytes.Compare(addrs[i].Bytes(), addrs[j].Bytes()) == -1
	})
	sort.Slice(peers, func(i, j int) bool {
		return bytes.Compare(peers[i].Address.Bytes(), peers[j].Address.Bytes()) == -1
	})

	for i, got := range peers {
		want := addrs[i]
		if !got.Address.Equal(want) {
			t.Errorf("got %v peer %s, want %s", i, got.Address, want)
		}
	}
}

// expectPeersEventually validates that peers with addresses are connected with
125
// retries. It is supposed to be used to validate asynchronous connecting on the
126 127 128 129 130 131 132 133 134 135
// peer that is connected to.
func expectPeersEventually(t *testing.T, s *libp2p.Service, addrs ...swarm.Address) {
	t.Helper()

	var peers []p2p.Peer
	for i := 0; i < 100; i++ {
		peers = s.Peers()
		if len(peers) == len(addrs) {
			break
		}
136
		time.Sleep(10 * time.Millisecond)
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
	}

	if len(peers) != len(addrs) {
		t.Fatalf("got peers %v, want %v", len(peers), len(addrs))
	}

	sort.Slice(addrs, func(i, j int) bool {
		return bytes.Compare(addrs[i].Bytes(), addrs[j].Bytes()) == -1
	})
	sort.Slice(peers, func(i, j int) bool {
		return bytes.Compare(peers[i].Address.Bytes(), peers[j].Address.Bytes()) == -1
	})

	for i, got := range peers {
		want := addrs[i]
		if !got.Address.Equal(want) {
			t.Errorf("got %v peer %s, want %s", i, got.Address, want)
		}
	}
156
}
Janos Guljas's avatar
Janos Guljas committed
157 158 159 160 161 162 163 164 165 166

func serviceUnderlayAddress(t *testing.T, s *libp2p.Service) multiaddr.Multiaddr {
	t.Helper()

	addrs, err := s.Addresses()
	if err != nil {
		t.Fatal(err)
	}
	return addrs[0]
}
167

168 169 170
type MockSenderMatcher struct {
	BlockHash []byte
}
171

172 173
func (m MockSenderMatcher) Matches(context.Context, []byte, uint64, swarm.Address) ([]byte, error) {
	return m.BlockHash, nil
174
}