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