blob: 783304d5314d772ffec8542f582f4820bb510c37 [file] [log] [blame]
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build js || wasip1
package net
// GOOS=js and GOOS=wasip1 do not have typical socket networking capabilities
// found on other platforms. To help run test suites of the stdlib packages,
// an in-memory "fake network" facility is implemented.
//
// The tests in this files are intended to validate the behavior of the fake
// network stack on these platforms.
import "testing"
func TestFakeConn(t *testing.T) {
tests := []struct {
name string
listen func() (Listener, error)
dial func(Addr) (Conn, error)
addr func(*testing.T, Addr)
}{
{
name: "Listener:tcp",
listen: func() (Listener, error) {
return Listen("tcp", ":0")
},
dial: func(addr Addr) (Conn, error) {
return Dial(addr.Network(), addr.String())
},
addr: testFakeTCPAddr,
},
{
name: "ListenTCP:tcp",
listen: func() (Listener, error) {
// Creating a listening TCP connection with a nil address must
// select an IP address on localhost with a random port.
// This test verifies that the fake network facility does that.
return ListenTCP("tcp", nil)
},
dial: func(addr Addr) (Conn, error) {
// Connecting a listening TCP connection will select a local
// address on the local network and connects to the destination
// address.
return DialTCP("tcp", nil, addr.(*TCPAddr))
},
addr: testFakeTCPAddr,
},
{
name: "ListenUnix:unix",
listen: func() (Listener, error) {
return ListenUnix("unix", &UnixAddr{Name: "test"})
},
dial: func(addr Addr) (Conn, error) {
return DialUnix("unix", nil, addr.(*UnixAddr))
},
addr: testFakeUnixAddr("unix", "test"),
},
{
name: "ListenUnix:unixpacket",
listen: func() (Listener, error) {
return ListenUnix("unixpacket", &UnixAddr{Name: "test"})
},
dial: func(addr Addr) (Conn, error) {
return DialUnix("unixpacket", nil, addr.(*UnixAddr))
},
addr: testFakeUnixAddr("unixpacket", "test"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
l, err := test.listen()
if err != nil {
t.Fatal(err)
}
defer l.Close()
test.addr(t, l.Addr())
c, err := test.dial(l.Addr())
if err != nil {
t.Fatal(err)
}
defer c.Close()
test.addr(t, c.LocalAddr())
test.addr(t, c.RemoteAddr())
})
}
}
func TestFakePacketConn(t *testing.T) {
tests := []struct {
name string
listen func() (PacketConn, error)
dial func(Addr) (Conn, error)
addr func(*testing.T, Addr)
}{
{
name: "ListenPacket:udp",
listen: func() (PacketConn, error) {
return ListenPacket("udp", ":0")
},
dial: func(addr Addr) (Conn, error) {
return Dial(addr.Network(), addr.String())
},
addr: testFakeUDPAddr,
},
{
name: "ListenUDP:udp",
listen: func() (PacketConn, error) {
// Creating a listening UDP connection with a nil address must
// select an IP address on localhost with a random port.
// This test verifies that the fake network facility does that.
return ListenUDP("udp", nil)
},
dial: func(addr Addr) (Conn, error) {
// Connecting a listening UDP connection will select a local
// address on the local network and connects to the destination
// address.
return DialUDP("udp", nil, addr.(*UDPAddr))
},
addr: testFakeUDPAddr,
},
{
name: "ListenUnixgram:unixgram",
listen: func() (PacketConn, error) {
return ListenUnixgram("unixgram", &UnixAddr{Name: "test"})
},
dial: func(addr Addr) (Conn, error) {
return DialUnix("unixgram", nil, addr.(*UnixAddr))
},
addr: testFakeUnixAddr("unixgram", "test"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
l, err := test.listen()
if err != nil {
t.Fatal(err)
}
defer l.Close()
test.addr(t, l.LocalAddr())
c, err := test.dial(l.LocalAddr())
if err != nil {
t.Fatal(err)
}
defer c.Close()
test.addr(t, c.LocalAddr())
test.addr(t, c.RemoteAddr())
})
}
}
func testFakeTCPAddr(t *testing.T, addr Addr) {
t.Helper()
if a, ok := addr.(*TCPAddr); !ok {
t.Errorf("Addr is not *TCPAddr: %T", addr)
} else {
testFakeNetAddr(t, a.IP, a.Port)
}
}
func testFakeUDPAddr(t *testing.T, addr Addr) {
t.Helper()
if a, ok := addr.(*UDPAddr); !ok {
t.Errorf("Addr is not *UDPAddr: %T", addr)
} else {
testFakeNetAddr(t, a.IP, a.Port)
}
}
func testFakeNetAddr(t *testing.T, ip IP, port int) {
t.Helper()
if port == 0 {
t.Error("network address is missing port")
} else if len(ip) == 0 {
t.Error("network address is missing IP")
} else if !ip.Equal(IPv4(127, 0, 0, 1)) {
t.Errorf("network address has wrong IP: %s", ip)
}
}
func testFakeUnixAddr(net, name string) func(*testing.T, Addr) {
return func(t *testing.T, addr Addr) {
t.Helper()
if a, ok := addr.(*UnixAddr); !ok {
t.Errorf("Addr is not *UnixAddr: %T", addr)
} else if a.Net != net {
t.Errorf("unix address has wrong net: want=%q got=%q", net, a.Net)
} else if a.Name != name {
t.Errorf("unix address has wrong name: want=%q got=%q", name, a.Name)
}
}
}