1// Copyright 2019 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// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris 6 7package runtime_test 8 9import ( 10 "runtime" 11 "syscall" 12 "testing" 13 "unsafe" 14) 15 16func TestNonblockingPipe(t *testing.T) { 17 t.Parallel() 18 19 // NonblockingPipe is the test name for nonblockingPipe. 20 r, w, errno := runtime.NonblockingPipe() 21 if errno != 0 { 22 t.Fatal(syscall.Errno(errno)) 23 } 24 defer func() { 25 runtime.Close(r) 26 runtime.Close(w) 27 }() 28 29 checkIsPipe(t, r, w) 30 checkNonblocking(t, r, "reader") 31 checkCloseonexec(t, r, "reader") 32 checkNonblocking(t, w, "writer") 33 checkCloseonexec(t, w, "writer") 34} 35 36func checkIsPipe(t *testing.T, r, w int32) { 37 bw := byte(42) 38 if n := runtime.Write(uintptr(w), unsafe.Pointer(&bw), 1); n != 1 { 39 t.Fatalf("Write(w, &b, 1) == %d, expected 1", n) 40 } 41 var br byte 42 if n := runtime.Read(r, unsafe.Pointer(&br), 1); n != 1 { 43 t.Fatalf("Read(r, &b, 1) == %d, expected 1", n) 44 } 45 if br != bw { 46 t.Errorf("pipe read %d, expected %d", br, bw) 47 } 48} 49 50func checkNonblocking(t *testing.T, fd int32, name string) { 51 t.Helper() 52 flags, errno := fcntl(uintptr(fd), syscall.F_GETFL, 0) 53 if errno != 0 { 54 t.Errorf("fcntl(%s, F_GETFL) failed: %v", name, syscall.Errno(errno)) 55 } else if flags&syscall.O_NONBLOCK == 0 { 56 t.Errorf("O_NONBLOCK not set in %s flags %#x", name, flags) 57 } 58} 59 60func checkCloseonexec(t *testing.T, fd int32, name string) { 61 t.Helper() 62 flags, errno := fcntl(uintptr(fd), syscall.F_GETFD, 0) 63 if errno != 0 { 64 t.Errorf("fcntl(%s, F_GETFD) failed: %v", name, syscall.Errno(errno)) 65 } else if flags&syscall.FD_CLOEXEC == 0 { 66 t.Errorf("FD_CLOEXEC not set in %s flags %#x", name, flags) 67 } 68} 69 70func TestSetNonblock(t *testing.T) { 71 t.Parallel() 72 73 r, w, errno := runtime.Pipe() 74 if errno != 0 { 75 t.Fatal(syscall.Errno(errno)) 76 } 77 defer func() { 78 runtime.Close(r) 79 runtime.Close(w) 80 }() 81 82 checkIsPipe(t, r, w) 83 84 runtime.SetNonblock(r) 85 runtime.SetNonblock(w) 86 checkNonblocking(t, r, "reader") 87 checkNonblocking(t, w, "writer") 88 89 runtime.Closeonexec(r) 90 runtime.Closeonexec(w) 91 checkCloseonexec(t, r, "reader") 92 checkCloseonexec(t, w, "writer") 93} 94 95//extern __go_fcntl_uintptr 96func fcntlUintptr(fd, cmd, arg uintptr) (uintptr, uintptr) 97 98// Call fcntl libc function rather than calling syscall. 99func fcntl(fd uintptr, cmd int, arg uintptr) (uintptr, syscall.Errno) { 100 res, errno := fcntlUintptr(fd, uintptr(cmd), arg) 101 return res, syscall.Errno(errno) 102} 103