github.com/m10x/go/src@v0.0.0-20220112094212-ba61592315da/net/net_test.go (about)

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