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

View as plain text