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

View as plain text