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

View as plain text