Source file src/net/file_test.go

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

View as plain text