Black Lives Matter. Support the Equal Justice Initiative.

Source file src/net/unixsock_test.go

Documentation: net

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

View as plain text