github.com/Kalvelign/golang-windows-sys-lib@v0.0.0-20221121121202-63da651435e1/unix/syscall_darwin_test.go (about) 1 // Copyright 2018 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 package unix_test 6 7 import ( 8 "bytes" 9 "io/ioutil" 10 "net" 11 "os" 12 "path" 13 "testing" 14 15 "golang.org/x/sys/unix" 16 ) 17 18 var testData = []byte("This is a test\n") 19 20 // stringsFromByteSlice converts a sequence of attributes to a []string. 21 // On Darwin, each entry is a NULL-terminated string. 22 func stringsFromByteSlice(buf []byte) []string { 23 var result []string 24 off := 0 25 for i, b := range buf { 26 if b == 0 { 27 result = append(result, string(buf[off:i])) 28 off = i + 1 29 } 30 } 31 return result 32 } 33 34 func createTestFile(t *testing.T, dir string) (f *os.File, cleanup func() error) { 35 file, err := ioutil.TempFile(dir, t.Name()) 36 if err != nil { 37 t.Fatal(err) 38 } 39 40 _, err = file.Write(testData) 41 if err != nil { 42 t.Fatal(err) 43 } 44 45 err = file.Close() 46 if err != nil { 47 t.Fatal(err) 48 } 49 50 return file, func() error { 51 return os.Remove(file.Name()) 52 } 53 } 54 55 func TestClonefile(t *testing.T) { 56 file, cleanup := createTestFile(t, "") 57 defer cleanup() 58 59 clonedName := file.Name() + "-cloned" 60 err := unix.Clonefile(file.Name(), clonedName, 0) 61 if err == unix.ENOSYS || err == unix.ENOTSUP { 62 t.Skip("clonefile is not available or supported, skipping test") 63 } else if err != nil { 64 t.Fatal(err) 65 } 66 defer os.Remove(clonedName) 67 68 clonedData, err := ioutil.ReadFile(clonedName) 69 if err != nil { 70 t.Fatal(err) 71 } 72 73 if !bytes.Equal(testData, clonedData) { 74 t.Errorf("Clonefile: got %q, expected %q", clonedData, testData) 75 } 76 } 77 78 func TestClonefileatWithCwd(t *testing.T) { 79 file, cleanup := createTestFile(t, "") 80 defer cleanup() 81 82 clonedName := file.Name() + "-cloned" 83 err := unix.Clonefileat(unix.AT_FDCWD, file.Name(), unix.AT_FDCWD, clonedName, 0) 84 if err == unix.ENOSYS || err == unix.ENOTSUP { 85 t.Skip("clonefileat is not available or supported, skipping test") 86 } else if err != nil { 87 t.Fatal(err) 88 } 89 defer os.Remove(clonedName) 90 91 clonedData, err := ioutil.ReadFile(clonedName) 92 if err != nil { 93 t.Fatal(err) 94 } 95 96 if !bytes.Equal(testData, clonedData) { 97 t.Errorf("Clonefileat: got %q, expected %q", clonedData, testData) 98 } 99 } 100 101 func TestClonefileatWithRelativePaths(t *testing.T) { 102 srcDir, err := ioutil.TempDir("", "src") 103 if err != nil { 104 t.Fatal(err) 105 } 106 defer os.RemoveAll(srcDir) 107 108 dstDir, err := ioutil.TempDir("", "dest") 109 if err != nil { 110 t.Fatal(err) 111 } 112 defer os.RemoveAll(dstDir) 113 114 srcFd, err := unix.Open(srcDir, unix.O_RDONLY|unix.O_DIRECTORY, 0) 115 if err != nil { 116 t.Fatal(err) 117 } 118 defer unix.Close(srcFd) 119 120 dstFd, err := unix.Open(dstDir, unix.O_RDONLY|unix.O_DIRECTORY, 0) 121 if err != nil { 122 t.Fatal(err) 123 } 124 defer unix.Close(dstFd) 125 126 srcFile, cleanup := createTestFile(t, srcDir) 127 defer cleanup() 128 129 dstFile, err := ioutil.TempFile(dstDir, "TestClonefileat") 130 if err != nil { 131 t.Fatal(err) 132 } 133 err = os.Remove(dstFile.Name()) 134 if err != nil { 135 t.Fatal(err) 136 } 137 138 src := path.Base(srcFile.Name()) 139 dst := path.Base(dstFile.Name()) 140 err = unix.Clonefileat(srcFd, src, dstFd, dst, 0) 141 if err == unix.ENOSYS || err == unix.ENOTSUP { 142 t.Skip("clonefileat is not available or supported, skipping test") 143 } else if err != nil { 144 t.Fatal(err) 145 } 146 147 clonedData, err := ioutil.ReadFile(dstFile.Name()) 148 if err != nil { 149 t.Fatal(err) 150 } 151 152 if !bytes.Equal(testData, clonedData) { 153 t.Errorf("Clonefileat: got %q, expected %q", clonedData, testData) 154 } 155 } 156 157 func TestFclonefileat(t *testing.T) { 158 file, cleanup := createTestFile(t, "") 159 defer cleanup() 160 161 fd, err := unix.Open(file.Name(), unix.O_RDONLY, 0) 162 if err != nil { 163 t.Fatal(err) 164 } 165 defer unix.Close(fd) 166 167 dstFile, err := ioutil.TempFile("", "TestFclonefileat") 168 if err != nil { 169 t.Fatal(err) 170 } 171 os.Remove(dstFile.Name()) 172 173 err = unix.Fclonefileat(fd, unix.AT_FDCWD, dstFile.Name(), 0) 174 if err == unix.ENOSYS || err == unix.ENOTSUP { 175 t.Skip("clonefileat is not available or supported, skipping test") 176 } else if err != nil { 177 t.Fatal(err) 178 } 179 180 clonedData, err := ioutil.ReadFile(dstFile.Name()) 181 if err != nil { 182 t.Fatal(err) 183 } 184 185 if !bytes.Equal(testData, clonedData) { 186 t.Errorf("Fclonefileat: got %q, expected %q", clonedData, testData) 187 } 188 } 189 190 func TestFcntlFstore(t *testing.T) { 191 f, err := ioutil.TempFile("", t.Name()) 192 if err != nil { 193 t.Fatal(err) 194 } 195 defer os.Remove(f.Name()) 196 defer f.Close() 197 198 fstore := &unix.Fstore_t{ 199 Flags: unix.F_ALLOCATEALL, 200 Posmode: unix.F_PEOFPOSMODE, 201 Offset: 0, 202 Length: 1 << 10, 203 } 204 err = unix.FcntlFstore(f.Fd(), unix.F_PREALLOCATE, fstore) 205 if err == unix.EOPNOTSUPP { 206 t.Skipf("fcntl with F_PREALLOCATE not supported, skipping test") 207 } else if err != nil { 208 t.Fatalf("FcntlFstore: %v", err) 209 } 210 211 st, err := f.Stat() 212 if err != nil { 213 t.Fatal(err) 214 } 215 216 if st.Size() != 0 { 217 t.Errorf("FcntlFstore: got size = %d, want %d", st.Size(), 0) 218 } 219 220 } 221 222 func TestGetsockoptXucred(t *testing.T) { 223 fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0) 224 if err != nil { 225 t.Fatalf("Socketpair: %v", err) 226 } 227 228 srvFile := os.NewFile(uintptr(fds[0]), "server") 229 cliFile := os.NewFile(uintptr(fds[1]), "client") 230 defer srvFile.Close() 231 defer cliFile.Close() 232 233 srv, err := net.FileConn(srvFile) 234 if err != nil { 235 t.Fatalf("FileConn: %v", err) 236 } 237 defer srv.Close() 238 239 cli, err := net.FileConn(cliFile) 240 if err != nil { 241 t.Fatalf("FileConn: %v", err) 242 } 243 defer cli.Close() 244 245 cred, err := unix.GetsockoptXucred(fds[1], unix.SOL_LOCAL, unix.LOCAL_PEERCRED) 246 if err != nil { 247 t.Fatal(err) 248 } 249 t.Logf("got: %+v", cred) 250 if got, want := cred.Uid, os.Getuid(); int(got) != int(want) { 251 t.Errorf("uid = %v; want %v", got, want) 252 } 253 if cred.Ngroups > 0 { 254 if got, want := cred.Groups[0], os.Getgid(); int(got) != int(want) { 255 t.Errorf("gid = %v; want %v", got, want) 256 } 257 } 258 } 259 260 func TestSysctlKinfoProc(t *testing.T) { 261 pid := unix.Getpid() 262 kp, err := unix.SysctlKinfoProc("kern.proc.pid", pid) 263 if err != nil { 264 t.Fatalf("SysctlKinfoProc: %v", err) 265 } 266 if got, want := int(kp.Proc.P_pid), pid; got != want { 267 t.Errorf("got pid %d, want %d", got, want) 268 } 269 } 270 271 func TestSysctlKinfoProcSlice(t *testing.T) { 272 kps, err := unix.SysctlKinfoProcSlice("kern.proc.all") 273 if err != nil { 274 t.Fatalf("SysctlKinfoProc: %v", err) 275 } 276 if len(kps) == 0 { 277 t.Errorf("SysctlKinfoProcSlice: expected at least one process") 278 } 279 280 uid := unix.Getuid() 281 kps, err = unix.SysctlKinfoProcSlice("kern.proc.uid", uid) 282 if err != nil { 283 t.Fatalf("SysctlKinfoProc: %v", err) 284 } 285 if len(kps) == 0 { 286 t.Errorf("SysctlKinfoProcSlice: expected at least one process") 287 } 288 289 for _, kp := range kps { 290 if got, want := int(kp.Eproc.Ucred.Uid), uid; got != want { 291 t.Errorf("process %d: got uid %d, want %d", kp.Proc.P_pid, got, want) 292 } 293 } 294 }