summaryrefslogtreecommitdiffstats
path: root/src/os/stat_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/os/stat_test.go')
-rw-r--r--src/os/stat_test.go292
1 files changed, 292 insertions, 0 deletions
diff --git a/src/os/stat_test.go b/src/os/stat_test.go
new file mode 100644
index 0000000..c409f0f
--- /dev/null
+++ b/src/os/stat_test.go
@@ -0,0 +1,292 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os_test
+
+import (
+ "internal/testenv"
+ "io/fs"
+ "os"
+ "path/filepath"
+ "runtime"
+ "testing"
+)
+
+// testStatAndLstat verifies that all os.Stat, os.Lstat os.File.Stat and os.Readdir work.
+func testStatAndLstat(t *testing.T, path string, isLink bool, statCheck, lstatCheck func(*testing.T, string, fs.FileInfo)) {
+ // test os.Stat
+ sfi, err := os.Stat(path)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ statCheck(t, path, sfi)
+
+ // test os.Lstat
+ lsfi, err := os.Lstat(path)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ lstatCheck(t, path, lsfi)
+
+ if isLink {
+ if os.SameFile(sfi, lsfi) {
+ t.Errorf("stat and lstat of %q should not be the same", path)
+ }
+ } else {
+ if !os.SameFile(sfi, lsfi) {
+ t.Errorf("stat and lstat of %q should be the same", path)
+ }
+ }
+
+ // test os.File.Stat
+ f, err := os.Open(path)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer f.Close()
+
+ sfi2, err := f.Stat()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ statCheck(t, path, sfi2)
+
+ if !os.SameFile(sfi, sfi2) {
+ t.Errorf("stat of open %q file and stat of %q should be the same", path, path)
+ }
+
+ if isLink {
+ if os.SameFile(sfi2, lsfi) {
+ t.Errorf("stat of opened %q file and lstat of %q should not be the same", path, path)
+ }
+ } else {
+ if !os.SameFile(sfi2, lsfi) {
+ t.Errorf("stat of opened %q file and lstat of %q should be the same", path, path)
+ }
+ }
+
+ // test fs.FileInfo returned by os.Readdir
+ if len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) {
+ // skip os.Readdir test of directories with slash at the end
+ return
+ }
+ parentdir := filepath.Dir(path)
+ parent, err := os.Open(parentdir)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer parent.Close()
+
+ fis, err := parent.Readdir(-1)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ var lsfi2 fs.FileInfo
+ base := filepath.Base(path)
+ for _, fi2 := range fis {
+ if fi2.Name() == base {
+ lsfi2 = fi2
+ break
+ }
+ }
+ if lsfi2 == nil {
+ t.Errorf("failed to find %q in its parent", path)
+ return
+ }
+ lstatCheck(t, path, lsfi2)
+
+ if !os.SameFile(lsfi, lsfi2) {
+ t.Errorf("lstat of %q file in %q directory and %q should be the same", lsfi2.Name(), parentdir, path)
+ }
+}
+
+// testIsDir verifies that fi refers to directory.
+func testIsDir(t *testing.T, path string, fi fs.FileInfo) {
+ t.Helper()
+ if !fi.IsDir() {
+ t.Errorf("%q should be a directory", path)
+ }
+ if fi.Mode()&fs.ModeSymlink != 0 {
+ t.Errorf("%q should not be a symlink", path)
+ }
+}
+
+// testIsSymlink verifies that fi refers to symlink.
+func testIsSymlink(t *testing.T, path string, fi fs.FileInfo) {
+ t.Helper()
+ if fi.IsDir() {
+ t.Errorf("%q should not be a directory", path)
+ }
+ if fi.Mode()&fs.ModeSymlink == 0 {
+ t.Errorf("%q should be a symlink", path)
+ }
+}
+
+// testIsFile verifies that fi refers to file.
+func testIsFile(t *testing.T, path string, fi fs.FileInfo) {
+ t.Helper()
+ if fi.IsDir() {
+ t.Errorf("%q should not be a directory", path)
+ }
+ if fi.Mode()&fs.ModeSymlink != 0 {
+ t.Errorf("%q should not be a symlink", path)
+ }
+}
+
+func testDirStats(t *testing.T, path string) {
+ testStatAndLstat(t, path, false, testIsDir, testIsDir)
+}
+
+func testFileStats(t *testing.T, path string) {
+ testStatAndLstat(t, path, false, testIsFile, testIsFile)
+}
+
+func testSymlinkStats(t *testing.T, path string, isdir bool) {
+ if isdir {
+ testStatAndLstat(t, path, true, testIsDir, testIsSymlink)
+ } else {
+ testStatAndLstat(t, path, true, testIsFile, testIsSymlink)
+ }
+}
+
+func testSymlinkSameFile(t *testing.T, path, link string) {
+ pathfi, err := os.Stat(path)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ linkfi, err := os.Stat(link)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if !os.SameFile(pathfi, linkfi) {
+ t.Errorf("os.Stat(%q) and os.Stat(%q) are not the same file", path, link)
+ }
+
+ linkfi, err = os.Lstat(link)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if os.SameFile(pathfi, linkfi) {
+ t.Errorf("os.Stat(%q) and os.Lstat(%q) are the same file", path, link)
+ }
+}
+
+func TestDirAndSymlinkStats(t *testing.T) {
+ testenv.MustHaveSymlink(t)
+
+ tmpdir, err := os.MkdirTemp("", "TestDirAndSymlinkStats")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ dir := filepath.Join(tmpdir, "dir")
+ err = os.Mkdir(dir, 0777)
+ if err != nil {
+ t.Fatal(err)
+ }
+ testDirStats(t, dir)
+
+ dirlink := filepath.Join(tmpdir, "link")
+ err = os.Symlink(dir, dirlink)
+ if err != nil {
+ t.Fatal(err)
+ }
+ testSymlinkStats(t, dirlink, true)
+ testSymlinkSameFile(t, dir, dirlink)
+
+ linklink := filepath.Join(tmpdir, "linklink")
+ err = os.Symlink(dirlink, linklink)
+ if err != nil {
+ t.Fatal(err)
+ }
+ testSymlinkStats(t, linklink, true)
+ testSymlinkSameFile(t, dir, linklink)
+}
+
+func TestFileAndSymlinkStats(t *testing.T) {
+ testenv.MustHaveSymlink(t)
+
+ tmpdir, err := os.MkdirTemp("", "TestFileAndSymlinkStats")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ file := filepath.Join(tmpdir, "file")
+ err = os.WriteFile(file, []byte(""), 0644)
+ if err != nil {
+ t.Fatal(err)
+ }
+ testFileStats(t, file)
+
+ filelink := filepath.Join(tmpdir, "link")
+ err = os.Symlink(file, filelink)
+ if err != nil {
+ t.Fatal(err)
+ }
+ testSymlinkStats(t, filelink, false)
+ testSymlinkSameFile(t, file, filelink)
+
+ linklink := filepath.Join(tmpdir, "linklink")
+ err = os.Symlink(filelink, linklink)
+ if err != nil {
+ t.Fatal(err)
+ }
+ testSymlinkStats(t, linklink, false)
+ testSymlinkSameFile(t, file, linklink)
+}
+
+// see issue 27225 for details
+func TestSymlinkWithTrailingSlash(t *testing.T) {
+ testenv.MustHaveSymlink(t)
+
+ tmpdir, err := os.MkdirTemp("", "TestSymlinkWithTrailingSlash")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ dir := filepath.Join(tmpdir, "dir")
+ err = os.Mkdir(dir, 0777)
+ if err != nil {
+ t.Fatal(err)
+ }
+ dirlink := filepath.Join(tmpdir, "link")
+ err = os.Symlink(dir, dirlink)
+ if err != nil {
+ t.Fatal(err)
+ }
+ dirlinkWithSlash := dirlink + string(os.PathSeparator)
+
+ if runtime.GOOS == "windows" {
+ testSymlinkStats(t, dirlinkWithSlash, true)
+ } else {
+ testDirStats(t, dirlinkWithSlash)
+ }
+
+ fi1, err := os.Stat(dir)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ fi2, err := os.Stat(dirlinkWithSlash)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if !os.SameFile(fi1, fi2) {
+ t.Errorf("os.Stat(%q) and os.Stat(%q) are not the same file", dir, dirlinkWithSlash)
+ }
+}