Source file src/net/mockserver_test.go

     1  // Copyright 2013 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  import (
    10  	"context"
    11  	"errors"
    12  	"fmt"
    13  	"os"
    14  	"path/filepath"
    15  	"sync"
    16  	"testing"
    17  	"time"
    18  )
    19  
    20  // testUnixAddr uses os.MkdirTemp to get a name that is unique.
    21  func testUnixAddr(t testing.TB) string {
    22  	// Pass an empty pattern to get a directory name that is as short as possible.
    23  	// If we end up with a name longer than the sun_path field in the sockaddr_un
    24  	// struct, we won't be able to make the syscall to open the socket.
    25  	d, err := os.MkdirTemp("", "")
    26  	if err != nil {
    27  		t.Fatal(err)
    28  	}
    29  	t.Cleanup(func() {
    30  		if err := os.RemoveAll(d); err != nil {
    31  			t.Error(err)
    32  		}
    33  	})
    34  	return filepath.Join(d, "sock")
    35  }
    36  
    37  func newLocalListener(t testing.TB, network string, lcOpt ...*ListenConfig) Listener {
    38  	var lc *ListenConfig
    39  	switch len(lcOpt) {
    40  	case 0:
    41  		lc = new(ListenConfig)
    42  	case 1:
    43  		lc = lcOpt[0]
    44  	default:
    45  		t.Helper()
    46  		t.Fatal("too many ListenConfigs passed to newLocalListener: want 0 or 1")
    47  	}
    48  
    49  	listen := func(net, addr string) Listener {
    50  		ln, err := lc.Listen(context.Background(), net, addr)
    51  		if err != nil {
    52  			t.Helper()
    53  			t.Fatal(err)
    54  		}
    55  		return ln
    56  	}
    57  
    58  	switch network {
    59  	case "tcp":
    60  		if supportsIPv4() {
    61  			if !supportsIPv6() {
    62  				return listen("tcp4", "127.0.0.1:0")
    63  			}
    64  			if ln, err := Listen("tcp4", "127.0.0.1:0"); err == nil {
    65  				return ln
    66  			}
    67  		}
    68  		if supportsIPv6() {
    69  			return listen("tcp6", "[::1]:0")
    70  		}
    71  	case "tcp4":
    72  		if supportsIPv4() {
    73  			return listen("tcp4", "127.0.0.1:0")
    74  		}
    75  	case "tcp6":
    76  		if supportsIPv6() {
    77  			return listen("tcp6", "[::1]:0")
    78  		}
    79  	case "unix", "unixpacket":
    80  		return listen(network, testUnixAddr(t))
    81  	}
    82  
    83  	t.Helper()
    84  	t.Fatalf("%s is not supported", network)
    85  	return nil
    86  }
    87  
    88  func newDualStackListener() (lns []*TCPListener, err error) {
    89  	var args = []struct {
    90  		network string
    91  		TCPAddr
    92  	}{
    93  		{"tcp4", TCPAddr{IP: IPv4(127, 0, 0, 1)}},
    94  		{"tcp6", TCPAddr{IP: IPv6loopback}},
    95  	}
    96  	for i := 0; i < 64; i++ {
    97  		var port int
    98  		var lns []*TCPListener
    99  		for _, arg := range args {
   100  			arg.TCPAddr.Port = port
   101  			ln, err := ListenTCP(arg.network, &arg.TCPAddr)
   102  			if err != nil {
   103  				continue
   104  			}
   105  			port = ln.Addr().(*TCPAddr).Port
   106  			lns = append(lns, ln)
   107  		}
   108  		if len(lns) != len(args) {
   109  			for _, ln := range lns {
   110  				ln.Close()
   111  			}
   112  			continue
   113  		}
   114  		return lns, nil
   115  	}
   116  	return nil, errors.New("no dualstack port available")
   117  }
   118  
   119  type localServer struct {
   120  	lnmu sync.RWMutex
   121  	Listener
   122  	done chan bool // signal that indicates server stopped
   123  	cl   []Conn    // accepted connection list
   124  }
   125  
   126  func (ls *localServer) buildup(handler func(*localServer, Listener)) error {
   127  	go func() {
   128  		handler(ls, ls.Listener)
   129  		close(ls.done)
   130  	}()
   131  	return nil
   132  }
   133  
   134  func (ls *localServer) teardown() error {
   135  	ls.lnmu.Lock()
   136  	defer ls.lnmu.Unlock()
   137  	if ls.Listener != nil {
   138  		network := ls.Listener.Addr().Network()
   139  		address := ls.Listener.Addr().String()
   140  		ls.Listener.Close()
   141  		for _, c := range ls.cl {
   142  			if err := c.Close(); err != nil {
   143  				return err
   144  			}
   145  		}
   146  		<-ls.done
   147  		ls.Listener = nil
   148  		switch network {
   149  		case "unix", "unixpacket":
   150  			os.Remove(address)
   151  		}
   152  	}
   153  	return nil
   154  }
   155  
   156  func newLocalServer(t testing.TB, network string) *localServer {
   157  	t.Helper()
   158  	ln := newLocalListener(t, network)
   159  	return &localServer{Listener: ln, done: make(chan bool)}
   160  }
   161  
   162  type streamListener struct {
   163  	network, address string
   164  	Listener
   165  	done chan bool // signal that indicates server stopped
   166  }
   167  
   168  func (sl *streamListener) newLocalServer() *localServer {
   169  	return &localServer{Listener: sl.Listener, done: make(chan bool)}
   170  }
   171  
   172  type dualStackServer struct {
   173  	lnmu sync.RWMutex
   174  	lns  []streamListener
   175  	port string
   176  
   177  	cmu sync.RWMutex
   178  	cs  []Conn // established connections at the passive open side
   179  }
   180  
   181  func (dss *dualStackServer) buildup(handler func(*dualStackServer, Listener)) error {
   182  	for i := range dss.lns {
   183  		go func(i int) {
   184  			handler(dss, dss.lns[i].Listener)
   185  			close(dss.lns[i].done)
   186  		}(i)
   187  	}
   188  	return nil
   189  }
   190  
   191  func (dss *dualStackServer) teardownNetwork(network string) error {
   192  	dss.lnmu.Lock()
   193  	for i := range dss.lns {
   194  		if network == dss.lns[i].network && dss.lns[i].Listener != nil {
   195  			dss.lns[i].Listener.Close()
   196  			<-dss.lns[i].done
   197  			dss.lns[i].Listener = nil
   198  		}
   199  	}
   200  	dss.lnmu.Unlock()
   201  	return nil
   202  }
   203  
   204  func (dss *dualStackServer) teardown() error {
   205  	dss.lnmu.Lock()
   206  	for i := range dss.lns {
   207  		if dss.lns[i].Listener != nil {
   208  			dss.lns[i].Listener.Close()
   209  			<-dss.lns[i].done
   210  		}
   211  	}
   212  	dss.lns = dss.lns[:0]
   213  	dss.lnmu.Unlock()
   214  	dss.cmu.Lock()
   215  	for _, c := range dss.cs {
   216  		c.Close()
   217  	}
   218  	dss.cs = dss.cs[:0]
   219  	dss.cmu.Unlock()
   220  	return nil
   221  }
   222  
   223  func newDualStackServer() (*dualStackServer, error) {
   224  	lns, err := newDualStackListener()
   225  	if err != nil {
   226  		return nil, err
   227  	}
   228  	_, port, err := SplitHostPort(lns[0].Addr().String())
   229  	if err != nil {
   230  		lns[0].Close()
   231  		lns[1].Close()
   232  		return nil, err
   233  	}
   234  	return &dualStackServer{
   235  		lns: []streamListener{
   236  			{network: "tcp4", address: lns[0].Addr().String(), Listener: lns[0], done: make(chan bool)},
   237  			{network: "tcp6", address: lns[1].Addr().String(), Listener: lns[1], done: make(chan bool)},
   238  		},
   239  		port: port,
   240  	}, nil
   241  }
   242  
   243  func (ls *localServer) transponder(ln Listener, ch chan<- error) {
   244  	defer close(ch)
   245  
   246  	switch ln := ln.(type) {
   247  	case *TCPListener:
   248  		ln.SetDeadline(time.Now().Add(someTimeout))
   249  	case *UnixListener:
   250  		ln.SetDeadline(time.Now().Add(someTimeout))
   251  	}
   252  	c, err := ln.Accept()
   253  	if err != nil {
   254  		if perr := parseAcceptError(err); perr != nil {
   255  			ch <- perr
   256  		}
   257  		ch <- err
   258  		return
   259  	}
   260  	ls.cl = append(ls.cl, c)
   261  
   262  	network := ln.Addr().Network()
   263  	if c.LocalAddr().Network() != network || c.RemoteAddr().Network() != network {
   264  		ch <- fmt.Errorf("got %v->%v; expected %v->%v", c.LocalAddr().Network(), c.RemoteAddr().Network(), network, network)
   265  		return
   266  	}
   267  	c.SetDeadline(time.Now().Add(someTimeout))
   268  	c.SetReadDeadline(time.Now().Add(someTimeout))
   269  	c.SetWriteDeadline(time.Now().Add(someTimeout))
   270  
   271  	b := make([]byte, 256)
   272  	n, err := c.Read(b)
   273  	if err != nil {
   274  		if perr := parseReadError(err); perr != nil {
   275  			ch <- perr
   276  		}
   277  		ch <- err
   278  		return
   279  	}
   280  	if _, err := c.Write(b[:n]); err != nil {
   281  		if perr := parseWriteError(err); perr != nil {
   282  			ch <- perr
   283  		}
   284  		ch <- err
   285  		return
   286  	}
   287  }
   288  
   289  func transceiver(c Conn, wb []byte, ch chan<- error) {
   290  	defer close(ch)
   291  
   292  	c.SetDeadline(time.Now().Add(someTimeout))
   293  	c.SetReadDeadline(time.Now().Add(someTimeout))
   294  	c.SetWriteDeadline(time.Now().Add(someTimeout))
   295  
   296  	n, err := c.Write(wb)
   297  	if err != nil {
   298  		if perr := parseWriteError(err); perr != nil {
   299  			ch <- perr
   300  		}
   301  		ch <- err
   302  		return
   303  	}
   304  	if n != len(wb) {
   305  		ch <- fmt.Errorf("wrote %d; want %d", n, len(wb))
   306  	}
   307  	rb := make([]byte, len(wb))
   308  	n, err = c.Read(rb)
   309  	if err != nil {
   310  		if perr := parseReadError(err); perr != nil {
   311  			ch <- perr
   312  		}
   313  		ch <- err
   314  		return
   315  	}
   316  	if n != len(wb) {
   317  		ch <- fmt.Errorf("read %d; want %d", n, len(wb))
   318  	}
   319  }
   320  
   321  func newLocalPacketListener(t testing.TB, network string, lcOpt ...*ListenConfig) PacketConn {
   322  	var lc *ListenConfig
   323  	switch len(lcOpt) {
   324  	case 0:
   325  		lc = new(ListenConfig)
   326  	case 1:
   327  		lc = lcOpt[0]
   328  	default:
   329  		t.Helper()
   330  		t.Fatal("too many ListenConfigs passed to newLocalListener: want 0 or 1")
   331  	}
   332  
   333  	listenPacket := func(net, addr string) PacketConn {
   334  		c, err := lc.ListenPacket(context.Background(), net, addr)
   335  		if err != nil {
   336  			t.Helper()
   337  			t.Fatal(err)
   338  		}
   339  		return c
   340  	}
   341  
   342  	switch network {
   343  	case "udp":
   344  		if supportsIPv4() {
   345  			return listenPacket("udp4", "127.0.0.1:0")
   346  		}
   347  		if supportsIPv6() {
   348  			return listenPacket("udp6", "[::1]:0")
   349  		}
   350  	case "udp4":
   351  		if supportsIPv4() {
   352  			return listenPacket("udp4", "127.0.0.1:0")
   353  		}
   354  	case "udp6":
   355  		if supportsIPv6() {
   356  			return listenPacket("udp6", "[::1]:0")
   357  		}
   358  	case "unixgram":
   359  		return listenPacket(network, testUnixAddr(t))
   360  	}
   361  
   362  	t.Helper()
   363  	t.Fatalf("%s is not supported", network)
   364  	return nil
   365  }
   366  
   367  func newDualStackPacketListener() (cs []*UDPConn, err error) {
   368  	var args = []struct {
   369  		network string
   370  		UDPAddr
   371  	}{
   372  		{"udp4", UDPAddr{IP: IPv4(127, 0, 0, 1)}},
   373  		{"udp6", UDPAddr{IP: IPv6loopback}},
   374  	}
   375  	for i := 0; i < 64; i++ {
   376  		var port int
   377  		var cs []*UDPConn
   378  		for _, arg := range args {
   379  			arg.UDPAddr.Port = port
   380  			c, err := ListenUDP(arg.network, &arg.UDPAddr)
   381  			if err != nil {
   382  				continue
   383  			}
   384  			port = c.LocalAddr().(*UDPAddr).Port
   385  			cs = append(cs, c)
   386  		}
   387  		if len(cs) != len(args) {
   388  			for _, c := range cs {
   389  				c.Close()
   390  			}
   391  			continue
   392  		}
   393  		return cs, nil
   394  	}
   395  	return nil, errors.New("no dualstack port available")
   396  }
   397  
   398  type localPacketServer struct {
   399  	pcmu sync.RWMutex
   400  	PacketConn
   401  	done chan bool // signal that indicates server stopped
   402  }
   403  
   404  func (ls *localPacketServer) buildup(handler func(*localPacketServer, PacketConn)) error {
   405  	go func() {
   406  		handler(ls, ls.PacketConn)
   407  		close(ls.done)
   408  	}()
   409  	return nil
   410  }
   411  
   412  func (ls *localPacketServer) teardown() error {
   413  	ls.pcmu.Lock()
   414  	if ls.PacketConn != nil {
   415  		network := ls.PacketConn.LocalAddr().Network()
   416  		address := ls.PacketConn.LocalAddr().String()
   417  		ls.PacketConn.Close()
   418  		<-ls.done
   419  		ls.PacketConn = nil
   420  		switch network {
   421  		case "unixgram":
   422  			os.Remove(address)
   423  		}
   424  	}
   425  	ls.pcmu.Unlock()
   426  	return nil
   427  }
   428  
   429  func newLocalPacketServer(t testing.TB, network string) *localPacketServer {
   430  	t.Helper()
   431  	c := newLocalPacketListener(t, network)
   432  	return &localPacketServer{PacketConn: c, done: make(chan bool)}
   433  }
   434  
   435  type packetListener struct {
   436  	PacketConn
   437  }
   438  
   439  func (pl *packetListener) newLocalServer() *localPacketServer {
   440  	return &localPacketServer{PacketConn: pl.PacketConn, done: make(chan bool)}
   441  }
   442  
   443  func packetTransponder(c PacketConn, ch chan<- error) {
   444  	defer close(ch)
   445  
   446  	c.SetDeadline(time.Now().Add(someTimeout))
   447  	c.SetReadDeadline(time.Now().Add(someTimeout))
   448  	c.SetWriteDeadline(time.Now().Add(someTimeout))
   449  
   450  	b := make([]byte, 256)
   451  	n, peer, err := c.ReadFrom(b)
   452  	if err != nil {
   453  		if perr := parseReadError(err); perr != nil {
   454  			ch <- perr
   455  		}
   456  		ch <- err
   457  		return
   458  	}
   459  	if peer == nil { // for connected-mode sockets
   460  		switch c.LocalAddr().Network() {
   461  		case "udp":
   462  			peer, err = ResolveUDPAddr("udp", string(b[:n]))
   463  		case "unixgram":
   464  			peer, err = ResolveUnixAddr("unixgram", string(b[:n]))
   465  		}
   466  		if err != nil {
   467  			ch <- err
   468  			return
   469  		}
   470  	}
   471  	if _, err := c.WriteTo(b[:n], peer); err != nil {
   472  		if perr := parseWriteError(err); perr != nil {
   473  			ch <- perr
   474  		}
   475  		ch <- err
   476  		return
   477  	}
   478  }
   479  
   480  func packetTransceiver(c PacketConn, wb []byte, dst Addr, ch chan<- error) {
   481  	defer close(ch)
   482  
   483  	c.SetDeadline(time.Now().Add(someTimeout))
   484  	c.SetReadDeadline(time.Now().Add(someTimeout))
   485  	c.SetWriteDeadline(time.Now().Add(someTimeout))
   486  
   487  	n, err := c.WriteTo(wb, dst)
   488  	if err != nil {
   489  		if perr := parseWriteError(err); perr != nil {
   490  			ch <- perr
   491  		}
   492  		ch <- err
   493  		return
   494  	}
   495  	if n != len(wb) {
   496  		ch <- fmt.Errorf("wrote %d; want %d", n, len(wb))
   497  	}
   498  	rb := make([]byte, len(wb))
   499  	n, _, err = c.ReadFrom(rb)
   500  	if err != nil {
   501  		if perr := parseReadError(err); perr != nil {
   502  			ch <- perr
   503  		}
   504  		ch <- err
   505  		return
   506  	}
   507  	if n != len(wb) {
   508  		ch <- fmt.Errorf("read %d; want %d", n, len(wb))
   509  	}
   510  }
   511  

View as plain text