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"
179 Remove(path
) // Just in case
181 fi
, err
:= Stat(path
)
183 t
.Fatal("got nil, want error")
186 t
.Errorf("got %v, want nil", fi
)
188 if perr
, ok
:= err
.(*PathError
); !ok
{
189 t
.Errorf("got %T, want %T", err
, perr
)
192 testenv
.MustHaveSymlink(t
)
195 Remove(link
) // Just in case
196 err
= Symlink(path
, link
)
204 t
.Fatal("got nil, want error")
207 t
.Errorf("got %v, want nil", fi
)
209 if perr
, ok
:= err
.(*PathError
); !ok
{
210 t
.Errorf("got %T, want %T", err
, perr
)
214 func TestFstat(t
*testing
.T
) {
215 path
:= sfdir
+ "/" + sfname
216 file
, err1
:= Open(path
)
218 t
.Fatal("open failed:", err1
)
221 dir
, err2
:= file
.Stat()
223 t
.Fatal("fstat failed:", err2
)
225 if !equal(sfname
, dir
.Name()) {
226 t
.Error("name should be ", sfname
, "; is", dir
.Name())
228 filesize
:= size(path
, t
)
229 if dir
.Size() != filesize
{
230 t
.Error("size should be", filesize
, "; is", dir
.Size())
234 func TestLstat(t
*testing
.T
) {
235 path
:= sfdir
+ "/" + sfname
236 dir
, err
:= Lstat(path
)
238 t
.Fatal("lstat failed:", err
)
240 if !equal(sfname
, dir
.Name()) {
241 t
.Error("name should be ", sfname
, "; is", dir
.Name())
243 filesize
:= size(path
, t
)
244 if dir
.Size() != filesize
{
245 t
.Error("size should be", filesize
, "; is", dir
.Size())
249 // Read with length 0 should not return EOF.
250 func TestRead0(t
*testing
.T
) {
251 path
:= sfdir
+ "/" + sfname
254 t
.Fatal("open failed:", err
)
260 if n
!= 0 || err
!= nil {
261 t
.Errorf("Read(0) = %d, %v, want 0, nil", n
, err
)
263 b
= make([]byte, 100)
265 if n
<= 0 || err
!= nil {
266 t
.Errorf("Read(100) = %d, %v, want >0, nil", n
, err
)
270 // Reading a closed file should should return ErrClosed error
271 func TestReadClosed(t
*testing
.T
) {
272 path
:= sfdir
+ "/" + sfname
273 file
, err
:= Open(path
)
275 t
.Fatal("open failed:", err
)
277 file
.Close() // close immediately
279 b
:= make([]byte, 100)
280 _
, err
= file
.Read(b
)
282 e
, ok
:= err
.(*PathError
)
284 t
.Fatalf("Read: %T(%v), want PathError", e
, e
)
287 if e
.Err
!= ErrClosed
{
288 t
.Errorf("Read: %v, want PathError(ErrClosed)", e
)
292 func testReaddirnames(dir
string, contents
[]string, t
*testing
.T
) {
293 file
, err
:= Open(dir
)
295 t
.Fatalf("open %q failed: %v", dir
, err
)
298 s
, err2
:= file
.Readdirnames(-1)
300 t
.Fatalf("readdirnames %q failed: %v", dir
, err2
)
302 for _
, m
:= range contents
{
304 for _
, n
:= range s
{
305 if n
== "." || n
== ".." {
306 t
.Errorf("got %s in directory", n
)
310 t
.Error("present twice:", m
)
316 t
.Error("could not find", m
)
321 func testReaddir(dir
string, contents
[]string, t
*testing
.T
) {
322 file
, err
:= Open(dir
)
324 t
.Fatalf("open %q failed: %v", dir
, err
)
327 s
, err2
:= file
.Readdir(-1)
329 t
.Fatalf("readdir %q failed: %v", dir
, err2
)
331 for _
, m
:= range contents
{
333 for _
, n
:= range s
{
334 if equal(m
, n
.Name()) {
336 t
.Error("present twice:", m
)
342 t
.Error("could not find", m
)
347 func TestReaddirnames(t
*testing
.T
) {
348 testReaddirnames(".", dot
, t
)
349 testReaddirnames(sysdir
.name
, sysdir
.files
, t
)
352 func TestReaddir(t
*testing
.T
) {
353 testReaddir(".", dot
, t
)
354 testReaddir(sysdir
.name
, sysdir
.files
, t
)
357 func benchmarkReaddirname(path
string, b
*testing
.B
) {
359 for i
:= 0; i
< b
.N
; i
++ {
362 b
.Fatalf("open %q failed: %v", path
, err
)
364 ns
, err
:= f
.Readdirnames(-1)
367 b
.Fatalf("readdirnames %q failed: %v", path
, err
)
371 b
.Logf("benchmarkReaddirname %q: %d entries", path
, nentries
)
374 func benchmarkReaddir(path
string, b
*testing
.B
) {
376 for i
:= 0; i
< b
.N
; i
++ {
379 b
.Fatalf("open %q failed: %v", path
, err
)
381 fs
, err
:= f
.Readdir(-1)
384 b
.Fatalf("readdir %q failed: %v", path
, err
)
388 b
.Logf("benchmarkReaddir %q: %d entries", path
, nentries
)
391 func BenchmarkReaddirname(b
*testing
.B
) {
392 benchmarkReaddirname(".", b
)
395 func BenchmarkReaddir(b
*testing
.B
) {
396 benchmarkReaddir(".", b
)
399 func benchmarkStat(b
*testing
.B
, path
string) {
401 for i
:= 0; i
< b
.N
; i
++ {
404 b
.Fatalf("Stat(%q) failed: %v", path
, err
)
409 func benchmarkLstat(b
*testing
.B
, path
string) {
411 for i
:= 0; i
< b
.N
; i
++ {
412 _
, err
:= Lstat(path
)
414 b
.Fatalf("Lstat(%q) failed: %v", path
, err
)
419 func BenchmarkStatDot(b
*testing
.B
) {
420 benchmarkStat(b
, ".")
423 func BenchmarkStatFile(b
*testing
.B
) {
424 benchmarkStat(b
, filepath
.Join(runtime
.GOROOT(), "src/os/os_test.go"))
427 func BenchmarkStatDir(b
*testing
.B
) {
428 benchmarkStat(b
, filepath
.Join(runtime
.GOROOT(), "src/os"))
431 func BenchmarkLstatDot(b
*testing
.B
) {
432 benchmarkLstat(b
, ".")
435 func BenchmarkLstatFile(b
*testing
.B
) {
436 benchmarkLstat(b
, filepath
.Join(runtime
.GOROOT(), "src/os/os_test.go"))
439 func BenchmarkLstatDir(b
*testing
.B
) {
440 benchmarkLstat(b
, filepath
.Join(runtime
.GOROOT(), "src/os"))
443 // Read the directory one entry at a time.
444 func smallReaddirnames(file
*File
, length
int, t
*testing
.T
) []string {
445 names
:= make([]string, length
)
448 d
, err
:= file
.Readdirnames(1)
453 t
.Fatalf("readdirnames %q failed: %v", file
.Name(), err
)
456 t
.Fatalf("readdirnames %q returned empty slice and no error", file
.Name())
461 return names
[0:count
]
464 // Check that reading a directory one entry at a time gives the same result
465 // as reading it all at once.
466 func TestReaddirnamesOneAtATime(t
*testing
.T
) {
467 // big directory that doesn't change often.
469 switch runtime
.GOOS
{
473 switch runtime
.GOARCH
{
484 dir
= Getenv("SystemRoot") + "\\system32"
486 file
, err
:= Open(dir
)
488 t
.Fatalf("open %q failed: %v", dir
, err
)
491 all
, err1
:= file
.Readdirnames(-1)
493 t
.Fatalf("readdirnames %q failed: %v", dir
, err1
)
495 file1
, err2
:= Open(dir
)
497 t
.Fatalf("open %q failed: %v", dir
, err2
)
500 small
:= smallReaddirnames(file1
, len(all
)+100, t
) // +100 in case we screw up
501 if len(small
) < len(all
) {
502 t
.Fatalf("len(small) is %d, less than %d", len(small
), len(all
))
504 for i
, n
:= range all
{
506 t
.Errorf("small read %q mismatch: %v", small
[i
], n
)
511 func TestReaddirNValues(t
*testing
.T
) {
513 t
.Skip("test.short; skipping")
515 dir
, err
:= ioutil
.TempDir("", "")
517 t
.Fatalf("TempDir: %v", err
)
520 for i
:= 1; i
<= 105; i
++ {
521 f
, err
:= Create(filepath
.Join(dir
, fmt
.Sprintf("%d", i
)))
523 t
.Fatalf("Create: %v", err
)
525 f
.Write([]byte(strings
.Repeat("X", i
)))
534 t
.Fatalf("Open directory: %v", err
)
538 readDirExpect
:= func(n
, want
int, wantErr error
) {
539 fi
, err
:= d
.Readdir(n
)
541 t
.Fatalf("Readdir of %d got error %v, want %v", n
, err
, wantErr
)
543 if g
, e
:= len(fi
), want
; g
!= e
{
544 t
.Errorf("Readdir of %d got %d files, want %d", n
, g
, e
)
548 readDirNamesExpect
:= func(n
, want
int, wantErr error
) {
549 fi
, err
:= d
.Readdirnames(n
)
551 t
.Fatalf("Readdirnames of %d got error %v, want %v", n
, err
, wantErr
)
553 if g
, e
:= len(fi
), want
; g
!= e
{
554 t
.Errorf("Readdirnames of %d got %d files, want %d", n
, g
, e
)
558 for _
, fn
:= range []func(int, int, error
){readDirExpect
, readDirNamesExpect
} {
559 // Test the slurp case
565 // Slurp with -1 instead
572 // Test the bounded case
576 fn(105, 102, nil) // and tests buffer >100 case
582 func touch(t
*testing
.T
, name
string) {
583 f
, err
:= Create(name
)
587 if err
:= f
.Close(); err
!= nil {
592 func TestReaddirStatFailures(t
*testing
.T
) {
593 switch runtime
.GOOS
{
594 case "windows", "plan9":
595 // Windows and Plan 9 already do this correctly,
596 // but are structured with different syscalls such
597 // that they don't use Lstat, so the hook below for
598 // testing it wouldn't work.
599 t
.Skipf("skipping test on %v", runtime
.GOOS
)
601 dir
, err
:= ioutil
.TempDir("", "")
603 t
.Fatalf("TempDir: %v", err
)
606 touch(t
, filepath
.Join(dir
, "good1"))
607 touch(t
, filepath
.Join(dir
, "x")) // will disappear or have an error
608 touch(t
, filepath
.Join(dir
, "good2"))
612 var xerr error
// error to return for x
613 *LstatP
= func(path
string) (FileInfo
, error
) {
614 if xerr
!= nil && strings
.HasSuffix(path
, "x") {
619 readDir
:= func() ([]FileInfo
, error
) {
627 mustReadDir
:= func(testName
string) []FileInfo
{
628 fis
, err
:= readDir()
630 t
.Fatalf("%s: Readdir: %v", testName
, err
)
634 names
:= func(fis
[]FileInfo
) []string {
635 s
:= make([]string, len(fis
))
636 for i
, fi
:= range fis
{
643 if got
, want
:= names(mustReadDir("initial readdir")),
644 []string{"good1", "good2", "x"}; !reflect
.DeepEqual(got
, want
) {
645 t
.Errorf("initial readdir got %q; want %q", got
, want
)
649 if got
, want
:= names(mustReadDir("with x disappearing")),
650 []string{"good1", "good2"}; !reflect
.DeepEqual(got
, want
) {
651 t
.Errorf("with x disappearing, got %q; want %q", got
, want
)
654 xerr
= errors
.New("some real error")
655 if _
, err
:= readDir(); err
!= xerr
{
656 t
.Errorf("with a non-ErrNotExist error, got error %v; want %v", err
, xerr
)
660 // Readdir on a regular file should fail.
661 func TestReaddirOfFile(t
*testing
.T
) {
662 f
, err
:= ioutil
.TempFile("", "_Go_ReaddirOfFile")
666 defer Remove(f
.Name())
667 f
.Write([]byte("foo"))
669 reg
, err
:= Open(f
.Name())
675 names
, err
:= reg
.Readdirnames(-1)
677 t
.Error("Readdirnames succeeded; want non-nil error")
680 t
.Errorf("unexpected dir names in regular file: %q", names
)
684 func TestHardLink(t
*testing
.T
) {
685 testenv
.MustHaveLink(t
)
688 from
, to
:= "hardlinktestfrom", "hardlinktestto"
689 Remove(from
) // Just in case.
690 file
, err
:= Create(to
)
692 t
.Fatalf("open %q failed: %v", to
, err
)
695 if err
= file
.Close(); err
!= nil {
696 t
.Errorf("close %q failed: %v", to
, err
)
700 t
.Fatalf("link %q, %q failed: %v", to
, from
, err
)
703 none
:= "hardlinktestnone"
704 err
= Link(none
, none
)
705 // Check the returned error is well-formed.
706 if lerr
, ok
:= err
.(*LinkError
); !ok || lerr
.Error() == "" {
707 t
.Errorf("link %q, %q failed to return a valid error", none
, none
)
711 tostat
, err
:= Stat(to
)
713 t
.Fatalf("stat %q failed: %v", to
, err
)
715 fromstat
, err
:= Stat(from
)
717 t
.Fatalf("stat %q failed: %v", from
, err
)
719 if !SameFile(tostat
, fromstat
) {
720 t
.Errorf("link %q, %q did not create hard link", to
, from
)
722 // We should not be able to perform the same Link() a second time
724 switch err
:= err
.(type) {
726 if err
.Op
!= "link" {
727 t
.Errorf("Link(%q, %q) err.Op = %q; want %q", to
, from
, err
.Op
, "link")
730 t
.Errorf("Link(%q, %q) err.Old = %q; want %q", to
, from
, err
.Old
, to
)
733 t
.Errorf("Link(%q, %q) err.New = %q; want %q", to
, from
, err
.New
, from
)
735 if !IsExist(err
.Err
) {
736 t
.Errorf("Link(%q, %q) err.Err = %q; want %q", to
, from
, err
.Err
, "file exists error")
739 t
.Errorf("link %q, %q: expected error, got nil", from
, to
)
741 t
.Errorf("link %q, %q: expected %T, got %T %v", from
, to
, new(LinkError
), err
, err
)
745 // chtmpdir changes the working directory to a new temporary directory and
746 // provides a cleanup function. Used when PWD is read-only.
747 func chtmpdir(t
*testing
.T
) func() {
748 if runtime
.GOOS
!= "darwin" ||
(runtime
.GOARCH
!= "arm" && runtime
.GOARCH
!= "arm64") {
749 return func() {} // only needed on darwin/arm{,64}
751 oldwd
, err
:= Getwd()
753 t
.Fatalf("chtmpdir: %v", err
)
755 d
, err
:= ioutil
.TempDir("", "test")
757 t
.Fatalf("chtmpdir: %v", err
)
759 if err
:= Chdir(d
); err
!= nil {
760 t
.Fatalf("chtmpdir: %v", err
)
763 if err
:= Chdir(oldwd
); err
!= nil {
764 t
.Fatalf("chtmpdir: %v", err
)
770 func TestSymlink(t
*testing
.T
) {
771 testenv
.MustHaveSymlink(t
)
774 from
, to
:= "symlinktestfrom", "symlinktestto"
775 Remove(from
) // Just in case.
776 file
, err
:= Create(to
)
778 t
.Fatalf("Create(%q) failed: %v", to
, err
)
781 if err
= file
.Close(); err
!= nil {
782 t
.Errorf("Close(%q) failed: %v", to
, err
)
784 err
= Symlink(to
, from
)
786 t
.Fatalf("Symlink(%q, %q) failed: %v", to
, from
, err
)
789 tostat
, err
:= Lstat(to
)
791 t
.Fatalf("Lstat(%q) failed: %v", to
, err
)
793 if tostat
.Mode()&ModeSymlink
!= 0 {
794 t
.Fatalf("Lstat(%q).Mode()&ModeSymlink = %v, want 0", to
, tostat
.Mode()&ModeSymlink
)
796 fromstat
, err
:= Stat(from
)
798 t
.Fatalf("Stat(%q) failed: %v", from
, err
)
800 if !SameFile(tostat
, fromstat
) {
801 t
.Errorf("Symlink(%q, %q) did not create symlink", to
, from
)
803 fromstat
, err
= Lstat(from
)
805 t
.Fatalf("Lstat(%q) failed: %v", from
, err
)
807 if fromstat
.Mode()&ModeSymlink
== 0 {
808 t
.Fatalf("Lstat(%q).Mode()&ModeSymlink = 0, want %v", from
, ModeSymlink
)
810 fromstat
, err
= Stat(from
)
812 t
.Fatalf("Stat(%q) failed: %v", from
, err
)
814 if fromstat
.Name() != from
{
815 t
.Errorf("Stat(%q).Name() = %q, want %q", from
, fromstat
.Name(), from
)
817 if fromstat
.Mode()&ModeSymlink
!= 0 {
818 t
.Fatalf("Stat(%q).Mode()&ModeSymlink = %v, want 0", from
, fromstat
.Mode()&ModeSymlink
)
820 s
, err
:= Readlink(from
)
822 t
.Fatalf("Readlink(%q) failed: %v", from
, err
)
825 t
.Fatalf("Readlink(%q) = %q, want %q", from
, s
, to
)
827 file
, err
= Open(from
)
829 t
.Fatalf("Open(%q) failed: %v", from
, err
)
834 func TestLongSymlink(t
*testing
.T
) {
835 testenv
.MustHaveSymlink(t
)
838 s
:= "0123456789abcdef"
839 // Long, but not too long: a common limit is 255.
840 s
= s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
841 from
:= "longsymlinktestfrom"
842 Remove(from
) // Just in case.
843 err
:= Symlink(s
, from
)
845 t
.Fatalf("symlink %q, %q failed: %v", s
, from
, err
)
848 r
, err
:= Readlink(from
)
850 t
.Fatalf("readlink %q failed: %v", from
, err
)
853 t
.Fatalf("after symlink %q != %q", r
, s
)
857 func TestRename(t
*testing
.T
) {
859 from
, to
:= "renamefrom", "renameto"
860 // Ensure we are not testing the overwrite case here.
864 file
, err
:= Create(from
)
866 t
.Fatalf("open %q failed: %v", from
, err
)
868 if err
= file
.Close(); err
!= nil {
869 t
.Errorf("close %q failed: %v", from
, err
)
871 err
= Rename(from
, to
)
873 t
.Fatalf("rename %q, %q failed: %v", to
, from
, err
)
878 t
.Errorf("stat %q failed: %v", to
, err
)
882 func TestRenameOverwriteDest(t
*testing
.T
) {
884 from
, to
:= "renamefrom", "renameto"
889 toData
:= []byte("to")
890 fromData
:= []byte("from")
892 err
:= ioutil
.WriteFile(to
, toData
, 0777)
894 t
.Fatalf("write file %q failed: %v", to
, err
)
897 err
= ioutil
.WriteFile(from
, fromData
, 0777)
899 t
.Fatalf("write file %q failed: %v", from
, err
)
901 err
= Rename(from
, to
)
903 t
.Fatalf("rename %q, %q failed: %v", to
, from
, err
)
909 t
.Errorf("from file %q still exists", from
)
911 if err
!= nil && !IsNotExist(err
) {
912 t
.Fatalf("stat from: %v", err
)
914 toFi
, err
:= Stat(to
)
916 t
.Fatalf("stat %q failed: %v", to
, err
)
918 if toFi
.Size() != int64(len(fromData
)) {
919 t
.Errorf(`"to" size = %d; want %d (old "from" size)`, toFi
.Size(), len(fromData
))
923 func TestRenameFailed(t
*testing
.T
) {
925 from
, to
:= "renamefrom", "renameto"
926 // Ensure we are not testing the overwrite case here.
930 err
:= Rename(from
, to
)
931 switch err
:= err
.(type) {
933 if err
.Op
!= "rename" {
934 t
.Errorf("rename %q, %q: err.Op: want %q, got %q", from
, to
, "rename", err
.Op
)
937 t
.Errorf("rename %q, %q: err.Old: want %q, got %q", from
, to
, from
, err
.Old
)
940 t
.Errorf("rename %q, %q: err.New: want %q, got %q", from
, to
, to
, err
.New
)
943 t
.Errorf("rename %q, %q: expected error, got nil", from
, to
)
945 // cleanup whatever was placed in "renameto"
948 t
.Errorf("rename %q, %q: expected %T, got %T %v", from
, to
, new(LinkError
), err
, err
)
952 func TestRenameNotExisting(t
*testing
.T
) {
954 from
, to
:= "doesnt-exist", "dest"
959 if err
:= Rename(from
, to
); !IsNotExist(err
) {
960 t
.Errorf("Rename(%q, %q) = %v; want an IsNotExist error", from
, to
, err
)
964 func TestRenameToDirFailed(t
*testing
.T
) {
966 from
, to
:= "renamefrom", "renameto"
975 err
:= Rename(from
, to
)
976 switch err
:= err
.(type) {
978 if err
.Op
!= "rename" {
979 t
.Errorf("rename %q, %q: err.Op: want %q, got %q", from
, to
, "rename", err
.Op
)
982 t
.Errorf("rename %q, %q: err.Old: want %q, got %q", from
, to
, from
, err
.Old
)
985 t
.Errorf("rename %q, %q: err.New: want %q, got %q", from
, to
, to
, err
.New
)
988 t
.Errorf("rename %q, %q: expected error, got nil", from
, to
)
990 // cleanup whatever was placed in "renameto"
993 t
.Errorf("rename %q, %q: expected %T, got %T %v", from
, to
, new(LinkError
), err
, err
)
997 func exec(t
*testing
.T
, dir
, cmd
string, args
[]string, expect
string) {
1000 t
.Fatalf("Pipe: %v", err
)
1003 attr
:= &ProcAttr
{Dir
: dir
, Files
: []*File
{nil, w
, Stderr
}}
1004 p
, err
:= StartProcess(cmd
, args
, attr
)
1006 t
.Fatalf("StartProcess: %v", err
)
1012 output
:= b
.String()
1014 fi1
, _
:= Stat(strings
.TrimSpace(output
))
1015 fi2
, _
:= Stat(expect
)
1016 if !SameFile(fi1
, fi2
) {
1017 t
.Errorf("exec %q returned %q wanted %q",
1018 strings
.Join(append([]string{cmd
}, args
...), " "), output
, expect
)
1023 func TestStartProcess(t
*testing
.T
) {
1024 testenv
.MustHaveExec(t
)
1028 switch runtime
.GOOS
{
1030 t
.Skip("android doesn't have /bin/pwd")
1032 cmd
= Getenv("COMSPEC")
1033 dir
= Getenv("SystemRoot")
1034 args
= []string{"/c", "cd"}
1037 cmd
, err
= osexec
.LookPath("pwd")
1039 t
.Fatalf("Can't find pwd: %v", err
)
1043 t
.Logf("Testing with %v", cmd
)
1045 cmddir
, cmdbase
:= filepath
.Split(cmd
)
1046 args
= append([]string{cmdbase
}, args
...)
1047 // Test absolute executable path.
1048 exec(t
, dir
, cmd
, args
, dir
)
1049 // Test relative executable path.
1050 exec(t
, cmddir
, cmdbase
, args
, cmddir
)
1053 func checkMode(t
*testing
.T
, path
string, mode FileMode
) {
1054 dir
, err
:= Stat(path
)
1056 t
.Fatalf("Stat %q (looking for mode %#o): %s", path
, mode
, err
)
1058 if dir
.Mode()&0777 != mode
{
1059 t
.Errorf("Stat %q: mode %#o want %#o", path
, dir
.Mode(), mode
)
1063 func TestChmod(t
*testing
.T
) {
1064 // Chmod is not supported under windows.
1065 if runtime
.GOOS
== "windows" {
1068 f
:= newFile("TestChmod", t
)
1069 defer Remove(f
.Name())
1072 if err
:= Chmod(f
.Name(), 0456); err
!= nil {
1073 t
.Fatalf("chmod %s 0456: %s", f
.Name(), err
)
1075 checkMode(t
, f
.Name(), 0456)
1077 if err
:= f
.Chmod(0123); err
!= nil {
1078 t
.Fatalf("chmod %s 0123: %s", f
.Name(), err
)
1080 checkMode(t
, f
.Name(), 0123)
1083 func checkSize(t
*testing
.T
, f
*File
, size
int64) {
1084 dir
, err
:= f
.Stat()
1086 t
.Fatalf("Stat %q (looking for size %d): %s", f
.Name(), size
, err
)
1088 if dir
.Size() != size
{
1089 t
.Errorf("Stat %q: size %d want %d", f
.Name(), dir
.Size(), size
)
1093 func TestFTruncate(t
*testing
.T
) {
1094 f
:= newFile("TestFTruncate", t
)
1095 defer Remove(f
.Name())
1099 f
.Write([]byte("hello, world\n"))
1104 checkSize(t
, f
, 1024)
1107 _
, err
:= f
.Write([]byte("surprise!"))
1109 checkSize(t
, f
, 13+9) // wrote at offset past where hello, world was.
1113 func TestTruncate(t
*testing
.T
) {
1114 f
:= newFile("TestTruncate", t
)
1115 defer Remove(f
.Name())
1119 f
.Write([]byte("hello, world\n"))
1121 Truncate(f
.Name(), 10)
1123 Truncate(f
.Name(), 1024)
1124 checkSize(t
, f
, 1024)
1125 Truncate(f
.Name(), 0)
1127 _
, err
:= f
.Write([]byte("surprise!"))
1129 checkSize(t
, f
, 13+9) // wrote at offset past where hello, world was.
1133 // Use TempDir (via newFile) to make sure we're on a local file system,
1134 // so that timings are not distorted by latency and caching.
1135 // On NFS, timings can be off due to caching of meta-data on
1136 // NFS servers (Issue 848).
1137 func TestChtimes(t
*testing
.T
) {
1138 f
:= newFile("TestChtimes", t
)
1139 defer Remove(f
.Name())
1141 f
.Write([]byte("hello, world\n"))
1144 testChtimes(t
, f
.Name())
1147 // Use TempDir (via newDir) to make sure we're on a local file system,
1148 // so that timings are not distorted by latency and caching.
1149 // On NFS, timings can be off due to caching of meta-data on
1150 // NFS servers (Issue 848).
1151 func TestChtimesDir(t
*testing
.T
) {
1152 name
:= newDir("TestChtimes", t
)
1153 defer RemoveAll(name
)
1155 testChtimes(t
, name
)
1158 func testChtimes(t
*testing
.T
, name
string) {
1159 st
, err
:= Stat(name
)
1161 t
.Fatalf("Stat %s: %s", name
, err
)
1165 // Move access and modification time back a second
1166 at
:= Atime(preStat
)
1167 mt
:= preStat
.ModTime()
1168 err
= Chtimes(name
, at
.Add(-time
.Second
), mt
.Add(-time
.Second
))
1170 t
.Fatalf("Chtimes %s: %s", name
, err
)
1173 st
, err
= Stat(name
)
1175 t
.Fatalf("second Stat %s: %s", name
, err
)
1179 pat
:= Atime(postStat
)
1180 pmt
:= postStat
.ModTime()
1181 if !pat
.Before(at
) {
1182 switch runtime
.GOOS
{
1183 case "plan9", "nacl":
1186 // Mtime is the time of the last change of
1187 // content. Similarly, atime is set whenever
1188 // the contents are accessed; also, it is set
1189 // whenever mtime is set.
1191 mounts
, _
:= ioutil
.ReadFile("/proc/mounts")
1192 if strings
.Contains(string(mounts
), "noatime") {
1193 t
.Logf("AccessTime didn't go backwards, but see a filesystem mounted noatime; ignoring. Issue 19293.")
1195 t
.Logf("AccessTime didn't go backwards; was=%v, after=%v (Ignoring on NetBSD, assuming noatime, Issue 19293)", at
, pat
)
1198 t
.Errorf("AccessTime didn't go backwards; was=%v, after=%v", at
, pat
)
1202 if !pmt
.Before(mt
) {
1203 t
.Errorf("ModTime didn't go backwards; was=%v, after=%v", mt
, pmt
)
1207 func TestChdirAndGetwd(t
*testing
.T
) {
1208 // TODO(brainman): file.Chdir() is not implemented on windows.
1209 if runtime
.GOOS
== "windows" {
1212 fd
, err
:= Open(".")
1214 t
.Fatalf("Open .: %s", err
)
1216 // These are chosen carefully not to be symlinks on a Mac
1217 // (unlike, say, /var, /etc), except /tmp, which we handle below.
1218 dirs
:= []string{"/", "/usr/bin", "/tmp"}
1219 // /usr/bin does not usually exist on Plan 9 or Android.
1220 switch runtime
.GOOS
{
1222 dirs
= []string{"/", "/system/bin"}
1224 dirs
= []string{"/", "/usr"}
1226 switch runtime
.GOARCH
{
1227 case "arm", "arm64":
1228 d1
, err
:= ioutil
.TempDir("", "d1")
1230 t
.Fatalf("TempDir: %v", err
)
1232 d2
, err
:= ioutil
.TempDir("", "d2")
1234 t
.Fatalf("TempDir: %v", err
)
1236 dirs
= []string{d1
, d2
}
1239 oldwd
:= Getenv("PWD")
1240 for mode
:= 0; mode
< 2; mode
++ {
1241 for _
, d
:= range dirs
{
1245 fd1
, err1
:= Open(d
)
1247 t
.Errorf("Open %s: %s", d
, err1
)
1254 Setenv("PWD", "/tmp")
1256 pwd
, err1
:= Getwd()
1257 Setenv("PWD", oldwd
)
1260 // We changed the current directory and cannot go back.
1261 // Don't let the tests continue; they'll scribble
1262 // all over some other directory.
1263 fmt
.Fprintf(Stderr
, "fchdir back to dot failed: %s\n", err2
)
1268 t
.Fatalf("Chdir %s: %s", d
, err
)
1272 t
.Fatalf("Getwd in %s: %s", d
, err1
)
1276 t
.Fatalf("Getwd returned %q want %q", pwd
, d
)
1283 // Test that Chdir+Getwd is program-wide.
1284 func TestProgWideChdir(t
*testing
.T
) {
1286 c
:= make(chan bool)
1287 cpwd
:= make(chan string)
1288 for i
:= 0; i
< N
; i
++ {
1290 // Lock half the goroutines in their own operating system
1291 // thread to exercise more scheduler possibilities.
1293 // On Plan 9, after calling LockOSThread, the goroutines
1294 // run on different processes which don't share the working
1295 // directory. This used to be an issue because Go expects
1296 // the working directory to be program-wide.
1298 runtime
.LockOSThread()
1303 t
.Errorf("Getwd on goroutine %d: %v", i
, err
)
1309 oldwd
, err
:= Getwd()
1311 t
.Fatalf("Getwd: %v", err
)
1313 d
, err
:= ioutil
.TempDir("", "test")
1315 t
.Fatalf("TempDir: %v", err
)
1318 if err
:= Chdir(oldwd
); err
!= nil {
1319 t
.Fatalf("Chdir: %v", err
)
1323 if err
:= Chdir(d
); err
!= nil {
1324 t
.Fatalf("Chdir: %v", err
)
1326 // OS X sets TMPDIR to a symbolic link.
1327 // So we resolve our working directory again before the test.
1330 t
.Fatalf("Getwd: %v", err
)
1333 for i
:= 0; i
< N
; i
++ {
1336 t
.Errorf("Getwd returned %q; want %q", pwd
, d
)
1341 func TestSeek(t
*testing
.T
) {
1342 f
:= newFile("TestSeek", t
)
1343 defer Remove(f
.Name())
1346 const data
= "hello, world\n"
1347 io
.WriteString(f
, data
)
1355 {0, io
.SeekCurrent
, int64(len(data
))},
1356 {0, io
.SeekStart
, 0},
1357 {5, io
.SeekStart
, 5},
1358 {0, io
.SeekEnd
, int64(len(data
))},
1359 {0, io
.SeekStart
, 0},
1360 {-1, io
.SeekEnd
, int64(len(data
)) - 1},
1361 {1 << 33, io
.SeekStart
, 1 << 33},
1362 {1 << 33, io
.SeekEnd
, 1<<33 + int64(len(data
))},
1364 // Issue 21681, Windows 4G-1, etc:
1365 {1<<32 - 1, io
.SeekStart
, 1<<32 - 1},
1366 {0, io
.SeekCurrent
, 1<<32 - 1},
1367 {2<<32 - 1, io
.SeekStart
, 2<<32 - 1},
1368 {0, io
.SeekCurrent
, 2<<32 - 1},
1370 for i
, tt
:= range tests
{
1371 if runtime
.GOOS
== "nacl" && tt
.out
> 1<<30 {
1372 t
.Logf("skipping test case #%d on nacl; https://golang.org/issue/21728", i
)
1375 off
, err
:= f
.Seek(tt
.in
, tt
.whence
)
1376 if off
!= tt
.out || err
!= nil {
1377 if e
, ok
:= err
.(*PathError
); ok
&& e
.Err
== syscall
.EINVAL
&& tt
.out
> 1<<32 && runtime
.GOOS
== "linux" {
1378 mounts
, _
:= ioutil
.ReadFile("/proc/mounts")
1379 if strings
.Contains(string(mounts
), "reiserfs") {
1380 // Reiserfs rejects the big seeks.
1381 t
.Skipf("skipping test known to fail on reiserfs; https://golang.org/issue/91")
1384 t
.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i
, tt
.in
, tt
.whence
, off
, err
, tt
.out
)
1389 func TestSeekError(t
*testing
.T
) {
1390 switch runtime
.GOOS
{
1391 case "js", "nacl", "plan9":
1392 t
.Skipf("skipping test on %v", runtime
.GOOS
)
1399 _
, err
= r
.Seek(0, 0)
1401 t
.Fatal("Seek on pipe should fail")
1403 if perr
, ok
:= err
.(*PathError
); !ok || perr
.Err
!= syscall
.ESPIPE
{
1404 t
.Errorf("Seek returned error %v, want &PathError{Err: syscall.ESPIPE}", err
)
1406 _
, err
= w
.Seek(0, 0)
1408 t
.Fatal("Seek on pipe should fail")
1410 if perr
, ok
:= err
.(*PathError
); !ok || perr
.Err
!= syscall
.ESPIPE
{
1411 t
.Errorf("Seek returned error %v, want &PathError{Err: syscall.ESPIPE}", err
)
1415 type openErrorTest
struct {
1421 var openErrorTests
= []openErrorTest
{
1423 sfdir
+ "/no-such-file",
1433 sfdir
+ "/" + sfname
+ "/no-such-file",
1439 func TestOpenError(t
*testing
.T
) {
1440 for _
, tt
:= range openErrorTests
{
1441 f
, err
:= OpenFile(tt
.path
, tt
.mode
, 0)
1443 t
.Errorf("Open(%q, %d) succeeded", tt
.path
, tt
.mode
)
1447 perr
, ok
:= err
.(*PathError
)
1449 t
.Errorf("Open(%q, %d) returns error of %T type; want *PathError", tt
.path
, tt
.mode
, err
)
1451 if perr
.Err
!= tt
.error
{
1452 if runtime
.GOOS
== "plan9" {
1453 syscallErrStr
:= perr
.Err
.Error()
1454 expectedErrStr
:= strings
.Replace(tt
.error
.Error(), "file ", "", 1)
1455 if !strings
.HasSuffix(syscallErrStr
, expectedErrStr
) {
1456 // Some Plan 9 file servers incorrectly return
1457 // EACCES rather than EISDIR when a directory is
1458 // opened for write.
1459 if tt
.error
== syscall
.EISDIR
&& strings
.HasSuffix(syscallErrStr
, syscall
.EACCES
.Error()) {
1462 t
.Errorf("Open(%q, %d) = _, %q; want suffix %q", tt
.path
, tt
.mode
, syscallErrStr
, expectedErrStr
)
1466 if runtime
.GOOS
== "dragonfly" {
1467 // DragonFly incorrectly returns EACCES rather
1468 // EISDIR when a directory is opened for write.
1469 if tt
.error
== syscall
.EISDIR
&& perr
.Err
== syscall
.EACCES
{
1473 t
.Errorf("Open(%q, %d) = _, %q; want %q", tt
.path
, tt
.mode
, perr
.Err
.Error(), tt
.error
.Error())
1478 func TestOpenNoName(t
*testing
.T
) {
1481 t
.Fatal(`Open("") succeeded`)
1486 func runBinHostname(t
*testing
.T
, argv
[]string) string {
1487 // Run /bin/hostname and collect output.
1493 const path
= "/bin/hostname"
1494 p
, err
:= StartProcess(path
, argv
, &ProcAttr
{Files
: []*File
{nil, w
, Stderr
}})
1496 if _
, err
:= Stat(path
); IsNotExist(err
) {
1497 t
.Skipf("skipping test; test requires %s but it does not exist", path
)
1507 t
.Fatalf("run hostname Wait: %v", err
)
1511 t
.Errorf("expected an error from Kill running 'hostname'")
1513 output
:= b
.String()
1514 if n
:= len(output
); n
> 0 && output
[n
-1] == '\n' {
1515 output
= output
[0 : n
-1]
1518 t
.Fatalf("/bin/hostname produced no output")
1524 func testWindowsHostname(t
*testing
.T
, hostname
string) {
1525 cmd
:= osexec
.Command("hostname")
1526 out
, err
:= cmd
.CombinedOutput()
1528 t
.Fatalf("Failed to execute hostname command: %v %s", err
, out
)
1530 want
:= strings
.Trim(string(out
), "\r\n")
1531 if hostname
!= want
{
1532 t
.Fatalf("Hostname() = %q != system hostname of %q", hostname
, want
)
1536 func TestHostname(t
*testing
.T
) {
1537 hostname
, err
:= Hostname()
1542 t
.Fatal("Hostname returned empty string and no error")
1544 if strings
.Contains(hostname
, "\x00") {
1545 t
.Fatalf("unexpected zero byte in hostname: %q", hostname
)
1548 // There is no other way to fetch hostname on windows, but via winapi.
1549 // On Plan 9 it can be taken from #c/sysname as Hostname() does.
1550 switch runtime
.GOOS
{
1551 case "android", "plan9":
1552 // No /bin/hostname to verify against.
1555 testWindowsHostname(t
, hostname
)
1559 testenv
.MustHaveExec(t
)
1561 // Check internal Hostname() against the output of /bin/hostname.
1562 // Allow that the internal Hostname returns a Fully Qualified Domain Name
1563 // and the /bin/hostname only returns the first component
1565 if runtime
.GOOS
== "aix" {
1566 want
= runBinHostname(t
, []string{"hostname", "-s"})
1568 want
= runBinHostname(t
, []string{"hostname"})
1570 if hostname
!= want
{
1571 i
:= strings
.Index(hostname
, ".")
1572 if i
< 0 || hostname
[0:i
] != want
{
1573 t
.Errorf("Hostname() = %q, want %q", hostname
, want
)
1578 func TestReadAt(t
*testing
.T
) {
1579 f
:= newFile("TestReadAt", t
)
1580 defer Remove(f
.Name())
1583 const data
= "hello, world\n"
1584 io
.WriteString(f
, data
)
1586 b
:= make([]byte, 5)
1587 n
, err
:= f
.ReadAt(b
, 7)
1588 if err
!= nil || n
!= len(b
) {
1589 t
.Fatalf("ReadAt 7: %d, %v", n
, err
)
1591 if string(b
) != "world" {
1592 t
.Fatalf("ReadAt 7: have %q want %q", string(b
), "world")
1596 // Verify that ReadAt doesn't affect seek offset.
1597 // In the Plan 9 kernel, there used to be a bug in the implementation of
1598 // the pread syscall, where the channel offset was erroneously updated after
1599 // calling pread on a file.
1600 func TestReadAtOffset(t
*testing
.T
) {
1601 f
:= newFile("TestReadAtOffset", t
)
1602 defer Remove(f
.Name())
1605 const data
= "hello, world\n"
1606 io
.WriteString(f
, data
)
1609 b
:= make([]byte, 5)
1611 n
, err
:= f
.ReadAt(b
, 7)
1612 if err
!= nil || n
!= len(b
) {
1613 t
.Fatalf("ReadAt 7: %d, %v", n
, err
)
1615 if string(b
) != "world" {
1616 t
.Fatalf("ReadAt 7: have %q want %q", string(b
), "world")
1620 if err
!= nil || n
!= len(b
) {
1621 t
.Fatalf("Read: %d, %v", n
, err
)
1623 if string(b
) != "hello" {
1624 t
.Fatalf("Read: have %q want %q", string(b
), "hello")
1628 // Verify that ReadAt doesn't allow negative offset.
1629 func TestReadAtNegativeOffset(t
*testing
.T
) {
1630 f
:= newFile("TestReadAtNegativeOffset", t
)
1631 defer Remove(f
.Name())
1634 const data
= "hello, world\n"
1635 io
.WriteString(f
, data
)
1638 b
:= make([]byte, 5)
1640 n
, err
:= f
.ReadAt(b
, -10)
1642 const wantsub
= "negative offset"
1643 if !strings
.Contains(fmt
.Sprint(err
), wantsub
) || n
!= 0 {
1644 t
.Errorf("ReadAt(-10) = %v, %v; want 0, ...%q...", n
, err
, wantsub
)
1648 func TestWriteAt(t
*testing
.T
) {
1649 f
:= newFile("TestWriteAt", t
)
1650 defer Remove(f
.Name())
1653 const data
= "hello, world\n"
1654 io
.WriteString(f
, data
)
1656 n
, err
:= f
.WriteAt([]byte("WORLD"), 7)
1657 if err
!= nil || n
!= 5 {
1658 t
.Fatalf("WriteAt 7: %d, %v", n
, err
)
1661 b
, err
:= ioutil
.ReadFile(f
.Name())
1663 t
.Fatalf("ReadFile %s: %v", f
.Name(), err
)
1665 if string(b
) != "hello, WORLD\n" {
1666 t
.Fatalf("after write: have %q want %q", string(b
), "hello, WORLD\n")
1670 // Verify that WriteAt doesn't allow negative offset.
1671 func TestWriteAtNegativeOffset(t
*testing
.T
) {
1672 f
:= newFile("TestWriteAtNegativeOffset", t
)
1673 defer Remove(f
.Name())
1676 n
, err
:= f
.WriteAt([]byte("WORLD"), -10)
1678 const wantsub
= "negative offset"
1679 if !strings
.Contains(fmt
.Sprint(err
), wantsub
) || n
!= 0 {
1680 t
.Errorf("WriteAt(-10) = %v, %v; want 0, ...%q...", n
, err
, wantsub
)
1684 func writeFile(t
*testing
.T
, fname
string, flag
int, text
string) string {
1685 f
, err
:= OpenFile(fname
, flag
, 0666)
1687 t
.Fatalf("Open: %v", err
)
1689 n
, err
:= io
.WriteString(f
, text
)
1691 t
.Fatalf("WriteString: %d, %v", n
, err
)
1694 data
, err
:= ioutil
.ReadFile(fname
)
1696 t
.Fatalf("ReadFile: %v", err
)
1701 func TestAppend(t
*testing
.T
) {
1703 const f
= "append.txt"
1705 s
:= writeFile(t
, f
, O_CREATE|O_TRUNC|O_RDWR
, "new")
1707 t
.Fatalf("writeFile: have %q want %q", s
, "new")
1709 s
= writeFile(t
, f
, O_APPEND|O_RDWR
, "|append")
1710 if s
!= "new|append" {
1711 t
.Fatalf("writeFile: have %q want %q", s
, "new|append")
1713 s
= writeFile(t
, f
, O_CREATE|O_APPEND|O_RDWR
, "|append")
1714 if s
!= "new|append|append" {
1715 t
.Fatalf("writeFile: have %q want %q", s
, "new|append|append")
1719 t
.Fatalf("Remove: %v", err
)
1721 s
= writeFile(t
, f
, O_CREATE|O_APPEND|O_RDWR
, "new&append")
1722 if s
!= "new&append" {
1723 t
.Fatalf("writeFile: after append have %q want %q", s
, "new&append")
1725 s
= writeFile(t
, f
, O_CREATE|O_RDWR
, "old")
1726 if s
!= "old&append" {
1727 t
.Fatalf("writeFile: after create have %q want %q", s
, "old&append")
1729 s
= writeFile(t
, f
, O_CREATE|O_TRUNC|O_RDWR
, "new")
1731 t
.Fatalf("writeFile: after truncate have %q want %q", s
, "new")
1735 func TestStatDirWithTrailingSlash(t
*testing
.T
) {
1736 // Create new temporary directory and arrange to clean it up.
1737 path
, err
:= ioutil
.TempDir("", "/_TestStatDirWithSlash_")
1739 t
.Fatalf("TempDir: %s", err
)
1741 defer RemoveAll(path
)
1743 // Stat of path should succeed.
1746 t
.Fatalf("stat %s failed: %s", path
, err
)
1749 // Stat of path+"/" should succeed too.
1753 t
.Fatalf("stat %s failed: %s", path
, err
)
1757 func TestNilProcessStateString(t
*testing
.T
) {
1758 var ps
*ProcessState
1761 t
.Errorf("(*ProcessState)(nil).String() = %q, want %q", s
, "<nil>")
1765 func TestSameFile(t
*testing
.T
) {
1767 fa
, err
:= Create("a")
1769 t
.Fatalf("Create(a): %v", err
)
1771 defer Remove(fa
.Name())
1773 fb
, err
:= Create("b")
1775 t
.Fatalf("Create(b): %v", err
)
1777 defer Remove(fb
.Name())
1780 ia1
, err
:= Stat("a")
1782 t
.Fatalf("Stat(a): %v", err
)
1784 ia2
, err
:= Stat("a")
1786 t
.Fatalf("Stat(a): %v", err
)
1788 if !SameFile(ia1
, ia2
) {
1789 t
.Errorf("files should be same")
1792 ib
, err
:= Stat("b")
1794 t
.Fatalf("Stat(b): %v", err
)
1796 if SameFile(ia1
, ib
) {
1797 t
.Errorf("files should be different")
1801 func testDevNullFileInfo(t
*testing
.T
, statname
, devNullName
string, fi FileInfo
, ignoreCase
bool) {
1802 pre
:= fmt
.Sprintf("%s(%q): ", statname
, devNullName
)
1803 name
:= filepath
.Base(devNullName
)
1805 if strings
.ToUpper(fi
.Name()) != strings
.ToUpper(name
) {
1806 t
.Errorf(pre
+"wrong file name have %v want %v", fi
.Name(), name
)
1809 if fi
.Name() != name
{
1810 t
.Errorf(pre
+"wrong file name have %v want %v", fi
.Name(), name
)
1814 t
.Errorf(pre
+"wrong file size have %d want 0", fi
.Size())
1816 if fi
.Mode()&ModeDevice
== 0 {
1817 t
.Errorf(pre
+"wrong file mode %q: ModeDevice is not set", fi
.Mode())
1819 if fi
.Mode()&ModeCharDevice
== 0 {
1820 t
.Errorf(pre
+"wrong file mode %q: ModeCharDevice is not set", fi
.Mode())
1822 if fi
.Mode().IsRegular() {
1823 t
.Errorf(pre
+"wrong file mode %q: IsRegular returns true", fi
.Mode())
1827 func testDevNullFile(t
*testing
.T
, devNullName
string, ignoreCase
bool) {
1828 f
, err
:= Open(devNullName
)
1830 t
.Fatalf("Open(%s): %v", devNullName
, err
)
1836 t
.Fatalf("Stat(%s): %v", devNullName
, err
)
1838 testDevNullFileInfo(t
, "f.Stat", devNullName
, fi
, ignoreCase
)
1840 fi
, err
= Stat(devNullName
)
1842 t
.Fatalf("Stat(%s): %v", devNullName
, err
)
1844 testDevNullFileInfo(t
, "Stat", devNullName
, fi
, ignoreCase
)
1847 func TestDevNullFile(t
*testing
.T
) {
1848 testDevNullFile(t
, DevNull
, false)
1851 var testLargeWrite
= flag
.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output")
1853 func TestLargeWriteToConsole(t
*testing
.T
) {
1854 if !*testLargeWrite
{
1855 t
.Skip("skipping console-flooding test; enable with -large_write")
1857 b
:= make([]byte, 32000)
1862 n
, err
:= Stdout
.Write(b
)
1864 t
.Fatalf("Write to os.Stdout failed: %v", err
)
1867 t
.Errorf("Write to os.Stdout should return %d; got %d", len(b
), n
)
1869 n
, err
= Stderr
.Write(b
)
1871 t
.Fatalf("Write to os.Stderr failed: %v", err
)
1874 t
.Errorf("Write to os.Stderr should return %d; got %d", len(b
), n
)
1878 func TestStatDirModeExec(t
*testing
.T
) {
1881 path
, err
:= ioutil
.TempDir("", "go-build")
1883 t
.Fatalf("Failed to create temp directory: %v", err
)
1885 defer RemoveAll(path
)
1887 if err
:= Chmod(path
, 0777); err
!= nil {
1888 t
.Fatalf("Chmod %q 0777: %v", path
, err
)
1891 dir
, err
:= Stat(path
)
1893 t
.Fatalf("Stat %q (looking for mode %#o): %s", path
, mode
, err
)
1895 if dir
.Mode()&mode
!= mode
{
1896 t
.Errorf("Stat %q: mode %#o want %#o", path
, dir
.Mode()&mode
, mode
)
1900 func TestStatStdin(t
*testing
.T
) {
1901 switch runtime
.GOOS
{
1902 case "android", "plan9":
1903 t
.Skipf("%s doesn't have /bin/sh", runtime
.GOOS
)
1906 testenv
.MustHaveExec(t
)
1908 if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
1909 st
, err
:= Stdin
.Stat()
1911 t
.Fatalf("Stat failed: %v", err
)
1913 fmt
.Println(st
.Mode() & ModeNamedPipe
)
1917 fi
, err
:= Stdin
.Stat()
1921 switch mode
:= fi
.Mode(); {
1922 case mode
&ModeCharDevice
!= 0 && mode
&ModeDevice
!= 0:
1923 case mode
&ModeNamedPipe
!= 0:
1925 t
.Fatalf("unexpected Stdin mode (%v), want ModeCharDevice or ModeNamedPipe", mode
)
1929 if runtime
.GOOS
== "windows" {
1930 cmd
= osexec
.Command("cmd", "/c", "echo output | "+Args
[0]+" -test.run=TestStatStdin")
1932 cmd
= osexec
.Command("/bin/sh", "-c", "echo output | "+Args
[0]+" -test.run=TestStatStdin")
1934 cmd
.Env
= append(Environ(), "GO_WANT_HELPER_PROCESS=1")
1936 output
, err
:= cmd
.CombinedOutput()
1938 t
.Fatalf("Failed to spawn child process: %v %q", err
, string(output
))
1941 // result will be like "prw-rw-rw"
1942 if len(output
) < 1 || output
[0] != 'p' {
1943 t
.Fatalf("Child process reports stdin is not pipe '%v'", string(output
))
1947 func TestStatRelativeSymlink(t
*testing
.T
) {
1948 testenv
.MustHaveSymlink(t
)
1950 tmpdir
, err
:= ioutil
.TempDir("", "TestStatRelativeSymlink")
1954 defer RemoveAll(tmpdir
)
1956 target
:= filepath
.Join(tmpdir
, "target")
1957 f
, err
:= Create(target
)
1968 link
:= filepath
.Join(tmpdir
, "link")
1969 err
= Symlink(filepath
.Base(target
), link
)
1974 st1
, err
:= Stat(link
)
1979 if !SameFile(st
, st1
) {
1980 t
.Error("Stat doesn't follow relative symlink")
1983 if runtime
.GOOS
== "windows" {
1985 err
= Symlink(target
[len(filepath
.VolumeName(target
)):], link
)
1990 st1
, err
:= Stat(link
)
1995 if !SameFile(st
, st1
) {
1996 t
.Error("Stat doesn't follow relative symlink")
2001 func TestReadAtEOF(t
*testing
.T
) {
2002 f
:= newFile("TestReadAtEOF", t
)
2003 defer Remove(f
.Name())
2006 _
, err
:= f
.ReadAt(make([]byte, 10), 0)
2011 t
.Fatalf("ReadAt succeeded")
2013 t
.Fatalf("ReadAt failed: %s", err
)
2017 func TestLongPath(t
*testing
.T
) {
2018 tmpdir
:= newDir("TestLongPath", t
)
2019 defer func(d
string) {
2020 if err
:= RemoveAll(d
); err
!= nil {
2021 t
.Fatalf("RemoveAll failed: %v", err
)
2025 // Test the boundary of 247 and fewer bytes (normal) and 248 and more bytes (adjusted).
2026 sizes
:= []int{247, 248, 249, 400}
2027 for len(tmpdir
) < 400 {
2028 tmpdir
+= "/dir3456789"
2030 for _
, sz
:= range sizes
{
2031 t
.Run(fmt
.Sprintf("length=%d", sz
), func(t
*testing
.T
) {
2032 sizedTempDir
:= tmpdir
[:sz
-1] + "x" // Ensure it does not end with a slash.
2034 // The various sized runs are for this call to trigger the boundary
2036 if err
:= MkdirAll(sizedTempDir
, 0755); err
!= nil {
2037 t
.Fatalf("MkdirAll failed: %v", err
)
2039 data
:= []byte("hello world\n")
2040 if err
:= ioutil
.WriteFile(sizedTempDir
+"/foo.txt", data
, 0644); err
!= nil {
2041 t
.Fatalf("ioutil.WriteFile() failed: %v", err
)
2043 if err
:= Rename(sizedTempDir
+"/foo.txt", sizedTempDir
+"/bar.txt"); err
!= nil {
2044 t
.Fatalf("Rename failed: %v", err
)
2046 mtime
:= time
.Now().Truncate(time
.Minute
)
2047 if err
:= Chtimes(sizedTempDir
+"/bar.txt", mtime
, mtime
); err
!= nil {
2048 t
.Fatalf("Chtimes failed: %v", err
)
2050 names
:= []string{"bar.txt"}
2051 if testenv
.HasSymlink() {
2052 if err
:= Symlink(sizedTempDir
+"/bar.txt", sizedTempDir
+"/symlink.txt"); err
!= nil {
2053 t
.Fatalf("Symlink failed: %v", err
)
2055 names
= append(names
, "symlink.txt")
2057 if testenv
.HasLink() {
2058 if err
:= Link(sizedTempDir
+"/bar.txt", sizedTempDir
+"/link.txt"); err
!= nil {
2059 t
.Fatalf("Link failed: %v", err
)
2061 names
= append(names
, "link.txt")
2063 for _
, wantSize
:= range []int64{int64(len(data
)), 0} {
2064 for _
, name
:= range names
{
2065 path
:= sizedTempDir
+ "/" + name
2066 dir
, err
:= Stat(path
)
2068 t
.Fatalf("Stat(%q) failed: %v", path
, err
)
2070 filesize
:= size(path
, t
)
2071 if dir
.Size() != filesize || filesize
!= wantSize
{
2072 t
.Errorf("Size(%q) is %d, len(ReadFile()) is %d, want %d", path
, dir
.Size(), filesize
, wantSize
)
2074 err
= Chmod(path
, dir
.Mode())
2076 t
.Fatalf("Chmod(%q) failed: %v", path
, err
)
2079 if err
:= Truncate(sizedTempDir
+"/bar.txt", 0); err
!= nil {
2080 t
.Fatalf("Truncate failed: %v", err
)
2087 func testKillProcess(t
*testing
.T
, processKiller
func(p
*Process
)) {
2088 testenv
.MustHaveExec(t
)
2090 // Re-exec the test binary itself to emulate "sleep 1".
2091 cmd
:= osexec
.Command(Args
[0], "-test.run", "TestSleep")
2094 t
.Fatalf("Failed to start test process: %v", err
)
2097 time
.Sleep(100 * time
.Millisecond
)
2098 processKiller(cmd
.Process
)
2102 t
.Errorf("Test process succeeded, but expected to fail")
2106 // TestSleep emulates "sleep 1". It is a helper for testKillProcess, so we
2107 // don't have to rely on an external "sleep" command being available.
2108 func TestSleep(t
*testing
.T
) {
2109 if testing
.Short() {
2110 t
.Skip("Skipping in short mode")
2112 time
.Sleep(time
.Second
)
2115 func TestKillStartProcess(t
*testing
.T
) {
2116 testKillProcess(t
, func(p
*Process
) {
2119 t
.Fatalf("Failed to kill test process: %v", err
)
2124 func TestGetppid(t
*testing
.T
) {
2125 if runtime
.GOOS
== "plan9" {
2126 // TODO: golang.org/issue/8206
2127 t
.Skipf("skipping test on plan9; see issue 8206")
2130 testenv
.MustHaveExec(t
)
2132 if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
2133 fmt
.Print(Getppid())
2137 cmd
:= osexec
.Command(Args
[0], "-test.run=TestGetppid")
2138 cmd
.Env
= append(Environ(), "GO_WANT_HELPER_PROCESS=1")
2140 // verify that Getppid() from the forked process reports our process id
2141 output
, err
:= cmd
.CombinedOutput()
2143 t
.Fatalf("Failed to spawn child process: %v %q", err
, string(output
))
2146 childPpid
:= string(output
)
2147 ourPid
:= fmt
.Sprintf("%d", Getpid())
2148 if childPpid
!= ourPid
{
2149 t
.Fatalf("Child process reports parent process id '%v', expected '%v'", childPpid
, ourPid
)
2153 func TestKillFindProcess(t
*testing
.T
) {
2154 testKillProcess(t
, func(p
*Process
) {
2155 p2
, err
:= FindProcess(p
.Pid
)
2157 t
.Fatalf("Failed to find test process: %v", err
)
2161 t
.Fatalf("Failed to kill test process: %v", err
)
2166 var nilFileMethodTests
= []struct {
2170 {"Chdir", func(f
*File
) error
{ return f
.Chdir() }},
2171 {"Close", func(f
*File
) error
{ return f
.Close() }},
2172 {"Chmod", func(f
*File
) error
{ return f
.Chmod(0) }},
2173 {"Chown", func(f
*File
) error
{ return f
.Chown(0, 0) }},
2174 {"Read", func(f
*File
) error
{ _
, err
:= f
.Read(make([]byte, 0)); return err
}},
2175 {"ReadAt", func(f
*File
) error
{ _
, err
:= f
.ReadAt(make([]byte, 0), 0); return err
}},
2176 {"Readdir", func(f
*File
) error
{ _
, err
:= f
.Readdir(1); return err
}},
2177 {"Readdirnames", func(f
*File
) error
{ _
, err
:= f
.Readdirnames(1); return err
}},
2178 {"Seek", func(f
*File
) error
{ _
, err
:= f
.Seek(0, io
.SeekStart
); return err
}},
2179 {"Stat", func(f
*File
) error
{ _
, err
:= f
.Stat(); return err
}},
2180 {"Sync", func(f
*File
) error
{ return f
.Sync() }},
2181 {"Truncate", func(f
*File
) error
{ return f
.Truncate(0) }},
2182 {"Write", func(f
*File
) error
{ _
, err
:= f
.Write(make([]byte, 0)); return err
}},
2183 {"WriteAt", func(f
*File
) error
{ _
, err
:= f
.WriteAt(make([]byte, 0), 0); return err
}},
2184 {"WriteString", func(f
*File
) error
{ _
, err
:= f
.WriteString(""); return err
}},
2187 // Test that all File methods give ErrInvalid if the receiver is nil.
2188 func TestNilFileMethods(t
*testing
.T
) {
2189 for _
, tt
:= range nilFileMethodTests
{
2192 if got
!= ErrInvalid
{
2193 t
.Errorf("%v should fail when f is nil; got %v", tt
.name
, got
)
2198 func mkdirTree(t
*testing
.T
, root
string, level
, max
int) {
2203 for i
:= 'a'; i
< 'c'; i
++ {
2204 dir
:= filepath
.Join(root
, string(i
))
2205 if err
:= Mkdir(dir
, 0700); err
!= nil {
2208 mkdirTree(t
, dir
, level
, max
)
2212 // Test that simultaneous RemoveAll do not report an error.
2213 // As long as it gets removed, we should be happy.
2214 func TestRemoveAllRace(t
*testing
.T
) {
2215 if runtime
.GOOS
== "windows" {
2216 // Windows has very strict rules about things like
2217 // removing directories while someone else has
2218 // them open. The racing doesn't work out nicely
2219 // like it does on Unix.
2220 t
.Skip("skipping on windows")
2223 n
:= runtime
.GOMAXPROCS(16)
2224 defer runtime
.GOMAXPROCS(n
)
2225 root
, err
:= ioutil
.TempDir("", "issue")
2229 mkdirTree(t
, root
, 1, 6)
2230 hold
:= make(chan struct{})
2231 var wg sync
.WaitGroup
2232 for i
:= 0; i
< 4; i
++ {
2237 err
:= RemoveAll(root
)
2239 t
.Errorf("unexpected error: %T, %q", err
, err
)
2243 close(hold
) // let workers race to remove root
2247 // Test that reading from a pipe doesn't use up a thread.
2248 func TestPipeThreads(t
*testing
.T
) {
2249 switch runtime
.GOOS
{
2251 t
.Skip("skipping on FreeBSD; issue 19093")
2253 t
.Skip("skipping on Solaris; issue 19111")
2255 t
.Skip("skipping on Windows; issue 19098")
2257 t
.Skip("skipping on Plan 9; does not support runtime poller")
2259 t
.Skip("skipping on js; no support for os.Pipe")
2264 // OpenBSD has a low default for max number of files.
2265 if runtime
.GOOS
== "openbsd" {
2269 r
:= make([]*File
, threads
)
2270 w
:= make([]*File
, threads
)
2271 for i
:= 0; i
< threads
; i
++ {
2272 rp
, wp
, err
:= Pipe()
2274 for j
:= 0; j
< i
; j
++ {
2284 defer debug
.SetMaxThreads(debug
.SetMaxThreads(threads
/ 2))
2286 creading
:= make(chan bool, threads
)
2287 cdone
:= make(chan bool, threads
)
2288 for i
:= 0; i
< threads
; i
++ {
2292 if _
, err
:= r
[i
].Read(b
[:]); err
!= nil {
2295 if err
:= r
[i
].Close(); err
!= nil {
2302 for i
:= 0; i
< threads
; i
++ {
2306 // If we are still alive, it means that the 100 goroutines did
2307 // not require 100 threads.
2309 for i
:= 0; i
< threads
; i
++ {
2310 if _
, err
:= w
[i
].Write([]byte{0}); err
!= nil {
2313 if err
:= w
[i
].Close(); err
!= nil {
2320 func TestDoubleCloseError(t
*testing
.T
) {
2321 path
:= sfdir
+ "/" + sfname
2322 file
, err
:= Open(path
)
2326 if err
:= file
.Close(); err
!= nil {
2327 t
.Fatalf("unexpected error from Close: %v", err
)
2329 if err
:= file
.Close(); err
== nil {
2330 t
.Error("second Close did not fail")
2331 } else if pe
, ok
:= err
.(*PathError
); !ok
{
2332 t
.Errorf("second Close returned unexpected error type %T; expected os.PathError", pe
)
2333 } else if pe
.Err
!= ErrClosed
{
2334 t
.Errorf("second Close returned %q, wanted %q", err
, ErrClosed
)
2336 t
.Logf("second close returned expected error %q", err
)