github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/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  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  
    24  	for _, network := range []string{"tcp", "unix", "unixpacket"} {
    25  		if !testableNetwork(network) {
    26  			t.Logf("skipping %s test", network)
    27  			continue
    28  		}
    29  
    30  		ln, err := newLocalListener(network)
    31  		if err != nil {
    32  			t.Fatal(err)
    33  		}
    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); 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  func TestCloseWrite(t *testing.T) {
    71  	switch runtime.GOOS {
    72  	case "nacl", "plan9":
    73  		t.Skipf("not supported on %s", runtime.GOOS)
    74  	}
    75  
    76  	handler := func(ls *localServer, ln Listener) {
    77  		c, err := ln.Accept()
    78  		if err != nil {
    79  			t.Error(err)
    80  			return
    81  		}
    82  		defer c.Close()
    83  
    84  		var b [1]byte
    85  		n, err := c.Read(b[:])
    86  		if n != 0 || err != io.EOF {
    87  			t.Errorf("got (%d, %v); want (0, io.EOF)", n, err)
    88  			return
    89  		}
    90  		switch c := c.(type) {
    91  		case *TCPConn:
    92  			err = c.CloseWrite()
    93  		case *UnixConn:
    94  			err = c.CloseWrite()
    95  		}
    96  		if err != nil {
    97  			if perr := parseCloseError(err); perr != nil {
    98  				t.Error(perr)
    99  			}
   100  			t.Error(err)
   101  			return
   102  		}
   103  		n, err = c.Write(b[:])
   104  		if err == nil {
   105  			t.Errorf("got (%d, %v); want (any, error)", n, err)
   106  			return
   107  		}
   108  	}
   109  
   110  	for _, network := range []string{"tcp", "unix", "unixpacket"} {
   111  		if !testableNetwork(network) {
   112  			t.Logf("skipping %s test", network)
   113  			continue
   114  		}
   115  
   116  		ls, err := newLocalServer(network)
   117  		if err != nil {
   118  			t.Fatal(err)
   119  		}
   120  		defer ls.teardown()
   121  		if err := ls.buildup(handler); err != nil {
   122  			t.Fatal(err)
   123  		}
   124  
   125  		c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
   126  		if err != nil {
   127  			t.Fatal(err)
   128  		}
   129  		switch network {
   130  		case "unix", "unixpacket":
   131  			defer os.Remove(c.LocalAddr().String())
   132  		}
   133  		defer c.Close()
   134  
   135  		switch c := c.(type) {
   136  		case *TCPConn:
   137  			err = c.CloseWrite()
   138  		case *UnixConn:
   139  			err = c.CloseWrite()
   140  		}
   141  		if err != nil {
   142  			if perr := parseCloseError(err); perr != nil {
   143  				t.Error(perr)
   144  			}
   145  			t.Fatal(err)
   146  		}
   147  		var b [1]byte
   148  		n, err := c.Read(b[:])
   149  		if n != 0 || err != io.EOF {
   150  			t.Fatalf("got (%d, %v); want (0, io.EOF)", n, err)
   151  		}
   152  		n, err = c.Write(b[:])
   153  		if err == nil {
   154  			t.Fatalf("got (%d, %v); want (any, error)", n, err)
   155  		}
   156  	}
   157  }
   158  
   159  func TestConnClose(t *testing.T) {
   160  	for _, network := range []string{"tcp", "unix", "unixpacket"} {
   161  		if !testableNetwork(network) {
   162  			t.Logf("skipping %s test", network)
   163  			continue
   164  		}
   165  
   166  		ln, err := newLocalListener(network)
   167  		if err != nil {
   168  			t.Fatal(err)
   169  		}
   170  		switch network {
   171  		case "unix", "unixpacket":
   172  			defer os.Remove(ln.Addr().String())
   173  		}
   174  		defer ln.Close()
   175  
   176  		c, err := Dial(ln.Addr().Network(), ln.Addr().String())
   177  		if err != nil {
   178  			t.Fatal(err)
   179  		}
   180  		switch network {
   181  		case "unix", "unixpacket":
   182  			defer os.Remove(c.LocalAddr().String())
   183  		}
   184  		defer c.Close()
   185  
   186  		if err := c.Close(); err != nil {
   187  			if perr := parseCloseError(err); perr != nil {
   188  				t.Error(perr)
   189  			}
   190  			t.Fatal(err)
   191  		}
   192  		var b [1]byte
   193  		n, err := c.Read(b[:])
   194  		if n != 0 || err == nil {
   195  			t.Fatalf("got (%d, %v); want (0, error)", n, err)
   196  		}
   197  	}
   198  }
   199  
   200  func TestListenerClose(t *testing.T) {
   201  	for _, network := range []string{"tcp", "unix", "unixpacket"} {
   202  		if !testableNetwork(network) {
   203  			t.Logf("skipping %s test", network)
   204  			continue
   205  		}
   206  
   207  		ln, err := newLocalListener(network)
   208  		if err != nil {
   209  			t.Fatal(err)
   210  		}
   211  		switch network {
   212  		case "unix", "unixpacket":
   213  			defer os.Remove(ln.Addr().String())
   214  		}
   215  
   216  		dst := ln.Addr().String()
   217  		if err := ln.Close(); err != nil {
   218  			if perr := parseCloseError(err); perr != nil {
   219  				t.Error(perr)
   220  			}
   221  			t.Fatal(err)
   222  		}
   223  		c, err := ln.Accept()
   224  		if err == nil {
   225  			c.Close()
   226  			t.Fatal("should fail")
   227  		}
   228  
   229  		if network == "tcp" {
   230  			// We will have two TCP FSMs inside the
   231  			// kernel here. There's no guarantee that a
   232  			// signal comes from the far end FSM will be
   233  			// delivered immediately to the near end FSM,
   234  			// especially on the platforms that allow
   235  			// multiple consumer threads to pull pending
   236  			// established connections at the same time by
   237  			// enabling SO_REUSEPORT option such as Linux,
   238  			// DragonFly BSD. So we need to give some time
   239  			// quantum to the kernel.
   240  			//
   241  			// Note that net.inet.tcp.reuseport_ext=1 by
   242  			// default on DragonFly BSD.
   243  			time.Sleep(time.Millisecond)
   244  
   245  			cc, err := Dial("tcp", dst)
   246  			if err == nil {
   247  				t.Error("Dial to closed TCP listener succeeded.")
   248  				cc.Close()
   249  			}
   250  		}
   251  	}
   252  }
   253  
   254  func TestPacketConnClose(t *testing.T) {
   255  	for _, network := range []string{"udp", "unixgram"} {
   256  		if !testableNetwork(network) {
   257  			t.Logf("skipping %s test", network)
   258  			continue
   259  		}
   260  
   261  		c, err := newLocalPacketListener(network)
   262  		if err != nil {
   263  			t.Fatal(err)
   264  		}
   265  		switch network {
   266  		case "unixgram":
   267  			defer os.Remove(c.LocalAddr().String())
   268  		}
   269  		defer c.Close()
   270  
   271  		if err := c.Close(); err != nil {
   272  			if perr := parseCloseError(err); perr != nil {
   273  				t.Error(perr)
   274  			}
   275  			t.Fatal(err)
   276  		}
   277  		var b [1]byte
   278  		n, _, err := c.ReadFrom(b[:])
   279  		if n != 0 || err == nil {
   280  			t.Fatalf("got (%d, %v); want (0, error)", n, err)
   281  		}
   282  	}
   283  }
   284  
   285  // nacl was previous failing to reuse an address.
   286  func TestListenCloseListen(t *testing.T) {
   287  	const maxTries = 10
   288  	for tries := 0; tries < maxTries; tries++ {
   289  		ln, err := newLocalListener("tcp")
   290  		if err != nil {
   291  			t.Fatal(err)
   292  		}
   293  		addr := ln.Addr().String()
   294  		if err := ln.Close(); err != nil {
   295  			if perr := parseCloseError(err); perr != nil {
   296  				t.Error(perr)
   297  			}
   298  			t.Fatal(err)
   299  		}
   300  		ln, err = Listen("tcp", addr)
   301  		if err == nil {
   302  			// Success. nacl couldn't do this before.
   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, err := newLocalServer("tcp")
   347  	if err != nil {
   348  		t.Fatal(err)
   349  	}
   350  	defer ls.teardown()
   351  	if err := ls.buildup(handler); err != nil {
   352  		t.Fatal(err)
   353  	}
   354  
   355  	c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
   356  	if err != nil {
   357  		t.Fatal(err)
   358  	}
   359  	c.Close()
   360  
   361  	for err := range operr {
   362  		t.Error(err)
   363  	}
   364  }
   365  
   366  func TestZeroByteRead(t *testing.T) {
   367  	for _, network := range []string{"tcp", "unix", "unixpacket"} {
   368  		if !testableNetwork(network) {
   369  			t.Logf("skipping %s test", network)
   370  			continue
   371  		}
   372  
   373  		ln, err := newLocalListener(network)
   374  		if err != nil {
   375  			t.Fatal(err)
   376  		}
   377  		connc := make(chan Conn, 1)
   378  		go func() {
   379  			defer ln.Close()
   380  			c, err := ln.Accept()
   381  			if err != nil {
   382  				t.Error(err)
   383  			}
   384  			connc <- c // might be nil
   385  		}()
   386  		c, err := Dial(network, ln.Addr().String())
   387  		if err != nil {
   388  			t.Fatal(err)
   389  		}
   390  		defer c.Close()
   391  		sc := <-connc
   392  		if sc == nil {
   393  			continue
   394  		}
   395  		defer sc.Close()
   396  
   397  		if runtime.GOOS == "windows" {
   398  			// A zero byte read on Windows caused a wait for readability first.
   399  			// Rather than change that behavior, satisfy it in this test.
   400  			// See Issue 15735.
   401  			go io.WriteString(sc, "a")
   402  		}
   403  
   404  		n, err := c.Read(nil)
   405  		if n != 0 || err != nil {
   406  			t.Errorf("%s: zero byte client read = %v, %v; want 0, nil", network, n, err)
   407  		}
   408  
   409  		if runtime.GOOS == "windows" {
   410  			// Same as comment above.
   411  			go io.WriteString(c, "a")
   412  		}
   413  		n, err = sc.Read(nil)
   414  		if n != 0 || err != nil {
   415  			t.Errorf("%s: zero byte server read = %v, %v; want 0, nil", network, n, err)
   416  		}
   417  	}
   418  }
   419  
   420  // withTCPConnPair sets up a TCP connection between two peers, then
   421  // runs peer1 and peer2 concurrently. withTCPConnPair returns when
   422  // both have completed.
   423  func withTCPConnPair(t *testing.T, peer1, peer2 func(c *TCPConn) error) {
   424  	ln, err := newLocalListener("tcp")
   425  	if err != nil {
   426  		t.Fatal(err)
   427  	}
   428  	defer ln.Close()
   429  	errc := make(chan error, 2)
   430  	go func() {
   431  		c1, err := ln.Accept()
   432  		if err != nil {
   433  			errc <- err
   434  			return
   435  		}
   436  		defer c1.Close()
   437  		errc <- peer1(c1.(*TCPConn))
   438  	}()
   439  	go func() {
   440  		c2, err := Dial("tcp", ln.Addr().String())
   441  		if err != nil {
   442  			errc <- err
   443  			return
   444  		}
   445  		defer c2.Close()
   446  		errc <- peer2(c2.(*TCPConn))
   447  	}()
   448  	for i := 0; i < 2; i++ {
   449  		if err := <-errc; err != nil {
   450  			t.Fatal(err)
   451  		}
   452  	}
   453  }
   454  
   455  // Tests that a blocked Read is interrupted by a concurrent SetReadDeadline
   456  // modifying that Conn's read deadline to the past.
   457  // See golang.org/cl/30164 which documented this. The net/http package
   458  // depends on this.
   459  func TestReadTimeoutUnblocksRead(t *testing.T) {
   460  	if runtime.GOOS == "plan9" {
   461  		t.Skipf("not supported on %s; see golang.org/issue/17477", runtime.GOOS)
   462  	}
   463  	serverDone := make(chan struct{})
   464  	server := func(cs *TCPConn) error {
   465  		defer close(serverDone)
   466  		errc := make(chan error, 1)
   467  		go func() {
   468  			defer close(errc)
   469  			go func() {
   470  				// TODO: find a better way to wait
   471  				// until we're blocked in the cs.Read
   472  				// call below. Sleep is lame.
   473  				time.Sleep(100 * time.Millisecond)
   474  
   475  				// Interrupt the upcoming Read, unblocking it:
   476  				cs.SetReadDeadline(time.Unix(123, 0)) // time in the past
   477  			}()
   478  			var buf [1]byte
   479  			n, err := cs.Read(buf[:1])
   480  			if n != 0 || err == nil {
   481  				errc <- fmt.Errorf("Read = %v, %v; want 0, non-nil", n, err)
   482  			}
   483  		}()
   484  		select {
   485  		case err := <-errc:
   486  			return err
   487  		case <-time.After(5 * time.Second):
   488  			buf := make([]byte, 2<<20)
   489  			buf = buf[:runtime.Stack(buf, true)]
   490  			println("Stacks at timeout:\n", string(buf))
   491  			return errors.New("timeout waiting for Read to finish")
   492  		}
   493  
   494  	}
   495  	// Do nothing in the client. Never write. Just wait for the
   496  	// server's half to be done.
   497  	client := func(*TCPConn) error {
   498  		<-serverDone
   499  		return nil
   500  	}
   501  	withTCPConnPair(t, client, server)
   502  }