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