github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/sysfs/futimens_test.go (about) 1 //go:build windows || linux || darwin 2 3 package sysfs 4 5 import ( 6 "os" 7 "path" 8 "runtime" 9 "testing" 10 "time" 11 12 "github.com/wasilibs/wazerox/experimental/sys" 13 "github.com/wasilibs/wazerox/internal/platform" 14 "github.com/wasilibs/wazerox/internal/testing/require" 15 ) 16 17 func TestUtimens(t *testing.T) { 18 t.Run("doesn't exist", func(t *testing.T) { 19 err := utimens("nope", 0, 0) 20 require.EqualErrno(t, sys.ENOENT, err) 21 }) 22 testUtimens(t, false) 23 } 24 25 func testUtimens(t *testing.T, futimes bool) { 26 // Note: This sets microsecond granularity because Windows doesn't support 27 // nanosecond. 28 // 29 // Negative isn't tested as most platforms don't return consistent results. 30 tests := []struct { 31 name string 32 atim, mtim int64 33 }{ 34 { 35 name: "nil", 36 }, 37 { 38 name: "a=omit,m=omit", 39 atim: sys.UTIME_OMIT, 40 mtim: sys.UTIME_OMIT, 41 }, 42 { 43 name: "a=set,m=omit", 44 atim: int64(123*time.Second + 4*time.Microsecond), 45 mtim: sys.UTIME_OMIT, 46 }, 47 { 48 name: "a=omit,m=set", 49 atim: sys.UTIME_OMIT, 50 mtim: int64(123*time.Second + 4*time.Microsecond), 51 }, 52 { 53 name: "a=set,m=set", 54 atim: int64(123*time.Second + 4*time.Microsecond), 55 mtim: int64(223*time.Second + 5*time.Microsecond), 56 }, 57 } 58 for _, fileType := range []string{"dir", "file", "link"} { 59 for _, tt := range tests { 60 tc := tt 61 fileType := fileType 62 name := fileType + " " + tc.name 63 64 t.Run(name, func(t *testing.T) { 65 tmpDir := t.TempDir() 66 file := path.Join(tmpDir, "file") 67 err := os.WriteFile(file, []byte{}, 0o700) 68 require.NoError(t, err) 69 70 link := file + "-link" 71 require.NoError(t, os.Symlink(file, link)) 72 73 dir := path.Join(tmpDir, "dir") 74 err = os.Mkdir(dir, 0o700) 75 require.NoError(t, err) 76 77 var path, statPath string 78 switch fileType { 79 case "dir": 80 path = dir 81 statPath = dir 82 case "file": 83 path = file 84 statPath = file 85 case "link": 86 path = link 87 statPath = file 88 default: 89 panic(tc) 90 } 91 92 oldSt, errno := lstat(statPath) 93 require.EqualErrno(t, 0, errno) 94 95 if !futimes { 96 errno = utimens(path, tc.atim, tc.mtim) 97 require.EqualErrno(t, 0, errno) 98 } else { 99 flag := sys.O_RDWR 100 if path == dir { 101 flag = sys.O_RDONLY 102 if runtime.GOOS == "windows" { 103 // windows requires O_RDWR, which is invalid for directories 104 t.Skip("windows cannot update timestamps on a dir") 105 } 106 } 107 108 f := requireOpenFile(t, path, flag, 0) 109 110 errno = f.Utimens(tc.atim, tc.mtim) 111 require.EqualErrno(t, 0, f.Close()) 112 require.EqualErrno(t, 0, errno) 113 } 114 115 newSt, errno := lstat(statPath) 116 require.EqualErrno(t, 0, errno) 117 118 if platform.CompilerSupported() { 119 if tc.atim == sys.UTIME_OMIT { 120 require.Equal(t, oldSt.Atim, newSt.Atim) 121 } else { 122 require.Equal(t, tc.atim, newSt.Atim) 123 } 124 } 125 126 // When compiler isn't supported, we can still check mtim. 127 if tc.mtim == sys.UTIME_OMIT { 128 require.Equal(t, oldSt.Mtim, newSt.Mtim) 129 } else { 130 require.Equal(t, tc.mtim, newSt.Mtim) 131 } 132 }) 133 } 134 } 135 }