Source file src/net/unixsock_test.go

     1  // Copyright 2013 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 !plan9
     6  
     7  package net
     8  
     9  import (
    10  	"bytes"
    11  	"internal/testenv"
    12  	"os"
    13  	"reflect"
    14  	"runtime"
    15  	"syscall"
    16  	"testing"
    17  	"time"
    18  )
    19  
    20  func TestReadUnixgramWithUnnamedSocket(t *testing.T) {
    21  	if !testableNetwork("unixgram") {
    22  		t.Skip("unixgram test")
    23  	}
    24  	switch runtime.GOOS {
    25  	case "js", "wasip1":
    26  		t.Skipf("skipping: syscall.Socket not implemented on %s", runtime.GOOS)
    27  	}
    28  	if runtime.GOOS == "openbsd" {
    29  		testenv.SkipFlaky(t, 15157)
    30  	}
    31  
    32  	addr := testUnixAddr(t)
    33  	la, err := ResolveUnixAddr("unixgram", addr)
    34  	if err != nil {
    35  		t.Fatal(err)
    36  	}
    37  	c, err := ListenUnixgram("unixgram", la)
    38  	if err != nil {
    39  		t.Fatal(err)
    40  	}
    41  	defer func() {
    42  		c.Close()
    43  		os.Remove(addr)
    44  	}()
    45  
    46  	off := make(chan bool)
    47  	data := [5]byte{1, 2, 3, 4, 5}
    48  	go func() {
    49  		defer func() { off <- true }()
    50  		s, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
    51  		if err != nil {
    52  			t.Error(err)
    53  			return
    54  		}
    55  		defer syscall.Close(s)
    56  		rsa := &syscall.SockaddrUnix{Name: addr}
    57  		if err := syscall.Sendto(s, data[:], 0, rsa); err != nil {
    58  			t.Error(err)
    59  			return
    60  		}
    61  	}()
    62  
    63  	<-off
    64  	b := make([]byte, 64)
    65  	c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
    66  	n, from, err := c.ReadFrom(b)
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  	if from != nil {
    71  		t.Fatalf("unexpected peer address: %v", from)
    72  	}
    73  	if !bytes.Equal(b[:n], data[:]) {
    74  		t.Fatalf("got %v; want %v", b[:n], data[:])
    75  	}
    76  }
    77  
    78  func TestUnixgramZeroBytePayload(t *testing.T) {
    79  	if !testableNetwork("unixgram") {
    80  		t.Skip("unixgram test")
    81  	}
    82  
    83  	c1 := newLocalPacketListener(t, "unixgram")
    84  	defer os.Remove(c1.LocalAddr().String())
    85  	defer c1.Close()
    86  
    87  	c2, err := Dial("unixgram", c1.LocalAddr().String())
    88  	if err != nil {
    89  		t.Fatal(err)
    90  	}
    91  	defer os.Remove(c2.LocalAddr().String())
    92  	defer c2.Close()
    93  
    94  	for _, genericRead := range []bool{false, true} {
    95  		n, err := c2.Write(nil)
    96  		if err != nil {
    97  			t.Fatal(err)
    98  		}
    99  		if n != 0 {
   100  			t.Errorf("got %d; want 0", n)
   101  		}
   102  		c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
   103  		var b [1]byte
   104  		var peer Addr
   105  		if genericRead {
   106  			_, err = c1.(Conn).Read(b[:])
   107  		} else {
   108  			_, peer, err = c1.ReadFrom(b[:])
   109  		}
   110  		switch err {
   111  		case nil: // ReadFrom succeeds
   112  			if peer != nil { // peer is connected-mode
   113  				t.Fatalf("unexpected peer address: %v", peer)
   114  			}
   115  		default: // Read may timeout, it depends on the platform
   116  			if !isDeadlineExceeded(err) {
   117  				t.Fatal(err)
   118  			}
   119  		}
   120  	}
   121  }
   122  
   123  func TestUnixgramZeroByteBuffer(t *testing.T) {
   124  	if !testableNetwork("unixgram") {
   125  		t.Skip("unixgram test")
   126  	}
   127  	// issue 4352: Recvfrom failed with "address family not
   128  	// supported by protocol family" if zero-length buffer provided
   129  
   130  	c1 := newLocalPacketListener(t, "unixgram")
   131  	defer os.Remove(c1.LocalAddr().String())
   132  	defer c1.Close()
   133  
   134  	c2, err := Dial("unixgram", c1.LocalAddr().String())
   135  	if err != nil {
   136  		t.Fatal(err)
   137  	}
   138  	defer os.Remove(c2.LocalAddr().String())
   139  	defer c2.Close()
   140  
   141  	b := []byte("UNIXGRAM ZERO BYTE BUFFER TEST")
   142  	for _, genericRead := range []bool{false, true} {
   143  		n, err := c2.Write(b)
   144  		if err != nil {
   145  			t.Fatal(err)
   146  		}
   147  		if n != len(b) {
   148  			t.Errorf("got %d; want %d", n, len(b))
   149  		}
   150  		c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
   151  		var peer Addr
   152  		if genericRead {
   153  			_, err = c1.(Conn).Read(nil)
   154  		} else {
   155  			_, peer, err = c1.ReadFrom(nil)
   156  		}
   157  		switch err {
   158  		case nil: // ReadFrom succeeds
   159  			if peer != nil { // peer is connected-mode
   160  				t.Fatalf("unexpected peer address: %v", peer)
   161  			}
   162  		default: // Read may timeout, it depends on the platform
   163  			if !isDeadlineExceeded(err) {
   164  				t.Fatal(err)
   165  			}
   166  		}
   167  	}
   168  }
   169  
   170  func TestUnixgramWrite(t *testing.T) {
   171  	if !testableNetwork("unixgram") {
   172  		t.Skip("unixgram test")
   173  	}
   174  
   175  	addr := testUnixAddr(t)
   176  	laddr, err := ResolveUnixAddr("unixgram", addr)
   177  	if err != nil {
   178  		t.Fatal(err)
   179  	}
   180  	c, err := ListenPacket("unixgram", addr)
   181  	if err != nil {
   182  		t.Fatal(err)
   183  	}
   184  	defer os.Remove(addr)
   185  	defer c.Close()
   186  
   187  	testUnixgramWriteConn(t, laddr)
   188  	testUnixgramWritePacketConn(t, laddr)
   189  }
   190  
   191  func testUnixgramWriteConn(t *testing.T, raddr *UnixAddr) {
   192  	c, err := Dial("unixgram", raddr.String())
   193  	if err != nil {
   194  		t.Fatal(err)
   195  	}
   196  	defer c.Close()
   197  
   198  	b := []byte("CONNECTED-MODE SOCKET")
   199  	if _, err := c.(*UnixConn).WriteToUnix(b, raddr); err == nil {
   200  		t.Fatal("should fail")
   201  	} else if err.(*OpError).Err != ErrWriteToConnected {
   202  		t.Fatalf("should fail as ErrWriteToConnected: %v", err)
   203  	}
   204  	if _, err = c.(*UnixConn).WriteTo(b, raddr); err == nil {
   205  		t.Fatal("should fail")
   206  	} else if err.(*OpError).Err != ErrWriteToConnected {
   207  		t.Fatalf("should fail as ErrWriteToConnected: %v", err)
   208  	}
   209  	if _, _, err = c.(*UnixConn).WriteMsgUnix(b, nil, raddr); err == nil {
   210  		t.Fatal("should fail")
   211  	} else if err.(*OpError).Err != ErrWriteToConnected {
   212  		t.Fatalf("should fail as ErrWriteToConnected: %v", err)
   213  	}
   214  	if _, err := c.Write(b); err != nil {
   215  		t.Fatal(err)
   216  	}
   217  }
   218  
   219  func testUnixgramWritePacketConn(t *testing.T, raddr *UnixAddr) {
   220  	addr := testUnixAddr(t)
   221  	c, err := ListenPacket("unixgram", addr)
   222  	if err != nil {
   223  		t.Fatal(err)
   224  	}
   225  	defer os.Remove(addr)
   226  	defer c.Close()
   227  
   228  	b := []byte("UNCONNECTED-MODE SOCKET")
   229  	if _, err := c.(*UnixConn).WriteToUnix(b, raddr); err != nil {
   230  		t.Fatal(err)
   231  	}
   232  	if _, err := c.WriteTo(b, raddr); err != nil {
   233  		t.Fatal(err)
   234  	}
   235  	if _, _, err := c.(*UnixConn).WriteMsgUnix(b, nil, raddr); err != nil {
   236  		t.Fatal(err)
   237  	}
   238  	if _, err := c.(*UnixConn).Write(b); err == nil {
   239  		t.Fatal("should fail")
   240  	}
   241  }
   242  
   243  func TestUnixConnLocalAndRemoteNames(t *testing.T) {
   244  	if !testableNetwork("unix") {
   245  		t.Skip("unix test")
   246  	}
   247  
   248  	handler := func(ls *localServer, ln Listener) {}
   249  	for _, laddr := range []string{"", testUnixAddr(t)} {
   250  		taddr := testUnixAddr(t)
   251  		ta, err := ResolveUnixAddr("unix", taddr)
   252  		if err != nil {
   253  			t.Fatal(err)
   254  		}
   255  		ln, err := ListenUnix("unix", ta)
   256  		if err != nil {
   257  			t.Fatal(err)
   258  		}
   259  		ls := (&streamListener{Listener: ln}).newLocalServer()
   260  		defer ls.teardown()
   261  		if err := ls.buildup(handler); err != nil {
   262  			t.Fatal(err)
   263  		}
   264  
   265  		la, err := ResolveUnixAddr("unix", laddr)
   266  		if err != nil {
   267  			t.Fatal(err)
   268  		}
   269  		c, err := DialUnix("unix", la, ta)
   270  		if err != nil {
   271  			t.Fatal(err)
   272  		}
   273  		defer func() {
   274  			c.Close()
   275  			if la != nil {
   276  				defer os.Remove(laddr)
   277  			}
   278  		}()
   279  		if _, err := c.Write([]byte("UNIXCONN LOCAL AND REMOTE NAME TEST")); err != nil {
   280  			t.Fatal(err)
   281  		}
   282  
   283  		switch runtime.GOOS {
   284  		case "android", "linux", "windows":
   285  			if laddr == "" {
   286  				laddr = "@" // autobind feature
   287  			}
   288  		}
   289  		var connAddrs = [3]struct{ got, want Addr }{
   290  			{ln.Addr(), ta},
   291  			{c.LocalAddr(), &UnixAddr{Name: laddr, Net: "unix"}},
   292  			{c.RemoteAddr(), ta},
   293  		}
   294  		for _, ca := range connAddrs {
   295  			if !reflect.DeepEqual(ca.got, ca.want) {
   296  				t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
   297  			}
   298  		}
   299  	}
   300  }
   301  
   302  func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
   303  	if !testableNetwork("unixgram") {
   304  		t.Skip("unixgram test")
   305  	}
   306  
   307  	for _, laddr := range []string{"", testUnixAddr(t)} {
   308  		taddr := testUnixAddr(t)
   309  		ta, err := ResolveUnixAddr("unixgram", taddr)
   310  		if err != nil {
   311  			t.Fatal(err)
   312  		}
   313  		c1, err := ListenUnixgram("unixgram", ta)
   314  		if err != nil {
   315  			t.Fatal(err)
   316  		}
   317  		defer func() {
   318  			c1.Close()
   319  			os.Remove(taddr)
   320  		}()
   321  
   322  		var la *UnixAddr
   323  		if laddr != "" {
   324  			if la, err = ResolveUnixAddr("unixgram", laddr); err != nil {
   325  				t.Fatal(err)
   326  			}
   327  		}
   328  		c2, err := DialUnix("unixgram", la, ta)
   329  		if err != nil {
   330  			t.Fatal(err)
   331  		}
   332  		defer func() {
   333  			c2.Close()
   334  			if la != nil {
   335  				defer os.Remove(laddr)
   336  			}
   337  		}()
   338  
   339  		switch runtime.GOOS {
   340  		case "android", "linux":
   341  			if laddr == "" {
   342  				laddr = "@" // autobind feature
   343  			}
   344  		}
   345  
   346  		var connAddrs = [4]struct{ got, want Addr }{
   347  			{c1.LocalAddr(), ta},
   348  			{c1.RemoteAddr(), nil},
   349  			{c2.LocalAddr(), &UnixAddr{Name: laddr, Net: "unixgram"}},
   350  			{c2.RemoteAddr(), ta},
   351  		}
   352  		for _, ca := range connAddrs {
   353  			if !reflect.DeepEqual(ca.got, ca.want) {
   354  				t.Fatalf("got %#v; want %#v", ca.got, ca.want)
   355  			}
   356  		}
   357  	}
   358  }
   359  
   360  func TestUnixUnlink(t *testing.T) {
   361  	if !testableNetwork("unix") {
   362  		t.Skip("unix test")
   363  	}
   364  	switch runtime.GOOS {
   365  	case "js", "wasip1":
   366  		t.Skipf("skipping: %s does not support Unlink", runtime.GOOS)
   367  	}
   368  
   369  	name := testUnixAddr(t)
   370  
   371  	listen := func(t *testing.T) *UnixListener {
   372  		l, err := Listen("unix", name)
   373  		if err != nil {
   374  			t.Fatal(err)
   375  		}
   376  		return l.(*UnixListener)
   377  	}
   378  	fileListener := func(t *testing.T, l *UnixListener) (*os.File, Listener) {
   379  		f, err := l.File()
   380  		if err != nil {
   381  			t.Fatal(err)
   382  		}
   383  		ln, err := FileListener(f)
   384  		if err != nil {
   385  			t.Fatal(err)
   386  		}
   387  		return f, ln
   388  	}
   389  	checkExists := func(t *testing.T, desc string) {
   390  		if _, err := os.Stat(name); err != nil {
   391  			t.Fatalf("unix socket does not exist %s: %v", desc, err)
   392  		}
   393  	}
   394  	checkNotExists := func(t *testing.T, desc string) {
   395  		if _, err := os.Stat(name); err == nil {
   396  			t.Fatalf("unix socket does exist %s: %v", desc, err)
   397  		}
   398  	}
   399  
   400  	// Listener should remove on close.
   401  	t.Run("Listen", func(t *testing.T) {
   402  		l := listen(t)
   403  		checkExists(t, "after Listen")
   404  		l.Close()
   405  		checkNotExists(t, "after Listener close")
   406  	})
   407  
   408  	// FileListener should not.
   409  	t.Run("FileListener", func(t *testing.T) {
   410  		l := listen(t)
   411  		f, l1 := fileListener(t, l)
   412  		checkExists(t, "after FileListener")
   413  		f.Close()
   414  		checkExists(t, "after File close")
   415  		l1.Close()
   416  		checkExists(t, "after FileListener close")
   417  		l.Close()
   418  		checkNotExists(t, "after Listener close")
   419  	})
   420  
   421  	// Only first call to l.Close should remove.
   422  	t.Run("SecondClose", func(t *testing.T) {
   423  		l := listen(t)
   424  		checkExists(t, "after Listen")
   425  		l.Close()
   426  		checkNotExists(t, "after Listener close")
   427  		if err := os.WriteFile(name, []byte("hello world"), 0666); err != nil {
   428  			t.Fatalf("cannot recreate socket file: %v", err)
   429  		}
   430  		checkExists(t, "after writing temp file")
   431  		l.Close()
   432  		checkExists(t, "after second Listener close")
   433  		os.Remove(name)
   434  	})
   435  
   436  	// SetUnlinkOnClose should do what it says.
   437  
   438  	t.Run("Listen/SetUnlinkOnClose(true)", func(t *testing.T) {
   439  		l := listen(t)
   440  		checkExists(t, "after Listen")
   441  		l.SetUnlinkOnClose(true)
   442  		l.Close()
   443  		checkNotExists(t, "after Listener close")
   444  	})
   445  
   446  	t.Run("Listen/SetUnlinkOnClose(false)", func(t *testing.T) {
   447  		l := listen(t)
   448  		checkExists(t, "after Listen")
   449  		l.SetUnlinkOnClose(false)
   450  		l.Close()
   451  		checkExists(t, "after Listener close")
   452  		os.Remove(name)
   453  	})
   454  
   455  	t.Run("FileListener/SetUnlinkOnClose(true)", func(t *testing.T) {
   456  		l := listen(t)
   457  		f, l1 := fileListener(t, l)
   458  		checkExists(t, "after FileListener")
   459  		l1.(*UnixListener).SetUnlinkOnClose(true)
   460  		f.Close()
   461  		checkExists(t, "after File close")
   462  		l1.Close()
   463  		checkNotExists(t, "after FileListener close")
   464  		l.Close()
   465  	})
   466  
   467  	t.Run("FileListener/SetUnlinkOnClose(false)", func(t *testing.T) {
   468  		l := listen(t)
   469  		f, l1 := fileListener(t, l)
   470  		checkExists(t, "after FileListener")
   471  		l1.(*UnixListener).SetUnlinkOnClose(false)
   472  		f.Close()
   473  		checkExists(t, "after File close")
   474  		l1.Close()
   475  		checkExists(t, "after FileListener close")
   476  		l.Close()
   477  	})
   478  }
   479  

View as plain text