Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

swarm: add mock net.PacketConn for testing #2443

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions go.mod
Expand Up @@ -59,6 +59,7 @@ require (
golang.org/x/sys v0.10.0
golang.org/x/tools v0.11.0
google.golang.org/protobuf v1.30.0
tailscale.com v1.40.1
)

require (
Expand All @@ -75,7 +76,6 @@ require (
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
Expand All @@ -99,8 +99,8 @@ require (
github.com/opencontainers/runtime-spec v1.0.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/prometheus/common v0.41.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
Expand Down
355 changes: 11 additions & 344 deletions go.sum

Large diffs are not rendered by default.

47 changes: 47 additions & 0 deletions p2p/host/basic/basic_host_test.go
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"net/netip"
"reflect"
"sort"
"strings"
Expand All @@ -22,6 +23,7 @@ import (
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
swarmt "github.com/libp2p/go-libp2p/p2p/net/swarm/testing"
"github.com/libp2p/go-libp2p/p2p/protocol/identify"
"tailscale.com/tstest/natlab"

ma "github.com/multiformats/go-multiaddr"

Expand Down Expand Up @@ -892,5 +894,50 @@ func TestInferWebtransportAddrsFromQuic(t *testing.T) {
})

}
}

func TestAddressDiscovery(t *testing.T) {
inet := &natlab.Network{Name: "internet", Prefix4: netip.MustParsePrefix("1.2.3.0/24")}
type TestHost struct {
*BasicHost
Addr ma.Multiaddr
}
port := 1000
newHost := func(name string) TestHost {
m := &natlab.Machine{Name: name}
mif := m.Attach("eth0", inet)
port++
listenAddr := ma.StringCast(fmt.Sprintf("/ip4/0.0.0.0/udp/%d/quic-v1", port))
publicAddr := ma.StringCast(fmt.Sprintf("/ip4/%s/udp/%d/quic-v1", mif.V4().String(), port))
h, err := NewHost(swarmt.GenSwarm(t, swarmt.OptQUICListenAddress(listenAddr), swarmt.OptUDPTransport(swarmt.UDPTransport(m))), nil)
if err != nil {
t.Fatal(err)
}
return TestHost{BasicHost: h, Addr: publicAddr}
}

var peers []TestHost
for i := 0; i < identify.ActivationThresh; i++ {
h := newHost(fmt.Sprintf("peer-%d", i))
h.Start()
peers = append(peers, h)
}

h := newHost("host")
h.Start()
for _, p := range peers {
ctx := network.WithDialPeerTimeout(context.Background(), 1*time.Second)
h.Peerstore().AddAddr(p.ID(), p.Addr, peerstore.TempAddrTTL)
err := h.Connect(ctx, peer.AddrInfo{ID: p.ID()})
if err != nil {
t.Fatal(err)
}
}

require.Eventually(t,
func() bool {
return ma.Contains(h.Addrs(), h.Addr)
},
5*time.Second,
100*time.Millisecond)
}
46 changes: 43 additions & 3 deletions p2p/net/swarm/testing/testing.go
@@ -1,7 +1,9 @@
package testing

import (
"context"
"crypto/rand"
"net"
"testing"
"time"

Expand All @@ -24,6 +26,7 @@ import (
quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
"github.com/libp2p/go-libp2p/p2p/transport/quicreuse"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
"tailscale.com/tstest/natlab"

ma "github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/require"
Expand All @@ -38,6 +41,8 @@ type config struct {
sk crypto.PrivKey
swarmOpts []swarm.Option
eventBus event.Bus
quicListenAddr ma.Multiaddr
udpTransport quicreuse.UDPTransport
clock
}

Expand Down Expand Up @@ -101,6 +106,18 @@ func OptPeerPrivateKey(sk crypto.PrivKey) Option {
}
}

func OptQUICListenAddress(addr ma.Multiaddr) Option {
return func(_ *testing.T, c *config) {
c.quicListenAddr = addr
}
}

func OptUDPTransport(tr quicreuse.UDPTransport) Option {
return func(_ *testing.T, c *config) {
c.udpTransport = tr
}
}

func EventBus(b event.Bus) Option {
return func(_ *testing.T, c *config) {
c.eventBus = b
Expand Down Expand Up @@ -175,10 +192,11 @@ func GenSwarm(t *testing.T, opts ...Option) *swarm.Swarm {
}
}
if !cfg.disableQUIC {
reuse, err := quicreuse.NewConnManager([32]byte{})
reuse, err := quicreuse.NewConnManager([32]byte{}, quicreuse.WithUDPTransport(cfg.udpTransport))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { reuse.Close() })
quicTransport, err := quic.NewTransport(priv, reuse, nil, cfg.connectionGater, nil)
if err != nil {
t.Fatal(err)
Expand All @@ -187,8 +205,14 @@ func GenSwarm(t *testing.T, opts ...Option) *swarm.Swarm {
t.Fatal(err)
}
if !cfg.dialOnly {
if err := s.Listen(ma.StringCast("/ip4/127.0.0.1/udp/0/quic")); err != nil {
t.Fatal(err)
if cfg.quicListenAddr == nil {
if err := s.Listen(ma.StringCast("/ip4/127.0.0.1/udp/0/quic")); err != nil {
t.Fatal(err)
}
} else {
if err := s.Listen(cfg.quicListenAddr); err != nil {
t.Fatal(err)
}
}
}
}
Expand All @@ -198,6 +222,22 @@ func GenSwarm(t *testing.T, opts ...Option) *swarm.Swarm {
return s
}

type udpTransport struct {
listenPacket func(network string, laddr *net.UDPAddr) (net.PacketConn, error)
}

func (u udpTransport) ListenPacket(network string, laddr *net.UDPAddr) (net.PacketConn, error) {
return u.listenPacket(network, laddr)
}

func UDPTransport(m *natlab.Machine) quicreuse.UDPTransport {
tr := udpTransport{}
tr.listenPacket = func(network string, laddr *net.UDPAddr) (net.PacketConn, error) {
return m.ListenPacket(context.Background(), network, laddr.String())
}
return tr
}

// DivulgeAddresses adds swarm a's addresses to swarm b's peerstore.
func DivulgeAddresses(a, b network.Network) {
id := a.LocalPeer()
Expand Down