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", "windows", "js", "wasip1":
    33  		t.Skipf("not supported on %s", runtime.GOOS)
    34  	}
    35  
    36  	for _, tt := range fileConnTests {
    37  		if !testableNetwork(tt.network) {
    38  			t.Logf("skipping %s test", tt.network)
    39  			continue
    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  var fileListenerTests = []struct {
   124  	network string
   125  }{
   126  	{"tcp"},
   127  	{"unix"},
   128  	{"unixpacket"},
   129  }
   130  
   131  func TestFileListener(t *testing.T) {
   132  	switch runtime.GOOS {
   133  	case "plan9", "windows", "js", "wasip1":
   134  		t.Skipf("not supported on %s", runtime.GOOS)
   135  	}
   136  
   137  	for _, tt := range fileListenerTests {
   138  		if !testableNetwork(tt.network) {
   139  			t.Logf("skipping %s test", tt.network)
   140  			continue
   141  		}
   142  
   143  		ln1 := newLocalListener(t, tt.network)
   144  		switch tt.network {
   145  		case "unix", "unixpacket":
   146  			defer os.Remove(ln1.Addr().String())
   147  		}
   148  		addr := ln1.Addr()
   149  
   150  		var (
   151  			f   *os.File
   152  			err error
   153  		)
   154  		switch ln1 := ln1.(type) {
   155  		case *TCPListener:
   156  			f, err = ln1.File()
   157  		case *UnixListener:
   158  			f, err = ln1.File()
   159  		}
   160  		switch tt.network {
   161  		case "unix", "unixpacket":
   162  			defer ln1.Close() // UnixListener.Close calls syscall.Unlink internally
   163  		default:
   164  			if err := ln1.Close(); err != nil {
   165  				t.Error(err)
   166  			}
   167  		}
   168  		if err != nil {
   169  			if perr := parseCommonError(err); perr != nil {
   170  				t.Error(perr)
   171  			}
   172  			t.Fatal(err)
   173  		}
   174  
   175  		ln2, err := FileListener(f)
   176  		if err := f.Close(); err != nil {
   177  			t.Error(err)
   178  		}
   179  		if err != nil {
   180  			if perr := parseCommonError(err); perr != nil {
   181  				t.Error(perr)
   182  			}
   183  			t.Fatal(err)
   184  		}
   185  		defer ln2.Close()
   186  
   187  		var wg sync.WaitGroup
   188  		wg.Add(1)
   189  		go func() {
   190  			defer wg.Done()
   191  			c, err := Dial(ln2.Addr().Network(), ln2.Addr().String())
   192  			if err != nil {
   193  				if perr := parseDialError(err); perr != nil {
   194  					t.Error(perr)
   195  				}
   196  				t.Error(err)
   197  				return
   198  			}
   199  			c.Close()
   200  		}()
   201  		c, err := ln2.Accept()
   202  		if err != nil {
   203  			if perr := parseAcceptError(err); perr != nil {
   204  				t.Error(perr)
   205  			}
   206  			t.Fatal(err)
   207  		}
   208  		c.Close()
   209  		wg.Wait()
   210  		if !reflect.DeepEqual(ln2.Addr(), addr) {
   211  			t.Fatalf("got %#v; want %#v", ln2.Addr(), addr)
   212  		}
   213  	}
   214  }
   215  
   216  var filePacketConnTests = []struct {
   217  	network string
   218  }{
   219  	{"udp"},
   220  	{"unixgram"},
   221  }
   222  
   223  func TestFilePacketConn(t *testing.T) {
   224  	switch runtime.GOOS {
   225  	case "plan9", "windows", "js", "wasip1":
   226  		t.Skipf("not supported on %s", runtime.GOOS)
   227  	}
   228  
   229  	for _, tt := range filePacketConnTests {
   230  		if !testableNetwork(tt.network) {
   231  			t.Logf("skipping %s test", tt.network)
   232  			continue
   233  		}
   234  
   235  		c1 := newLocalPacketListener(t, tt.network)
   236  		switch tt.network {
   237  		case "unixgram":
   238  			defer os.Remove(c1.LocalAddr().String())
   239  		}
   240  		addr := c1.LocalAddr()
   241  
   242  		var (
   243  			f   *os.File
   244  			err error
   245  		)
   246  		switch c1 := c1.(type) {
   247  		case *UDPConn:
   248  			f, err = c1.File()
   249  		case *UnixConn:
   250  			f, err = c1.File()
   251  		}
   252  		if err := c1.Close(); err != nil {
   253  			if perr := parseCloseError(err, false); perr != nil {
   254  				t.Error(perr)
   255  			}
   256  			t.Error(err)
   257  		}
   258  		if err != nil {
   259  			if perr := parseCommonError(err); perr != nil {
   260  				t.Error(perr)
   261  			}
   262  			t.Fatal(err)
   263  		}
   264  
   265  		c2, err := FilePacketConn(f)
   266  		if err := f.Close(); err != nil {
   267  			t.Error(err)
   268  		}
   269  		if err != nil {
   270  			if perr := parseCommonError(err); perr != nil {
   271  				t.Error(perr)
   272  			}
   273  			t.Fatal(err)
   274  		}
   275  		defer c2.Close()
   276  
   277  		if _, err := c2.WriteTo([]byte("FILEPACKETCONN TEST"), addr); err != nil {
   278  			if perr := parseWriteError(err); perr != nil {
   279  				t.Error(perr)
   280  			}
   281  			t.Fatal(err)
   282  		}
   283  		if !reflect.DeepEqual(c2.LocalAddr(), addr) {
   284  			t.Fatalf("got %#v; want %#v", c2.LocalAddr(), addr)
   285  		}
   286  	}
   287  }
   288  
   289  // Issue 24483.
   290  func TestFileCloseRace(t *testing.T) {
   291  	switch runtime.GOOS {
   292  	case "plan9", "windows", "js", "wasip1":
   293  		t.Skipf("not supported on %s", runtime.GOOS)
   294  	}
   295  	if !testableNetwork("tcp") {
   296  		t.Skip("tcp not supported")
   297  	}
   298  
   299  	handler := func(ls *localServer, ln Listener) {
   300  		c, err := ln.Accept()
   301  		if err != nil {
   302  			return
   303  		}
   304  		defer c.Close()
   305  		var b [1]byte
   306  		c.Read(b[:])
   307  	}
   308  
   309  	ls := newLocalServer(t, "tcp")
   310  	defer ls.teardown()
   311  	if err := ls.buildup(handler); err != nil {
   312  		t.Fatal(err)
   313  	}
   314  
   315  	const tries = 100
   316  	for i := 0; i < tries; i++ {
   317  		c1, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
   318  		if err != nil {
   319  			t.Fatal(err)
   320  		}
   321  		tc := c1.(*TCPConn)
   322  
   323  		var wg sync.WaitGroup
   324  		wg.Add(2)
   325  		go func() {
   326  			defer wg.Done()
   327  			f, err := tc.File()
   328  			if err == nil {
   329  				f.Close()
   330  			}
   331  		}()
   332  		go func() {
   333  			defer wg.Done()
   334  			c1.Close()
   335  		}()
   336  		wg.Wait()
   337  	}
   338  }
   339  

View as plain text