tree-optimization/116791 - Elementwise SLP vectorization
[official-gcc.git] / libgo / go / os / os_test.go
blob59e4fb693d60faf0f787f225efb9d6e505d67d6a
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.
5 package os_test
7 import (
8 "bytes"
9 "errors"
10 "flag"
11 "fmt"
12 "internal/testenv"
13 "io"
14 "io/fs"
15 "os"
16 . "os"
17 osexec "os/exec"
18 "path/filepath"
19 "reflect"
20 "runtime"
21 "runtime/debug"
22 "sort"
23 "strings"
24 "sync"
25 "syscall"
26 "testing"
27 "testing/fstest"
28 "time"
31 func TestMain(m *testing.M) {
32 if Getenv("GO_OS_TEST_DRAIN_STDIN") == "1" {
33 os.Stdout.Close()
34 io.Copy(io.Discard, os.Stdin)
35 Exit(0)
38 Exit(m.Run())
41 var dot = []string{
42 "dir.go",
43 "env.go",
44 "error.go",
45 "file.go",
46 "os_test.go",
47 "types.go",
50 type sysDir struct {
51 name string
52 files []string
55 var sysdir = func() *sysDir {
56 switch runtime.GOOS {
57 case "android":
58 return &sysDir{
59 "/system/lib",
60 []string{
61 "libmedia.so",
62 "libpowermanager.so",
65 case "ios":
66 wd, err := syscall.Getwd()
67 if err != nil {
68 wd = err.Error()
70 sd := &sysDir{
71 filepath.Join(wd, "..", ".."),
72 []string{
73 "ResourceRules.plist",
74 "Info.plist",
77 found := true
78 for _, f := range sd.files {
79 path := filepath.Join(sd.name, f)
80 if _, err := Stat(path); err != nil {
81 found = false
82 break
85 if found {
86 return sd
88 // In a self-hosted iOS build the above files might
89 // not exist. Look for system files instead below.
90 case "windows":
91 return &sysDir{
92 Getenv("SystemRoot") + "\\system32\\drivers\\etc",
93 []string{
94 "networks",
95 "protocol",
96 "services",
99 case "plan9":
100 return &sysDir{
101 "/lib/ndb",
102 []string{
103 "common",
104 "local",
108 return &sysDir{
109 "/etc",
110 []string{
111 "group",
112 "hosts",
113 "passwd",
118 func size(name string, t *testing.T) int64 {
119 file, err := Open(name)
120 if err != nil {
121 t.Fatal("open failed:", err)
123 defer func() {
124 if err := file.Close(); err != nil {
125 t.Error(err)
128 n, err := io.Copy(io.Discard, file)
129 if err != nil {
130 t.Fatal(err)
132 return n
135 func equal(name1, name2 string) (r bool) {
136 switch runtime.GOOS {
137 case "windows":
138 r = strings.ToLower(name1) == strings.ToLower(name2)
139 default:
140 r = name1 == name2
142 return
145 // localTmp returns a local temporary directory not on NFS.
146 func localTmp() string {
147 switch runtime.GOOS {
148 case "android", "ios", "windows":
149 return TempDir()
151 return "/tmp"
154 func newFile(testName string, t *testing.T) (f *File) {
155 f, err := os.CreateTemp(localTmp(), "_Go_"+testName)
156 if err != nil {
157 t.Fatalf("TempFile %s: %s", testName, err)
159 return
162 func newDir(testName string, t *testing.T) (name string) {
163 name, err := os.MkdirTemp(localTmp(), "_Go_"+testName)
164 if err != nil {
165 t.Fatalf("TempDir %s: %s", testName, err)
167 return
170 var sfdir = sysdir.name
171 var sfname = sysdir.files[0]
173 func TestStat(t *testing.T) {
174 path := sfdir + "/" + sfname
175 dir, err := Stat(path)
176 if err != nil {
177 t.Fatal("stat failed:", err)
179 if !equal(sfname, dir.Name()) {
180 t.Error("name should be ", sfname, "; is", dir.Name())
182 filesize := size(path, t)
183 if dir.Size() != filesize {
184 t.Error("size should be", filesize, "; is", dir.Size())
188 func TestStatError(t *testing.T) {
189 defer chtmpdir(t)()
191 path := "no-such-file"
193 fi, err := Stat(path)
194 if err == nil {
195 t.Fatal("got nil, want error")
197 if fi != nil {
198 t.Errorf("got %v, want nil", fi)
200 if perr, ok := err.(*PathError); !ok {
201 t.Errorf("got %T, want %T", err, perr)
204 testenv.MustHaveSymlink(t)
206 link := "symlink"
207 err = Symlink(path, link)
208 if err != nil {
209 t.Fatal(err)
212 fi, err = Stat(link)
213 if err == nil {
214 t.Fatal("got nil, want error")
216 if fi != nil {
217 t.Errorf("got %v, want nil", fi)
219 if perr, ok := err.(*PathError); !ok {
220 t.Errorf("got %T, want %T", err, perr)
224 func TestFstat(t *testing.T) {
225 path := sfdir + "/" + sfname
226 file, err1 := Open(path)
227 if err1 != nil {
228 t.Fatal("open failed:", err1)
230 defer file.Close()
231 dir, err2 := file.Stat()
232 if err2 != nil {
233 t.Fatal("fstat failed:", err2)
235 if !equal(sfname, dir.Name()) {
236 t.Error("name should be ", sfname, "; is", dir.Name())
238 filesize := size(path, t)
239 if dir.Size() != filesize {
240 t.Error("size should be", filesize, "; is", dir.Size())
244 func TestLstat(t *testing.T) {
245 path := sfdir + "/" + sfname
246 dir, err := Lstat(path)
247 if err != nil {
248 t.Fatal("lstat failed:", err)
250 if !equal(sfname, dir.Name()) {
251 t.Error("name should be ", sfname, "; is", dir.Name())
253 filesize := size(path, t)
254 if dir.Size() != filesize {
255 t.Error("size should be", filesize, "; is", dir.Size())
259 // Read with length 0 should not return EOF.
260 func TestRead0(t *testing.T) {
261 path := sfdir + "/" + sfname
262 f, err := Open(path)
263 if err != nil {
264 t.Fatal("open failed:", err)
266 defer f.Close()
268 b := make([]byte, 0)
269 n, err := f.Read(b)
270 if n != 0 || err != nil {
271 t.Errorf("Read(0) = %d, %v, want 0, nil", n, err)
273 b = make([]byte, 100)
274 n, err = f.Read(b)
275 if n <= 0 || err != nil {
276 t.Errorf("Read(100) = %d, %v, want >0, nil", n, err)
280 // Reading a closed file should return ErrClosed error
281 func TestReadClosed(t *testing.T) {
282 path := sfdir + "/" + sfname
283 file, err := Open(path)
284 if err != nil {
285 t.Fatal("open failed:", err)
287 file.Close() // close immediately
289 b := make([]byte, 100)
290 _, err = file.Read(b)
292 e, ok := err.(*PathError)
293 if !ok {
294 t.Fatalf("Read: %T(%v), want PathError", e, e)
297 if e.Err != ErrClosed {
298 t.Errorf("Read: %v, want PathError(ErrClosed)", e)
302 func testReaddirnames(dir string, contents []string, t *testing.T) {
303 file, err := Open(dir)
304 if err != nil {
305 t.Fatalf("open %q failed: %v", dir, err)
307 defer file.Close()
308 s, err2 := file.Readdirnames(-1)
309 if err2 != nil {
310 t.Fatalf("Readdirnames %q failed: %v", dir, err2)
312 for _, m := range contents {
313 found := false
314 for _, n := range s {
315 if n == "." || n == ".." {
316 t.Errorf("got %q in directory", n)
318 if !equal(m, n) {
319 continue
321 if found {
322 t.Error("present twice:", m)
324 found = true
326 if !found {
327 t.Error("could not find", m)
330 if s == nil {
331 t.Error("Readdirnames returned nil instead of empty slice")
335 func testReaddir(dir string, contents []string, t *testing.T) {
336 file, err := Open(dir)
337 if err != nil {
338 t.Fatalf("open %q failed: %v", dir, err)
340 defer file.Close()
341 s, err2 := file.Readdir(-1)
342 if err2 != nil {
343 t.Fatalf("Readdir %q failed: %v", dir, err2)
345 for _, m := range contents {
346 found := false
347 for _, n := range s {
348 if n.Name() == "." || n.Name() == ".." {
349 t.Errorf("got %q in directory", n.Name())
351 if !equal(m, n.Name()) {
352 continue
354 if found {
355 t.Error("present twice:", m)
357 found = true
359 if !found {
360 t.Error("could not find", m)
363 if s == nil {
364 t.Error("Readdir returned nil instead of empty slice")
368 func testReadDir(dir string, contents []string, t *testing.T) {
369 file, err := Open(dir)
370 if err != nil {
371 t.Fatalf("open %q failed: %v", dir, err)
373 defer file.Close()
374 s, err2 := file.ReadDir(-1)
375 if err2 != nil {
376 t.Fatalf("ReadDir %q failed: %v", dir, err2)
378 for _, m := range contents {
379 found := false
380 for _, n := range s {
381 if n.Name() == "." || n.Name() == ".." {
382 t.Errorf("got %q in directory", n)
384 if !equal(m, n.Name()) {
385 continue
387 if found {
388 t.Error("present twice:", m)
390 found = true
391 lstat, err := Lstat(dir + "/" + m)
392 if err != nil {
393 t.Fatal(err)
395 if n.IsDir() != lstat.IsDir() {
396 t.Errorf("%s: IsDir=%v, want %v", m, n.IsDir(), lstat.IsDir())
398 if n.Type() != lstat.Mode().Type() {
399 t.Errorf("%s: IsDir=%v, want %v", m, n.Type(), lstat.Mode().Type())
401 info, err := n.Info()
402 if err != nil {
403 t.Errorf("%s: Info: %v", m, err)
404 continue
406 if !SameFile(info, lstat) {
407 t.Errorf("%s: Info: SameFile(info, lstat) = false", m)
410 if !found {
411 t.Error("could not find", m)
414 if s == nil {
415 t.Error("ReadDir returned nil instead of empty slice")
419 func TestFileReaddirnames(t *testing.T) {
420 testReaddirnames(".", dot, t)
421 testReaddirnames(sysdir.name, sysdir.files, t)
422 testReaddirnames(t.TempDir(), nil, t)
425 func TestFileReaddir(t *testing.T) {
426 testReaddir(".", dot, t)
427 testReaddir(sysdir.name, sysdir.files, t)
428 testReaddir(t.TempDir(), nil, t)
431 func TestFileReadDir(t *testing.T) {
432 testReadDir(".", dot, t)
433 testReadDir(sysdir.name, sysdir.files, t)
434 testReadDir(t.TempDir(), nil, t)
437 func benchmarkReaddirname(path string, b *testing.B) {
438 var nentries int
439 for i := 0; i < b.N; i++ {
440 f, err := Open(path)
441 if err != nil {
442 b.Fatalf("open %q failed: %v", path, err)
444 ns, err := f.Readdirnames(-1)
445 f.Close()
446 if err != nil {
447 b.Fatalf("readdirnames %q failed: %v", path, err)
449 nentries = len(ns)
451 b.Logf("benchmarkReaddirname %q: %d entries", path, nentries)
454 func benchmarkReaddir(path string, b *testing.B) {
455 var nentries int
456 for i := 0; i < b.N; i++ {
457 f, err := Open(path)
458 if err != nil {
459 b.Fatalf("open %q failed: %v", path, err)
461 fs, err := f.Readdir(-1)
462 f.Close()
463 if err != nil {
464 b.Fatalf("readdir %q failed: %v", path, err)
466 nentries = len(fs)
468 b.Logf("benchmarkReaddir %q: %d entries", path, nentries)
471 func benchmarkReadDir(path string, b *testing.B) {
472 var nentries int
473 for i := 0; i < b.N; i++ {
474 f, err := Open(path)
475 if err != nil {
476 b.Fatalf("open %q failed: %v", path, err)
478 fs, err := f.ReadDir(-1)
479 f.Close()
480 if err != nil {
481 b.Fatalf("readdir %q failed: %v", path, err)
483 nentries = len(fs)
485 b.Logf("benchmarkReadDir %q: %d entries", path, nentries)
488 func BenchmarkReaddirname(b *testing.B) {
489 benchmarkReaddirname(".", b)
492 func BenchmarkReaddir(b *testing.B) {
493 benchmarkReaddir(".", b)
496 func BenchmarkReadDir(b *testing.B) {
497 benchmarkReadDir(".", b)
500 func benchmarkStat(b *testing.B, path string) {
501 b.ResetTimer()
502 for i := 0; i < b.N; i++ {
503 _, err := Stat(path)
504 if err != nil {
505 b.Fatalf("Stat(%q) failed: %v", path, err)
510 func benchmarkLstat(b *testing.B, path string) {
511 b.ResetTimer()
512 for i := 0; i < b.N; i++ {
513 _, err := Lstat(path)
514 if err != nil {
515 b.Fatalf("Lstat(%q) failed: %v", path, err)
520 func BenchmarkStatDot(b *testing.B) {
521 benchmarkStat(b, ".")
524 func BenchmarkStatFile(b *testing.B) {
525 benchmarkStat(b, filepath.Join(runtime.GOROOT(), "src/os/os_test.go"))
528 func BenchmarkStatDir(b *testing.B) {
529 benchmarkStat(b, filepath.Join(runtime.GOROOT(), "src/os"))
532 func BenchmarkLstatDot(b *testing.B) {
533 benchmarkLstat(b, ".")
536 func BenchmarkLstatFile(b *testing.B) {
537 benchmarkLstat(b, filepath.Join(runtime.GOROOT(), "src/os/os_test.go"))
540 func BenchmarkLstatDir(b *testing.B) {
541 benchmarkLstat(b, filepath.Join(runtime.GOROOT(), "src/os"))
544 // Read the directory one entry at a time.
545 func smallReaddirnames(file *File, length int, t *testing.T) []string {
546 names := make([]string, length)
547 count := 0
548 for {
549 d, err := file.Readdirnames(1)
550 if err == io.EOF {
551 break
553 if err != nil {
554 t.Fatalf("readdirnames %q failed: %v", file.Name(), err)
556 if len(d) == 0 {
557 t.Fatalf("readdirnames %q returned empty slice and no error", file.Name())
559 names[count] = d[0]
560 count++
562 return names[0:count]
565 // Check that reading a directory one entry at a time gives the same result
566 // as reading it all at once.
567 func TestReaddirnamesOneAtATime(t *testing.T) {
568 // big directory that doesn't change often.
569 dir := "/usr/bin"
570 switch runtime.GOOS {
571 case "android":
572 dir = "/system/bin"
573 case "ios":
574 wd, err := Getwd()
575 if err != nil {
576 t.Fatal(err)
578 dir = wd
579 case "plan9":
580 dir = "/bin"
581 case "windows":
582 dir = Getenv("SystemRoot") + "\\system32"
584 file, err := Open(dir)
585 if err != nil {
586 t.Fatalf("open %q failed: %v", dir, err)
588 defer file.Close()
589 all, err1 := file.Readdirnames(-1)
590 if err1 != nil {
591 t.Fatalf("readdirnames %q failed: %v", dir, err1)
593 file1, err2 := Open(dir)
594 if err2 != nil {
595 t.Fatalf("open %q failed: %v", dir, err2)
597 defer file1.Close()
598 small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up
599 if len(small) < len(all) {
600 t.Fatalf("len(small) is %d, less than %d", len(small), len(all))
602 for i, n := range all {
603 if small[i] != n {
604 t.Errorf("small read %q mismatch: %v", small[i], n)
609 func TestReaddirNValues(t *testing.T) {
610 if testing.Short() {
611 t.Skip("test.short; skipping")
613 dir := t.TempDir()
614 for i := 1; i <= 105; i++ {
615 f, err := Create(filepath.Join(dir, fmt.Sprintf("%d", i)))
616 if err != nil {
617 t.Fatalf("Create: %v", err)
619 f.Write([]byte(strings.Repeat("X", i)))
620 f.Close()
623 var d *File
624 openDir := func() {
625 var err error
626 d, err = Open(dir)
627 if err != nil {
628 t.Fatalf("Open directory: %v", err)
632 readdirExpect := func(n, want int, wantErr error) {
633 t.Helper()
634 fi, err := d.Readdir(n)
635 if err != wantErr {
636 t.Fatalf("Readdir of %d got error %v, want %v", n, err, wantErr)
638 if g, e := len(fi), want; g != e {
639 t.Errorf("Readdir of %d got %d files, want %d", n, g, e)
643 readDirExpect := func(n, want int, wantErr error) {
644 t.Helper()
645 de, err := d.ReadDir(n)
646 if err != wantErr {
647 t.Fatalf("ReadDir of %d got error %v, want %v", n, err, wantErr)
649 if g, e := len(de), want; g != e {
650 t.Errorf("ReadDir of %d got %d files, want %d", n, g, e)
654 readdirnamesExpect := func(n, want int, wantErr error) {
655 t.Helper()
656 fi, err := d.Readdirnames(n)
657 if err != wantErr {
658 t.Fatalf("Readdirnames of %d got error %v, want %v", n, err, wantErr)
660 if g, e := len(fi), want; g != e {
661 t.Errorf("Readdirnames of %d got %d files, want %d", n, g, e)
665 for _, fn := range []func(int, int, error){readdirExpect, readdirnamesExpect, readDirExpect} {
666 // Test the slurp case
667 openDir()
668 fn(0, 105, nil)
669 fn(0, 0, nil)
670 d.Close()
672 // Slurp with -1 instead
673 openDir()
674 fn(-1, 105, nil)
675 fn(-2, 0, nil)
676 fn(0, 0, nil)
677 d.Close()
679 // Test the bounded case
680 openDir()
681 fn(1, 1, nil)
682 fn(2, 2, nil)
683 fn(105, 102, nil) // and tests buffer >100 case
684 fn(3, 0, io.EOF)
685 d.Close()
689 func touch(t *testing.T, name string) {
690 f, err := Create(name)
691 if err != nil {
692 t.Fatal(err)
694 if err := f.Close(); err != nil {
695 t.Fatal(err)
699 func TestReaddirStatFailures(t *testing.T) {
700 switch runtime.GOOS {
701 case "windows", "plan9":
702 // Windows and Plan 9 already do this correctly,
703 // but are structured with different syscalls such
704 // that they don't use Lstat, so the hook below for
705 // testing it wouldn't work.
706 t.Skipf("skipping test on %v", runtime.GOOS)
708 dir := t.TempDir()
709 touch(t, filepath.Join(dir, "good1"))
710 touch(t, filepath.Join(dir, "x")) // will disappear or have an error
711 touch(t, filepath.Join(dir, "good2"))
712 defer func() {
713 *LstatP = Lstat
715 var xerr error // error to return for x
716 *LstatP = func(path string) (FileInfo, error) {
717 if xerr != nil && strings.HasSuffix(path, "x") {
718 return nil, xerr
720 return Lstat(path)
722 readDir := func() ([]FileInfo, error) {
723 d, err := Open(dir)
724 if err != nil {
725 t.Fatal(err)
727 defer d.Close()
728 return d.Readdir(-1)
730 mustReadDir := func(testName string) []FileInfo {
731 fis, err := readDir()
732 if err != nil {
733 t.Fatalf("%s: Readdir: %v", testName, err)
735 return fis
737 names := func(fis []FileInfo) []string {
738 s := make([]string, len(fis))
739 for i, fi := range fis {
740 s[i] = fi.Name()
742 sort.Strings(s)
743 return s
746 if got, want := names(mustReadDir("initial readdir")),
747 []string{"good1", "good2", "x"}; !reflect.DeepEqual(got, want) {
748 t.Errorf("initial readdir got %q; want %q", got, want)
751 xerr = ErrNotExist
752 if got, want := names(mustReadDir("with x disappearing")),
753 []string{"good1", "good2"}; !reflect.DeepEqual(got, want) {
754 t.Errorf("with x disappearing, got %q; want %q", got, want)
757 xerr = errors.New("some real error")
758 if _, err := readDir(); err != xerr {
759 t.Errorf("with a non-ErrNotExist error, got error %v; want %v", err, xerr)
763 // Readdir on a regular file should fail.
764 func TestReaddirOfFile(t *testing.T) {
765 f, err := os.CreateTemp("", "_Go_ReaddirOfFile")
766 if err != nil {
767 t.Fatal(err)
769 defer Remove(f.Name())
770 f.Write([]byte("foo"))
771 f.Close()
772 reg, err := Open(f.Name())
773 if err != nil {
774 t.Fatal(err)
776 defer reg.Close()
778 names, err := reg.Readdirnames(-1)
779 if err == nil {
780 t.Error("Readdirnames succeeded; want non-nil error")
782 var pe *PathError
783 if !errors.As(err, &pe) || pe.Path != f.Name() {
784 t.Errorf("Readdirnames returned %q; want a PathError with path %q", err, f.Name())
786 if len(names) > 0 {
787 t.Errorf("unexpected dir names in regular file: %q", names)
791 func TestHardLink(t *testing.T) {
792 testenv.MustHaveLink(t)
794 defer chtmpdir(t)()
795 from, to := "hardlinktestfrom", "hardlinktestto"
796 file, err := Create(to)
797 if err != nil {
798 t.Fatalf("open %q failed: %v", to, err)
800 if err = file.Close(); err != nil {
801 t.Errorf("close %q failed: %v", to, err)
803 err = Link(to, from)
804 if err != nil {
805 t.Fatalf("link %q, %q failed: %v", to, from, err)
808 none := "hardlinktestnone"
809 err = Link(none, none)
810 // Check the returned error is well-formed.
811 if lerr, ok := err.(*LinkError); !ok || lerr.Error() == "" {
812 t.Errorf("link %q, %q failed to return a valid error", none, none)
815 tostat, err := Stat(to)
816 if err != nil {
817 t.Fatalf("stat %q failed: %v", to, err)
819 fromstat, err := Stat(from)
820 if err != nil {
821 t.Fatalf("stat %q failed: %v", from, err)
823 if !SameFile(tostat, fromstat) {
824 t.Errorf("link %q, %q did not create hard link", to, from)
826 // We should not be able to perform the same Link() a second time
827 err = Link(to, from)
828 switch err := err.(type) {
829 case *LinkError:
830 if err.Op != "link" {
831 t.Errorf("Link(%q, %q) err.Op = %q; want %q", to, from, err.Op, "link")
833 if err.Old != to {
834 t.Errorf("Link(%q, %q) err.Old = %q; want %q", to, from, err.Old, to)
836 if err.New != from {
837 t.Errorf("Link(%q, %q) err.New = %q; want %q", to, from, err.New, from)
839 if !IsExist(err.Err) {
840 t.Errorf("Link(%q, %q) err.Err = %q; want %q", to, from, err.Err, "file exists error")
842 case nil:
843 t.Errorf("link %q, %q: expected error, got nil", from, to)
844 default:
845 t.Errorf("link %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err)
849 // chtmpdir changes the working directory to a new temporary directory and
850 // provides a cleanup function.
851 func chtmpdir(t *testing.T) func() {
852 oldwd, err := Getwd()
853 if err != nil {
854 t.Fatalf("chtmpdir: %v", err)
856 d, err := os.MkdirTemp("", "test")
857 if err != nil {
858 t.Fatalf("chtmpdir: %v", err)
860 if err := Chdir(d); err != nil {
861 t.Fatalf("chtmpdir: %v", err)
863 return func() {
864 if err := Chdir(oldwd); err != nil {
865 t.Fatalf("chtmpdir: %v", err)
867 RemoveAll(d)
871 func TestSymlink(t *testing.T) {
872 testenv.MustHaveSymlink(t)
874 defer chtmpdir(t)()
875 from, to := "symlinktestfrom", "symlinktestto"
876 file, err := Create(to)
877 if err != nil {
878 t.Fatalf("Create(%q) failed: %v", to, err)
880 if err = file.Close(); err != nil {
881 t.Errorf("Close(%q) failed: %v", to, err)
883 err = Symlink(to, from)
884 if err != nil {
885 t.Fatalf("Symlink(%q, %q) failed: %v", to, from, err)
887 tostat, err := Lstat(to)
888 if err != nil {
889 t.Fatalf("Lstat(%q) failed: %v", to, err)
891 if tostat.Mode()&ModeSymlink != 0 {
892 t.Fatalf("Lstat(%q).Mode()&ModeSymlink = %v, want 0", to, tostat.Mode()&ModeSymlink)
894 fromstat, err := Stat(from)
895 if err != nil {
896 t.Fatalf("Stat(%q) failed: %v", from, err)
898 if !SameFile(tostat, fromstat) {
899 t.Errorf("Symlink(%q, %q) did not create symlink", to, from)
901 fromstat, err = Lstat(from)
902 if err != nil {
903 t.Fatalf("Lstat(%q) failed: %v", from, err)
905 if fromstat.Mode()&ModeSymlink == 0 {
906 t.Fatalf("Lstat(%q).Mode()&ModeSymlink = 0, want %v", from, ModeSymlink)
908 fromstat, err = Stat(from)
909 if err != nil {
910 t.Fatalf("Stat(%q) failed: %v", from, err)
912 if fromstat.Name() != from {
913 t.Errorf("Stat(%q).Name() = %q, want %q", from, fromstat.Name(), from)
915 if fromstat.Mode()&ModeSymlink != 0 {
916 t.Fatalf("Stat(%q).Mode()&ModeSymlink = %v, want 0", from, fromstat.Mode()&ModeSymlink)
918 s, err := Readlink(from)
919 if err != nil {
920 t.Fatalf("Readlink(%q) failed: %v", from, err)
922 if s != to {
923 t.Fatalf("Readlink(%q) = %q, want %q", from, s, to)
925 file, err = Open(from)
926 if err != nil {
927 t.Fatalf("Open(%q) failed: %v", from, err)
929 file.Close()
932 func TestLongSymlink(t *testing.T) {
933 testenv.MustHaveSymlink(t)
935 defer chtmpdir(t)()
936 s := "0123456789abcdef"
937 // Long, but not too long: a common limit is 255.
938 s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s
939 from := "longsymlinktestfrom"
940 err := Symlink(s, from)
941 if err != nil {
942 t.Fatalf("symlink %q, %q failed: %v", s, from, err)
944 r, err := Readlink(from)
945 if err != nil {
946 t.Fatalf("readlink %q failed: %v", from, err)
948 if r != s {
949 t.Fatalf("after symlink %q != %q", r, s)
953 func TestRename(t *testing.T) {
954 defer chtmpdir(t)()
955 from, to := "renamefrom", "renameto"
957 file, err := Create(from)
958 if err != nil {
959 t.Fatalf("open %q failed: %v", from, err)
961 if err = file.Close(); err != nil {
962 t.Errorf("close %q failed: %v", from, err)
964 err = Rename(from, to)
965 if err != nil {
966 t.Fatalf("rename %q, %q failed: %v", to, from, err)
968 _, err = Stat(to)
969 if err != nil {
970 t.Errorf("stat %q failed: %v", to, err)
974 func TestRenameOverwriteDest(t *testing.T) {
975 defer chtmpdir(t)()
976 from, to := "renamefrom", "renameto"
978 toData := []byte("to")
979 fromData := []byte("from")
981 err := os.WriteFile(to, toData, 0777)
982 if err != nil {
983 t.Fatalf("write file %q failed: %v", to, err)
986 err = os.WriteFile(from, fromData, 0777)
987 if err != nil {
988 t.Fatalf("write file %q failed: %v", from, err)
990 err = Rename(from, to)
991 if err != nil {
992 t.Fatalf("rename %q, %q failed: %v", to, from, err)
995 _, err = Stat(from)
996 if err == nil {
997 t.Errorf("from file %q still exists", from)
999 if err != nil && !IsNotExist(err) {
1000 t.Fatalf("stat from: %v", err)
1002 toFi, err := Stat(to)
1003 if err != nil {
1004 t.Fatalf("stat %q failed: %v", to, err)
1006 if toFi.Size() != int64(len(fromData)) {
1007 t.Errorf(`"to" size = %d; want %d (old "from" size)`, toFi.Size(), len(fromData))
1011 func TestRenameFailed(t *testing.T) {
1012 defer chtmpdir(t)()
1013 from, to := "renamefrom", "renameto"
1015 err := Rename(from, to)
1016 switch err := err.(type) {
1017 case *LinkError:
1018 if err.Op != "rename" {
1019 t.Errorf("rename %q, %q: err.Op: want %q, got %q", from, to, "rename", err.Op)
1021 if err.Old != from {
1022 t.Errorf("rename %q, %q: err.Old: want %q, got %q", from, to, from, err.Old)
1024 if err.New != to {
1025 t.Errorf("rename %q, %q: err.New: want %q, got %q", from, to, to, err.New)
1027 case nil:
1028 t.Errorf("rename %q, %q: expected error, got nil", from, to)
1029 default:
1030 t.Errorf("rename %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err)
1034 func TestRenameNotExisting(t *testing.T) {
1035 defer chtmpdir(t)()
1036 from, to := "doesnt-exist", "dest"
1038 Mkdir(to, 0777)
1040 if err := Rename(from, to); !IsNotExist(err) {
1041 t.Errorf("Rename(%q, %q) = %v; want an IsNotExist error", from, to, err)
1045 func TestRenameToDirFailed(t *testing.T) {
1046 defer chtmpdir(t)()
1047 from, to := "renamefrom", "renameto"
1049 Mkdir(from, 0777)
1050 Mkdir(to, 0777)
1052 err := Rename(from, to)
1053 switch err := err.(type) {
1054 case *LinkError:
1055 if err.Op != "rename" {
1056 t.Errorf("rename %q, %q: err.Op: want %q, got %q", from, to, "rename", err.Op)
1058 if err.Old != from {
1059 t.Errorf("rename %q, %q: err.Old: want %q, got %q", from, to, from, err.Old)
1061 if err.New != to {
1062 t.Errorf("rename %q, %q: err.New: want %q, got %q", from, to, to, err.New)
1064 case nil:
1065 t.Errorf("rename %q, %q: expected error, got nil", from, to)
1066 default:
1067 t.Errorf("rename %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err)
1071 func TestRenameCaseDifference(pt *testing.T) {
1072 from, to := "renameFROM", "RENAMEfrom"
1073 tests := []struct {
1074 name string
1075 create func() error
1077 {"dir", func() error {
1078 return Mkdir(from, 0777)
1080 {"file", func() error {
1081 fd, err := Create(from)
1082 if err != nil {
1083 return err
1085 return fd.Close()
1089 for _, test := range tests {
1090 pt.Run(test.name, func(t *testing.T) {
1091 defer chtmpdir(t)()
1093 if err := test.create(); err != nil {
1094 t.Fatalf("failed to create test file: %s", err)
1097 if _, err := Stat(to); err != nil {
1098 // Sanity check that the underlying filesystem is not case sensitive.
1099 if IsNotExist(err) {
1100 t.Skipf("case sensitive filesystem")
1102 t.Fatalf("stat %q, got: %q", to, err)
1105 if err := Rename(from, to); err != nil {
1106 t.Fatalf("unexpected error when renaming from %q to %q: %s", from, to, err)
1109 fd, err := Open(".")
1110 if err != nil {
1111 t.Fatalf("Open .: %s", err)
1114 // Stat does not return the real case of the file (it returns what the called asked for)
1115 // So we have to use readdir to get the real name of the file.
1116 dirNames, err := fd.Readdirnames(-1)
1117 if err != nil {
1118 t.Fatalf("readdirnames: %s", err)
1121 if dirNamesLen := len(dirNames); dirNamesLen != 1 {
1122 t.Fatalf("unexpected dirNames len, got %q, want %q", dirNamesLen, 1)
1125 if dirNames[0] != to {
1126 t.Errorf("unexpected name, got %q, want %q", dirNames[0], to)
1132 func exec(t *testing.T, dir, cmd string, args []string, expect string) {
1133 r, w, err := Pipe()
1134 if err != nil {
1135 t.Fatalf("Pipe: %v", err)
1137 defer r.Close()
1138 attr := &ProcAttr{Dir: dir, Files: []*File{nil, w, Stderr}}
1139 p, err := StartProcess(cmd, args, attr)
1140 if err != nil {
1141 t.Fatalf("StartProcess: %v", err)
1143 w.Close()
1145 var b bytes.Buffer
1146 io.Copy(&b, r)
1147 output := b.String()
1149 fi1, _ := Stat(strings.TrimSpace(output))
1150 fi2, _ := Stat(expect)
1151 if !SameFile(fi1, fi2) {
1152 t.Errorf("exec %q returned %q wanted %q",
1153 strings.Join(append([]string{cmd}, args...), " "), output, expect)
1155 p.Wait()
1158 func TestStartProcess(t *testing.T) {
1159 testenv.MustHaveExec(t)
1161 var dir, cmd string
1162 var args []string
1163 switch runtime.GOOS {
1164 case "android":
1165 t.Skip("android doesn't have /bin/pwd")
1166 case "windows":
1167 cmd = Getenv("COMSPEC")
1168 dir = Getenv("SystemRoot")
1169 args = []string{"/c", "cd"}
1170 default:
1171 var err error
1172 cmd, err = osexec.LookPath("pwd")
1173 if err != nil {
1174 t.Fatalf("Can't find pwd: %v", err)
1176 dir = "/"
1177 args = []string{}
1178 t.Logf("Testing with %v", cmd)
1180 cmddir, cmdbase := filepath.Split(cmd)
1181 args = append([]string{cmdbase}, args...)
1182 // Test absolute executable path.
1183 exec(t, dir, cmd, args, dir)
1184 // Test relative executable path.
1185 exec(t, cmddir, cmdbase, args, cmddir)
1188 func checkMode(t *testing.T, path string, mode FileMode) {
1189 dir, err := Stat(path)
1190 if err != nil {
1191 t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
1193 if dir.Mode()&ModePerm != mode {
1194 t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode(), mode)
1198 func TestChmod(t *testing.T) {
1199 f := newFile("TestChmod", t)
1200 defer Remove(f.Name())
1201 defer f.Close()
1202 // Creation mode is read write
1204 fm := FileMode(0456)
1205 if runtime.GOOS == "windows" {
1206 fm = FileMode(0444) // read-only file
1208 if err := Chmod(f.Name(), fm); err != nil {
1209 t.Fatalf("chmod %s %#o: %s", f.Name(), fm, err)
1211 checkMode(t, f.Name(), fm)
1213 fm = FileMode(0123)
1214 if runtime.GOOS == "windows" {
1215 fm = FileMode(0666) // read-write file
1217 if err := f.Chmod(fm); err != nil {
1218 t.Fatalf("chmod %s %#o: %s", f.Name(), fm, err)
1220 checkMode(t, f.Name(), fm)
1223 func checkSize(t *testing.T, f *File, size int64) {
1224 t.Helper()
1225 dir, err := f.Stat()
1226 if err != nil {
1227 t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err)
1229 if dir.Size() != size {
1230 t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size)
1234 func TestFTruncate(t *testing.T) {
1235 f := newFile("TestFTruncate", t)
1236 defer Remove(f.Name())
1237 defer f.Close()
1239 checkSize(t, f, 0)
1240 f.Write([]byte("hello, world\n"))
1241 checkSize(t, f, 13)
1242 f.Truncate(10)
1243 checkSize(t, f, 10)
1244 f.Truncate(1024)
1245 checkSize(t, f, 1024)
1246 f.Truncate(0)
1247 checkSize(t, f, 0)
1248 _, err := f.Write([]byte("surprise!"))
1249 if err == nil {
1250 checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
1254 func TestTruncate(t *testing.T) {
1255 f := newFile("TestTruncate", t)
1256 defer Remove(f.Name())
1257 defer f.Close()
1259 checkSize(t, f, 0)
1260 f.Write([]byte("hello, world\n"))
1261 checkSize(t, f, 13)
1262 Truncate(f.Name(), 10)
1263 checkSize(t, f, 10)
1264 Truncate(f.Name(), 1024)
1265 checkSize(t, f, 1024)
1266 Truncate(f.Name(), 0)
1267 checkSize(t, f, 0)
1268 _, err := f.Write([]byte("surprise!"))
1269 if err == nil {
1270 checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
1274 // Use TempDir (via newFile) to make sure we're on a local file system,
1275 // so that timings are not distorted by latency and caching.
1276 // On NFS, timings can be off due to caching of meta-data on
1277 // NFS servers (Issue 848).
1278 func TestChtimes(t *testing.T) {
1279 f := newFile("TestChtimes", t)
1280 defer Remove(f.Name())
1282 f.Write([]byte("hello, world\n"))
1283 f.Close()
1285 testChtimes(t, f.Name())
1288 // Use TempDir (via newDir) to make sure we're on a local file system,
1289 // so that timings are not distorted by latency and caching.
1290 // On NFS, timings can be off due to caching of meta-data on
1291 // NFS servers (Issue 848).
1292 func TestChtimesDir(t *testing.T) {
1293 name := newDir("TestChtimes", t)
1294 defer RemoveAll(name)
1296 testChtimes(t, name)
1299 func testChtimes(t *testing.T, name string) {
1300 st, err := Stat(name)
1301 if err != nil {
1302 t.Fatalf("Stat %s: %s", name, err)
1304 preStat := st
1306 // Move access and modification time back a second
1307 at := Atime(preStat)
1308 mt := preStat.ModTime()
1309 err = Chtimes(name, at.Add(-time.Second), mt.Add(-time.Second))
1310 if err != nil {
1311 t.Fatalf("Chtimes %s: %s", name, err)
1314 st, err = Stat(name)
1315 if err != nil {
1316 t.Fatalf("second Stat %s: %s", name, err)
1318 postStat := st
1320 pat := Atime(postStat)
1321 pmt := postStat.ModTime()
1322 if !pat.Before(at) {
1323 switch runtime.GOOS {
1324 case "plan9":
1325 // Mtime is the time of the last change of
1326 // content. Similarly, atime is set whenever
1327 // the contents are accessed; also, it is set
1328 // whenever mtime is set.
1329 case "netbsd":
1330 mounts, _ := os.ReadFile("/proc/mounts")
1331 if strings.Contains(string(mounts), "noatime") {
1332 t.Logf("AccessTime didn't go backwards, but see a filesystem mounted noatime; ignoring. Issue 19293.")
1333 } else {
1334 t.Logf("AccessTime didn't go backwards; was=%v, after=%v (Ignoring on NetBSD, assuming noatime, Issue 19293)", at, pat)
1336 default:
1337 t.Errorf("AccessTime didn't go backwards; was=%v, after=%v", at, pat)
1341 if !pmt.Before(mt) {
1342 t.Errorf("ModTime didn't go backwards; was=%v, after=%v", mt, pmt)
1346 func TestFileChdir(t *testing.T) {
1347 // TODO(brainman): file.Chdir() is not implemented on windows.
1348 if runtime.GOOS == "windows" {
1349 return
1352 wd, err := Getwd()
1353 if err != nil {
1354 t.Fatalf("Getwd: %s", err)
1356 defer Chdir(wd)
1358 fd, err := Open(".")
1359 if err != nil {
1360 t.Fatalf("Open .: %s", err)
1362 defer fd.Close()
1364 if err := Chdir("/"); err != nil {
1365 t.Fatalf("Chdir /: %s", err)
1368 if err := fd.Chdir(); err != nil {
1369 t.Fatalf("fd.Chdir: %s", err)
1372 wdNew, err := Getwd()
1373 if err != nil {
1374 t.Fatalf("Getwd: %s", err)
1376 if wdNew != wd {
1377 t.Fatalf("fd.Chdir failed, got %s, want %s", wdNew, wd)
1381 func TestChdirAndGetwd(t *testing.T) {
1382 // TODO(brainman): file.Chdir() is not implemented on windows.
1383 if runtime.GOOS == "windows" {
1384 return
1386 fd, err := Open(".")
1387 if err != nil {
1388 t.Fatalf("Open .: %s", err)
1390 // These are chosen carefully not to be symlinks on a Mac
1391 // (unlike, say, /var, /etc), except /tmp, which we handle below.
1392 dirs := []string{"/", "/usr/bin", "/tmp"}
1393 // /usr/bin does not usually exist on Plan 9 or Android.
1394 switch runtime.GOOS {
1395 case "android":
1396 dirs = []string{"/system/bin"}
1397 case "plan9":
1398 dirs = []string{"/", "/usr"}
1399 case "ios":
1400 dirs = nil
1401 for _, d := range []string{"d1", "d2"} {
1402 dir, err := os.MkdirTemp("", d)
1403 if err != nil {
1404 t.Fatalf("TempDir: %v", err)
1406 // Expand symlinks so path equality tests work.
1407 dir, err = filepath.EvalSymlinks(dir)
1408 if err != nil {
1409 t.Fatalf("EvalSymlinks: %v", err)
1411 dirs = append(dirs, dir)
1414 oldwd := Getenv("PWD")
1415 for mode := 0; mode < 2; mode++ {
1416 for _, d := range dirs {
1417 if mode == 0 {
1418 err = Chdir(d)
1419 } else {
1420 fd1, err1 := Open(d)
1421 if err1 != nil {
1422 t.Errorf("Open %s: %s", d, err1)
1423 continue
1425 err = fd1.Chdir()
1426 fd1.Close()
1428 if d == "/tmp" {
1429 Setenv("PWD", "/tmp")
1431 pwd, err1 := Getwd()
1432 Setenv("PWD", oldwd)
1433 err2 := fd.Chdir()
1434 if err2 != nil {
1435 // We changed the current directory and cannot go back.
1436 // Don't let the tests continue; they'll scribble
1437 // all over some other directory.
1438 fmt.Fprintf(Stderr, "fchdir back to dot failed: %s\n", err2)
1439 Exit(1)
1441 if err != nil {
1442 fd.Close()
1443 t.Fatalf("Chdir %s: %s", d, err)
1445 if err1 != nil {
1446 fd.Close()
1447 t.Fatalf("Getwd in %s: %s", d, err1)
1449 if pwd != d {
1450 fd.Close()
1451 t.Fatalf("Getwd returned %q want %q", pwd, d)
1455 fd.Close()
1458 // Test that Chdir+Getwd is program-wide.
1459 func TestProgWideChdir(t *testing.T) {
1460 const N = 10
1461 const ErrPwd = "Error!"
1462 c := make(chan bool)
1463 cpwd := make(chan string, N)
1464 for i := 0; i < N; i++ {
1465 go func(i int) {
1466 // Lock half the goroutines in their own operating system
1467 // thread to exercise more scheduler possibilities.
1468 if i%2 == 1 {
1469 // On Plan 9, after calling LockOSThread, the goroutines
1470 // run on different processes which don't share the working
1471 // directory. This used to be an issue because Go expects
1472 // the working directory to be program-wide.
1473 // See issue 9428.
1474 runtime.LockOSThread()
1476 hasErr, closed := <-c
1477 if !closed && hasErr {
1478 cpwd <- ErrPwd
1479 return
1481 pwd, err := Getwd()
1482 if err != nil {
1483 t.Errorf("Getwd on goroutine %d: %v", i, err)
1484 cpwd <- ErrPwd
1485 return
1487 cpwd <- pwd
1488 }(i)
1490 oldwd, err := Getwd()
1491 if err != nil {
1492 c <- true
1493 t.Fatalf("Getwd: %v", err)
1495 d, err := os.MkdirTemp("", "test")
1496 if err != nil {
1497 c <- true
1498 t.Fatalf("TempDir: %v", err)
1500 defer func() {
1501 if err := Chdir(oldwd); err != nil {
1502 t.Fatalf("Chdir: %v", err)
1504 RemoveAll(d)
1506 if err := Chdir(d); err != nil {
1507 c <- true
1508 t.Fatalf("Chdir: %v", err)
1510 // OS X sets TMPDIR to a symbolic link.
1511 // So we resolve our working directory again before the test.
1512 d, err = Getwd()
1513 if err != nil {
1514 c <- true
1515 t.Fatalf("Getwd: %v", err)
1517 close(c)
1518 for i := 0; i < N; i++ {
1519 pwd := <-cpwd
1520 if pwd == ErrPwd {
1521 t.FailNow()
1523 if pwd != d {
1524 t.Errorf("Getwd returned %q; want %q", pwd, d)
1529 func TestSeek(t *testing.T) {
1530 f := newFile("TestSeek", t)
1531 defer Remove(f.Name())
1532 defer f.Close()
1534 const data = "hello, world\n"
1535 io.WriteString(f, data)
1537 type test struct {
1538 in int64
1539 whence int
1540 out int64
1542 var tests = []test{
1543 {0, io.SeekCurrent, int64(len(data))},
1544 {0, io.SeekStart, 0},
1545 {5, io.SeekStart, 5},
1546 {0, io.SeekEnd, int64(len(data))},
1547 {0, io.SeekStart, 0},
1548 {-1, io.SeekEnd, int64(len(data)) - 1},
1549 {1 << 33, io.SeekStart, 1 << 33},
1550 {1 << 33, io.SeekEnd, 1<<33 + int64(len(data))},
1552 // Issue 21681, Windows 4G-1, etc:
1553 {1<<32 - 1, io.SeekStart, 1<<32 - 1},
1554 {0, io.SeekCurrent, 1<<32 - 1},
1555 {2<<32 - 1, io.SeekStart, 2<<32 - 1},
1556 {0, io.SeekCurrent, 2<<32 - 1},
1558 for i, tt := range tests {
1559 if runtime.GOOS == "hurd" && tt.out > 1<<32 {
1560 t.Logf("skipping test case #%d on Hurd: file too large", i)
1561 continue
1563 off, err := f.Seek(tt.in, tt.whence)
1564 if off != tt.out || err != nil {
1565 if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 && runtime.GOOS == "linux" {
1566 mounts, _ := os.ReadFile("/proc/mounts")
1567 if strings.Contains(string(mounts), "reiserfs") {
1568 // Reiserfs rejects the big seeks.
1569 t.Skipf("skipping test known to fail on reiserfs; https://golang.org/issue/91")
1572 t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
1577 func TestSeekError(t *testing.T) {
1578 switch runtime.GOOS {
1579 case "js", "plan9":
1580 t.Skipf("skipping test on %v", runtime.GOOS)
1583 r, w, err := Pipe()
1584 if err != nil {
1585 t.Fatal(err)
1587 _, err = r.Seek(0, 0)
1588 if err == nil {
1589 t.Fatal("Seek on pipe should fail")
1591 if perr, ok := err.(*PathError); !ok || perr.Err != syscall.ESPIPE {
1592 t.Errorf("Seek returned error %v, want &PathError{Err: syscall.ESPIPE}", err)
1594 _, err = w.Seek(0, 0)
1595 if err == nil {
1596 t.Fatal("Seek on pipe should fail")
1598 if perr, ok := err.(*PathError); !ok || perr.Err != syscall.ESPIPE {
1599 t.Errorf("Seek returned error %v, want &PathError{Err: syscall.ESPIPE}", err)
1603 type openErrorTest struct {
1604 path string
1605 mode int
1606 error error
1609 var openErrorTests = []openErrorTest{
1611 sfdir + "/no-such-file",
1612 O_RDONLY,
1613 syscall.ENOENT,
1616 sfdir,
1617 O_WRONLY,
1618 syscall.EISDIR,
1621 sfdir + "/" + sfname + "/no-such-file",
1622 O_WRONLY,
1623 syscall.ENOTDIR,
1627 func TestOpenError(t *testing.T) {
1628 for _, tt := range openErrorTests {
1629 f, err := OpenFile(tt.path, tt.mode, 0)
1630 if err == nil {
1631 t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode)
1632 f.Close()
1633 continue
1635 perr, ok := err.(*PathError)
1636 if !ok {
1637 t.Errorf("Open(%q, %d) returns error of %T type; want *PathError", tt.path, tt.mode, err)
1639 if perr.Err != tt.error {
1640 if runtime.GOOS == "plan9" {
1641 syscallErrStr := perr.Err.Error()
1642 expectedErrStr := strings.Replace(tt.error.Error(), "file ", "", 1)
1643 if !strings.HasSuffix(syscallErrStr, expectedErrStr) {
1644 // Some Plan 9 file servers incorrectly return
1645 // EACCES rather than EISDIR when a directory is
1646 // opened for write.
1647 if tt.error == syscall.EISDIR && strings.HasSuffix(syscallErrStr, syscall.EACCES.Error()) {
1648 continue
1650 t.Errorf("Open(%q, %d) = _, %q; want suffix %q", tt.path, tt.mode, syscallErrStr, expectedErrStr)
1652 continue
1654 if runtime.GOOS == "dragonfly" {
1655 // DragonFly incorrectly returns EACCES rather
1656 // EISDIR when a directory is opened for write.
1657 if tt.error == syscall.EISDIR && perr.Err == syscall.EACCES {
1658 continue
1661 t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, perr.Err.Error(), tt.error.Error())
1666 func TestOpenNoName(t *testing.T) {
1667 f, err := Open("")
1668 if err == nil {
1669 f.Close()
1670 t.Fatal(`Open("") succeeded`)
1674 func runBinHostname(t *testing.T) string {
1675 // Run /bin/hostname and collect output.
1676 r, w, err := Pipe()
1677 if err != nil {
1678 t.Fatal(err)
1680 defer r.Close()
1681 const path = "/bin/hostname"
1682 argv := []string{"hostname"}
1683 if runtime.GOOS == "aix" {
1684 argv = []string{"hostname", "-s"}
1686 p, err := StartProcess(path, argv, &ProcAttr{Files: []*File{nil, w, Stderr}})
1687 if err != nil {
1688 if _, err := Stat(path); IsNotExist(err) {
1689 t.Skipf("skipping test; test requires %s but it does not exist", path)
1691 t.Fatal(err)
1693 w.Close()
1695 var b bytes.Buffer
1696 io.Copy(&b, r)
1697 _, err = p.Wait()
1698 if err != nil {
1699 t.Fatalf("run hostname Wait: %v", err)
1701 err = p.Kill()
1702 if err == nil {
1703 t.Errorf("expected an error from Kill running 'hostname'")
1705 output := b.String()
1706 if n := len(output); n > 0 && output[n-1] == '\n' {
1707 output = output[0 : n-1]
1709 if output == "" {
1710 t.Fatalf("/bin/hostname produced no output")
1713 return output
1716 func testWindowsHostname(t *testing.T, hostname string) {
1717 cmd := osexec.Command("hostname")
1718 out, err := cmd.CombinedOutput()
1719 if err != nil {
1720 t.Fatalf("Failed to execute hostname command: %v %s", err, out)
1722 want := strings.Trim(string(out), "\r\n")
1723 if hostname != want {
1724 t.Fatalf("Hostname() = %q != system hostname of %q", hostname, want)
1728 func TestHostname(t *testing.T) {
1729 hostname, err := Hostname()
1730 if err != nil {
1731 t.Fatal(err)
1733 if hostname == "" {
1734 t.Fatal("Hostname returned empty string and no error")
1736 if strings.Contains(hostname, "\x00") {
1737 t.Fatalf("unexpected zero byte in hostname: %q", hostname)
1740 // There is no other way to fetch hostname on windows, but via winapi.
1741 // On Plan 9 it can be taken from #c/sysname as Hostname() does.
1742 switch runtime.GOOS {
1743 case "android", "plan9":
1744 // No /bin/hostname to verify against.
1745 return
1746 case "windows":
1747 testWindowsHostname(t, hostname)
1748 return
1751 testenv.MustHaveExec(t)
1753 // Check internal Hostname() against the output of /bin/hostname.
1754 // Allow that the internal Hostname returns a Fully Qualified Domain Name
1755 // and the /bin/hostname only returns the first component
1756 want := runBinHostname(t)
1757 if hostname != want {
1758 host, _, ok := strings.Cut(hostname, ".")
1759 if !ok || host != want {
1760 t.Errorf("Hostname() = %q, want %q", hostname, want)
1765 func TestReadAt(t *testing.T) {
1766 f := newFile("TestReadAt", t)
1767 defer Remove(f.Name())
1768 defer f.Close()
1770 const data = "hello, world\n"
1771 io.WriteString(f, data)
1773 b := make([]byte, 5)
1774 n, err := f.ReadAt(b, 7)
1775 if err != nil || n != len(b) {
1776 t.Fatalf("ReadAt 7: %d, %v", n, err)
1778 if string(b) != "world" {
1779 t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
1783 // Verify that ReadAt doesn't affect seek offset.
1784 // In the Plan 9 kernel, there used to be a bug in the implementation of
1785 // the pread syscall, where the channel offset was erroneously updated after
1786 // calling pread on a file.
1787 func TestReadAtOffset(t *testing.T) {
1788 f := newFile("TestReadAtOffset", t)
1789 defer Remove(f.Name())
1790 defer f.Close()
1792 const data = "hello, world\n"
1793 io.WriteString(f, data)
1795 f.Seek(0, 0)
1796 b := make([]byte, 5)
1798 n, err := f.ReadAt(b, 7)
1799 if err != nil || n != len(b) {
1800 t.Fatalf("ReadAt 7: %d, %v", n, err)
1802 if string(b) != "world" {
1803 t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
1806 n, err = f.Read(b)
1807 if err != nil || n != len(b) {
1808 t.Fatalf("Read: %d, %v", n, err)
1810 if string(b) != "hello" {
1811 t.Fatalf("Read: have %q want %q", string(b), "hello")
1815 // Verify that ReadAt doesn't allow negative offset.
1816 func TestReadAtNegativeOffset(t *testing.T) {
1817 f := newFile("TestReadAtNegativeOffset", t)
1818 defer Remove(f.Name())
1819 defer f.Close()
1821 const data = "hello, world\n"
1822 io.WriteString(f, data)
1824 f.Seek(0, 0)
1825 b := make([]byte, 5)
1827 n, err := f.ReadAt(b, -10)
1829 const wantsub = "negative offset"
1830 if !strings.Contains(fmt.Sprint(err), wantsub) || n != 0 {
1831 t.Errorf("ReadAt(-10) = %v, %v; want 0, ...%q...", n, err, wantsub)
1835 func TestWriteAt(t *testing.T) {
1836 f := newFile("TestWriteAt", t)
1837 defer Remove(f.Name())
1838 defer f.Close()
1840 const data = "hello, world\n"
1841 io.WriteString(f, data)
1843 n, err := f.WriteAt([]byte("WORLD"), 7)
1844 if err != nil || n != 5 {
1845 t.Fatalf("WriteAt 7: %d, %v", n, err)
1848 b, err := os.ReadFile(f.Name())
1849 if err != nil {
1850 t.Fatalf("ReadFile %s: %v", f.Name(), err)
1852 if string(b) != "hello, WORLD\n" {
1853 t.Fatalf("after write: have %q want %q", string(b), "hello, WORLD\n")
1857 // Verify that WriteAt doesn't allow negative offset.
1858 func TestWriteAtNegativeOffset(t *testing.T) {
1859 f := newFile("TestWriteAtNegativeOffset", t)
1860 defer Remove(f.Name())
1861 defer f.Close()
1863 n, err := f.WriteAt([]byte("WORLD"), -10)
1865 const wantsub = "negative offset"
1866 if !strings.Contains(fmt.Sprint(err), wantsub) || n != 0 {
1867 t.Errorf("WriteAt(-10) = %v, %v; want 0, ...%q...", n, err, wantsub)
1871 // Verify that WriteAt doesn't work in append mode.
1872 func TestWriteAtInAppendMode(t *testing.T) {
1873 defer chtmpdir(t)()
1874 f, err := OpenFile("write_at_in_append_mode.txt", O_APPEND|O_CREATE, 0666)
1875 if err != nil {
1876 t.Fatalf("OpenFile: %v", err)
1878 defer f.Close()
1880 _, err = f.WriteAt([]byte(""), 1)
1881 if err != ErrWriteAtInAppendMode {
1882 t.Fatalf("f.WriteAt returned %v, expected %v", err, ErrWriteAtInAppendMode)
1886 func writeFile(t *testing.T, fname string, flag int, text string) string {
1887 f, err := OpenFile(fname, flag, 0666)
1888 if err != nil {
1889 t.Fatalf("Open: %v", err)
1891 n, err := io.WriteString(f, text)
1892 if err != nil {
1893 t.Fatalf("WriteString: %d, %v", n, err)
1895 f.Close()
1896 data, err := os.ReadFile(fname)
1897 if err != nil {
1898 t.Fatalf("ReadFile: %v", err)
1900 return string(data)
1903 func TestAppend(t *testing.T) {
1904 defer chtmpdir(t)()
1905 const f = "append.txt"
1906 s := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
1907 if s != "new" {
1908 t.Fatalf("writeFile: have %q want %q", s, "new")
1910 s = writeFile(t, f, O_APPEND|O_RDWR, "|append")
1911 if s != "new|append" {
1912 t.Fatalf("writeFile: have %q want %q", s, "new|append")
1914 s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "|append")
1915 if s != "new|append|append" {
1916 t.Fatalf("writeFile: have %q want %q", s, "new|append|append")
1918 err := Remove(f)
1919 if err != nil {
1920 t.Fatalf("Remove: %v", err)
1922 s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "new&append")
1923 if s != "new&append" {
1924 t.Fatalf("writeFile: after append have %q want %q", s, "new&append")
1926 s = writeFile(t, f, O_CREATE|O_RDWR, "old")
1927 if s != "old&append" {
1928 t.Fatalf("writeFile: after create have %q want %q", s, "old&append")
1930 s = writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
1931 if s != "new" {
1932 t.Fatalf("writeFile: after truncate have %q want %q", s, "new")
1936 func TestStatDirWithTrailingSlash(t *testing.T) {
1937 // Create new temporary directory and arrange to clean it up.
1938 path := t.TempDir()
1940 // Stat of path should succeed.
1941 if _, err := Stat(path); err != nil {
1942 t.Fatalf("stat %s failed: %s", path, err)
1945 // Stat of path+"/" should succeed too.
1946 path += "/"
1947 if _, err := Stat(path); err != nil {
1948 t.Fatalf("stat %s failed: %s", path, err)
1952 func TestNilProcessStateString(t *testing.T) {
1953 var ps *ProcessState
1954 s := ps.String()
1955 if s != "<nil>" {
1956 t.Errorf("(*ProcessState)(nil).String() = %q, want %q", s, "<nil>")
1960 func TestSameFile(t *testing.T) {
1961 defer chtmpdir(t)()
1962 fa, err := Create("a")
1963 if err != nil {
1964 t.Fatalf("Create(a): %v", err)
1966 fa.Close()
1967 fb, err := Create("b")
1968 if err != nil {
1969 t.Fatalf("Create(b): %v", err)
1971 fb.Close()
1973 ia1, err := Stat("a")
1974 if err != nil {
1975 t.Fatalf("Stat(a): %v", err)
1977 ia2, err := Stat("a")
1978 if err != nil {
1979 t.Fatalf("Stat(a): %v", err)
1981 if !SameFile(ia1, ia2) {
1982 t.Errorf("files should be same")
1985 ib, err := Stat("b")
1986 if err != nil {
1987 t.Fatalf("Stat(b): %v", err)
1989 if SameFile(ia1, ib) {
1990 t.Errorf("files should be different")
1994 func testDevNullFileInfo(t *testing.T, statname, devNullName string, fi FileInfo, ignoreCase bool) {
1995 pre := fmt.Sprintf("%s(%q): ", statname, devNullName)
1996 name := filepath.Base(devNullName)
1997 if ignoreCase {
1998 if strings.ToUpper(fi.Name()) != strings.ToUpper(name) {
1999 t.Errorf(pre+"wrong file name have %v want %v", fi.Name(), name)
2001 } else {
2002 if fi.Name() != name {
2003 t.Errorf(pre+"wrong file name have %v want %v", fi.Name(), name)
2006 if fi.Size() != 0 {
2007 t.Errorf(pre+"wrong file size have %d want 0", fi.Size())
2009 if fi.Mode()&ModeDevice == 0 {
2010 t.Errorf(pre+"wrong file mode %q: ModeDevice is not set", fi.Mode())
2012 if fi.Mode()&ModeCharDevice == 0 {
2013 t.Errorf(pre+"wrong file mode %q: ModeCharDevice is not set", fi.Mode())
2015 if fi.Mode().IsRegular() {
2016 t.Errorf(pre+"wrong file mode %q: IsRegular returns true", fi.Mode())
2020 func testDevNullFile(t *testing.T, devNullName string, ignoreCase bool) {
2021 f, err := Open(devNullName)
2022 if err != nil {
2023 t.Fatalf("Open(%s): %v", devNullName, err)
2025 defer f.Close()
2027 fi, err := f.Stat()
2028 if err != nil {
2029 t.Fatalf("Stat(%s): %v", devNullName, err)
2031 testDevNullFileInfo(t, "f.Stat", devNullName, fi, ignoreCase)
2033 fi, err = Stat(devNullName)
2034 if err != nil {
2035 t.Fatalf("Stat(%s): %v", devNullName, err)
2037 testDevNullFileInfo(t, "Stat", devNullName, fi, ignoreCase)
2040 func TestDevNullFile(t *testing.T) {
2041 testDevNullFile(t, DevNull, false)
2044 var testLargeWrite = flag.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output")
2046 func TestLargeWriteToConsole(t *testing.T) {
2047 if !*testLargeWrite {
2048 t.Skip("skipping console-flooding test; enable with -large_write")
2050 b := make([]byte, 32000)
2051 for i := range b {
2052 b[i] = '.'
2054 b[len(b)-1] = '\n'
2055 n, err := Stdout.Write(b)
2056 if err != nil {
2057 t.Fatalf("Write to os.Stdout failed: %v", err)
2059 if n != len(b) {
2060 t.Errorf("Write to os.Stdout should return %d; got %d", len(b), n)
2062 n, err = Stderr.Write(b)
2063 if err != nil {
2064 t.Fatalf("Write to os.Stderr failed: %v", err)
2066 if n != len(b) {
2067 t.Errorf("Write to os.Stderr should return %d; got %d", len(b), n)
2071 func TestStatDirModeExec(t *testing.T) {
2072 const mode = 0111
2074 path := t.TempDir()
2075 if err := Chmod(path, 0777); err != nil {
2076 t.Fatalf("Chmod %q 0777: %v", path, err)
2079 dir, err := Stat(path)
2080 if err != nil {
2081 t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
2083 if dir.Mode()&mode != mode {
2084 t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode()&mode, mode)
2088 func TestStatStdin(t *testing.T) {
2089 switch runtime.GOOS {
2090 case "android", "plan9":
2091 t.Skipf("%s doesn't have /bin/sh", runtime.GOOS)
2094 testenv.MustHaveExec(t)
2096 if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
2097 st, err := Stdin.Stat()
2098 if err != nil {
2099 t.Fatalf("Stat failed: %v", err)
2101 fmt.Println(st.Mode() & ModeNamedPipe)
2102 Exit(0)
2105 fi, err := Stdin.Stat()
2106 if err != nil {
2107 t.Fatal(err)
2109 switch mode := fi.Mode(); {
2110 case mode&ModeCharDevice != 0 && mode&ModeDevice != 0:
2111 case mode&ModeNamedPipe != 0:
2112 default:
2113 t.Fatalf("unexpected Stdin mode (%v), want ModeCharDevice or ModeNamedPipe", mode)
2116 var cmd *osexec.Cmd
2117 if runtime.GOOS == "windows" {
2118 cmd = osexec.Command("cmd", "/c", "echo output | "+Args[0]+" -test.run=TestStatStdin")
2119 } else {
2120 cmd = osexec.Command("/bin/sh", "-c", "echo output | "+Args[0]+" -test.run=TestStatStdin")
2122 cmd.Env = append(Environ(), "GO_WANT_HELPER_PROCESS=1")
2124 output, err := cmd.CombinedOutput()
2125 if err != nil {
2126 t.Fatalf("Failed to spawn child process: %v %q", err, string(output))
2129 // result will be like "prw-rw-rw"
2130 if len(output) < 1 || output[0] != 'p' {
2131 t.Fatalf("Child process reports stdin is not pipe '%v'", string(output))
2135 func TestStatRelativeSymlink(t *testing.T) {
2136 testenv.MustHaveSymlink(t)
2138 tmpdir := t.TempDir()
2139 target := filepath.Join(tmpdir, "target")
2140 f, err := Create(target)
2141 if err != nil {
2142 t.Fatal(err)
2144 defer f.Close()
2146 st, err := f.Stat()
2147 if err != nil {
2148 t.Fatal(err)
2151 link := filepath.Join(tmpdir, "link")
2152 err = Symlink(filepath.Base(target), link)
2153 if err != nil {
2154 t.Fatal(err)
2157 st1, err := Stat(link)
2158 if err != nil {
2159 t.Fatal(err)
2162 if !SameFile(st, st1) {
2163 t.Error("Stat doesn't follow relative symlink")
2166 if runtime.GOOS == "windows" {
2167 Remove(link)
2168 err = Symlink(target[len(filepath.VolumeName(target)):], link)
2169 if err != nil {
2170 t.Fatal(err)
2173 st1, err := Stat(link)
2174 if err != nil {
2175 t.Fatal(err)
2178 if !SameFile(st, st1) {
2179 t.Error("Stat doesn't follow relative symlink")
2184 func TestReadAtEOF(t *testing.T) {
2185 f := newFile("TestReadAtEOF", t)
2186 defer Remove(f.Name())
2187 defer f.Close()
2189 _, err := f.ReadAt(make([]byte, 10), 0)
2190 switch err {
2191 case io.EOF:
2192 // all good
2193 case nil:
2194 t.Fatalf("ReadAt succeeded")
2195 default:
2196 t.Fatalf("ReadAt failed: %s", err)
2200 func TestLongPath(t *testing.T) {
2201 tmpdir := newDir("TestLongPath", t)
2202 defer func(d string) {
2203 if err := RemoveAll(d); err != nil {
2204 t.Fatalf("RemoveAll failed: %v", err)
2206 }(tmpdir)
2208 // Test the boundary of 247 and fewer bytes (normal) and 248 and more bytes (adjusted).
2209 sizes := []int{247, 248, 249, 400}
2210 for len(tmpdir) < 400 {
2211 tmpdir += "/dir3456789"
2213 for _, sz := range sizes {
2214 t.Run(fmt.Sprintf("length=%d", sz), func(t *testing.T) {
2215 sizedTempDir := tmpdir[:sz-1] + "x" // Ensure it does not end with a slash.
2217 // The various sized runs are for this call to trigger the boundary
2218 // condition.
2219 if err := MkdirAll(sizedTempDir, 0755); err != nil {
2220 t.Fatalf("MkdirAll failed: %v", err)
2222 data := []byte("hello world\n")
2223 if err := os.WriteFile(sizedTempDir+"/foo.txt", data, 0644); err != nil {
2224 t.Fatalf("os.WriteFile() failed: %v", err)
2226 if err := Rename(sizedTempDir+"/foo.txt", sizedTempDir+"/bar.txt"); err != nil {
2227 t.Fatalf("Rename failed: %v", err)
2229 mtime := time.Now().Truncate(time.Minute)
2230 if err := Chtimes(sizedTempDir+"/bar.txt", mtime, mtime); err != nil {
2231 t.Fatalf("Chtimes failed: %v", err)
2233 names := []string{"bar.txt"}
2234 if testenv.HasSymlink() {
2235 if err := Symlink(sizedTempDir+"/bar.txt", sizedTempDir+"/symlink.txt"); err != nil {
2236 t.Fatalf("Symlink failed: %v", err)
2238 names = append(names, "symlink.txt")
2240 if testenv.HasLink() {
2241 if err := Link(sizedTempDir+"/bar.txt", sizedTempDir+"/link.txt"); err != nil {
2242 t.Fatalf("Link failed: %v", err)
2244 names = append(names, "link.txt")
2246 for _, wantSize := range []int64{int64(len(data)), 0} {
2247 for _, name := range names {
2248 path := sizedTempDir + "/" + name
2249 dir, err := Stat(path)
2250 if err != nil {
2251 t.Fatalf("Stat(%q) failed: %v", path, err)
2253 filesize := size(path, t)
2254 if dir.Size() != filesize || filesize != wantSize {
2255 t.Errorf("Size(%q) is %d, len(ReadFile()) is %d, want %d", path, dir.Size(), filesize, wantSize)
2257 err = Chmod(path, dir.Mode())
2258 if err != nil {
2259 t.Fatalf("Chmod(%q) failed: %v", path, err)
2262 if err := Truncate(sizedTempDir+"/bar.txt", 0); err != nil {
2263 t.Fatalf("Truncate failed: %v", err)
2270 func testKillProcess(t *testing.T, processKiller func(p *Process)) {
2271 testenv.MustHaveExec(t)
2272 t.Parallel()
2274 // Re-exec the test binary to start a process that hangs until stdin is closed.
2275 cmd := osexec.Command(Args[0])
2276 cmd.Env = append(os.Environ(), "GO_OS_TEST_DRAIN_STDIN=1")
2277 stdout, err := cmd.StdoutPipe()
2278 if err != nil {
2279 t.Fatal(err)
2281 stdin, err := cmd.StdinPipe()
2282 if err != nil {
2283 t.Fatal(err)
2285 err = cmd.Start()
2286 if err != nil {
2287 t.Fatalf("Failed to start test process: %v", err)
2290 defer func() {
2291 if err := cmd.Wait(); err == nil {
2292 t.Errorf("Test process succeeded, but expected to fail")
2294 stdin.Close() // Keep stdin alive until the process has finished dying.
2297 // Wait for the process to be started.
2298 // (It will close its stdout when it reaches TestMain.)
2299 io.Copy(io.Discard, stdout)
2301 processKiller(cmd.Process)
2304 func TestKillStartProcess(t *testing.T) {
2305 testKillProcess(t, func(p *Process) {
2306 err := p.Kill()
2307 if err != nil {
2308 t.Fatalf("Failed to kill test process: %v", err)
2313 func TestGetppid(t *testing.T) {
2314 if runtime.GOOS == "plan9" {
2315 // TODO: golang.org/issue/8206
2316 t.Skipf("skipping test on plan9; see issue 8206")
2319 testenv.MustHaveExec(t)
2321 if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
2322 fmt.Print(Getppid())
2323 Exit(0)
2326 cmd := osexec.Command(Args[0], "-test.run=TestGetppid")
2327 cmd.Env = append(Environ(), "GO_WANT_HELPER_PROCESS=1")
2329 // verify that Getppid() from the forked process reports our process id
2330 output, err := cmd.CombinedOutput()
2331 if err != nil {
2332 t.Fatalf("Failed to spawn child process: %v %q", err, string(output))
2335 childPpid := string(output)
2336 ourPid := fmt.Sprintf("%d", Getpid())
2337 if childPpid != ourPid {
2338 t.Fatalf("Child process reports parent process id '%v', expected '%v'", childPpid, ourPid)
2342 func TestKillFindProcess(t *testing.T) {
2343 testKillProcess(t, func(p *Process) {
2344 p2, err := FindProcess(p.Pid)
2345 if err != nil {
2346 t.Fatalf("Failed to find test process: %v", err)
2348 err = p2.Kill()
2349 if err != nil {
2350 t.Fatalf("Failed to kill test process: %v", err)
2355 var nilFileMethodTests = []struct {
2356 name string
2357 f func(*File) error
2359 {"Chdir", func(f *File) error { return f.Chdir() }},
2360 {"Close", func(f *File) error { return f.Close() }},
2361 {"Chmod", func(f *File) error { return f.Chmod(0) }},
2362 {"Chown", func(f *File) error { return f.Chown(0, 0) }},
2363 {"Read", func(f *File) error { _, err := f.Read(make([]byte, 0)); return err }},
2364 {"ReadAt", func(f *File) error { _, err := f.ReadAt(make([]byte, 0), 0); return err }},
2365 {"Readdir", func(f *File) error { _, err := f.Readdir(1); return err }},
2366 {"Readdirnames", func(f *File) error { _, err := f.Readdirnames(1); return err }},
2367 {"Seek", func(f *File) error { _, err := f.Seek(0, io.SeekStart); return err }},
2368 {"Stat", func(f *File) error { _, err := f.Stat(); return err }},
2369 {"Sync", func(f *File) error { return f.Sync() }},
2370 {"Truncate", func(f *File) error { return f.Truncate(0) }},
2371 {"Write", func(f *File) error { _, err := f.Write(make([]byte, 0)); return err }},
2372 {"WriteAt", func(f *File) error { _, err := f.WriteAt(make([]byte, 0), 0); return err }},
2373 {"WriteString", func(f *File) error { _, err := f.WriteString(""); return err }},
2376 // Test that all File methods give ErrInvalid if the receiver is nil.
2377 func TestNilFileMethods(t *testing.T) {
2378 for _, tt := range nilFileMethodTests {
2379 var file *File
2380 got := tt.f(file)
2381 if got != ErrInvalid {
2382 t.Errorf("%v should fail when f is nil; got %v", tt.name, got)
2387 func mkdirTree(t *testing.T, root string, level, max int) {
2388 if level >= max {
2389 return
2391 level++
2392 for i := 'a'; i < 'c'; i++ {
2393 dir := filepath.Join(root, string(i))
2394 if err := Mkdir(dir, 0700); err != nil {
2395 t.Fatal(err)
2397 mkdirTree(t, dir, level, max)
2401 // Test that simultaneous RemoveAll do not report an error.
2402 // As long as it gets removed, we should be happy.
2403 func TestRemoveAllRace(t *testing.T) {
2404 if runtime.GOOS == "windows" {
2405 // Windows has very strict rules about things like
2406 // removing directories while someone else has
2407 // them open. The racing doesn't work out nicely
2408 // like it does on Unix.
2409 t.Skip("skipping on windows")
2412 n := runtime.GOMAXPROCS(16)
2413 defer runtime.GOMAXPROCS(n)
2414 root, err := os.MkdirTemp("", "issue")
2415 if err != nil {
2416 t.Fatal(err)
2418 mkdirTree(t, root, 1, 6)
2419 hold := make(chan struct{})
2420 var wg sync.WaitGroup
2421 for i := 0; i < 4; i++ {
2422 wg.Add(1)
2423 go func() {
2424 defer wg.Done()
2425 <-hold
2426 err := RemoveAll(root)
2427 if err != nil {
2428 t.Errorf("unexpected error: %T, %q", err, err)
2432 close(hold) // let workers race to remove root
2433 wg.Wait()
2436 // Test that reading from a pipe doesn't use up a thread.
2437 func TestPipeThreads(t *testing.T) {
2438 switch runtime.GOOS {
2439 case "illumos", "solaris":
2440 t.Skip("skipping on Solaris and illumos; issue 19111")
2441 case "windows":
2442 t.Skip("skipping on Windows; issue 19098")
2443 case "plan9":
2444 t.Skip("skipping on Plan 9; does not support runtime poller")
2445 case "js":
2446 t.Skip("skipping on js; no support for os.Pipe")
2449 threads := 100
2451 // OpenBSD has a low default for max number of files.
2452 if runtime.GOOS == "openbsd" {
2453 threads = 50
2456 r := make([]*File, threads)
2457 w := make([]*File, threads)
2458 for i := 0; i < threads; i++ {
2459 rp, wp, err := Pipe()
2460 if err != nil {
2461 for j := 0; j < i; j++ {
2462 r[j].Close()
2463 w[j].Close()
2465 t.Fatal(err)
2467 r[i] = rp
2468 w[i] = wp
2471 defer debug.SetMaxThreads(debug.SetMaxThreads(threads / 2))
2473 creading := make(chan bool, threads)
2474 cdone := make(chan bool, threads)
2475 for i := 0; i < threads; i++ {
2476 go func(i int) {
2477 var b [1]byte
2478 creading <- true
2479 if _, err := r[i].Read(b[:]); err != nil {
2480 t.Error(err)
2482 if err := r[i].Close(); err != nil {
2483 t.Error(err)
2485 cdone <- true
2486 }(i)
2489 for i := 0; i < threads; i++ {
2490 <-creading
2493 // If we are still alive, it means that the 100 goroutines did
2494 // not require 100 threads.
2496 for i := 0; i < threads; i++ {
2497 if _, err := w[i].Write([]byte{0}); err != nil {
2498 t.Error(err)
2500 if err := w[i].Close(); err != nil {
2501 t.Error(err)
2503 <-cdone
2507 func testDoubleCloseError(t *testing.T, path string) {
2508 file, err := Open(path)
2509 if err != nil {
2510 t.Fatal(err)
2512 if err := file.Close(); err != nil {
2513 t.Fatalf("unexpected error from Close: %v", err)
2515 if err := file.Close(); err == nil {
2516 t.Error("second Close did not fail")
2517 } else if pe, ok := err.(*PathError); !ok {
2518 t.Errorf("second Close returned unexpected error type %T; expected fs.PathError", pe)
2519 } else if pe.Err != ErrClosed {
2520 t.Errorf("second Close returned %q, wanted %q", err, ErrClosed)
2521 } else {
2522 t.Logf("second close returned expected error %q", err)
2526 func TestDoubleCloseError(t *testing.T) {
2527 testDoubleCloseError(t, filepath.Join(sfdir, sfname))
2528 testDoubleCloseError(t, sfdir)
2531 func TestUserHomeDir(t *testing.T) {
2532 dir, err := UserHomeDir()
2533 if dir == "" && err == nil {
2534 t.Fatal("UserHomeDir returned an empty string but no error")
2536 if err != nil {
2537 t.Skipf("UserHomeDir failed: %v", err)
2539 fi, err := Stat(dir)
2540 if err != nil {
2541 t.Fatal(err)
2543 if !fi.IsDir() {
2544 t.Fatalf("dir %s is not directory; type = %v", dir, fi.Mode())
2548 func TestDirSeek(t *testing.T) {
2549 if runtime.GOOS == "windows" {
2550 testenv.SkipFlaky(t, 36019)
2552 wd, err := Getwd()
2553 if err != nil {
2554 t.Fatal(err)
2556 f, err := Open(wd)
2557 if err != nil {
2558 t.Fatal(err)
2560 dirnames1, err := f.Readdirnames(0)
2561 if err != nil {
2562 t.Fatal(err)
2565 ret, err := f.Seek(0, 0)
2566 if err != nil {
2567 t.Fatal(err)
2569 if ret != 0 {
2570 t.Fatalf("seek result not zero: %d", ret)
2573 dirnames2, err := f.Readdirnames(0)
2574 if err != nil {
2575 t.Fatal(err)
2576 return
2579 if len(dirnames1) != len(dirnames2) {
2580 t.Fatalf("listings have different lengths: %d and %d\n", len(dirnames1), len(dirnames2))
2582 for i, n1 := range dirnames1 {
2583 n2 := dirnames2[i]
2584 if n1 != n2 {
2585 t.Fatalf("different name i=%d n1=%s n2=%s\n", i, n1, n2)
2590 func TestReaddirSmallSeek(t *testing.T) {
2591 // See issue 37161. Read only one entry from a directory,
2592 // seek to the beginning, and read again. We should not see
2593 // duplicate entries.
2594 if runtime.GOOS == "windows" {
2595 testenv.SkipFlaky(t, 36019)
2597 wd, err := Getwd()
2598 if err != nil {
2599 t.Fatal(err)
2601 df, err := Open(filepath.Join(wd, "testdata", "issue37161"))
2602 if err != nil {
2603 t.Fatal(err)
2605 names1, err := df.Readdirnames(1)
2606 if err != nil {
2607 t.Fatal(err)
2609 if _, err = df.Seek(0, 0); err != nil {
2610 t.Fatal(err)
2612 names2, err := df.Readdirnames(0)
2613 if err != nil {
2614 t.Fatal(err)
2616 if len(names2) != 3 {
2617 t.Fatalf("first names: %v, second names: %v", names1, names2)
2621 // isDeadlineExceeded reports whether err is or wraps os.ErrDeadlineExceeded.
2622 // We also check that the error has a Timeout method that returns true.
2623 func isDeadlineExceeded(err error) bool {
2624 if !IsTimeout(err) {
2625 return false
2627 if !errors.Is(err, ErrDeadlineExceeded) {
2628 return false
2630 return true
2633 // Test that opening a file does not change its permissions. Issue 38225.
2634 func TestOpenFileKeepsPermissions(t *testing.T) {
2635 t.Parallel()
2636 dir := t.TempDir()
2637 name := filepath.Join(dir, "x")
2638 f, err := Create(name)
2639 if err != nil {
2640 t.Fatal(err)
2642 if err := f.Close(); err != nil {
2643 t.Error(err)
2645 f, err = OpenFile(name, O_WRONLY|O_CREATE|O_TRUNC, 0)
2646 if err != nil {
2647 t.Fatal(err)
2649 if fi, err := f.Stat(); err != nil {
2650 t.Error(err)
2651 } else if fi.Mode()&0222 == 0 {
2652 t.Errorf("f.Stat.Mode after OpenFile is %v, should be writable", fi.Mode())
2654 if err := f.Close(); err != nil {
2655 t.Error(err)
2657 if fi, err := Stat(name); err != nil {
2658 t.Error(err)
2659 } else if fi.Mode()&0222 == 0 {
2660 t.Errorf("Stat after OpenFile is %v, should be writable", fi.Mode())
2664 func TestDirFS(t *testing.T) {
2665 // On Windows, we force the MFT to update by reading the actual metadata from GetFileInformationByHandle and then
2666 // explicitly setting that. Otherwise it might get out of sync with FindFirstFile. See golang.org/issues/42637.
2667 if runtime.GOOS == "windows" {
2668 if err := filepath.WalkDir("./testdata/dirfs", func(path string, d fs.DirEntry, err error) error {
2669 if err != nil {
2670 t.Fatal(err)
2672 info, err := d.Info()
2673 if err != nil {
2674 t.Fatal(err)
2676 stat, err := Stat(path) // This uses GetFileInformationByHandle internally.
2677 if err != nil {
2678 t.Fatal(err)
2680 if stat.ModTime() == info.ModTime() {
2681 return nil
2683 if err := Chtimes(path, stat.ModTime(), stat.ModTime()); err != nil {
2684 t.Log(err) // We only log, not die, in case the test directory is not writable.
2686 return nil
2687 }); err != nil {
2688 t.Fatal(err)
2691 if err := fstest.TestFS(DirFS("./testdata/dirfs"), "a", "b", "dir/x"); err != nil {
2692 t.Fatal(err)
2695 // Test that Open does not accept backslash as separator.
2696 d := DirFS(".")
2697 _, err := d.Open(`testdata\dirfs`)
2698 if err == nil {
2699 t.Fatalf(`Open testdata\dirfs succeeded`)
2703 func TestDirFSPathsValid(t *testing.T) {
2704 if runtime.GOOS == "windows" {
2705 t.Skipf("skipping on Windows")
2708 d := t.TempDir()
2709 if err := os.WriteFile(filepath.Join(d, "control.txt"), []byte(string("Hello, world!")), 0644); err != nil {
2710 t.Fatal(err)
2712 if err := os.WriteFile(filepath.Join(d, `e:xperi\ment.txt`), []byte(string("Hello, colon and backslash!")), 0644); err != nil {
2713 t.Fatal(err)
2716 fsys := os.DirFS(d)
2717 err := fs.WalkDir(fsys, ".", func(path string, e fs.DirEntry, err error) error {
2718 if fs.ValidPath(e.Name()) {
2719 t.Logf("%q ok", e.Name())
2720 } else {
2721 t.Errorf("%q INVALID", e.Name())
2723 return nil
2725 if err != nil {
2726 t.Fatal(err)
2730 func TestReadFileProc(t *testing.T) {
2731 // Linux files in /proc report 0 size,
2732 // but then if ReadFile reads just a single byte at offset 0,
2733 // the read at offset 1 returns EOF instead of more data.
2734 // ReadFile has a minimum read size of 512 to work around this,
2735 // but test explicitly that it's working.
2736 name := "/proc/sys/fs/pipe-max-size"
2737 if _, err := Stat(name); err != nil {
2738 t.Skip(err)
2740 data, err := ReadFile(name)
2741 if err != nil {
2742 t.Fatal(err)
2744 if len(data) == 0 || data[len(data)-1] != '\n' {
2745 t.Fatalf("read %s: not newline-terminated: %q", name, data)
2749 func TestWriteStringAlloc(t *testing.T) {
2750 if runtime.GOOS == "js" {
2751 t.Skip("js allocates a lot during File.WriteString")
2753 d := t.TempDir()
2754 f, err := Create(filepath.Join(d, "whiteboard.txt"))
2755 if err != nil {
2756 t.Fatal(err)
2758 defer f.Close()
2759 allocs := testing.AllocsPerRun(100, func() {
2760 f.WriteString("I will not allocate when passed a string longer than 32 bytes.\n")
2762 if allocs != 0 {
2763 t.Errorf("expected 0 allocs for File.WriteString, got %v", allocs)