Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions p2p/test/transport/deadline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func TestReadWriteDeadlines(t *testing.T) {
sendBuf := make([]byte, 10<<20)
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
listener := tc.HostGenerator(t, TransportTestCaseOpts{})
defer listener.Close()
dialer := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
Expand Down
7 changes: 7 additions & 0 deletions p2p/test/transport/gating_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func TestInterceptPeerDial(t *testing.T) {
}
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
connGater := NewMockConnectionGater(ctrl)
Expand All @@ -90,6 +91,7 @@ func TestInterceptAddrDial(t *testing.T) {
}
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
connGater := NewMockConnectionGater(ctrl)
Expand All @@ -115,6 +117,7 @@ func TestInterceptSecuredOutgoing(t *testing.T) {
}
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
connGater := NewMockConnectionGater(ctrl)
Expand Down Expand Up @@ -148,6 +151,7 @@ func TestInterceptUpgradedOutgoing(t *testing.T) {
}
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
connGater := NewMockConnectionGater(ctrl)
Expand Down Expand Up @@ -184,6 +188,7 @@ func TestInterceptAccept(t *testing.T) {
}
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
connGater := NewMockConnectionGater(ctrl)
Expand Down Expand Up @@ -232,6 +237,7 @@ func TestInterceptSecuredIncoming(t *testing.T) {
}
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
connGater := NewMockConnectionGater(ctrl)
Expand Down Expand Up @@ -265,6 +271,7 @@ func TestInterceptUpgradedIncoming(t *testing.T) {
}
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
connGater := NewMockConnectionGater(ctrl)
Expand Down
1 change: 1 addition & 0 deletions p2p/test/transport/rcmgr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func TestResourceManagerIsUsed(t *testing.T) {
t.Run(tc.Name, func(t *testing.T) {
for _, testDialer := range []bool{true, false} {
t.Run(tc.Name+fmt.Sprintf(" test_dialer=%v", testDialer), func(t *testing.T) {
skipWindows(t, tc.Name)

var reservedMemory, releasedMemory atomic.Int32
defer func() {
Expand Down
127 changes: 127 additions & 0 deletions p2p/test/transport/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,22 @@ func selfSignedTLSConfig(t *testing.T) *tls.Config {
return tlsConfig
}

func skipIfNoIPv6(t *testing.T) {
t.Helper()
ln, err := net.Listen("tcp6", "[::1]:0")
if err != nil {
t.Skip("IPv6 loopback not available")
}
ln.Close()
}

func skipWindows(t *testing.T, transportName string) {
t.Helper()
if transportName == "WebRTC - IP6" && runtime.GOOS == "windows" {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need the transportName param. It's just skip windows helper

t.Skip("WebRTC IPv6 over loopback is not supported on Windows. See WebRTC - IP6 HostGenerator for details.")
}
}

var transportsToTest = []TransportTestCase{
{
Name: "TCP / Noise / Yamux",
Expand Down Expand Up @@ -353,11 +369,113 @@ var transportsToTest = []TransportTestCase{
return h
},
},
{
Name: "TCP / Noise / Yamux - IP6",
HostGenerator: func(t *testing.T, opts TransportTestCaseOpts) host.Host {
skipIfNoIPv6(t)
libp2pOpts := transformOpts(opts)
libp2pOpts = append(libp2pOpts, libp2p.Security(noise.ID, noise.New))
libp2pOpts = append(libp2pOpts, libp2p.Muxer(yamux.ID, yamux.DefaultTransport))
if opts.NoListen {
libp2pOpts = append(libp2pOpts, libp2p.NoListenAddrs)
} else {
libp2pOpts = append(libp2pOpts, libp2p.ListenAddrStrings("/ip6/::1/tcp/0"))
}
h, err := libp2p.New(libp2pOpts...)
require.NoError(t, err)
return h
},
},
{
Name: "TCP / TLS / Yamux - IP6",
HostGenerator: func(t *testing.T, opts TransportTestCaseOpts) host.Host {
skipIfNoIPv6(t)
libp2pOpts := transformOpts(opts)
libp2pOpts = append(libp2pOpts, libp2p.Security(libp2ptls.ID, libp2ptls.New))
libp2pOpts = append(libp2pOpts, libp2p.Muxer(yamux.ID, yamux.DefaultTransport))
if opts.NoListen {
libp2pOpts = append(libp2pOpts, libp2p.NoListenAddrs)
} else {
libp2pOpts = append(libp2pOpts, libp2p.ListenAddrStrings("/ip6/::1/tcp/0"))
}
h, err := libp2p.New(libp2pOpts...)
require.NoError(t, err)
return h
},
},
{
Name: "WebSocket - IP6",
HostGenerator: func(t *testing.T, opts TransportTestCaseOpts) host.Host {
skipIfNoIPv6(t)
libp2pOpts := transformOpts(opts)
if opts.NoListen {
libp2pOpts = append(libp2pOpts, libp2p.NoListenAddrs)
} else {
libp2pOpts = append(libp2pOpts, libp2p.ListenAddrStrings("/ip6/::1/tcp/0/ws"))
}
h, err := libp2p.New(libp2pOpts...)
require.NoError(t, err)
return h
},
},
{
Name: "QUIC - IP6",
HostGenerator: func(t *testing.T, opts TransportTestCaseOpts) host.Host {
skipIfNoIPv6(t)
libp2pOpts := transformOpts(opts)
if opts.NoListen {
libp2pOpts = append(libp2pOpts, libp2p.NoListenAddrs)
} else {
libp2pOpts = append(libp2pOpts, libp2p.ListenAddrStrings("/ip6/::1/udp/0/quic-v1"))
}
h, err := libp2p.New(libp2pOpts...)
require.NoError(t, err)
return h
},
},
{
Name: "WebTransport - IP6",
HostGenerator: func(t *testing.T, opts TransportTestCaseOpts) host.Host {
skipIfNoIPv6(t)
libp2pOpts := transformOpts(opts)
if opts.NoListen {
libp2pOpts = append(libp2pOpts, libp2p.NoListenAddrs)
} else {
libp2pOpts = append(libp2pOpts, libp2p.ListenAddrStrings("/ip6/::1/udp/0/quic-v1/webtransport"))
}
h, err := libp2p.New(libp2pOpts...)
require.NoError(t, err)
return h
},
},
{
Name: "WebRTC - IP6",
HostGenerator: func(t *testing.T, opts TransportTestCaseOpts) host.Host {
skipIfNoIPv6(t)
// The WebRTC IPv6 loopback listener is /ip6/::1/udp/.../webrtc-direct.
// Pion ICE gathers candidates on link-local/global IPv6 interfaces, and on
// Windows wsasendto rejects sends from those locals to ::1 with
// "The requested address is not valid in its context" (scope mismatch).
// Those packets never leave the stack, so captures show no IPv6 UDP loopback traffic.
skipWindows(t, "WebRTC - IP6")
libp2pOpts := transformOpts(opts)
libp2pOpts = append(libp2pOpts, libp2p.Transport(libp2pwebrtc.New))
if opts.NoListen {
libp2pOpts = append(libp2pOpts, libp2p.NoListenAddrs)
} else {
libp2pOpts = append(libp2pOpts, libp2p.ListenAddrStrings("/ip6/::1/udp/0/webrtc-direct"))
}
h, err := libp2p.New(libp2pOpts...)
require.NoError(t, err)
return h
},
},
}

func TestPing(t *testing.T) {
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
Copy link
Copy Markdown
Collaborator

@MarcoPolo MarcoPolo Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this or any other skipWindows calls inside the tests anymore. We can just call it from the host generator.

h1 := tc.HostGenerator(t, TransportTestCaseOpts{})
h2 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
defer h1.Close()
Expand Down Expand Up @@ -387,6 +505,7 @@ func TestBigPing(t *testing.T) {

for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
h1 := tc.HostGenerator(t, TransportTestCaseOpts{})
h2 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
defer h1.Close()
Expand Down Expand Up @@ -515,6 +634,7 @@ func TestManyStreams(t *testing.T) {
const streamCount = 128
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
h1 := tc.HostGenerator(t, TransportTestCaseOpts{NoRcmgr: true})
h2 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true, NoRcmgr: true})
defer h1.Close()
Expand Down Expand Up @@ -739,6 +859,7 @@ func TestMoreStreamsThanOurLimits(t *testing.T) {
func TestListenerStreamResets(t *testing.T) {
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
h1 := tc.HostGenerator(t, TransportTestCaseOpts{})
h2 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
defer h1.Close()
Expand Down Expand Up @@ -768,6 +889,7 @@ func TestListenerStreamResets(t *testing.T) {
func TestDialerStreamResets(t *testing.T) {
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
h1 := tc.HostGenerator(t, TransportTestCaseOpts{})
h2 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
defer h1.Close()
Expand Down Expand Up @@ -799,6 +921,7 @@ func TestDialerStreamResets(t *testing.T) {
func TestStreamReadDeadline(t *testing.T) {
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
h1 := tc.HostGenerator(t, TransportTestCaseOpts{})
h2 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
defer h1.Close()
Expand Down Expand Up @@ -853,6 +976,7 @@ func TestDiscoverPeerIDFromSecurityNegotiation(t *testing.T) {

for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
h1 := tc.HostGenerator(t, TransportTestCaseOpts{})
h2 := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
defer h1.Close()
Expand Down Expand Up @@ -897,6 +1021,7 @@ func TestCloseConnWhenBlocked(t *testing.T) {
continue
}
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockRcmgr := mocknetwork.NewMockResourceManager(ctrl)
Expand Down Expand Up @@ -977,6 +1102,7 @@ func TestConnDroppedWhenBlocked(t *testing.T) {
func TestConnClosedWhenRemoteCloses(t *testing.T) {
for _, tc := range transportsToTest {
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
server := tc.HostGenerator(t, TransportTestCaseOpts{})
client := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
defer server.Close()
Expand Down Expand Up @@ -1017,6 +1143,7 @@ func TestErrorCodes(t *testing.T) {
continue
}
t.Run(tc.Name, func(t *testing.T) {
skipWindows(t, tc.Name)
server := tc.HostGenerator(t, TransportTestCaseOpts{})
client := tc.HostGenerator(t, TransportTestCaseOpts{NoListen: true})
defer server.Close()
Expand Down