| // 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) |
| } |
| } |
| } |