Black Lives Matter. Support the Equal Justice Initiative.

Source file src/net/mockserver_test.go

Documentation: net

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

View as plain text