Source file src/net/net_test.go

     1  // Copyright 2009 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  
     7  package net
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"io"
    13  	"net/internal/socktest"
    14  	"os"
    15  	"runtime"
    16  	"testing"
    17  	"time"
    18  )
    19  
    20  func TestCloseRead(t *testing.T) {
    21  	switch runtime.GOOS {
    22  	case "plan9":
    23  		t.Skipf("not supported on %s", runtime.GOOS)
    24  	}
    25  	t.Parallel()
    26  
    27  	for _, network := range []string{"tcp", "unix", "unixpacket"} {
    28  		network := network
    29  		t.Run(network, func(t *testing.T) {
    30  			if !testableNetwork(network) {
    31  				t.Skipf("network %s is not testable on the current platform", network)
    32  			}
    33  			t.Parallel()
    34  
    35  			ln := newLocalListener(t, network)
    36  			switch network {
    37  			case "unix", "unixpacket":
    38  				defer os.Remove(ln.Addr().String())
    39  			}
    40  			defer ln.Close()
    41  
    42  			c, err := Dial(ln.Addr().Network(), ln.Addr().String())
    43  			if err != nil {
    44  				t.Fatal(err)
    45  			}
    46  			switch network {
    47  			case "unix", "unixpacket":
    48  				defer os.Remove(c.LocalAddr().String())
    49  			}
    50  			defer c.Close()
    51  
    52  			switch c := c.(type) {
    53  			case *TCPConn:
    54  				err = c.CloseRead()
    55  			case *UnixConn:
    56  				err = c.CloseRead()
    57  			}
    58  			if err != nil {
    59  				if perr := parseCloseError(err, true); perr != nil {
    60  					t.Error(perr)
    61  				}
    62  				t.Fatal(err)
    63  			}
    64  			var b [1]byte
    65  			n, err := c.Read(b[:])
    66  			if n != 0 || err == nil {
    67  				t.Fatalf("got (%d, %v); want (0, error)", n, err)
    68  			}
    69  		})
    70  	}
    71  }
    72  
    73  func TestCloseWrite(t *testing.T) {
    74  	switch runtime.GOOS {
    75  	case "plan9":
    76  		t.Skipf("not supported on %s", runtime.GOOS)
    77  	}
    78  
    79  	t.Parallel()
    80  	deadline, _ := t.Deadline()
    81  	if !deadline.IsZero() {
    82  		// Leave 10% headroom on the deadline to report errors and clean up.
    83  		deadline = deadline.Add(-time.Until(deadline) / 10)
    84  	}
    85  
    86  	for _, network := range []string{"tcp", "unix", "unixpacket"} {
    87  		network := network
    88  		t.Run(network, func(t *testing.T) {
    89  			if !testableNetwork(network) {
    90  				t.Skipf("network %s is not testable on the current platform", network)
    91  			}
    92  			t.Parallel()
    93  
    94  			handler := func(ls *localServer, ln Listener) {
    95  				c, err := ln.Accept()
    96  				if err != nil {
    97  					t.Error(err)
    98  					return
    99  				}
   100  
   101  				// Workaround for https://go.dev/issue/49352.
   102  				// On arm64 macOS (current as of macOS 12.4),
   103  				// reading from a socket at the same time as the client
   104  				// is closing it occasionally hangs for 60 seconds before
   105  				// returning ECONNRESET. Sleep for a bit to give the
   106  				// socket time to close before trying to read from it.
   107  				if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
   108  					time.Sleep(10 * time.Millisecond)
   109  				}
   110  
   111  				if !deadline.IsZero() {
   112  					c.SetDeadline(deadline)
   113  				}
   114  				defer c.Close()
   115  
   116  				var b [1]byte
   117  				n, err := c.Read(b[:])
   118  				if n != 0 || err != io.EOF {
   119  					t.Errorf("got (%d, %v); want (0, io.EOF)", n, err)
   120  					return
   121  				}
   122  				switch c := c.(type) {
   123  				case *TCPConn:
   124  					err = c.CloseWrite()
   125  				case *UnixConn:
   126  					err = c.CloseWrite()
   127  				}
   128  				if err != nil {
   129  					if perr := parseCloseError(err, true); perr != nil {
   130  						t.Error(perr)
   131  					}
   132  					t.Error(err)
   133  					return
   134  				}
   135  				n, err = c.Write(b[:])
   136  				if err == nil {
   137  					t.Errorf("got (%d, %v); want (any, error)", n, err)
   138  					return
   139  				}
   140  			}
   141  
   142  			ls := newLocalServer(t, network)
   143  			defer ls.teardown()
   144  			if err := ls.buildup(handler); err != nil {
   145  				t.Fatal(err)
   146  			}
   147  
   148  			c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
   149  			if err != nil {
   150  				t.Fatal(err)
   151  			}
   152  			if !deadline.IsZero() {
   153  				c.SetDeadline(deadline)
   154  			}
   155  			switch network {
   156  			case "unix", "unixpacket":
   157  				defer os.Remove(c.LocalAddr().String())
   158  			}
   159  			defer c.Close()
   160  
   161  			switch c := c.(type) {
   162  			case *TCPConn:
   163  				err = c.CloseWrite()
   164  			case *UnixConn:
   165  				err = c.CloseWrite()
   166  			}
   167  			if err != nil {
   168  				if perr := parseCloseError(err, true); perr != nil {
   169  					t.Error(perr)
   170  				}
   171  				t.Fatal(err)
   172  			}
   173  			var b [1]byte
   174  			n, err := c.Read(b[:])
   175  			if n != 0 || err != io.EOF {
   176  				t.Fatalf("got (%d, %v); want (0, io.EOF)", n, err)
   177  			}
   178  			n, err = c.Write(b[:])
   179  			if err == nil {
   180  				t.Fatalf("got (%d, %v); want (any, error)", n, err)
   181  			}
   182  		})
   183  	}
   184  }
   185  
   186  func TestConnClose(t *testing.T) {
   187  	t.Parallel()
   188  	for _, network := range []string{"tcp", "unix", "unixpacket"} {
   189  		network := network
   190  		t.Run(network, func(t *testing.T) {
   191  			if !testableNetwork(network) {
   192  				t.Skipf("network %s is not testable on the current platform", network)
   193  			}
   194  			t.Parallel()
   195  
   196  			ln := newLocalListener(t, network)
   197  			switch network {
   198  			case "unix", "unixpacket":
   199  				defer os.Remove(ln.Addr().String())
   200  			}
   201  			defer ln.Close()
   202  
   203  			c, err := Dial(ln.Addr().Network(), ln.Addr().String())
   204  			if err != nil {
   205  				t.Fatal(err)
   206  			}
   207  			switch network {
   208  			case "unix", "unixpacket":
   209  				defer os.Remove(c.LocalAddr().String())
   210  			}
   211  			defer c.Close()
   212  
   213  			if err := c.Close(); err != nil {
   214  				if perr := parseCloseError(err, false); perr != nil {
   215  					t.Error(perr)
   216  				}
   217  				t.Fatal(err)
   218  			}
   219  			var b [1]byte
   220  			n, err := c.Read(b[:])
   221  			if n != 0 || err == nil {
   222  				t.Fatalf("got (%d, %v); want (0, error)", n, err)
   223  			}
   224  		})
   225  	}
   226  }
   227  
   228  func TestListenerClose(t *testing.T) {
   229  	t.Parallel()
   230  	for _, network := range []string{"tcp", "unix", "unixpacket"} {
   231  		network := network
   232  		t.Run(network, func(t *testing.T) {
   233  			if !testableNetwork(network) {
   234  				t.Skipf("network %s is not testable on the current platform", network)
   235  			}
   236  			t.Parallel()
   237  
   238  			ln := newLocalListener(t, network)
   239  			switch network {
   240  			case "unix", "unixpacket":
   241  				defer os.Remove(ln.Addr().String())
   242  			}
   243  
   244  			if err := ln.Close(); err != nil {
   245  				if perr := parseCloseError(err, false); perr != nil {
   246  					t.Error(perr)
   247  				}
   248  				t.Fatal(err)
   249  			}
   250  			c, err := ln.Accept()
   251  			if err == nil {
   252  				c.Close()
   253  				t.Fatal("should fail")
   254  			}
   255  
   256  			// Note: we cannot ensure that a subsequent Dial does not succeed, because
   257  			// we do not in general have any guarantee that ln.Addr is not immediately
   258  			// reused. (TCP sockets enter a TIME_WAIT state when closed, but that only
   259  			// applies to existing connections for the port — it does not prevent the
   260  			// port itself from being used for entirely new connections in the
   261  			// meantime.)
   262  		})
   263  	}
   264  }
   265  
   266  func TestPacketConnClose(t *testing.T) {
   267  	t.Parallel()
   268  	for _, network := range []string{"udp", "unixgram"} {
   269  		network := network
   270  		t.Run(network, func(t *testing.T) {
   271  			if !testableNetwork(network) {
   272  				t.Skipf("network %s is not testable on the current platform", network)
   273  			}
   274  			t.Parallel()
   275  
   276  			c := newLocalPacketListener(t, network)
   277  			switch network {
   278  			case "unixgram":
   279  				defer os.Remove(c.LocalAddr().String())
   280  			}
   281  			defer c.Close()
   282  
   283  			if err := c.Close(); err != nil {
   284  				if perr := parseCloseError(err, false); perr != nil {
   285  					t.Error(perr)
   286  				}
   287  				t.Fatal(err)
   288  			}
   289  			var b [1]byte
   290  			n, _, err := c.ReadFrom(b[:])
   291  			if n != 0 || err == nil {
   292  				t.Fatalf("got (%d, %v); want (0, error)", n, err)
   293  			}
   294  		})
   295  	}
   296  }
   297  
   298  func TestListenCloseListen(t *testing.T) {
   299  	const maxTries = 10
   300  	for tries := 0; tries < maxTries; tries++ {
   301  		ln := newLocalListener(t, "tcp")
   302  		addr := ln.Addr().String()
   303  		// TODO: This is racy. The selected address could be reused in between this
   304  		// Close and the subsequent Listen.
   305  		if err := ln.Close(); err != nil {
   306  			if perr := parseCloseError(err, false); perr != nil {
   307  				t.Error(perr)
   308  			}
   309  			t.Fatal(err)
   310  		}
   311  		ln, err := Listen("tcp", addr)
   312  		if err == nil {
   313  			// Success. (This test didn't always make it here earlier.)
   314  			ln.Close()
   315  			return
   316  		}
   317  		t.Errorf("failed on try %d/%d: %v", tries+1, maxTries, err)
   318  	}
   319  	t.Fatalf("failed to listen/close/listen on same address after %d tries", maxTries)
   320  }
   321  
   322  // See golang.org/issue/6163, golang.org/issue/6987.
   323  func TestAcceptIgnoreAbortedConnRequest(t *testing.T) {
   324  	switch runtime.GOOS {
   325  	case "plan9":
   326  		t.Skipf("%s does not have full support of socktest", runtime.GOOS)
   327  	}
   328  
   329  	syserr := make(chan error)
   330  	go func() {
   331  		defer close(syserr)
   332  		for _, err := range abortedConnRequestErrors {
   333  			syserr <- err
   334  		}
   335  	}()
   336  	sw.Set(socktest.FilterAccept, func(so *socktest.Status) (socktest.AfterFilter, error) {
   337  		if err, ok := <-syserr; ok {
   338  			return nil, err
   339  		}
   340  		return nil, nil
   341  	})
   342  	defer sw.Set(socktest.FilterAccept, nil)
   343  
   344  	operr := make(chan error, 1)
   345  	handler := func(ls *localServer, ln Listener) {
   346  		defer close(operr)
   347  		c, err := ln.Accept()
   348  		if err != nil {
   349  			if perr := parseAcceptError(err); perr != nil {
   350  				operr <- perr
   351  			}
   352  			operr <- err
   353  			return
   354  		}
   355  		c.Close()
   356  	}
   357  	ls := newLocalServer(t, "tcp")
   358  	defer ls.teardown()
   359  	if err := ls.buildup(handler); err != nil {
   360  		t.Fatal(err)
   361  	}
   362  
   363  	c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
   364  	if err != nil {
   365  		t.Fatal(err)
   366  	}
   367  	c.Close()
   368  
   369  	for err := range operr {
   370  		t.Error(err)
   371  	}
   372  }
   373  
   374  func TestZeroByteRead(t *testing.T) {
   375  	t.Parallel()
   376  	for _, network := range []string{"tcp", "unix", "unixpacket"} {
   377  		network := network
   378  		t.Run(network, func(t *testing.T) {
   379  			if !testableNetwork(network) {
   380  				t.Skipf("network %s is not testable on the current platform", network)
   381  			}
   382  			t.Parallel()
   383  
   384  			ln := newLocalListener(t, network)
   385  			connc := make(chan Conn, 1)
   386  			go func() {
   387  				defer ln.Close()
   388  				c, err := ln.Accept()
   389  				if err != nil {
   390  					t.Error(err)
   391  				}
   392  				connc <- c // might be nil
   393  			}()
   394  			c, err := Dial(network, ln.Addr().String())
   395  			if err != nil {
   396  				t.Fatal(err)
   397  			}
   398  			defer c.Close()
   399  			sc := <-connc
   400  			if sc == nil {
   401  				return
   402  			}
   403  			defer sc.Close()
   404  
   405  			if runtime.GOOS == "windows" {
   406  				// A zero byte read on Windows caused a wait for readability first.
   407  				// Rather than change that behavior, satisfy it in this test.
   408  				// See Issue 15735.
   409  				go io.WriteString(sc, "a")
   410  			}
   411  
   412  			n, err := c.Read(nil)
   413  			if n != 0 || err != nil {
   414  				t.Errorf("%s: zero byte client read = %v, %v; want 0, nil", network, n, err)
   415  			}
   416  
   417  			if runtime.GOOS == "windows" {
   418  				// Same as comment above.
   419  				go io.WriteString(c, "a")
   420  			}
   421  			n, err = sc.Read(nil)
   422  			if n != 0 || err != nil {
   423  				t.Errorf("%s: zero byte server read = %v, %v; want 0, nil", network, n, err)
   424  			}
   425  		})
   426  	}
   427  }
   428  
   429  // withTCPConnPair sets up a TCP connection between two peers, then
   430  // runs peer1 and peer2 concurrently. withTCPConnPair returns when
   431  // both have completed.
   432  func withTCPConnPair(t *testing.T, peer1, peer2 func(c *TCPConn) error) {
   433  	ln := newLocalListener(t, "tcp")
   434  	defer ln.Close()
   435  	errc := make(chan error, 2)
   436  	go func() {
   437  		c1, err := ln.Accept()
   438  		if err != nil {
   439  			errc <- err
   440  			return
   441  		}
   442  		defer c1.Close()
   443  		errc <- peer1(c1.(*TCPConn))
   444  	}()
   445  	go func() {
   446  		c2, err := Dial("tcp", ln.Addr().String())
   447  		if err != nil {
   448  			errc <- err
   449  			return
   450  		}
   451  		defer c2.Close()
   452  		errc <- peer2(c2.(*TCPConn))
   453  	}()
   454  	for i := 0; i < 2; i++ {
   455  		if err := <-errc; err != nil {
   456  			t.Fatal(err)
   457  		}
   458  	}
   459  }
   460  
   461  // Tests that a blocked Read is interrupted by a concurrent SetReadDeadline
   462  // modifying that Conn's read deadline to the past.
   463  // See golang.org/cl/30164 which documented this. The net/http package
   464  // depends on this.
   465  func TestReadTimeoutUnblocksRead(t *testing.T) {
   466  	serverDone := make(chan struct{})
   467  	server := func(cs *TCPConn) error {
   468  		defer close(serverDone)
   469  		errc := make(chan error, 1)
   470  		go func() {
   471  			defer close(errc)
   472  			go func() {
   473  				// TODO: find a better way to wait
   474  				// until we're blocked in the cs.Read
   475  				// call below. Sleep is lame.
   476  				time.Sleep(100 * time.Millisecond)
   477  
   478  				// Interrupt the upcoming Read, unblocking it:
   479  				cs.SetReadDeadline(time.Unix(123, 0)) // time in the past
   480  			}()
   481  			var buf [1]byte
   482  			n, err := cs.Read(buf[:1])
   483  			if n != 0 || err == nil {
   484  				errc <- fmt.Errorf("Read = %v, %v; want 0, non-nil", n, err)
   485  			}
   486  		}()
   487  		select {
   488  		case err := <-errc:
   489  			return err
   490  		case <-time.After(5 * time.Second):
   491  			buf := make([]byte, 2<<20)
   492  			buf = buf[:runtime.Stack(buf, true)]
   493  			println("Stacks at timeout:\n", string(buf))
   494  			return errors.New("timeout waiting for Read to finish")
   495  		}
   496  
   497  	}
   498  	// Do nothing in the client. Never write. Just wait for the
   499  	// server's half to be done.
   500  	client := func(*TCPConn) error {
   501  		<-serverDone
   502  		return nil
   503  	}
   504  	withTCPConnPair(t, client, server)
   505  }
   506  
   507  // Issue 17695: verify that a blocked Read is woken up by a Close.
   508  func TestCloseUnblocksRead(t *testing.T) {
   509  	t.Parallel()
   510  	server := func(cs *TCPConn) error {
   511  		// Give the client time to get stuck in a Read:
   512  		time.Sleep(20 * time.Millisecond)
   513  		cs.Close()
   514  		return nil
   515  	}
   516  	client := func(ss *TCPConn) error {
   517  		n, err := ss.Read([]byte{0})
   518  		if n != 0 || err != io.EOF {
   519  			return fmt.Errorf("Read = %v, %v; want 0, EOF", n, err)
   520  		}
   521  		return nil
   522  	}
   523  	withTCPConnPair(t, client, server)
   524  }
   525  
   526  // Issue 24808: verify that ECONNRESET is not temporary for read.
   527  func TestNotTemporaryRead(t *testing.T) {
   528  	t.Parallel()
   529  
   530  	ln := newLocalListener(t, "tcp")
   531  	serverDone := make(chan struct{})
   532  	dialed := make(chan struct{})
   533  	go func() {
   534  		defer close(serverDone)
   535  
   536  		cs, err := ln.Accept()
   537  		if err != nil {
   538  			return
   539  		}
   540  		<-dialed
   541  		cs.(*TCPConn).SetLinger(0)
   542  		cs.Close()
   543  	}()
   544  	defer func() {
   545  		ln.Close()
   546  		<-serverDone
   547  	}()
   548  
   549  	ss, err := Dial("tcp", ln.Addr().String())
   550  	close(dialed)
   551  	if err != nil {
   552  		t.Fatal(err)
   553  	}
   554  	defer ss.Close()
   555  
   556  	_, err = ss.Read([]byte{0})
   557  	if err == nil {
   558  		t.Fatal("Read succeeded unexpectedly")
   559  	} else if err == io.EOF {
   560  		// This happens on Plan 9, but for some reason (prior to CL 385314) it was
   561  		// accepted everywhere else too.
   562  		if runtime.GOOS == "plan9" {
   563  			return
   564  		}
   565  		t.Fatal("Read unexpectedly returned io.EOF after socket was abruptly closed")
   566  	}
   567  	if ne, ok := err.(Error); !ok {
   568  		t.Errorf("Read error does not implement net.Error: %v", err)
   569  	} else if ne.Temporary() {
   570  		t.Errorf("Read error is unexpectedly temporary: %v", err)
   571  	}
   572  }
   573  
   574  // The various errors should implement the Error interface.
   575  func TestErrors(t *testing.T) {
   576  	var (
   577  		_ Error = &OpError{}
   578  		_ Error = &ParseError{}
   579  		_ Error = &AddrError{}
   580  		_ Error = UnknownNetworkError("")
   581  		_ Error = InvalidAddrError("")
   582  		_ Error = &timeoutError{}
   583  		_ Error = &DNSConfigError{}
   584  		_ Error = &DNSError{}
   585  	)
   586  
   587  	// ErrClosed was introduced as type error, so we can't check
   588  	// it using a declaration.
   589  	if _, ok := ErrClosed.(Error); !ok {
   590  		t.Fatal("ErrClosed does not implement Error")
   591  	}
   592  }
   593  

View as plain text