aboutsummaryrefslogtreecommitdiff
path: root/unix/syscall_unix_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'unix/syscall_unix_test.go')
-rw-r--r--unix/syscall_unix_test.go118
1 files changed, 116 insertions, 2 deletions
diff --git a/unix/syscall_unix_test.go b/unix/syscall_unix_test.go
index f2c0ed8..0517689 100644
--- a/unix/syscall_unix_test.go
+++ b/unix/syscall_unix_test.go
@@ -322,7 +322,7 @@ func passFDChild() {
}
}
-// TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage,
+// TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage, ParseOneSocketControlMessage,
// and ParseUnixRights are able to successfully round-trip lists of file descriptors.
func TestUnixRightsRoundtrip(t *testing.T) {
testCases := [...][][]int{
@@ -350,6 +350,23 @@ func TestUnixRightsRoundtrip(t *testing.T) {
if len(scms) != len(testCase) {
t.Fatalf("expected %v SocketControlMessage; got scms = %#v", len(testCase), scms)
}
+
+ var c int
+ for len(b) > 0 {
+ hdr, data, remainder, err := unix.ParseOneSocketControlMessage(b)
+ if err != nil {
+ t.Fatalf("ParseOneSocketControlMessage: %v", err)
+ }
+ if scms[c].Header != hdr || !bytes.Equal(scms[c].Data, data) {
+ t.Fatal("expected SocketControlMessage header and data to match")
+ }
+ b = remainder
+ c++
+ }
+ if c != len(scms) {
+ t.Fatalf("expected %d SocketControlMessages; got %d", len(scms), c)
+ }
+
for i, scm := range scms {
gotFds, err := unix.ParseUnixRights(&scm)
if err != nil {
@@ -975,7 +992,8 @@ func TestSendmsgBuffers(t *testing.T) {
}
n, oobn, recvflags, _, err := unix.RecvmsgBuffers(fds[1], bufs, nil, 0)
if err != nil {
- t.Fatal(err)
+ t.Error(err)
+ return
}
if n != 10 {
t.Errorf("got %d bytes, want 10", n)
@@ -1014,6 +1032,102 @@ func TestSendmsgBuffers(t *testing.T) {
}
}
+// Issue 56384.
+func TestRecvmsgControl(t *testing.T) {
+ switch runtime.GOOS {
+ case "solaris", "illumos":
+ // Test fails on Solaris, saying
+ // "got 0 control messages, want 1".
+ // Not sure why; Solaris recvmsg man page says
+ // "For processes on the same host, recvmsg() can be
+ // used to receive a file descriptor from another
+ // process, but it cannot receive ancillary data."
+ t.Skipf("skipping on %s", runtime.GOOS)
+ }
+
+ fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer unix.Close(fds[0])
+ defer unix.Close(fds[1])
+
+ const payload = "hello"
+
+ // Start a goroutine that sends a control message followed by
+ // a payload on fds[1].
+ go func() {
+ f, err := os.Create(filepath.Join(t.TempDir(), "file"))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer f.Close()
+
+ rc, err := f.SyscallConn()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ var rights []byte
+ err = rc.Control(func(fd uintptr) {
+ rights = unix.UnixRights(int(fd))
+ })
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ _, err = unix.SendmsgN(fds[1], nil, rights, nil, 0)
+ if err != nil {
+ t.Error(err)
+ }
+ if _, err := unix.Write(fds[1], []byte(payload)); err != nil {
+ t.Error(err)
+ }
+ }()
+
+ // Read the control message sent by the goroutine. The
+ // goroutine writes to fds[1], we read from fds[0].
+
+ cbuf := make([]byte, unix.CmsgSpace(4))
+ _, cn, _, _, err := unix.Recvmsg(fds[0], nil, cbuf, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ cbuf = cbuf[:cn]
+
+ // Read the payload sent by the goroutine.
+
+ buf := make([]byte, len(payload))
+ n, err := unix.Read(fds[0], buf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ buf = buf[:n]
+ if payload != string(buf) {
+ t.Errorf("read payload %q, want %q", buf, payload)
+ }
+
+ // Check the control message.
+
+ cmsgs, err := unix.ParseSocketControlMessage(cbuf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(cmsgs) != 1 {
+ t.Fatalf("got %d control messages, want 1", len(cmsgs))
+ }
+ cfds, err := unix.ParseUnixRights(&cmsgs[0])
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(cfds) != 1 {
+ t.Fatalf("got %d fds, want 1", len(cfds))
+ }
+ defer unix.Close(cfds[0])
+}
+
// mktmpfifo creates a temporary FIFO and provides a cleanup function.
func mktmpfifo(t *testing.T) (*os.File, func()) {
err := unix.Mkfifo("fifo", 0666)