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

View as plain text