1 // Copyright 2009 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.
43 var sysdir = func() *sysDir {
54 switch runtime.GOARCH {
56 wd, err := syscall.Getwd()
61 filepath.Join(wd, "..", ".."),
63 "ResourceRules.plist",
70 Getenv("SystemRoot") + "\\system32\\drivers\\etc",
96 func size(name string, t *testing.T) int64 {
97 file, err := Open(name)
99 t.Fatal("open failed:", err)
105 n, e := file.Read(buf[0:])
111 t.Fatal("read failed:", e)
117 func equal(name1, name2 string) (r bool) {
118 switch runtime.GOOS {
120 r = strings.ToLower(name1) == strings.ToLower(name2)
127 // localTmp returns a local temporary directory not on NFS.
128 func localTmp() string {
129 switch runtime.GOOS {
130 case "android", "windows":
133 switch runtime.GOARCH {
141 func newFile(testName string, t *testing.T) (f *File) {
142 f, err := ioutil.TempFile(localTmp(), "_Go_"+testName)
144 t.Fatalf("TempFile %s: %s", testName, err)
149 func newDir(testName string, t *testing.T) (name string) {
150 name, err := ioutil.TempDir(localTmp(), "_Go_"+testName)
152 t.Fatalf("TempDir %s: %s", testName, err)
157 var sfdir = sysdir.name
158 var sfname = sysdir.files[0]
160 func TestStat(t *testing.T) {
161 path := sfdir + "/" + sfname
162 dir, err := Stat(path)
164 t.Fatal("stat failed:", err)
166 if !equal(sfname, dir.Name()) {
167 t.Error("name should be ", sfname, "; is", dir.Name())
169 filesize := size(path, t)
170 if dir.Size() != filesize {
171 t.Error("size should be", filesize, "; is", dir.Size())
175 func TestStatError(t *testing.T) {
178 path := "no-such-file"
180 fi, err := Stat(path)
182 t.Fatal("got nil, want error")
185 t.Errorf("got %v, want nil", fi)
187 if perr, ok := err.(*PathError); !ok {
188 t.Errorf("got %T, want %T", err, perr)
191 testenv.MustHaveSymlink(t)
194 err = Symlink(path, link)
201 t.Fatal("got nil, want error")
204 t.Errorf("got %v, want nil", fi)
206 if perr, ok := err.(*PathError); !ok {
207 t.Errorf("got %T, want %T", err, perr)
211 func TestFstat(t *testing.T) {
212 path := sfdir + "/" + sfname
213 file, err1 := Open(path)
215 t.Fatal("open failed:", err1)
218 dir, err2 := file.Stat()
220 t.Fatal("fstat failed:", err2)
222 if !equal(sfname, dir.Name()) {
223 t.Error("name should be ", sfname, "; is", dir.Name())
225 filesize := size(path, t)
226 if dir.Size() != filesize {
227 t.Error("size should be", filesize, "; is", dir.Size())
231 func TestLstat(t *testing.T) {
232 path := sfdir + "/" + sfname
233 dir, err := Lstat(path)
235 t.Fatal("lstat failed:", err)
237 if !equal(sfname, dir.Name()) {
238 t.Error("name should be ", sfname, "; is", dir.Name())
240 filesize := size(path, t)
241 if dir.Size() != filesize {
242 t.Error("size should be", filesize, "; is", dir.Size())
246 // Read with length 0 should not return EOF.
247 func TestRead0(t *testing.T) {
248 path := sfdir + "/" + sfname
251 t.Fatal("open failed:", err)
257 if n != 0 || err != nil {
258 t.Errorf("Read(0) = %d, %v, want 0, nil", n, err)
260 b = make([]byte, 100)
262 if n <= 0 || err != nil {
263 t.Errorf("Read(100) = %d, %v, want >0, nil", n, err)
267 // Reading a closed file should return ErrClosed error
268 func TestReadClosed(t *testing.T) {
269 path := sfdir + "/" + sfname
270 file, err := Open(path)
272 t.Fatal("open failed:", err)
274 file.Close() // close immediately
276 b := make([]byte, 100)
277 _, err = file.Read(b)
279 e, ok := err.(*PathError)
281 t.Fatalf("Read: %T(%v), want PathError", e, e)
284 if e.Err != ErrClosed {
285 t.Errorf("Read: %v, want PathError(ErrClosed)", e)
289 func testReaddirnames(dir string, contents []string, t *testing.T) {
290 file, err := Open(dir)
292 t.Fatalf("open %q failed: %v", dir, err)
295 s, err2 := file.Readdirnames(-1)
297 t.Fatalf("readdirnames %q failed: %v", dir, err2)
299 for _, m := range contents {
301 for _, n := range s {
302 if n == "." || n == ".." {
303 t.Errorf("got %s in directory", n)
307 t.Error("present twice:", m)
313 t.Error("could not find", m)
318 func testReaddir(dir string, contents []string, t *testing.T) {
319 file, err := Open(dir)
321 t.Fatalf("open %q failed: %v", dir, err)
324 s, err2 := file.Readdir(-1)
326 t.Fatalf("readdir %q failed: %v", dir, err2)
328 for _, m := range contents {
330 for _, n := range s {
331 if equal(m, n.Name()) {
333 t.Error("present twice:", m)
339 t.Error("could not find", m)
344 func TestReaddirnames(t *testing.T) {
345 testReaddirnames(".", dot, t)
346 testReaddirnames(sysdir.name, sysdir.files, t)
349 func TestReaddir(t *testing.T) {
350 testReaddir(".", dot, t)
351 testReaddir(sysdir.name, sysdir.files, t)
354 func benchmarkReaddirname(path string, b *testing.B) {
356 for i := 0; i < b.N; i++ {
359 b.Fatalf("open %q failed: %v", path, err)
361 ns, err := f.Readdirnames(-1)
364 b.Fatalf("readdirnames %q failed: %v", path, err)
368 b.Logf("benchmarkReaddirname %q: %d entries", path, nentries)
371 func benchmarkReaddir(path string, b *testing.B) {
373 for i := 0; i < b.N; i++ {
376 b.Fatalf("open %q failed: %v", path, err)
378 fs, err := f.Readdir(-1)
381 b.Fatalf("readdir %q failed: %v", path, err)
385 b.Logf("benchmarkReaddir %q: %d entries", path, nentries)
388 func BenchmarkReaddirname(b *testing.B) {
389 benchmarkReaddirname(".", b)
392 func BenchmarkReaddir(b *testing.B) {
393 benchmarkReaddir(".", b)
396 func benchmarkStat(b *testing.B, path string) {
398 for i := 0; i < b.N; i++ {
401 b.Fatalf("Stat(%q) failed: %v", path, err)
406 func benchmarkLstat(b *testing.B, path string) {
408 for i := 0; i < b.N; i++ {
409 _, err := Lstat(path)
411 b.Fatalf("Lstat(%q) failed: %v", path, err)
416 func BenchmarkStatDot(b *testing.B) {
417 benchmarkStat(b, ".")
420 func BenchmarkStatFile(b *testing.B) {
421 benchmarkStat(b, filepath.Join(runtime.GOROOT(), "src/os/os_test.go"))
424 func BenchmarkStatDir(b *testing.B) {
425 benchmarkStat(b, filepath.Join(runtime.GOROOT(), "src/os"))
428 func BenchmarkLstatDot(b *testing.B) {
429 benchmarkLstat(b, ".")
432 func BenchmarkLstatFile(b *testing.B) {
433 benchmarkLstat(b, filepath.Join(runtime.GOROOT(), "src/os/os_test.go"))
436 func BenchmarkLstatDir(b *testing.B) {
437 benchmarkLstat(b, filepath.Join(runtime.GOROOT(), "src/os"))
440 // Read the directory one entry at a time.
441 func smallReaddirnames(file *File, length int, t *testing.T) []string {
442 names := make([]string, length)
445 d, err := file.Readdirnames(1)
450 t.Fatalf("readdirnames %q failed: %v", file.Name(), err)
453 t.Fatalf("readdirnames %q returned empty slice and no error", file.Name())
458 return names[0:count]
461 // Check that reading a directory one entry at a time gives the same result
462 // as reading it all at once.
463 func TestReaddirnamesOneAtATime(t *testing.T) {
464 // big directory that doesn't change often.
466 switch runtime.GOOS {
470 switch runtime.GOARCH {
481 dir = Getenv("SystemRoot") + "\\system32"
483 file, err := Open(dir)
485 t.Fatalf("open %q failed: %v", dir, err)
488 all, err1 := file.Readdirnames(-1)
490 t.Fatalf("readdirnames %q failed: %v", dir, err1)
492 file1, err2 := Open(dir)
494 t.Fatalf("open %q failed: %v", dir, err2)
497 small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up
498 if len(small) < len(all) {
499 t.Fatalf("len(small) is %d, less than %d", len(small), len(all))
501 for i, n := range all {
503 t.Errorf("small read %q mismatch: %v", small[i], n)
508 func TestReaddirNValues(t *testing.T) {
510 t.Skip("test.short; skipping")
512 dir, err := ioutil.TempDir("", "")
514 t.Fatalf("TempDir: %v", err)
517 for i := 1; i <= 105; i++ {
518 f, err := Create(filepath.Join(dir, fmt.Sprintf("%d", i)))
520 t.Fatalf("Create: %v", err)
522 f.Write([]byte(strings.Repeat("X", i)))
531 t.Fatalf("Open directory: %v", err)
535 readDirExpect := func(n, want int, wantErr error) {
536 fi, err := d.Readdir(n)
538 t.Fatalf("Readdir of %d got error %v, want %v", n, err, wantErr)
540 if g, e := len(fi), want; g != e {
541 t.Errorf("Readdir of %d got %d files, want %d", n, g, e)
545 readDirNamesExpect := func(n, want int, wantErr error) {
546 fi, err := d.Readdirnames(n)
548 t.Fatalf("Readdirnames of %d got error %v, want %v", n, err, wantErr)
550 if g, e := len(fi), want; g != e {
551 t.Errorf("Readdirnames of %d got %d files, want %d", n, g, e)
555 for _, fn := range []func(int, int, error){readDirExpect, readDirNamesExpect} {
556 // Test the slurp case
562 // Slurp with -1 instead
569 // Test the bounded case
573 fn(105, 102, nil) // and tests buffer >100 case
579 func touch(t *testing.T, name string) {
580 f, err := Create(name)
584 if err := f.Close(); err != nil {
589 func TestReaddirStatFailures(t *testing.T) {
590 switch runtime.GOOS {
591 case "windows", "plan9":
592 // Windows and Plan 9 already do this correctly,
593 // but are structured with different syscalls such
594 // that they don't use Lstat, so the hook below for
595 // testing it wouldn't work.
596 t.Skipf("skipping test on %v", runtime.GOOS)
598 dir, err := ioutil.TempDir("", "")
600 t.Fatalf("TempDir: %v", err)
603 touch(t, filepath.Join(dir, "good1"))
604 touch(t, filepath.Join(dir, "x")) // will disappear or have an error
605 touch(t, filepath.Join(dir, "good2"))
609 var xerr error // error to return for x
610 *LstatP = func(path string) (FileInfo, error) {
611 if xerr != nil && strings.HasSuffix(path, "x") {
616 readDir := func() ([]FileInfo, error) {
624 mustReadDir := func(testName string) []FileInfo {
625 fis, err := readDir()
627 t.Fatalf("%s: Readdir: %v", testName, err)
631 names := func(fis []FileInfo) []string {
632 s := make([]string, len(fis))
633 for i, fi := range fis {
640 if got, want := names(mustReadDir("initial readdir")),
641 []string{"good1", "good2", "x"}; !reflect.DeepEqual(got, want) {
642 t.Errorf("initial readdir got %q; want %q", got, want)
646 if got, want := names(mustReadDir("with x disappearing")),
647 []string{"good1", "good2"}; !reflect.DeepEqual(got, want) {
648 t.Errorf("with x disappearing, got %q; want %q", got, want)
651 xerr = errors.New("some real error")
652 if _, err := readDir(); err != xerr {
653 t.Errorf("with a non-ErrNotExist error, got error %v; want %v", err, xerr)
657 // Readdir on a regular file should fail.
658 func TestReaddirOfFile(t *testing.T) {
659 f, err := ioutil.TempFile("", "_Go_ReaddirOfFile")
663 defer Remove(f.Name())
664 f.Write([]byte("foo"))
666 reg, err := Open(f.Name())
672 names, err := reg.Readdirnames(-1)
674 t.Error("Readdirnames succeeded; want non-nil error")
677 t.Errorf("unexpected dir names in regular file: %q", names)
681 func TestHardLink(t *testing.T) {
682 testenv.MustHaveLink(t)
685 from, to := "hardlinktestfrom", "hardlinktestto"
686 file, err := Create(to)
688 t.Fatalf("open %q failed: %v", to, err)
690 if err = file.Close(); err != nil {
691 t.Errorf("close %q failed: %v", to, err)
695 t.Fatalf("link %q, %q failed: %v", to, from, err)
698 none := "hardlinktestnone"
699 err = Link(none, none)
700 // Check the returned error is well-formed.
701 if lerr, ok := err.(*LinkError); !ok || lerr.Error() == "" {
702 t.Errorf("link %q, %q failed to return a valid error", none, none)
705 tostat, err := Stat(to)
707 t.Fatalf("stat %q failed: %v", to, err)
709 fromstat, err := Stat(from)
711 t.Fatalf("stat %q failed: %v", from, err)
713 if !SameFile(tostat, fromstat) {
714 t.Errorf("link %q, %q did not create hard link", to, from)
716 // We should not be able to perform the same Link() a second time
718 switch err := err.(type) {
720 if err.Op != "link" {
721 t.Errorf("Link(%q, %q) err.Op = %q; want %q", to, from, err.Op, "link")
724 t.Errorf("Link(%q, %q) err.Old = %q; want %q", to, from, err.Old, to)
727 t.Errorf("Link(%q, %q) err.New = %q; want %q", to, from, err.New, from)
729 if !IsExist(err.Err) {
730 t.Errorf("Link(%q, %q) err.Err = %q; want %q", to, from, err.Err, "file exists error")
733 t.Errorf("link %q, %q: expected error, got nil", from, to)
735 t.Errorf("link %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err)
739 // chtmpdir changes the working directory to a new temporary directory and
740 // provides a cleanup function.
741 func chtmpdir(t *testing.T) func() {
742 oldwd, err := Getwd()
744 t.Fatalf("chtmpdir: %v", err)
746 d, err := ioutil.TempDir("", "test")
748 t.Fatalf("chtmpdir: %v", err)
750 if err := Chdir(d); err != nil {
751 t.Fatalf("chtmpdir: %v", err)
754 if err := Chdir(oldwd); err != nil {
755 t.Fatalf("chtmpdir: %v", err)
761 func TestSymlink(t *testing.T) {
762 testenv.MustHaveSymlink(t)
765 from, to := "symlinktestfrom", "symlinktestto"
766 file, err := Create(to)
768 t.Fatalf("Create(%q) failed: %v", to, err)
770 if err = file.Close(); err != nil {
771 t.Errorf("Close(%q) failed: %v", to, err)
773 err = Symlink(to, from)
775 t.Fatalf("Symlink(%q, %q) failed: %v", to, from, err)
777 tostat, err := Lstat(to)
779 t.Fatalf("Lstat(%q) failed: %v", to, err)
781 if tostat.Mode()&ModeSymlink != 0 {
782 t.Fatalf("Lstat(%q).Mode()&ModeSymlink = %v, want 0", to, tostat.Mode()&ModeSymlink)
784 fromstat, err := Stat(from)
786 t.Fatalf("Stat(%q) failed: %v", from, err)
788 if !SameFile(tostat, fromstat) {
789 t.Errorf("Symlink(%q, %q) did not create symlink", to, from)
791 fromstat, err = Lstat(from)
793 t.Fatalf("Lstat(%q) failed: %v", from, err)
795 if fromstat.Mode()&ModeSymlink == 0 {
796 t.Fatalf("Lstat(%q).Mode()&ModeSymlink = 0, want %v", from, ModeSymlink)
798 fromstat, err = Stat(from)
800 t.Fatalf("Stat(%q) failed: %v", from, err)
802 if fromstat.Name() != from {
803 t.Errorf("Stat(%q).Name() = %q, want %q", from, fromstat.Name(), from)
805 if fromstat.Mode()&ModeSymlink != 0 {
806 t.Fatalf("Stat(%q).Mode()&ModeSymlink = %v, want 0", from, fromstat.Mode()&ModeSymlink)
808 s, err := Readlink(from)
810 t.Fatalf("Readlink(%q) failed: %v", from, err)
813 t.Fatalf("Readlink(%q) = %q, want %q", from, s, to)
815 file, err = Open(from)
817 t.Fatalf("Open(%q) failed: %v", from, err)
822 func TestLongSymlink(t *testing.T) {
823 testenv.MustHaveSymlink(t)
826 s := "0123456789abcdef"
827 // Long, but not too long: a common limit is 255.
828 s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s
829 from := "longsymlinktestfrom"
830 err := Symlink(s, from)
832 t.Fatalf("symlink %q, %q failed: %v", s, from, err)
834 r, err := Readlink(from)
836 t.Fatalf("readlink %q failed: %v", from, err)
839 t.Fatalf("after symlink %q != %q", r, s)
843 func TestRename(t *testing.T) {
845 from, to := "renamefrom", "renameto"
847 file, err := Create(from)
849 t.Fatalf("open %q failed: %v", from, err)
851 if err = file.Close(); err != nil {
852 t.Errorf("close %q failed: %v", from, err)
854 err = Rename(from, to)
856 t.Fatalf("rename %q, %q failed: %v", to, from, err)
860 t.Errorf("stat %q failed: %v", to, err)
864 func TestRenameOverwriteDest(t *testing.T) {
866 from, to := "renamefrom", "renameto"
868 toData := []byte("to")
869 fromData := []byte("from")
871 err := ioutil.WriteFile(to, toData, 0777)
873 t.Fatalf("write file %q failed: %v", to, err)
876 err = ioutil.WriteFile(from, fromData, 0777)
878 t.Fatalf("write file %q failed: %v", from, err)
880 err = Rename(from, to)
882 t.Fatalf("rename %q, %q failed: %v", to, from, err)
887 t.Errorf("from file %q still exists", from)
889 if err != nil && !IsNotExist(err) {
890 t.Fatalf("stat from: %v", err)
892 toFi, err := Stat(to)
894 t.Fatalf("stat %q failed: %v", to, err)
896 if toFi.Size() != int64(len(fromData)) {
897 t.Errorf(`"to" size = %d; want %d (old "from" size)`, toFi.Size(), len(fromData))
901 func TestRenameFailed(t *testing.T) {
903 from, to := "renamefrom", "renameto"
905 err := Rename(from, to)
906 switch err := err.(type) {
908 if err.Op != "rename" {
909 t.Errorf("rename %q, %q: err.Op: want %q, got %q", from, to, "rename", err.Op)
912 t.Errorf("rename %q, %q: err.Old: want %q, got %q", from, to, from, err.Old)
915 t.Errorf("rename %q, %q: err.New: want %q, got %q", from, to, to, err.New)
918 t.Errorf("rename %q, %q: expected error, got nil", from, to)
920 t.Errorf("rename %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err)
924 func TestRenameNotExisting(t *testing.T) {
926 from, to := "doesnt-exist", "dest"
930 if err := Rename(from, to); !IsNotExist(err) {
931 t.Errorf("Rename(%q, %q) = %v; want an IsNotExist error", from, to, err)
935 func TestRenameToDirFailed(t *testing.T) {
937 from, to := "renamefrom", "renameto"
942 err := Rename(from, to)
943 switch err := err.(type) {
945 if err.Op != "rename" {
946 t.Errorf("rename %q, %q: err.Op: want %q, got %q", from, to, "rename", err.Op)
949 t.Errorf("rename %q, %q: err.Old: want %q, got %q", from, to, from, err.Old)
952 t.Errorf("rename %q, %q: err.New: want %q, got %q", from, to, to, err.New)
955 t.Errorf("rename %q, %q: expected error, got nil", from, to)
957 t.Errorf("rename %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err)
961 func exec(t *testing.T, dir, cmd string, args []string, expect string) {
964 t.Fatalf("Pipe: %v", err)
967 attr := &ProcAttr{Dir: dir, Files: []*File{nil, w, Stderr}}
968 p, err := StartProcess(cmd, args, attr)
970 t.Fatalf("StartProcess: %v", err)
978 fi1, _ := Stat(strings.TrimSpace(output))
979 fi2, _ := Stat(expect)
980 if !SameFile(fi1, fi2) {
981 t.Errorf("exec %q returned %q wanted %q",
982 strings.Join(append([]string{cmd}, args...), " "), output, expect)
987 func TestStartProcess(t *testing.T) {
988 testenv.MustHaveExec(t)
992 switch runtime.GOOS {
994 t.Skip("android doesn't have /bin/pwd")
996 cmd = Getenv("COMSPEC")
997 dir = Getenv("SystemRoot")
998 args = []string{"/c", "cd"}
1001 cmd, err = osexec.LookPath("pwd")
1003 t.Fatalf("Can't find pwd: %v", err)
1007 t.Logf("Testing with %v", cmd)
1009 cmddir, cmdbase := filepath.Split(cmd)
1010 args = append([]string{cmdbase}, args...)
1011 // Test absolute executable path.
1012 exec(t, dir, cmd, args, dir)
1013 // Test relative executable path.
1014 exec(t, cmddir, cmdbase, args, cmddir)
1017 func checkMode(t *testing.T, path string, mode FileMode) {
1018 dir, err := Stat(path)
1020 t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
1022 if dir.Mode()&0777 != mode {
1023 t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode(), mode)
1027 func TestChmod(t *testing.T) {
1028 // Chmod is not supported under windows.
1029 if runtime.GOOS == "windows" {
1032 f := newFile("TestChmod", t)
1033 defer Remove(f.Name())
1036 if err := Chmod(f.Name(), 0456); err != nil {
1037 t.Fatalf("chmod %s 0456: %s", f.Name(), err)
1039 checkMode(t, f.Name(), 0456)
1041 if err := f.Chmod(0123); err != nil {
1042 t.Fatalf("chmod %s 0123: %s", f.Name(), err)
1044 checkMode(t, f.Name(), 0123)
1047 func checkSize(t *testing.T, f *File, size int64) {
1048 dir, err := f.Stat()
1050 t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err)
1052 if dir.Size() != size {
1053 t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size)
1057 func TestFTruncate(t *testing.T) {
1058 f := newFile("TestFTruncate", t)
1059 defer Remove(f.Name())
1063 f.Write([]byte("hello, world\n"))
1068 checkSize(t, f, 1024)
1071 _, err := f.Write([]byte("surprise!"))
1073 checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
1077 func TestTruncate(t *testing.T) {
1078 f := newFile("TestTruncate", t)
1079 defer Remove(f.Name())
1083 f.Write([]byte("hello, world\n"))
1085 Truncate(f.Name(), 10)
1087 Truncate(f.Name(), 1024)
1088 checkSize(t, f, 1024)
1089 Truncate(f.Name(), 0)
1091 _, err := f.Write([]byte("surprise!"))
1093 checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
1097 // Use TempDir (via newFile) to make sure we're on a local file system,
1098 // so that timings are not distorted by latency and caching.
1099 // On NFS, timings can be off due to caching of meta-data on
1100 // NFS servers (Issue 848).
1101 func TestChtimes(t *testing.T) {
1102 f := newFile("TestChtimes", t)
1103 defer Remove(f.Name())
1105 f.Write([]byte("hello, world\n"))
1108 testChtimes(t, f.Name())
1111 // Use TempDir (via newDir) to make sure we're on a local file system,
1112 // so that timings are not distorted by latency and caching.
1113 // On NFS, timings can be off due to caching of meta-data on
1114 // NFS servers (Issue 848).
1115 func TestChtimesDir(t *testing.T) {
1116 name := newDir("TestChtimes", t)
1117 defer RemoveAll(name)
1119 testChtimes(t, name)
1122 func testChtimes(t *testing.T, name string) {
1123 st, err := Stat(name)
1125 t.Fatalf("Stat %s: %s", name, err)
1129 // Move access and modification time back a second
1130 at := Atime(preStat)
1131 mt := preStat.ModTime()
1132 err = Chtimes(name, at.Add(-time.Second), mt.Add(-time.Second))
1134 t.Fatalf("Chtimes %s: %s", name, err)
1137 st, err = Stat(name)
1139 t.Fatalf("second Stat %s: %s", name, err)
1143 pat := Atime(postStat)
1144 pmt := postStat.ModTime()
1145 if !pat.Before(at) {
1146 switch runtime.GOOS {
1147 case "plan9", "nacl":
1150 // Mtime is the time of the last change of
1151 // content. Similarly, atime is set whenever
1152 // the contents are accessed; also, it is set
1153 // whenever mtime is set.
1155 mounts, _ := ioutil.ReadFile("/proc/mounts")
1156 if strings.Contains(string(mounts), "noatime") {
1157 t.Logf("AccessTime didn't go backwards, but see a filesystem mounted noatime; ignoring. Issue 19293.")
1159 t.Logf("AccessTime didn't go backwards; was=%v, after=%v (Ignoring on NetBSD, assuming noatime, Issue 19293)", at, pat)
1162 t.Errorf("AccessTime didn't go backwards; was=%v, after=%v", at, pat)
1166 if !pmt.Before(mt) {
1167 t.Errorf("ModTime didn't go backwards; was=%v, after=%v", mt, pmt)
1171 func TestChdirAndGetwd(t *testing.T) {
1172 // TODO(brainman): file.Chdir() is not implemented on windows.
1173 if runtime.GOOS == "windows" {
1176 fd, err := Open(".")
1178 t.Fatalf("Open .: %s", err)
1180 // These are chosen carefully not to be symlinks on a Mac
1181 // (unlike, say, /var, /etc), except /tmp, which we handle below.
1182 dirs := []string{"/", "/usr/bin", "/tmp"}
1183 // /usr/bin does not usually exist on Plan 9 or Android.
1184 switch runtime.GOOS {
1186 dirs = []string{"/", "/system/bin"}
1188 dirs = []string{"/", "/usr"}
1190 switch runtime.GOARCH {
1191 case "arm", "arm64":
1192 d1, err := ioutil.TempDir("", "d1")
1194 t.Fatalf("TempDir: %v", err)
1196 d2, err := ioutil.TempDir("", "d2")
1198 t.Fatalf("TempDir: %v", err)
1200 dirs = []string{d1, d2}
1203 oldwd := Getenv("PWD")
1204 for mode := 0; mode < 2; mode++ {
1205 for _, d := range dirs {
1209 fd1, err1 := Open(d)
1211 t.Errorf("Open %s: %s", d, err1)
1218 Setenv("PWD", "/tmp")
1220 pwd, err1 := Getwd()
1221 Setenv("PWD", oldwd)
1224 // We changed the current directory and cannot go back.
1225 // Don't let the tests continue; they'll scribble
1226 // all over some other directory.
1227 fmt.Fprintf(Stderr, "fchdir back to dot failed: %s\n", err2)
1232 t.Fatalf("Chdir %s: %s", d, err)
1236 t.Fatalf("Getwd in %s: %s", d, err1)
1240 t.Fatalf("Getwd returned %q want %q", pwd, d)
1247 // Test that Chdir+Getwd is program-wide.
1248 func TestProgWideChdir(t *testing.T) {
1250 c := make(chan bool)
1251 cpwd := make(chan string)
1252 for i := 0; i < N; i++ {
1254 // Lock half the goroutines in their own operating system
1255 // thread to exercise more scheduler possibilities.
1257 // On Plan 9, after calling LockOSThread, the goroutines
1258 // run on different processes which don't share the working
1259 // directory. This used to be an issue because Go expects
1260 // the working directory to be program-wide.
1262 runtime.LockOSThread()
1267 t.Errorf("Getwd on goroutine %d: %v", i, err)
1273 oldwd, err := Getwd()
1275 t.Fatalf("Getwd: %v", err)
1277 d, err := ioutil.TempDir("", "test")
1279 t.Fatalf("TempDir: %v", err)
1282 if err := Chdir(oldwd); err != nil {
1283 t.Fatalf("Chdir: %v", err)
1287 if err := Chdir(d); err != nil {
1288 t.Fatalf("Chdir: %v", err)
1290 // OS X sets TMPDIR to a symbolic link.
1291 // So we resolve our working directory again before the test.
1294 t.Fatalf("Getwd: %v", err)
1297 for i := 0; i < N; i++ {
1300 t.Errorf("Getwd returned %q; want %q", pwd, d)
1305 func TestSeek(t *testing.T) {
1306 f := newFile("TestSeek", t)
1307 defer Remove(f.Name())
1310 const data = "hello, world\n"
1311 io.WriteString(f, data)
1319 {0, io.SeekCurrent, int64(len(data))},
1320 {0, io.SeekStart, 0},
1321 {5, io.SeekStart, 5},
1322 {0, io.SeekEnd, int64(len(data))},
1323 {0, io.SeekStart, 0},
1324 {-1, io.SeekEnd, int64(len(data)) - 1},
1325 {1 << 33, io.SeekStart, 1 << 33},
1326 {1 << 33, io.SeekEnd, 1<<33 + int64(len(data))},
1328 // Issue 21681, Windows 4G-1, etc:
1329 {1<<32 - 1, io.SeekStart, 1<<32 - 1},
1330 {0, io.SeekCurrent, 1<<32 - 1},
1331 {2<<32 - 1, io.SeekStart, 2<<32 - 1},
1332 {0, io.SeekCurrent, 2<<32 - 1},
1334 for i, tt := range tests {
1335 if runtime.GOOS == "nacl" && tt.out > 1<<30 {
1336 t.Logf("skipping test case #%d on nacl; https://golang.org/issue/21728", i)
1339 if runtime.GOOS == "hurd" && tt.out > 1<<32 {
1340 t.Logf("skipping test case #%d on Hurd: file too large", i)
1343 off, err := f.Seek(tt.in, tt.whence)
1344 if off != tt.out || err != nil {
1345 if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 && runtime.GOOS == "linux" {
1346 mounts, _ := ioutil.ReadFile("/proc/mounts")
1347 if strings.Contains(string(mounts), "reiserfs") {
1348 // Reiserfs rejects the big seeks.
1349 t.Skipf("skipping test known to fail on reiserfs; https://golang.org/issue/91")
1352 t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
1357 func TestSeekError(t *testing.T) {
1358 switch runtime.GOOS {
1359 case "js", "nacl", "plan9":
1360 t.Skipf("skipping test on %v", runtime.GOOS)
1367 _, err = r.Seek(0, 0)
1369 t.Fatal("Seek on pipe should fail")
1371 if perr, ok := err.(*PathError); !ok || perr.Err != syscall.ESPIPE {
1372 t.Errorf("Seek returned error %v, want &PathError{Err: syscall.ESPIPE}", err)
1374 _, err = w.Seek(0, 0)
1376 t.Fatal("Seek on pipe should fail")
1378 if perr, ok := err.(*PathError); !ok || perr.Err != syscall.ESPIPE {
1379 t.Errorf("Seek returned error %v, want &PathError{Err: syscall.ESPIPE}", err)
1383 type openErrorTest struct {
1389 var openErrorTests = []openErrorTest{
1391 sfdir + "/no-such-file",
1401 sfdir + "/" + sfname + "/no-such-file",
1407 func TestOpenError(t *testing.T) {
1408 for _, tt := range openErrorTests {
1409 f, err := OpenFile(tt.path, tt.mode, 0)
1411 t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode)
1415 perr, ok := err.(*PathError)
1417 t.Errorf("Open(%q, %d) returns error of %T type; want *PathError", tt.path, tt.mode, err)
1419 if perr.Err != tt.error {
1420 if runtime.GOOS == "plan9" {
1421 syscallErrStr := perr.Err.Error()
1422 expectedErrStr := strings.Replace(tt.error.Error(), "file ", "", 1)
1423 if !strings.HasSuffix(syscallErrStr, expectedErrStr) {
1424 // Some Plan 9 file servers incorrectly return
1425 // EACCES rather than EISDIR when a directory is
1426 // opened for write.
1427 if tt.error == syscall.EISDIR && strings.HasSuffix(syscallErrStr, syscall.EACCES.Error()) {
1430 t.Errorf("Open(%q, %d) = _, %q; want suffix %q", tt.path, tt.mode, syscallErrStr, expectedErrStr)
1434 if runtime.GOOS == "dragonfly" {
1435 // DragonFly incorrectly returns EACCES rather
1436 // EISDIR when a directory is opened for write.
1437 if tt.error == syscall.EISDIR && perr.Err == syscall.EACCES {
1441 t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, perr.Err.Error(), tt.error.Error())
1446 func TestOpenNoName(t *testing.T) {
1449 t.Fatal(`Open("") succeeded`)
1454 func runBinHostname(t *testing.T) string {
1455 // Run /bin/hostname and collect output.
1461 const path = "/bin/hostname"
1462 argv := []string{"hostname"}
1463 if runtime.GOOS == "aix" {
1464 argv = []string{"hostname", "-s"}
1466 p, err := StartProcess(path, argv, &ProcAttr{Files: []*File{nil, w, Stderr}})
1468 if _, err := Stat(path); IsNotExist(err) {
1469 t.Skipf("skipping test; test requires %s but it does not exist", path)
1479 t.Fatalf("run hostname Wait: %v", err)
1483 t.Errorf("expected an error from Kill running 'hostname'")
1485 output := b.String()
1486 if n := len(output); n > 0 && output[n-1] == '\n' {
1487 output = output[0 : n-1]
1490 t.Fatalf("/bin/hostname produced no output")
1496 func testWindowsHostname(t *testing.T, hostname string) {
1497 cmd := osexec.Command("hostname")
1498 out, err := cmd.CombinedOutput()
1500 t.Fatalf("Failed to execute hostname command: %v %s", err, out)
1502 want := strings.Trim(string(out), "\r\n")
1503 if hostname != want {
1504 t.Fatalf("Hostname() = %q != system hostname of %q", hostname, want)
1508 func TestHostname(t *testing.T) {
1509 hostname, err := Hostname()
1514 t.Fatal("Hostname returned empty string and no error")
1516 if strings.Contains(hostname, "\x00") {
1517 t.Fatalf("unexpected zero byte in hostname: %q", hostname)
1520 // There is no other way to fetch hostname on windows, but via winapi.
1521 // On Plan 9 it can be taken from #c/sysname as Hostname() does.
1522 switch runtime.GOOS {
1523 case "android", "plan9":
1524 // No /bin/hostname to verify against.
1527 testWindowsHostname(t, hostname)
1531 testenv.MustHaveExec(t)
1533 // Check internal Hostname() against the output of /bin/hostname.
1534 // Allow that the internal Hostname returns a Fully Qualified Domain Name
1535 // and the /bin/hostname only returns the first component
1536 want := runBinHostname(t)
1537 if hostname != want {
1538 i := strings.Index(hostname, ".")
1539 if i < 0 || hostname[0:i] != want {
1540 t.Errorf("Hostname() = %q, want %q", hostname, want)
1545 func TestReadAt(t *testing.T) {
1546 f := newFile("TestReadAt", t)
1547 defer Remove(f.Name())
1550 const data = "hello, world\n"
1551 io.WriteString(f, data)
1553 b := make([]byte, 5)
1554 n, err := f.ReadAt(b, 7)
1555 if err != nil || n != len(b) {
1556 t.Fatalf("ReadAt 7: %d, %v", n, err)
1558 if string(b) != "world" {
1559 t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
1563 // Verify that ReadAt doesn't affect seek offset.
1564 // In the Plan 9 kernel, there used to be a bug in the implementation of
1565 // the pread syscall, where the channel offset was erroneously updated after
1566 // calling pread on a file.
1567 func TestReadAtOffset(t *testing.T) {
1568 f := newFile("TestReadAtOffset", t)
1569 defer Remove(f.Name())
1572 const data = "hello, world\n"
1573 io.WriteString(f, data)
1576 b := make([]byte, 5)
1578 n, err := f.ReadAt(b, 7)
1579 if err != nil || n != len(b) {
1580 t.Fatalf("ReadAt 7: %d, %v", n, err)
1582 if string(b) != "world" {
1583 t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
1587 if err != nil || n != len(b) {
1588 t.Fatalf("Read: %d, %v", n, err)
1590 if string(b) != "hello" {
1591 t.Fatalf("Read: have %q want %q", string(b), "hello")
1595 // Verify that ReadAt doesn't allow negative offset.
1596 func TestReadAtNegativeOffset(t *testing.T) {
1597 f := newFile("TestReadAtNegativeOffset", t)
1598 defer Remove(f.Name())
1601 const data = "hello, world\n"
1602 io.WriteString(f, data)
1605 b := make([]byte, 5)
1607 n, err := f.ReadAt(b, -10)
1609 const wantsub = "negative offset"
1610 if !strings.Contains(fmt.Sprint(err), wantsub) || n != 0 {
1611 t.Errorf("ReadAt(-10) = %v, %v; want 0, ...%q...", n, err, wantsub)
1615 func TestWriteAt(t *testing.T) {
1616 f := newFile("TestWriteAt", t)
1617 defer Remove(f.Name())
1620 const data = "hello, world\n"
1621 io.WriteString(f, data)
1623 n, err := f.WriteAt([]byte("WORLD"), 7)
1624 if err != nil || n != 5 {
1625 t.Fatalf("WriteAt 7: %d, %v", n, err)
1628 b, err := ioutil.ReadFile(f.Name())
1630 t.Fatalf("ReadFile %s: %v", f.Name(), err)
1632 if string(b) != "hello, WORLD\n" {
1633 t.Fatalf("after write: have %q want %q", string(b), "hello, WORLD\n")
1637 // Verify that WriteAt doesn't allow negative offset.
1638 func TestWriteAtNegativeOffset(t *testing.T) {
1639 f := newFile("TestWriteAtNegativeOffset", t)
1640 defer Remove(f.Name())
1643 n, err := f.WriteAt([]byte("WORLD"), -10)
1645 const wantsub = "negative offset"
1646 if !strings.Contains(fmt.Sprint(err), wantsub) || n != 0 {
1647 t.Errorf("WriteAt(-10) = %v, %v; want 0, ...%q...", n, err, wantsub)
1651 func writeFile(t *testing.T, fname string, flag int, text string) string {
1652 f, err := OpenFile(fname, flag, 0666)
1654 t.Fatalf("Open: %v", err)
1656 n, err := io.WriteString(f, text)
1658 t.Fatalf("WriteString: %d, %v", n, err)
1661 data, err := ioutil.ReadFile(fname)
1663 t.Fatalf("ReadFile: %v", err)
1668 func TestAppend(t *testing.T) {
1670 const f = "append.txt"
1671 s := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
1673 t.Fatalf("writeFile: have %q want %q", s, "new")
1675 s = writeFile(t, f, O_APPEND|O_RDWR, "|append")
1676 if s != "new|append" {
1677 t.Fatalf("writeFile: have %q want %q", s, "new|append")
1679 s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "|append")
1680 if s != "new|append|append" {
1681 t.Fatalf("writeFile: have %q want %q", s, "new|append|append")
1685 t.Fatalf("Remove: %v", err)
1687 s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "new&append")
1688 if s != "new&append" {
1689 t.Fatalf("writeFile: after append have %q want %q", s, "new&append")
1691 s = writeFile(t, f, O_CREATE|O_RDWR, "old")
1692 if s != "old&append" {
1693 t.Fatalf("writeFile: after create have %q want %q", s, "old&append")
1695 s = writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
1697 t.Fatalf("writeFile: after truncate have %q want %q", s, "new")
1701 func TestStatDirWithTrailingSlash(t *testing.T) {
1702 // Create new temporary directory and arrange to clean it up.
1703 path, err := ioutil.TempDir("", "/_TestStatDirWithSlash_")
1705 t.Fatalf("TempDir: %s", err)
1707 defer RemoveAll(path)
1709 // Stat of path should succeed.
1712 t.Fatalf("stat %s failed: %s", path, err)
1715 // Stat of path+"/" should succeed too.
1719 t.Fatalf("stat %s failed: %s", path, err)
1723 func TestNilProcessStateString(t *testing.T) {
1724 var ps *ProcessState
1727 t.Errorf("(*ProcessState)(nil).String() = %q, want %q", s, "<nil>")
1731 func TestSameFile(t *testing.T) {
1733 fa, err := Create("a")
1735 t.Fatalf("Create(a): %v", err)
1738 fb, err := Create("b")
1740 t.Fatalf("Create(b): %v", err)
1744 ia1, err := Stat("a")
1746 t.Fatalf("Stat(a): %v", err)
1748 ia2, err := Stat("a")
1750 t.Fatalf("Stat(a): %v", err)
1752 if !SameFile(ia1, ia2) {
1753 t.Errorf("files should be same")
1756 ib, err := Stat("b")
1758 t.Fatalf("Stat(b): %v", err)
1760 if SameFile(ia1, ib) {
1761 t.Errorf("files should be different")
1765 func testDevNullFileInfo(t *testing.T, statname, devNullName string, fi FileInfo, ignoreCase bool) {
1766 pre := fmt.Sprintf("%s(%q): ", statname, devNullName)
1767 name := filepath.Base(devNullName)
1769 if strings.ToUpper(fi.Name()) != strings.ToUpper(name) {
1770 t.Errorf(pre+"wrong file name have %v want %v", fi.Name(), name)
1773 if fi.Name() != name {
1774 t.Errorf(pre+"wrong file name have %v want %v", fi.Name(), name)
1778 t.Errorf(pre+"wrong file size have %d want 0", fi.Size())
1780 if fi.Mode()&ModeDevice == 0 {
1781 t.Errorf(pre+"wrong file mode %q: ModeDevice is not set", fi.Mode())
1783 if fi.Mode()&ModeCharDevice == 0 {
1784 t.Errorf(pre+"wrong file mode %q: ModeCharDevice is not set", fi.Mode())
1786 if fi.Mode().IsRegular() {
1787 t.Errorf(pre+"wrong file mode %q: IsRegular returns true", fi.Mode())
1791 func testDevNullFile(t *testing.T, devNullName string, ignoreCase bool) {
1792 f, err := Open(devNullName)
1794 t.Fatalf("Open(%s): %v", devNullName, err)
1800 t.Fatalf("Stat(%s): %v", devNullName, err)
1802 testDevNullFileInfo(t, "f.Stat", devNullName, fi, ignoreCase)
1804 fi, err = Stat(devNullName)
1806 t.Fatalf("Stat(%s): %v", devNullName, err)
1808 testDevNullFileInfo(t, "Stat", devNullName, fi, ignoreCase)
1811 func TestDevNullFile(t *testing.T) {
1812 testDevNullFile(t, DevNull, false)
1815 var testLargeWrite = flag.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output")
1817 func TestLargeWriteToConsole(t *testing.T) {
1818 if !*testLargeWrite {
1819 t.Skip("skipping console-flooding test; enable with -large_write")
1821 b := make([]byte, 32000)
1826 n, err := Stdout.Write(b)
1828 t.Fatalf("Write to os.Stdout failed: %v", err)
1831 t.Errorf("Write to os.Stdout should return %d; got %d", len(b), n)
1833 n, err = Stderr.Write(b)
1835 t.Fatalf("Write to os.Stderr failed: %v", err)
1838 t.Errorf("Write to os.Stderr should return %d; got %d", len(b), n)
1842 func TestStatDirModeExec(t *testing.T) {
1845 path, err := ioutil.TempDir("", "go-build")
1847 t.Fatalf("Failed to create temp directory: %v", err)
1849 defer RemoveAll(path)
1851 if err := Chmod(path, 0777); err != nil {
1852 t.Fatalf("Chmod %q 0777: %v", path, err)
1855 dir, err := Stat(path)
1857 t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
1859 if dir.Mode()&mode != mode {
1860 t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode()&mode, mode)
1864 func TestStatStdin(t *testing.T) {
1865 switch runtime.GOOS {
1866 case "android", "plan9":
1867 t.Skipf("%s doesn't have /bin/sh", runtime.GOOS)
1870 testenv.MustHaveExec(t)
1872 if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
1873 st, err := Stdin.Stat()
1875 t.Fatalf("Stat failed: %v", err)
1877 fmt.Println(st.Mode() & ModeNamedPipe)
1881 fi, err := Stdin.Stat()
1885 switch mode := fi.Mode(); {
1886 case mode&ModeCharDevice != 0 && mode&ModeDevice != 0:
1887 case mode&ModeNamedPipe != 0:
1889 t.Fatalf("unexpected Stdin mode (%v), want ModeCharDevice or ModeNamedPipe", mode)
1893 if runtime.GOOS == "windows" {
1894 cmd = osexec.Command("cmd", "/c", "echo output | "+Args[0]+" -test.run=TestStatStdin")
1896 cmd = osexec.Command("/bin/sh", "-c", "echo output | "+Args[0]+" -test.run=TestStatStdin")
1898 cmd.Env = append(Environ(), "GO_WANT_HELPER_PROCESS=1")
1900 output, err := cmd.CombinedOutput()
1902 t.Fatalf("Failed to spawn child process: %v %q", err, string(output))
1905 // result will be like "prw-rw-rw"
1906 if len(output) < 1 || output[0] != 'p' {
1907 t.Fatalf("Child process reports stdin is not pipe '%v'", string(output))
1911 func TestStatRelativeSymlink(t *testing.T) {
1912 testenv.MustHaveSymlink(t)
1914 tmpdir, err := ioutil.TempDir("", "TestStatRelativeSymlink")
1918 defer RemoveAll(tmpdir)
1920 target := filepath.Join(tmpdir, "target")
1921 f, err := Create(target)
1932 link := filepath.Join(tmpdir, "link")
1933 err = Symlink(filepath.Base(target), link)
1938 st1, err := Stat(link)
1943 if !SameFile(st, st1) {
1944 t.Error("Stat doesn't follow relative symlink")
1947 if runtime.GOOS == "windows" {
1949 err = Symlink(target[len(filepath.VolumeName(target)):], link)
1954 st1, err := Stat(link)
1959 if !SameFile(st, st1) {
1960 t.Error("Stat doesn't follow relative symlink")
1965 func TestReadAtEOF(t *testing.T) {
1966 f := newFile("TestReadAtEOF", t)
1967 defer Remove(f.Name())
1970 _, err := f.ReadAt(make([]byte, 10), 0)
1975 t.Fatalf("ReadAt succeeded")
1977 t.Fatalf("ReadAt failed: %s", err)
1981 func TestLongPath(t *testing.T) {
1982 tmpdir := newDir("TestLongPath", t)
1983 defer func(d string) {
1984 if err := RemoveAll(d); err != nil {
1985 t.Fatalf("RemoveAll failed: %v", err)
1989 // Test the boundary of 247 and fewer bytes (normal) and 248 and more bytes (adjusted).
1990 sizes := []int{247, 248, 249, 400}
1991 for len(tmpdir) < 400 {
1992 tmpdir += "/dir3456789"
1994 for _, sz := range sizes {
1995 t.Run(fmt.Sprintf("length=%d", sz), func(t *testing.T) {
1996 sizedTempDir := tmpdir[:sz-1] + "x" // Ensure it does not end with a slash.
1998 // The various sized runs are for this call to trigger the boundary
2000 if err := MkdirAll(sizedTempDir, 0755); err != nil {
2001 t.Fatalf("MkdirAll failed: %v", err)
2003 data := []byte("hello world\n")
2004 if err := ioutil.WriteFile(sizedTempDir+"/foo.txt", data, 0644); err != nil {
2005 t.Fatalf("ioutil.WriteFile() failed: %v", err)
2007 if err := Rename(sizedTempDir+"/foo.txt", sizedTempDir+"/bar.txt"); err != nil {
2008 t.Fatalf("Rename failed: %v", err)
2010 mtime := time.Now().Truncate(time.Minute)
2011 if err := Chtimes(sizedTempDir+"/bar.txt", mtime, mtime); err != nil {
2012 t.Fatalf("Chtimes failed: %v", err)
2014 names := []string{"bar.txt"}
2015 if testenv.HasSymlink() {
2016 if err := Symlink(sizedTempDir+"/bar.txt", sizedTempDir+"/symlink.txt"); err != nil {
2017 t.Fatalf("Symlink failed: %v", err)
2019 names = append(names, "symlink.txt")
2021 if testenv.HasLink() {
2022 if err := Link(sizedTempDir+"/bar.txt", sizedTempDir+"/link.txt"); err != nil {
2023 t.Fatalf("Link failed: %v", err)
2025 names = append(names, "link.txt")
2027 for _, wantSize := range []int64{int64(len(data)), 0} {
2028 for _, name := range names {
2029 path := sizedTempDir + "/" + name
2030 dir, err := Stat(path)
2032 t.Fatalf("Stat(%q) failed: %v", path, err)
2034 filesize := size(path, t)
2035 if dir.Size() != filesize || filesize != wantSize {
2036 t.Errorf("Size(%q) is %d, len(ReadFile()) is %d, want %d", path, dir.Size(), filesize, wantSize)
2038 err = Chmod(path, dir.Mode())
2040 t.Fatalf("Chmod(%q) failed: %v", path, err)
2043 if err := Truncate(sizedTempDir+"/bar.txt", 0); err != nil {
2044 t.Fatalf("Truncate failed: %v", err)
2051 func testKillProcess(t *testing.T, processKiller func(p *Process)) {
2052 testenv.MustHaveExec(t)
2054 // Re-exec the test binary itself to emulate "sleep 1".
2055 cmd := osexec.Command(Args[0], "-test.run", "TestSleep")
2058 t.Fatalf("Failed to start test process: %v", err)
2061 time.Sleep(100 * time.Millisecond)
2062 processKiller(cmd.Process)
2066 t.Errorf("Test process succeeded, but expected to fail")
2070 // TestSleep emulates "sleep 1". It is a helper for testKillProcess, so we
2071 // don't have to rely on an external "sleep" command being available.
2072 func TestSleep(t *testing.T) {
2073 if testing.Short() {
2074 t.Skip("Skipping in short mode")
2076 time.Sleep(time.Second)
2079 func TestKillStartProcess(t *testing.T) {
2080 testKillProcess(t, func(p *Process) {
2083 t.Fatalf("Failed to kill test process: %v", err)
2088 func TestGetppid(t *testing.T) {
2089 if runtime.GOOS == "plan9" {
2090 // TODO: golang.org/issue/8206
2091 t.Skipf("skipping test on plan9; see issue 8206")
2094 testenv.MustHaveExec(t)
2096 if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
2097 fmt.Print(Getppid())
2101 cmd := osexec.Command(Args[0], "-test.run=TestGetppid")
2102 cmd.Env = append(Environ(), "GO_WANT_HELPER_PROCESS=1")
2104 // verify that Getppid() from the forked process reports our process id
2105 output, err := cmd.CombinedOutput()
2107 t.Fatalf("Failed to spawn child process: %v %q", err, string(output))
2110 childPpid := string(output)
2111 ourPid := fmt.Sprintf("%d", Getpid())
2112 if childPpid != ourPid {
2113 t.Fatalf("Child process reports parent process id '%v', expected '%v'", childPpid, ourPid)
2117 func TestKillFindProcess(t *testing.T) {
2118 testKillProcess(t, func(p *Process) {
2119 p2, err := FindProcess(p.Pid)
2121 t.Fatalf("Failed to find test process: %v", err)
2125 t.Fatalf("Failed to kill test process: %v", err)
2130 var nilFileMethodTests = []struct {
2134 {"Chdir", func(f *File) error { return f.Chdir() }},
2135 {"Close", func(f *File) error { return f.Close() }},
2136 {"Chmod", func(f *File) error { return f.Chmod(0) }},
2137 {"Chown", func(f *File) error { return f.Chown(0, 0) }},
2138 {"Read", func(f *File) error { _, err := f.Read(make([]byte, 0)); return err }},
2139 {"ReadAt", func(f *File) error { _, err := f.ReadAt(make([]byte, 0), 0); return err }},
2140 {"Readdir", func(f *File) error { _, err := f.Readdir(1); return err }},
2141 {"Readdirnames", func(f *File) error { _, err := f.Readdirnames(1); return err }},
2142 {"Seek", func(f *File) error { _, err := f.Seek(0, io.SeekStart); return err }},
2143 {"Stat", func(f *File) error { _, err := f.Stat(); return err }},
2144 {"Sync", func(f *File) error { return f.Sync() }},
2145 {"Truncate", func(f *File) error { return f.Truncate(0) }},
2146 {"Write", func(f *File) error { _, err := f.Write(make([]byte, 0)); return err }},
2147 {"WriteAt", func(f *File) error { _, err := f.WriteAt(make([]byte, 0), 0); return err }},
2148 {"WriteString", func(f *File) error { _, err := f.WriteString(""); return err }},
2151 // Test that all File methods give ErrInvalid if the receiver is nil.
2152 func TestNilFileMethods(t *testing.T) {
2153 for _, tt := range nilFileMethodTests {
2156 if got != ErrInvalid {
2157 t.Errorf("%v should fail when f is nil; got %v", tt.name, got)
2162 func mkdirTree(t *testing.T, root string, level, max int) {
2167 for i := 'a'; i < 'c'; i++ {
2168 dir := filepath.Join(root, string(i))
2169 if err := Mkdir(dir, 0700); err != nil {
2172 mkdirTree(t, dir, level, max)
2176 // Test that simultaneous RemoveAll do not report an error.
2177 // As long as it gets removed, we should be happy.
2178 func TestRemoveAllRace(t *testing.T) {
2179 if runtime.GOOS == "windows" {
2180 // Windows has very strict rules about things like
2181 // removing directories while someone else has
2182 // them open. The racing doesn't work out nicely
2183 // like it does on Unix.
2184 t.Skip("skipping on windows")
2187 n := runtime.GOMAXPROCS(16)
2188 defer runtime.GOMAXPROCS(n)
2189 root, err := ioutil.TempDir("", "issue")
2193 mkdirTree(t, root, 1, 6)
2194 hold := make(chan struct{})
2195 var wg sync.WaitGroup
2196 for i := 0; i < 4; i++ {
2201 err := RemoveAll(root)
2203 t.Errorf("unexpected error: %T, %q", err, err)
2207 close(hold) // let workers race to remove root
2211 // Test that reading from a pipe doesn't use up a thread.
2212 func TestPipeThreads(t *testing.T) {
2213 switch runtime.GOOS {
2215 t.Skip("skipping on FreeBSD; issue 19093")
2217 t.Skip("skipping on Solaris; issue 19111")
2219 t.Skip("skipping on Windows; issue 19098")
2221 t.Skip("skipping on Plan 9; does not support runtime poller")
2223 t.Skip("skipping on js; no support for os.Pipe")
2228 // OpenBSD has a low default for max number of files.
2229 if runtime.GOOS == "openbsd" {
2233 r := make([]*File, threads)
2234 w := make([]*File, threads)
2235 for i := 0; i < threads; i++ {
2236 rp, wp, err := Pipe()
2238 for j := 0; j < i; j++ {
2248 defer debug.SetMaxThreads(debug.SetMaxThreads(threads / 2))
2250 creading := make(chan bool, threads)
2251 cdone := make(chan bool, threads)
2252 for i := 0; i < threads; i++ {
2256 if _, err := r[i].Read(b[:]); err != nil {
2259 if err := r[i].Close(); err != nil {
2266 for i := 0; i < threads; i++ {
2270 // If we are still alive, it means that the 100 goroutines did
2271 // not require 100 threads.
2273 for i := 0; i < threads; i++ {
2274 if _, err := w[i].Write([]byte{0}); err != nil {
2277 if err := w[i].Close(); err != nil {
2284 func TestDoubleCloseError(t *testing.T) {
2285 path := sfdir + "/" + sfname
2286 file, err := Open(path)
2290 if err := file.Close(); err != nil {
2291 t.Fatalf("unexpected error from Close: %v", err)
2293 if err := file.Close(); err == nil {
2294 t.Error("second Close did not fail")
2295 } else if pe, ok := err.(*PathError); !ok {
2296 t.Errorf("second Close returned unexpected error type %T; expected os.PathError", pe)
2297 } else if pe.Err != ErrClosed {
2298 t.Errorf("second Close returned %q, wanted %q", err, ErrClosed)
2300 t.Logf("second close returned expected error %q", err)
2304 func TestUserHomeDir(t *testing.T) {
2305 dir, err := UserHomeDir()
2306 if dir == "" && err == nil {
2307 t.Fatal("UserHomeDir returned an empty string but no error")
2310 t.Skipf("UserHomeDir failed: %v", err)
2312 fi, err := Stat(dir)
2317 t.Fatalf("dir %s is not directory; type = %v", dir, fi.Mode())