github.com/go-xe2/third@v1.0.3/golang.org/x/sys/unix/syscall_linux_test.go (about) 1 // Copyright 2016 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 linux 6 7 package unix_test 8 9 import ( 10 "io/ioutil" 11 "os" 12 "runtime" 13 "runtime/debug" 14 "testing" 15 "time" 16 17 "github.com/go-xe2/third/golang.org/x/sys/unix" 18 ) 19 20 func TestIoctlGetInt(t *testing.T) { 21 f, err := os.Open("/dev/random") 22 if err != nil { 23 t.Fatalf("failed to open device: %v", err) 24 } 25 defer f.Close() 26 27 v, err := unix.IoctlGetInt(int(f.Fd()), unix.RNDGETENTCNT) 28 if err != nil { 29 t.Fatalf("failed to perform ioctl: %v", err) 30 } 31 32 t.Logf("%d bits of entropy available", v) 33 } 34 35 func TestPpoll(t *testing.T) { 36 if runtime.GOOS == "android" { 37 t.Skip("mkfifo syscall is not available on android, skipping test") 38 } 39 40 f, cleanup := mktmpfifo(t) 41 defer cleanup() 42 43 const timeout = 100 * time.Millisecond 44 45 ok := make(chan bool, 1) 46 go func() { 47 select { 48 case <-time.After(10 * timeout): 49 t.Errorf("Ppoll: failed to timeout after %d", 10*timeout) 50 case <-ok: 51 } 52 }() 53 54 fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}} 55 timeoutTs := unix.NsecToTimespec(int64(timeout)) 56 n, err := unix.Ppoll(fds, &timeoutTs, nil) 57 ok <- true 58 if err != nil { 59 t.Errorf("Ppoll: unexpected error: %v", err) 60 return 61 } 62 if n != 0 { 63 t.Errorf("Ppoll: wrong number of events: got %v, expected %v", n, 0) 64 return 65 } 66 } 67 68 func TestTime(t *testing.T) { 69 var ut unix.Time_t 70 ut2, err := unix.Time(&ut) 71 if err != nil { 72 t.Fatalf("Time: %v", err) 73 } 74 if ut != ut2 { 75 t.Errorf("Time: return value %v should be equal to argument %v", ut2, ut) 76 } 77 78 var now time.Time 79 80 for i := 0; i < 10; i++ { 81 ut, err = unix.Time(nil) 82 if err != nil { 83 t.Fatalf("Time: %v", err) 84 } 85 86 now = time.Now() 87 88 if int64(ut) == now.Unix() { 89 return 90 } 91 } 92 93 t.Errorf("Time: return value %v should be nearly equal to time.Now().Unix() %v", ut, now.Unix()) 94 } 95 96 func TestUtime(t *testing.T) { 97 defer chtmpdir(t)() 98 99 touch(t, "file1") 100 101 buf := &unix.Utimbuf{ 102 Modtime: 12345, 103 } 104 105 err := unix.Utime("file1", buf) 106 if err != nil { 107 t.Fatalf("Utime: %v", err) 108 } 109 110 fi, err := os.Stat("file1") 111 if err != nil { 112 t.Fatal(err) 113 } 114 115 if fi.ModTime().Unix() != 12345 { 116 t.Errorf("Utime: failed to change modtime: expected %v, got %v", 12345, fi.ModTime().Unix()) 117 } 118 } 119 120 func TestUtimesNanoAt(t *testing.T) { 121 defer chtmpdir(t)() 122 123 symlink := "symlink1" 124 os.Remove(symlink) 125 err := os.Symlink("nonexisting", symlink) 126 if err != nil { 127 t.Fatal(err) 128 } 129 130 ts := []unix.Timespec{ 131 {Sec: 1111, Nsec: 2222}, 132 {Sec: 3333, Nsec: 4444}, 133 } 134 err = unix.UtimesNanoAt(unix.AT_FDCWD, symlink, ts, unix.AT_SYMLINK_NOFOLLOW) 135 if err != nil { 136 t.Fatalf("UtimesNanoAt: %v", err) 137 } 138 139 var st unix.Stat_t 140 err = unix.Lstat(symlink, &st) 141 if err != nil { 142 t.Fatalf("Lstat: %v", err) 143 } 144 145 // Only check Mtim, Atim might not be supported by the underlying filesystem 146 expected := ts[1] 147 if st.Mtim.Nsec == 0 { 148 // Some filesystems only support 1-second time stamp resolution 149 // and will always set Nsec to 0. 150 expected.Nsec = 0 151 } 152 if st.Mtim != expected { 153 t.Errorf("UtimesNanoAt: wrong mtime: expected %v, got %v", expected, st.Mtim) 154 } 155 } 156 157 func TestRlimitAs(t *testing.T) { 158 // disable GC during to avoid flaky test 159 defer debug.SetGCPercent(debug.SetGCPercent(-1)) 160 161 var rlim unix.Rlimit 162 err := unix.Getrlimit(unix.RLIMIT_AS, &rlim) 163 if err != nil { 164 t.Fatalf("Getrlimit: %v", err) 165 } 166 var zero unix.Rlimit 167 if zero == rlim { 168 t.Fatalf("Getrlimit: got zero value %#v", rlim) 169 } 170 set := rlim 171 set.Cur = uint64(unix.Getpagesize()) 172 err = unix.Setrlimit(unix.RLIMIT_AS, &set) 173 if err != nil { 174 t.Fatalf("Setrlimit: set failed: %#v %v", set, err) 175 } 176 177 // RLIMIT_AS was set to the page size, so mmap()'ing twice the page size 178 // should fail. See 'man 2 getrlimit'. 179 _, err = unix.Mmap(-1, 0, 2*unix.Getpagesize(), unix.PROT_NONE, unix.MAP_ANON|unix.MAP_PRIVATE) 180 if err == nil { 181 t.Fatal("Mmap: unexpectedly succeeded after setting RLIMIT_AS") 182 } 183 184 err = unix.Setrlimit(unix.RLIMIT_AS, &rlim) 185 if err != nil { 186 t.Fatalf("Setrlimit: restore failed: %#v %v", rlim, err) 187 } 188 189 b, err := unix.Mmap(-1, 0, 2*unix.Getpagesize(), unix.PROT_NONE, unix.MAP_ANON|unix.MAP_PRIVATE) 190 if err != nil { 191 t.Fatalf("Mmap: %v", err) 192 } 193 err = unix.Munmap(b) 194 if err != nil { 195 t.Fatalf("Munmap: %v", err) 196 } 197 } 198 199 func TestSelect(t *testing.T) { 200 _, err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0}) 201 if err != nil { 202 t.Fatalf("Select: %v", err) 203 } 204 205 dur := 150 * time.Millisecond 206 tv := unix.NsecToTimeval(int64(dur)) 207 start := time.Now() 208 _, err = unix.Select(0, nil, nil, nil, &tv) 209 took := time.Since(start) 210 if err != nil { 211 t.Fatalf("Select: %v", err) 212 } 213 214 if took < dur { 215 t.Errorf("Select: timeout should have been at least %v, got %v", dur, took) 216 } 217 } 218 219 func TestPselect(t *testing.T) { 220 _, err := unix.Pselect(0, nil, nil, nil, &unix.Timespec{Sec: 0, Nsec: 0}, nil) 221 if err != nil { 222 t.Fatalf("Pselect: %v", err) 223 } 224 225 dur := 2500 * time.Microsecond 226 ts := unix.NsecToTimespec(int64(dur)) 227 start := time.Now() 228 _, err = unix.Pselect(0, nil, nil, nil, &ts, nil) 229 took := time.Since(start) 230 if err != nil { 231 t.Fatalf("Pselect: %v", err) 232 } 233 234 if took < dur { 235 t.Errorf("Pselect: timeout should have been at least %v, got %v", dur, took) 236 } 237 } 238 239 func TestSchedSetaffinity(t *testing.T) { 240 runtime.LockOSThread() 241 defer runtime.UnlockOSThread() 242 243 var oldMask unix.CPUSet 244 err := unix.SchedGetaffinity(0, &oldMask) 245 if err != nil { 246 t.Fatalf("SchedGetaffinity: %v", err) 247 } 248 249 var newMask unix.CPUSet 250 newMask.Zero() 251 if newMask.Count() != 0 { 252 t.Errorf("CpuZero: didn't zero CPU set: %v", newMask) 253 } 254 cpu := 1 255 newMask.Set(cpu) 256 if newMask.Count() != 1 || !newMask.IsSet(cpu) { 257 t.Errorf("CpuSet: didn't set CPU %d in set: %v", cpu, newMask) 258 } 259 cpu = 5 260 newMask.Set(cpu) 261 if newMask.Count() != 2 || !newMask.IsSet(cpu) { 262 t.Errorf("CpuSet: didn't set CPU %d in set: %v", cpu, newMask) 263 } 264 newMask.Clear(cpu) 265 if newMask.Count() != 1 || newMask.IsSet(cpu) { 266 t.Errorf("CpuClr: didn't clear CPU %d in set: %v", cpu, newMask) 267 } 268 269 if runtime.NumCPU() < 2 { 270 t.Skip("skipping setaffinity tests on single CPU system") 271 } 272 if runtime.GOOS == "android" { 273 t.Skip("skipping setaffinity tests on android") 274 } 275 276 // On a system like ppc64x where some cores can be disabled using ppc64_cpu, 277 // setaffinity should only be called with enabled cores. The valid cores 278 // are found from the oldMask, but if none are found then the setaffinity 279 // tests are skipped. Issue #27875. 280 if !oldMask.IsSet(cpu) { 281 newMask.Zero() 282 for i := 0; i < len(oldMask); i++ { 283 if oldMask.IsSet(i) { 284 newMask.Set(i) 285 break 286 } 287 } 288 if newMask.Count() == 0 { 289 t.Skip("skipping setaffinity tests if CPU not available") 290 } 291 } 292 293 err = unix.SchedSetaffinity(0, &newMask) 294 if err != nil { 295 t.Fatalf("SchedSetaffinity: %v", err) 296 } 297 298 var gotMask unix.CPUSet 299 err = unix.SchedGetaffinity(0, &gotMask) 300 if err != nil { 301 t.Fatalf("SchedGetaffinity: %v", err) 302 } 303 304 if gotMask != newMask { 305 t.Errorf("SchedSetaffinity: returned affinity mask does not match set affinity mask") 306 } 307 308 // Restore old mask so it doesn't affect successive tests 309 err = unix.SchedSetaffinity(0, &oldMask) 310 if err != nil { 311 t.Fatalf("SchedSetaffinity: %v", err) 312 } 313 } 314 315 func TestStatx(t *testing.T) { 316 var stx unix.Statx_t 317 err := unix.Statx(unix.AT_FDCWD, ".", 0, 0, &stx) 318 if err == unix.ENOSYS || err == unix.EPERM { 319 t.Skip("statx syscall is not available, skipping test") 320 } else if err != nil { 321 t.Fatalf("Statx: %v", err) 322 } 323 324 defer chtmpdir(t)() 325 touch(t, "file1") 326 327 var st unix.Stat_t 328 err = unix.Stat("file1", &st) 329 if err != nil { 330 t.Fatalf("Stat: %v", err) 331 } 332 333 flags := unix.AT_STATX_SYNC_AS_STAT 334 err = unix.Statx(unix.AT_FDCWD, "file1", flags, unix.STATX_ALL, &stx) 335 if err != nil { 336 t.Fatalf("Statx: %v", err) 337 } 338 339 if uint32(stx.Mode) != st.Mode { 340 t.Errorf("Statx: returned stat mode does not match Stat") 341 } 342 343 ctime := unix.StatxTimestamp{Sec: int64(st.Ctim.Sec), Nsec: uint32(st.Ctim.Nsec)} 344 mtime := unix.StatxTimestamp{Sec: int64(st.Mtim.Sec), Nsec: uint32(st.Mtim.Nsec)} 345 346 if stx.Ctime != ctime { 347 t.Errorf("Statx: returned stat ctime does not match Stat") 348 } 349 if stx.Mtime != mtime { 350 t.Errorf("Statx: returned stat mtime does not match Stat") 351 } 352 353 err = os.Symlink("file1", "symlink1") 354 if err != nil { 355 t.Fatal(err) 356 } 357 358 err = unix.Lstat("symlink1", &st) 359 if err != nil { 360 t.Fatalf("Lstat: %v", err) 361 } 362 363 err = unix.Statx(unix.AT_FDCWD, "symlink1", flags, unix.STATX_BASIC_STATS, &stx) 364 if err != nil { 365 t.Fatalf("Statx: %v", err) 366 } 367 368 // follow symlink, expect a regulat file 369 if stx.Mode&unix.S_IFREG == 0 { 370 t.Errorf("Statx: didn't follow symlink") 371 } 372 373 err = unix.Statx(unix.AT_FDCWD, "symlink1", flags|unix.AT_SYMLINK_NOFOLLOW, unix.STATX_ALL, &stx) 374 if err != nil { 375 t.Fatalf("Statx: %v", err) 376 } 377 378 // follow symlink, expect a symlink 379 if stx.Mode&unix.S_IFLNK == 0 { 380 t.Errorf("Statx: unexpectedly followed symlink") 381 } 382 if uint32(stx.Mode) != st.Mode { 383 t.Errorf("Statx: returned stat mode does not match Lstat") 384 } 385 386 ctime = unix.StatxTimestamp{Sec: int64(st.Ctim.Sec), Nsec: uint32(st.Ctim.Nsec)} 387 mtime = unix.StatxTimestamp{Sec: int64(st.Mtim.Sec), Nsec: uint32(st.Mtim.Nsec)} 388 389 if stx.Ctime != ctime { 390 t.Errorf("Statx: returned stat ctime does not match Lstat") 391 } 392 if stx.Mtime != mtime { 393 t.Errorf("Statx: returned stat mtime does not match Lstat") 394 } 395 } 396 397 // stringsFromByteSlice converts a sequence of attributes to a []string. 398 // On Linux, each entry is a NULL-terminated string. 399 func stringsFromByteSlice(buf []byte) []string { 400 var result []string 401 off := 0 402 for i, b := range buf { 403 if b == 0 { 404 result = append(result, string(buf[off:i])) 405 off = i + 1 406 } 407 } 408 return result 409 } 410 411 func TestFaccessat(t *testing.T) { 412 defer chtmpdir(t)() 413 touch(t, "file1") 414 415 err := unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, 0) 416 if err != nil { 417 t.Errorf("Faccessat: unexpected error: %v", err) 418 } 419 420 err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, 2) 421 if err != unix.EINVAL { 422 t.Errorf("Faccessat: unexpected error: %v, want EINVAL", err) 423 } 424 425 err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, unix.AT_EACCESS) 426 if err != nil { 427 t.Errorf("Faccessat: unexpected error: %v", err) 428 } 429 430 err = os.Symlink("file1", "symlink1") 431 if err != nil { 432 t.Fatal(err) 433 } 434 435 err = unix.Faccessat(unix.AT_FDCWD, "symlink1", unix.R_OK, unix.AT_SYMLINK_NOFOLLOW) 436 if err != nil { 437 t.Errorf("Faccessat SYMLINK_NOFOLLOW: unexpected error %v", err) 438 } 439 440 // We can't really test AT_SYMLINK_NOFOLLOW, because there 441 // doesn't seem to be any way to change the mode of a symlink. 442 // We don't test AT_EACCESS because such tests are only 443 // meaningful if run as root. 444 445 err = unix.Fchmodat(unix.AT_FDCWD, "file1", 0, 0) 446 if err != nil { 447 t.Errorf("Fchmodat: unexpected error %v", err) 448 } 449 450 err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.F_OK, unix.AT_SYMLINK_NOFOLLOW) 451 if err != nil { 452 t.Errorf("Faccessat: unexpected error: %v", err) 453 } 454 455 err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, unix.AT_SYMLINK_NOFOLLOW) 456 if err != unix.EACCES { 457 if unix.Getuid() != 0 { 458 t.Errorf("Faccessat: unexpected error: %v, want EACCES", err) 459 } 460 } 461 } 462 463 func TestSyncFileRange(t *testing.T) { 464 file, err := ioutil.TempFile("", "TestSyncFileRange") 465 if err != nil { 466 t.Fatal(err) 467 } 468 defer os.Remove(file.Name()) 469 defer file.Close() 470 471 err = unix.SyncFileRange(int(file.Fd()), 0, 0, 0) 472 if err == unix.ENOSYS || err == unix.EPERM { 473 t.Skip("sync_file_range syscall is not available, skipping test") 474 } else if err != nil { 475 t.Fatalf("SyncFileRange: %v", err) 476 } 477 478 // invalid flags 479 flags := 0xf00 480 err = unix.SyncFileRange(int(file.Fd()), 0, 0, flags) 481 if err != unix.EINVAL { 482 t.Fatalf("SyncFileRange: unexpected error: %v, want EINVAL", err) 483 } 484 } 485 486 func TestClockNanosleep(t *testing.T) { 487 delay := 100 * time.Millisecond 488 489 // Relative timespec. 490 start := time.Now() 491 rel := unix.NsecToTimespec(delay.Nanoseconds()) 492 err := unix.ClockNanosleep(unix.CLOCK_MONOTONIC, 0, &rel, nil) 493 if err == unix.ENOSYS || err == unix.EPERM { 494 t.Skip("clock_nanosleep syscall is not available, skipping test") 495 } else if err != nil { 496 t.Errorf("ClockNanosleep(CLOCK_MONOTONIC, 0, %#v, nil) = %v", &rel, err) 497 } else if slept := time.Now().Sub(start); slept < delay { 498 t.Errorf("ClockNanosleep(CLOCK_MONOTONIC, 0, %#v, nil) slept only %v", &rel, slept) 499 } 500 501 // Absolute timespec. 502 start = time.Now() 503 until := start.Add(delay) 504 abs := unix.NsecToTimespec(until.UnixNano()) 505 err = unix.ClockNanosleep(unix.CLOCK_REALTIME, unix.TIMER_ABSTIME, &abs, nil) 506 if err != nil { 507 t.Errorf("ClockNanosleep(CLOCK_REALTIME, TIMER_ABSTIME, %#v (=%v), nil) = %v", &abs, until, err) 508 } else if slept := time.Now().Sub(start); slept < delay { 509 t.Errorf("ClockNanosleep(CLOCK_REALTIME, TIMER_ABSTIME, %#v (=%v), nil) slept only %v", &abs, until, slept) 510 } 511 512 // Invalid clock. clock_nanosleep(2) says EINVAL, but it’s actually EOPNOTSUPP. 513 err = unix.ClockNanosleep(unix.CLOCK_THREAD_CPUTIME_ID, 0, &rel, nil) 514 if err != unix.EINVAL && err != unix.EOPNOTSUPP { 515 t.Errorf("ClockNanosleep(CLOCK_THREAD_CPUTIME_ID, 0, %#v, nil) = %v, want EINVAL or EOPNOTSUPP", &rel, err) 516 } 517 }