Black Lives Matter. Support the Equal Justice Initiative.

Source file src/net/file_test.go

Documentation: net

     1  // Copyright 2011 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  // +build !js
     7  
     8  package net
     9  
    10  import (
    11  	"os"
    12  	"reflect"
    13  	"runtime"
    14  	"sync"
    15  	"testing"
    16  )
    17  
    18  // The full stack test cases for IPConn have been moved to the
    19  // following:
    20  //      golang.org/x/net/ipv4
    21  //      golang.org/x/net/ipv6
    22  //      golang.org/x/net/icmp
    23  
    24  var fileConnTests = []struct {
    25  	network string
    26  }{
    27  	{"tcp"},
    28  	{"udp"},
    29  	{"unix"},
    30  	{"unixpacket"},
    31  }
    32  
    33  func TestFileConn(t *testing.T) {
    34  	switch runtime.GOOS {
    35  	case "plan9", "windows":
    36  		t.Skipf("not supported on %s", runtime.GOOS)
    37  	}
    38  
    39  	for _, tt := range fileConnTests {
    40  		if !testableNetwork(tt.network) {
    41  			t.Logf("skipping %s test", tt.network)
    42  			continue
    43  		}
    44  
    45  		var network, address string
    46  		switch tt.network {
    47  		case "udp":
    48  			c, err := newLocalPacketListener(tt.network)
    49  			if err != nil {
    50  				t.Fatal(err)
    51  			}
    52  			defer c.Close()
    53  			network = c.LocalAddr().Network()
    54  			address = c.LocalAddr().String()
    55  		default:
    56  			handler := func(ls *localServer, ln Listener) {
    57  				c, err := ln.Accept()
    58  				if err != nil {
    59  					return
    60  				}
    61  				defer c.Close()
    62  				var b [1]byte
    63  				c.Read(b[:])
    64  			}
    65  			ls, err := newLocalServer(tt.network)
    66  			if err != nil {
    67  				t.Fatal(err)
    68  			}
    69  			defer ls.teardown()
    70  			if err := ls.buildup(handler); err != nil {
    71  				t.Fatal(err)
    72  			}
    73  			network = ls.Listener.Addr().Network()
    74  			address = ls.Listener.Addr().String()
    75  		}
    76  
    77  		c1, err := Dial(network, address)
    78  		if err != nil {
    79  			if perr := parseDialError(err); perr != nil {
    80  				t.Error(perr)
    81  			}
    82  			t.Fatal(err)
    83  		}
    84  		addr := c1.LocalAddr()
    85  
    86  		var f *os.File
    87  		switch c1 := c1.(type) {
    88  		case *TCPConn:
    89  			f, err = c1.File()
    90  		case *UDPConn:
    91  			f, err = c1.File()
    92  		case *UnixConn:
    93  			f, err = c1.File()
    94  		}
    95  		if err := c1.Close(); err != nil {
    96  			if perr := parseCloseError(err, false); perr != nil {
    97  				t.Error(perr)
    98  			}
    99  			t.Error(err)
   100  		}
   101  		if err != nil {
   102  			if perr := parseCommonError(err); perr != nil {
   103  				t.Error(perr)
   104  			}
   105  			t.Fatal(err)
   106  		}
   107  
   108  		c2, err := FileConn(f)
   109  		if err := f.Close(); err != nil {
   110  			t.Error(err)
   111  		}
   112  		if err != nil {
   113  			if perr := parseCommonError(err); perr != nil {
   114  				t.Error(perr)
   115  			}
   116  			t.Fatal(err)
   117  		}
   118  		defer c2.Close()
   119  
   120  		if _, err := c2.Write([]byte("FILECONN TEST")); err != nil {
   121  			if perr := parseWriteError(err); perr != nil {
   122  				t.Error(perr)
   123  			}
   124  			t.Fatal(err)
   125  		}
   126  		if !reflect.DeepEqual(c2.LocalAddr(), addr) {
   127  			t.Fatalf("got %#v; want %#v", c2.LocalAddr(), addr)
   128  		}
   129  	}
   130  }
   131  
   132  var fileListenerTests = []struct {
   133  	network string
   134  }{
   135  	{"tcp"},
   136  	{"unix"},
   137  	{"unixpacket"},
   138  }
   139  
   140  func TestFileListener(t *testing.T) {
   141  	switch runtime.GOOS {
   142  	case "plan9", "windows":
   143  		t.Skipf("not supported on %s", runtime.GOOS)
   144  	}
   145  
   146  	for _, tt := range fileListenerTests {
   147  		if !testableNetwork(tt.network) {
   148  			t.Logf("skipping %s test", tt.network)
   149  			continue
   150  		}
   151  
   152  		ln1, err := newLocalListener(tt.network)
   153  		if err != nil {
   154  			t.Fatal(err)
   155  		}
   156  		switch tt.network {
   157  		case "unix", "unixpacket":
   158  			defer os.Remove(ln1.Addr().String())
   159  		}
   160  		addr := ln1.Addr()
   161  
   162  		var f *os.File
   163  		switch ln1 := ln1.(type) {
   164  		case *TCPListener:
   165  			f, err = ln1.File()
   166  		case *UnixListener:
   167  			f, err = ln1.File()
   168  		}
   169  		switch tt.network {
   170  		case "unix", "unixpacket":
   171  			defer ln1.Close() // UnixListener.Close calls syscall.Unlink internally
   172  		default:
   173  			if err := ln1.Close(); err != nil {
   174  				t.Error(err)
   175  			}
   176  		}
   177  		if err != nil {
   178  			if perr := parseCommonError(err); perr != nil {
   179  				t.Error(perr)
   180  			}
   181  			t.Fatal(err)
   182  		}
   183  
   184  		ln2, err := FileListener(f)
   185  		if err := f.Close(); err != nil {
   186  			t.Error(err)
   187  		}
   188  		if err != nil {
   189  			if perr := parseCommonError(err); perr != nil {
   190  				t.Error(perr)
   191  			}
   192  			t.Fatal(err)
   193  		}
   194  		defer ln2.Close()
   195  
   196  		var wg sync.WaitGroup
   197  		wg.Add(1)
   198  		go func() {
   199  			defer wg.Done()
   200  			c, err := Dial(ln2.Addr().Network(), ln2.Addr().String())
   201  			if err != nil {
   202  				if perr := parseDialError(err); perr != nil {
   203  					t.Error(perr)
   204  				}
   205  				t.Error(err)
   206  				return
   207  			}
   208  			c.Close()
   209  		}()
   210  		c, err := ln2.Accept()
   211  		if err != nil {
   212  			if perr := parseAcceptError(err); perr != nil {
   213  				t.Error(perr)
   214  			}
   215  			t.Fatal(err)
   216  		}
   217  		c.Close()
   218  		wg.Wait()
   219  		if !reflect.DeepEqual(ln2.Addr(), addr) {
   220  			t.Fatalf("got %#v; want %#v", ln2.Addr(), addr)
   221  		}
   222  	}
   223  }
   224  
   225  var filePacketConnTests = []struct {
   226  	network string
   227  }{
   228  	{"udp"},
   229  	{"unixgram"},
   230  }
   231  
   232  func TestFilePacketConn(t *testing.T) {
   233  	switch runtime.GOOS {
   234  	case "plan9", "windows":
   235  		t.Skipf("not supported on %s", runtime.GOOS)
   236  	}
   237  
   238  	for _, tt := range filePacketConnTests {
   239  		if !testableNetwork(tt.network) {
   240  			t.Logf("skipping %s test", tt.network)
   241  			continue
   242  		}
   243  
   244  		c1, err := newLocalPacketListener(tt.network)
   245  		if err != nil {
   246  			t.Fatal(err)
   247  		}
   248  		switch tt.network {
   249  		case "unixgram":
   250  			defer os.Remove(c1.LocalAddr().String())
   251  		}
   252  		addr := c1.LocalAddr()
   253  
   254  		var f *os.File
   255  		switch c1 := c1.(type) {
   256  		case *UDPConn:
   257  			f, err = c1.File()
   258  		case *UnixConn:
   259  			f, err = c1.File()
   260  		}
   261  		if err := c1.Close(); err != nil {
   262  			if perr := parseCloseError(err, false); perr != nil {
   263  				t.Error(perr)
   264  			}
   265  			t.Error(err)
   266  		}
   267  		if err != nil {
   268  			if perr := parseCommonError(err); perr != nil {
   269  				t.Error(perr)
   270  			}
   271  			t.Fatal(err)
   272  		}
   273  
   274  		c2, err := FilePacketConn(f)
   275  		if err := f.Close(); err != nil {
   276  			t.Error(err)
   277  		}
   278  		if err != nil {
   279  			if perr := parseCommonError(err); perr != nil {
   280  				t.Error(perr)
   281  			}
   282  			t.Fatal(err)
   283  		}
   284  		defer c2.Close()
   285  
   286  		if _, err := c2.WriteTo([]byte("FILEPACKETCONN TEST"), addr); err != nil {
   287  			if perr := parseWriteError(err); perr != nil {
   288  				t.Error(perr)
   289  			}
   290  			t.Fatal(err)
   291  		}
   292  		if !reflect.DeepEqual(c2.LocalAddr(), addr) {
   293  			t.Fatalf("got %#v; want %#v", c2.LocalAddr(), addr)
   294  		}
   295  	}
   296  }
   297  
   298  // Issue 24483.
   299  func TestFileCloseRace(t *testing.T) {
   300  	switch runtime.GOOS {
   301  	case "plan9", "windows":
   302  		t.Skipf("not supported on %s", runtime.GOOS)
   303  	}
   304  	if !testableNetwork("tcp") {
   305  		t.Skip("tcp not supported")
   306  	}
   307  
   308  	handler := func(ls *localServer, ln Listener) {
   309  		c, err := ln.Accept()
   310  		if err != nil {
   311  			return
   312  		}
   313  		defer c.Close()
   314  		var b [1]byte
   315  		c.Read(b[:])
   316  	}
   317  
   318  	ls, err := newLocalServer("tcp")
   319  	if err != nil {
   320  		t.Fatal(err)
   321  	}
   322  	defer ls.teardown()
   323  	if err := ls.buildup(handler); err != nil {
   324  		t.Fatal(err)
   325  	}
   326  
   327  	const tries = 100
   328  	for i := 0; i < tries; i++ {
   329  		c1, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
   330  		if err != nil {
   331  			t.Fatal(err)
   332  		}
   333  		tc := c1.(*TCPConn)
   334  
   335  		var wg sync.WaitGroup
   336  		wg.Add(2)
   337  		go func() {
   338  			defer wg.Done()
   339  			f, err := tc.File()
   340  			if err == nil {
   341  				f.Close()
   342  			}
   343  		}()
   344  		go func() {
   345  			defer wg.Done()
   346  			c1.Close()
   347  		}()
   348  		wg.Wait()
   349  	}
   350  }
   351  

View as plain text