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 && !windows
     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  		laddr := laddr
   251  		taddr := testUnixAddr(t)
   252  		ta, err := ResolveUnixAddr("unix", taddr)
   253  		if err != nil {
   254  			t.Fatal(err)
   255  		}
   256  		ln, err := ListenUnix("unix", ta)
   257  		if err != nil {
   258  			t.Fatal(err)
   259  		}
   260  		ls := (&streamListener{Listener: ln}).newLocalServer()
   261  		defer ls.teardown()
   262  		if err := ls.buildup(handler); err != nil {
   263  			t.Fatal(err)
   264  		}
   265  
   266  		la, err := ResolveUnixAddr("unix", laddr)
   267  		if err != nil {
   268  			t.Fatal(err)
   269  		}
   270  		c, err := DialUnix("unix", la, ta)
   271  		if err != nil {
   272  			t.Fatal(err)
   273  		}
   274  		defer func() {
   275  			c.Close()
   276  			if la != nil {
   277  				defer os.Remove(laddr)
   278  			}
   279  		}()
   280  		if _, err := c.Write([]byte("UNIXCONN LOCAL AND REMOTE NAME TEST")); err != nil {
   281  			t.Fatal(err)
   282  		}
   283  
   284  		switch runtime.GOOS {
   285  		case "android", "linux":
   286  			if laddr == "" {
   287  				laddr = "@" // autobind feature
   288  			}
   289  		}
   290  		var connAddrs = [3]struct{ got, want Addr }{
   291  			{ln.Addr(), ta},
   292  			{c.LocalAddr(), &UnixAddr{Name: laddr, Net: "unix"}},
   293  			{c.RemoteAddr(), ta},
   294  		}
   295  		for _, ca := range connAddrs {
   296  			if !reflect.DeepEqual(ca.got, ca.want) {
   297  				t.Fatalf("got %#v, expected %#v", ca.got, ca.want)
   298  			}
   299  		}
   300  	}
   301  }
   302  
   303  func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
   304  	if !testableNetwork("unixgram") {
   305  		t.Skip("unixgram test")
   306  	}
   307  
   308  	for _, laddr := range []string{"", testUnixAddr(t)} {
   309  		laddr := laddr
   310  		taddr := testUnixAddr(t)
   311  		ta, err := ResolveUnixAddr("unixgram", taddr)
   312  		if err != nil {
   313  			t.Fatal(err)
   314  		}
   315  		c1, err := ListenUnixgram("unixgram", ta)
   316  		if err != nil {
   317  			t.Fatal(err)
   318  		}
   319  		defer func() {
   320  			c1.Close()
   321  			os.Remove(taddr)
   322  		}()
   323  
   324  		var la *UnixAddr
   325  		if laddr != "" {
   326  			if la, err = ResolveUnixAddr("unixgram", laddr); err != nil {
   327  				t.Fatal(err)
   328  			}
   329  		}
   330  		c2, err := DialUnix("unixgram", la, ta)
   331  		if err != nil {
   332  			t.Fatal(err)
   333  		}
   334  		defer func() {
   335  			c2.Close()
   336  			if la != nil {
   337  				defer os.Remove(laddr)
   338  			}
   339  		}()
   340  
   341  		switch runtime.GOOS {
   342  		case "android", "linux":
   343  			if laddr == "" {
   344  				laddr = "@" // autobind feature
   345  			}
   346  		}
   347  
   348  		var connAddrs = [4]struct{ got, want Addr }{
   349  			{c1.LocalAddr(), ta},
   350  			{c1.RemoteAddr(), nil},
   351  			{c2.LocalAddr(), &UnixAddr{Name: laddr, Net: "unixgram"}},
   352  			{c2.RemoteAddr(), ta},
   353  		}
   354  		for _, ca := range connAddrs {
   355  			if !reflect.DeepEqual(ca.got, ca.want) {
   356  				t.Fatalf("got %#v; want %#v", ca.got, ca.want)
   357  			}
   358  		}
   359  	}
   360  }
   361  
   362  func TestUnixUnlink(t *testing.T) {
   363  	if !testableNetwork("unix") {
   364  		t.Skip("unix test")
   365  	}
   366  	switch runtime.GOOS {
   367  	case "js", "wasip1":
   368  		t.Skipf("skipping: %s does not support Unlink", runtime.GOOS)
   369  	}
   370  
   371  	name := testUnixAddr(t)
   372  
   373  	listen := func(t *testing.T) *UnixListener {
   374  		l, err := Listen("unix", name)
   375  		if err != nil {
   376  			t.Fatal(err)
   377  		}
   378  		return l.(*UnixListener)
   379  	}
   380  	checkExists := func(t *testing.T, desc string) {
   381  		if _, err := os.Stat(name); err != nil {
   382  			t.Fatalf("unix socket does not exist %s: %v", desc, err)
   383  		}
   384  	}
   385  	checkNotExists := func(t *testing.T, desc string) {
   386  		if _, err := os.Stat(name); err == nil {
   387  			t.Fatalf("unix socket does exist %s: %v", desc, err)
   388  		}
   389  	}
   390  
   391  	// Listener should remove on close.
   392  	t.Run("Listen", func(t *testing.T) {
   393  		l := listen(t)
   394  		checkExists(t, "after Listen")
   395  		l.Close()
   396  		checkNotExists(t, "after Listener close")
   397  	})
   398  
   399  	// FileListener should not.
   400  	t.Run("FileListener", func(t *testing.T) {
   401  		l := listen(t)
   402  		f, _ := l.File()
   403  		l1, _ := FileListener(f)
   404  		checkExists(t, "after FileListener")
   405  		f.Close()
   406  		checkExists(t, "after File close")
   407  		l1.Close()
   408  		checkExists(t, "after FileListener close")
   409  		l.Close()
   410  		checkNotExists(t, "after Listener close")
   411  	})
   412  
   413  	// Only first call to l.Close should remove.
   414  	t.Run("SecondClose", func(t *testing.T) {
   415  		l := listen(t)
   416  		checkExists(t, "after Listen")
   417  		l.Close()
   418  		checkNotExists(t, "after Listener close")
   419  		if err := os.WriteFile(name, []byte("hello world"), 0666); err != nil {
   420  			t.Fatalf("cannot recreate socket file: %v", err)
   421  		}
   422  		checkExists(t, "after writing temp file")
   423  		l.Close()
   424  		checkExists(t, "after second Listener close")
   425  		os.Remove(name)
   426  	})
   427  
   428  	// SetUnlinkOnClose should do what it says.
   429  
   430  	t.Run("Listen/SetUnlinkOnClose(true)", func(t *testing.T) {
   431  		l := listen(t)
   432  		checkExists(t, "after Listen")
   433  		l.SetUnlinkOnClose(true)
   434  		l.Close()
   435  		checkNotExists(t, "after Listener close")
   436  	})
   437  
   438  	t.Run("Listen/SetUnlinkOnClose(false)", func(t *testing.T) {
   439  		l := listen(t)
   440  		checkExists(t, "after Listen")
   441  		l.SetUnlinkOnClose(false)
   442  		l.Close()
   443  		checkExists(t, "after Listener close")
   444  		os.Remove(name)
   445  	})
   446  
   447  	t.Run("FileListener/SetUnlinkOnClose(true)", func(t *testing.T) {
   448  		l := listen(t)
   449  		f, _ := l.File()
   450  		l1, _ := FileListener(f)
   451  		checkExists(t, "after FileListener")
   452  		l1.(*UnixListener).SetUnlinkOnClose(true)
   453  		f.Close()
   454  		checkExists(t, "after File close")
   455  		l1.Close()
   456  		checkNotExists(t, "after FileListener close")
   457  		l.Close()
   458  	})
   459  
   460  	t.Run("FileListener/SetUnlinkOnClose(false)", func(t *testing.T) {
   461  		l := listen(t)
   462  		f, _ := l.File()
   463  		l1, _ := FileListener(f)
   464  		checkExists(t, "after FileListener")
   465  		l1.(*UnixListener).SetUnlinkOnClose(false)
   466  		f.Close()
   467  		checkExists(t, "after File close")
   468  		l1.Close()
   469  		checkExists(t, "after FileListener close")
   470  		l.Close()
   471  	})
   472  }
   473  

View as plain text