github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/os/stat_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 os_test 6 7 import ( 8 "internal/testenv" 9 "io/fs" 10 "os" 11 "path/filepath" 12 "runtime" 13 "testing" 14 ) 15 16 // testStatAndLstat verifies that all os.Stat, os.Lstat os.File.Stat and os.Readdir work. 17 func testStatAndLstat(t *testing.T, path string, isLink bool, statCheck, lstatCheck func(*testing.T, string, fs.FileInfo)) { 18 // test os.Stat 19 sfi, err := os.Stat(path) 20 if err != nil { 21 t.Error(err) 22 return 23 } 24 statCheck(t, path, sfi) 25 26 // test os.Lstat 27 lsfi, err := os.Lstat(path) 28 if err != nil { 29 t.Error(err) 30 return 31 } 32 lstatCheck(t, path, lsfi) 33 34 if isLink { 35 if os.SameFile(sfi, lsfi) { 36 t.Errorf("stat and lstat of %q should not be the same", path) 37 } 38 } else { 39 if !os.SameFile(sfi, lsfi) { 40 t.Errorf("stat and lstat of %q should be the same", path) 41 } 42 } 43 44 // test os.File.Stat 45 f, err := os.Open(path) 46 if err != nil { 47 t.Error(err) 48 return 49 } 50 defer f.Close() 51 52 sfi2, err := f.Stat() 53 if err != nil { 54 t.Error(err) 55 return 56 } 57 statCheck(t, path, sfi2) 58 59 if !os.SameFile(sfi, sfi2) { 60 t.Errorf("stat of open %q file and stat of %q should be the same", path, path) 61 } 62 63 if isLink { 64 if os.SameFile(sfi2, lsfi) { 65 t.Errorf("stat of opened %q file and lstat of %q should not be the same", path, path) 66 } 67 } else { 68 if !os.SameFile(sfi2, lsfi) { 69 t.Errorf("stat of opened %q file and lstat of %q should be the same", path, path) 70 } 71 } 72 73 // test fs.FileInfo returned by os.Readdir 74 if len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) { 75 // skip os.Readdir test of directories with slash at the end 76 return 77 } 78 parentdir := filepath.Dir(path) 79 parent, err := os.Open(parentdir) 80 if err != nil { 81 t.Error(err) 82 return 83 } 84 defer parent.Close() 85 86 fis, err := parent.Readdir(-1) 87 if err != nil { 88 t.Error(err) 89 return 90 } 91 var lsfi2 fs.FileInfo 92 base := filepath.Base(path) 93 for _, fi2 := range fis { 94 if fi2.Name() == base { 95 lsfi2 = fi2 96 break 97 } 98 } 99 if lsfi2 == nil { 100 t.Errorf("failed to find %q in its parent", path) 101 return 102 } 103 lstatCheck(t, path, lsfi2) 104 105 if !os.SameFile(lsfi, lsfi2) { 106 t.Errorf("lstat of %q file in %q directory and %q should be the same", lsfi2.Name(), parentdir, path) 107 } 108 } 109 110 // testIsDir verifies that fi refers to directory. 111 func testIsDir(t *testing.T, path string, fi fs.FileInfo) { 112 t.Helper() 113 if !fi.IsDir() { 114 t.Errorf("%q should be a directory", path) 115 } 116 if fi.Mode()&fs.ModeSymlink != 0 { 117 t.Errorf("%q should not be a symlink", path) 118 } 119 } 120 121 // testIsSymlink verifies that fi refers to symlink. 122 func testIsSymlink(t *testing.T, path string, fi fs.FileInfo) { 123 t.Helper() 124 if fi.IsDir() { 125 t.Errorf("%q should not be a directory", path) 126 } 127 if fi.Mode()&fs.ModeSymlink == 0 { 128 t.Errorf("%q should be a symlink", path) 129 } 130 } 131 132 // testIsFile verifies that fi refers to file. 133 func testIsFile(t *testing.T, path string, fi fs.FileInfo) { 134 t.Helper() 135 if fi.IsDir() { 136 t.Errorf("%q should not be a directory", path) 137 } 138 if fi.Mode()&fs.ModeSymlink != 0 { 139 t.Errorf("%q should not be a symlink", path) 140 } 141 } 142 143 func testDirStats(t *testing.T, path string) { 144 testStatAndLstat(t, path, false, testIsDir, testIsDir) 145 } 146 147 func testFileStats(t *testing.T, path string) { 148 testStatAndLstat(t, path, false, testIsFile, testIsFile) 149 } 150 151 func testSymlinkStats(t *testing.T, path string, isdir bool) { 152 if isdir { 153 testStatAndLstat(t, path, true, testIsDir, testIsSymlink) 154 } else { 155 testStatAndLstat(t, path, true, testIsFile, testIsSymlink) 156 } 157 } 158 159 func testSymlinkSameFile(t *testing.T, path, link string) { 160 pathfi, err := os.Stat(path) 161 if err != nil { 162 t.Error(err) 163 return 164 } 165 166 linkfi, err := os.Stat(link) 167 if err != nil { 168 t.Error(err) 169 return 170 } 171 if !os.SameFile(pathfi, linkfi) { 172 t.Errorf("os.Stat(%q) and os.Stat(%q) are not the same file", path, link) 173 } 174 175 linkfi, err = os.Lstat(link) 176 if err != nil { 177 t.Error(err) 178 return 179 } 180 if os.SameFile(pathfi, linkfi) { 181 t.Errorf("os.Stat(%q) and os.Lstat(%q) are the same file", path, link) 182 } 183 } 184 185 func TestDirAndSymlinkStats(t *testing.T) { 186 testenv.MustHaveSymlink(t) 187 188 tmpdir := t.TempDir() 189 dir := filepath.Join(tmpdir, "dir") 190 if err := os.Mkdir(dir, 0777); err != nil { 191 t.Fatal(err) 192 } 193 testDirStats(t, dir) 194 195 dirlink := filepath.Join(tmpdir, "link") 196 if err := os.Symlink(dir, dirlink); err != nil { 197 t.Fatal(err) 198 } 199 testSymlinkStats(t, dirlink, true) 200 testSymlinkSameFile(t, dir, dirlink) 201 202 linklink := filepath.Join(tmpdir, "linklink") 203 if err := os.Symlink(dirlink, linklink); err != nil { 204 t.Fatal(err) 205 } 206 testSymlinkStats(t, linklink, true) 207 testSymlinkSameFile(t, dir, linklink) 208 } 209 210 func TestFileAndSymlinkStats(t *testing.T) { 211 testenv.MustHaveSymlink(t) 212 213 tmpdir := t.TempDir() 214 file := filepath.Join(tmpdir, "file") 215 if err := os.WriteFile(file, []byte(""), 0644); err != nil { 216 t.Fatal(err) 217 } 218 testFileStats(t, file) 219 220 filelink := filepath.Join(tmpdir, "link") 221 if err := os.Symlink(file, filelink); err != nil { 222 t.Fatal(err) 223 } 224 testSymlinkStats(t, filelink, false) 225 testSymlinkSameFile(t, file, filelink) 226 227 linklink := filepath.Join(tmpdir, "linklink") 228 if err := os.Symlink(filelink, linklink); err != nil { 229 t.Fatal(err) 230 } 231 testSymlinkStats(t, linklink, false) 232 testSymlinkSameFile(t, file, linklink) 233 } 234 235 // see issue 27225 for details 236 func TestSymlinkWithTrailingSlash(t *testing.T) { 237 testenv.MustHaveSymlink(t) 238 239 tmpdir := t.TempDir() 240 dir := filepath.Join(tmpdir, "dir") 241 if err := os.Mkdir(dir, 0777); err != nil { 242 t.Fatal(err) 243 } 244 dirlink := filepath.Join(tmpdir, "link") 245 if err := os.Symlink(dir, dirlink); err != nil { 246 t.Fatal(err) 247 } 248 dirlinkWithSlash := dirlink + string(os.PathSeparator) 249 250 if runtime.GOOS == "windows" { 251 testSymlinkStats(t, dirlinkWithSlash, true) 252 } else { 253 testDirStats(t, dirlinkWithSlash) 254 } 255 256 fi1, err := os.Stat(dir) 257 if err != nil { 258 t.Error(err) 259 return 260 } 261 fi2, err := os.Stat(dirlinkWithSlash) 262 if err != nil { 263 t.Error(err) 264 return 265 } 266 if !os.SameFile(fi1, fi2) { 267 t.Errorf("os.Stat(%q) and os.Stat(%q) are not the same file", dir, dirlinkWithSlash) 268 } 269 }