Source file src/net/net_fake_test.go

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build js || wasip1
     6  
     7  package net
     8  
     9  // GOOS=js and GOOS=wasip1 do not have typical socket networking capabilities
    10  // found on other platforms. To help run test suites of the stdlib packages,
    11  // an in-memory "fake network" facility is implemented.
    12  //
    13  // The tests in this files are intended to validate the behavior of the fake
    14  // network stack on these platforms.
    15  
    16  import "testing"
    17  
    18  func TestFakeConn(t *testing.T) {
    19  	tests := []struct {
    20  		name   string
    21  		listen func() (Listener, error)
    22  		dial   func(Addr) (Conn, error)
    23  		addr   func(*testing.T, Addr)
    24  	}{
    25  		{
    26  			name: "Listener:tcp",
    27  			listen: func() (Listener, error) {
    28  				return Listen("tcp", ":0")
    29  			},
    30  			dial: func(addr Addr) (Conn, error) {
    31  				return Dial(addr.Network(), addr.String())
    32  			},
    33  			addr: testFakeTCPAddr,
    34  		},
    35  
    36  		{
    37  			name: "ListenTCP:tcp",
    38  			listen: func() (Listener, error) {
    39  				// Creating a listening TCP connection with a nil address must
    40  				// select an IP address on localhost with a random port.
    41  				// This test verifies that the fake network facility does that.
    42  				return ListenTCP("tcp", nil)
    43  			},
    44  			dial: func(addr Addr) (Conn, error) {
    45  				// Connecting a listening TCP connection will select a local
    46  				// address on the local network and connects to the destination
    47  				// address.
    48  				return DialTCP("tcp", nil, addr.(*TCPAddr))
    49  			},
    50  			addr: testFakeTCPAddr,
    51  		},
    52  
    53  		{
    54  			name: "ListenUnix:unix",
    55  			listen: func() (Listener, error) {
    56  				return ListenUnix("unix", &UnixAddr{Name: "test"})
    57  			},
    58  			dial: func(addr Addr) (Conn, error) {
    59  				return DialUnix("unix", nil, addr.(*UnixAddr))
    60  			},
    61  			addr: testFakeUnixAddr("unix", "test"),
    62  		},
    63  
    64  		{
    65  			name: "ListenUnix:unixpacket",
    66  			listen: func() (Listener, error) {
    67  				return ListenUnix("unixpacket", &UnixAddr{Name: "test"})
    68  			},
    69  			dial: func(addr Addr) (Conn, error) {
    70  				return DialUnix("unixpacket", nil, addr.(*UnixAddr))
    71  			},
    72  			addr: testFakeUnixAddr("unixpacket", "test"),
    73  		},
    74  	}
    75  
    76  	for _, test := range tests {
    77  		t.Run(test.name, func(t *testing.T) {
    78  			l, err := test.listen()
    79  			if err != nil {
    80  				t.Fatal(err)
    81  			}
    82  			defer l.Close()
    83  			test.addr(t, l.Addr())
    84  
    85  			c, err := test.dial(l.Addr())
    86  			if err != nil {
    87  				t.Fatal(err)
    88  			}
    89  			defer c.Close()
    90  			test.addr(t, c.LocalAddr())
    91  			test.addr(t, c.RemoteAddr())
    92  		})
    93  	}
    94  }
    95  
    96  func TestFakePacketConn(t *testing.T) {
    97  	tests := []struct {
    98  		name   string
    99  		listen func() (PacketConn, error)
   100  		dial   func(Addr) (Conn, error)
   101  		addr   func(*testing.T, Addr)
   102  	}{
   103  		{
   104  			name: "ListenPacket:udp",
   105  			listen: func() (PacketConn, error) {
   106  				return ListenPacket("udp", ":0")
   107  			},
   108  			dial: func(addr Addr) (Conn, error) {
   109  				return Dial(addr.Network(), addr.String())
   110  			},
   111  			addr: testFakeUDPAddr,
   112  		},
   113  
   114  		{
   115  			name: "ListenUDP:udp",
   116  			listen: func() (PacketConn, error) {
   117  				// Creating a listening UDP connection with a nil address must
   118  				// select an IP address on localhost with a random port.
   119  				// This test verifies that the fake network facility does that.
   120  				return ListenUDP("udp", nil)
   121  			},
   122  			dial: func(addr Addr) (Conn, error) {
   123  				// Connecting a listening UDP connection will select a local
   124  				// address on the local network and connects to the destination
   125  				// address.
   126  				return DialUDP("udp", nil, addr.(*UDPAddr))
   127  			},
   128  			addr: testFakeUDPAddr,
   129  		},
   130  
   131  		{
   132  			name: "ListenUnixgram:unixgram",
   133  			listen: func() (PacketConn, error) {
   134  				return ListenUnixgram("unixgram", &UnixAddr{Name: "test"})
   135  			},
   136  			dial: func(addr Addr) (Conn, error) {
   137  				return DialUnix("unixgram", nil, addr.(*UnixAddr))
   138  			},
   139  			addr: testFakeUnixAddr("unixgram", "test"),
   140  		},
   141  	}
   142  
   143  	for _, test := range tests {
   144  		t.Run(test.name, func(t *testing.T) {
   145  			l, err := test.listen()
   146  			if err != nil {
   147  				t.Fatal(err)
   148  			}
   149  			defer l.Close()
   150  			test.addr(t, l.LocalAddr())
   151  
   152  			c, err := test.dial(l.LocalAddr())
   153  			if err != nil {
   154  				t.Fatal(err)
   155  			}
   156  			defer c.Close()
   157  			test.addr(t, c.LocalAddr())
   158  			test.addr(t, c.RemoteAddr())
   159  		})
   160  	}
   161  }
   162  
   163  func testFakeTCPAddr(t *testing.T, addr Addr) {
   164  	t.Helper()
   165  	if a, ok := addr.(*TCPAddr); !ok {
   166  		t.Errorf("Addr is not *TCPAddr: %T", addr)
   167  	} else {
   168  		testFakeNetAddr(t, a.IP, a.Port)
   169  	}
   170  }
   171  
   172  func testFakeUDPAddr(t *testing.T, addr Addr) {
   173  	t.Helper()
   174  	if a, ok := addr.(*UDPAddr); !ok {
   175  		t.Errorf("Addr is not *UDPAddr: %T", addr)
   176  	} else {
   177  		testFakeNetAddr(t, a.IP, a.Port)
   178  	}
   179  }
   180  
   181  func testFakeNetAddr(t *testing.T, ip IP, port int) {
   182  	t.Helper()
   183  	if port == 0 {
   184  		t.Error("network address is missing port")
   185  	} else if len(ip) == 0 {
   186  		t.Error("network address is missing IP")
   187  	} else if !ip.Equal(IPv4(127, 0, 0, 1)) {
   188  		t.Errorf("network address has wrong IP: %s", ip)
   189  	}
   190  }
   191  
   192  func testFakeUnixAddr(net, name string) func(*testing.T, Addr) {
   193  	return func(t *testing.T, addr Addr) {
   194  		t.Helper()
   195  		if a, ok := addr.(*UnixAddr); !ok {
   196  			t.Errorf("Addr is not *UnixAddr: %T", addr)
   197  		} else if a.Net != net {
   198  			t.Errorf("unix address has wrong net: want=%q got=%q", net, a.Net)
   199  		} else if a.Name != name {
   200  			t.Errorf("unix address has wrong name: want=%q got=%q", name, a.Name)
   201  		}
   202  	}
   203  }
   204  

View as plain text