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",
68 for _
, f
:= range sd
.files
{
69 path
:= filepath
.Join(sd
.name
, f
)
70 if _
, err
:= Stat(path
); err
!= nil {
78 // In a self-hosted iOS build the above files might
79 // not exist. Look for system files instead below.
83 Getenv("SystemRoot") + "\\system32\\drivers\\etc",
109 func size(name
string, t
*testing
.T
) int64 {
110 file
, err
:= Open(name
)
112 t
.Fatal("open failed:", err
)
118 n
, e
:= file
.Read(buf
[0:])
124 t
.Fatal("read failed:", e
)
130 func equal(name1
, name2
string) (r
bool) {
131 switch runtime
.GOOS
{
133 r
= strings
.ToLower(name1
) == strings
.ToLower(name2
)
140 // localTmp returns a local temporary directory not on NFS.
141 func localTmp() string {
142 switch runtime
.GOOS
{
143 case "android", "windows":
146 switch runtime
.GOARCH
{
154 func newFile(testName
string, t
*testing
.T
) (f
*File
) {
155 f
, err
:= ioutil
.TempFile(localTmp(), "_Go_"+testName
)
157 t
.Fatalf("TempFile %s: %s", testName
, err
)
162 func newDir(testName
string, t
*testing
.T
) (name
string) {
163 name
, err
:= ioutil
.TempDir(localTmp(), "_Go_"+testName
)
165 t
.Fatalf("TempDir %s: %s", testName
, err
)
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
)
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
) {
191 path
:= "no-such-file"
193 fi
, err
:= Stat(path
)
195 t
.Fatal("got nil, want error")
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
)
207 err
= Symlink(path
, link
)
214 t
.Fatal("got nil, want error")
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
)
228 t
.Fatal("open failed:", err1
)
231 dir
, err2
:= file
.Stat()
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
)
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
264 t
.Fatal("open failed:", err
)
270 if n
!= 0 || err
!= nil {
271 t
.Errorf("Read(0) = %d, %v, want 0, nil", n
, err
)
273 b
= make([]byte, 100)
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
)
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
)
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
)
305 t
.Fatalf("open %q failed: %v", dir
, err
)
308 s
, err2
:= file
.Readdirnames(-1)
310 t
.Fatalf("readdirnames %q failed: %v", dir
, err2
)
312 for _
, m
:= range contents
{
314 for _
, n
:= range s
{
315 if n
== "." || n
== ".." {
316 t
.Errorf("got %s in directory", n
)
320 t
.Error("present twice:", m
)
326 t
.Error("could not find", m
)
331 func testReaddir(dir
string, contents
[]string, t
*testing
.T
) {
332 file
, err
:= Open(dir
)
334 t
.Fatalf("open %q failed: %v", dir
, err
)
337 s
, err2
:= file
.Readdir(-1)
339 t
.Fatalf("readdir %q failed: %v", dir
, err2
)
341 for _
, m
:= range contents
{
343 for _
, n
:= range s
{
344 if equal(m
, n
.Name()) {
346 t
.Error("present twice:", m
)
352 t
.Error("could not find", m
)
357 func TestReaddirnames(t
*testing
.T
) {
358 testReaddirnames(".", dot
, t
)
359 testReaddirnames(sysdir
.name
, sysdir
.files
, t
)
362 func TestReaddir(t
*testing
.T
) {
363 testReaddir(".", dot
, t
)
364 testReaddir(sysdir
.name
, sysdir
.files
, t
)
367 func benchmarkReaddirname(path
string, b
*testing
.B
) {
369 for i
:= 0; i
< b
.N
; i
++ {
372 b
.Fatalf("open %q failed: %v", path
, err
)
374 ns
, err
:= f
.Readdirnames(-1)
377 b
.Fatalf("readdirnames %q failed: %v", path
, err
)
381 b
.Logf("benchmarkReaddirname %q: %d entries", path
, nentries
)
384 func benchmarkReaddir(path
string, b
*testing
.B
) {
386 for i
:= 0; i
< b
.N
; i
++ {
389 b
.Fatalf("open %q failed: %v", path
, err
)
391 fs
, err
:= f
.Readdir(-1)
394 b
.Fatalf("readdir %q failed: %v", path
, err
)
398 b
.Logf("benchmarkReaddir %q: %d entries", path
, nentries
)
401 func BenchmarkReaddirname(b
*testing
.B
) {
402 benchmarkReaddirname(".", b
)
405 func BenchmarkReaddir(b
*testing
.B
) {
406 benchmarkReaddir(".", b
)
409 func benchmarkStat(b
*testing
.B
, path
string) {
411 for i
:= 0; i
< b
.N
; i
++ {
414 b
.Fatalf("Stat(%q) failed: %v", path
, err
)
419 func benchmarkLstat(b
*testing
.B
, path
string) {
421 for i
:= 0; i
< b
.N
; i
++ {
422 _
, err
:= Lstat(path
)
424 b
.Fatalf("Lstat(%q) failed: %v", path
, err
)
429 func BenchmarkStatDot(b
*testing
.B
) {
430 benchmarkStat(b
, ".")
433 func BenchmarkStatFile(b
*testing
.B
) {
434 benchmarkStat(b
, filepath
.Join(runtime
.GOROOT(), "src/os/os_test.go"))
437 func BenchmarkStatDir(b
*testing
.B
) {
438 benchmarkStat(b
, filepath
.Join(runtime
.GOROOT(), "src/os"))
441 func BenchmarkLstatDot(b
*testing
.B
) {
442 benchmarkLstat(b
, ".")
445 func BenchmarkLstatFile(b
*testing
.B
) {
446 benchmarkLstat(b
, filepath
.Join(runtime
.GOROOT(), "src/os/os_test.go"))
449 func BenchmarkLstatDir(b
*testing
.B
) {
450 benchmarkLstat(b
, filepath
.Join(runtime
.GOROOT(), "src/os"))
453 // Read the directory one entry at a time.
454 func smallReaddirnames(file
*File
, length
int, t
*testing
.T
) []string {
455 names
:= make([]string, length
)
458 d
, err
:= file
.Readdirnames(1)
463 t
.Fatalf("readdirnames %q failed: %v", file
.Name(), err
)
466 t
.Fatalf("readdirnames %q returned empty slice and no error", file
.Name())
471 return names
[0:count
]
474 // Check that reading a directory one entry at a time gives the same result
475 // as reading it all at once.
476 func TestReaddirnamesOneAtATime(t
*testing
.T
) {
477 // big directory that doesn't change often.
479 switch runtime
.GOOS
{
483 switch runtime
.GOARCH
{
494 dir
= Getenv("SystemRoot") + "\\system32"
496 file
, err
:= Open(dir
)
498 t
.Fatalf("open %q failed: %v", dir
, err
)
501 all
, err1
:= file
.Readdirnames(-1)
503 t
.Fatalf("readdirnames %q failed: %v", dir
, err1
)
505 file1
, err2
:= Open(dir
)
507 t
.Fatalf("open %q failed: %v", dir
, err2
)
510 small
:= smallReaddirnames(file1
, len(all
)+100, t
) // +100 in case we screw up
511 if len(small
) < len(all
) {
512 t
.Fatalf("len(small) is %d, less than %d", len(small
), len(all
))
514 for i
, n
:= range all
{
516 t
.Errorf("small read %q mismatch: %v", small
[i
], n
)
521 func TestReaddirNValues(t
*testing
.T
) {
523 t
.Skip("test.short; skipping")
525 dir
, err
:= ioutil
.TempDir("", "")
527 t
.Fatalf("TempDir: %v", err
)
530 for i
:= 1; i
<= 105; i
++ {
531 f
, err
:= Create(filepath
.Join(dir
, fmt
.Sprintf("%d", i
)))
533 t
.Fatalf("Create: %v", err
)
535 f
.Write([]byte(strings
.Repeat("X", i
)))
544 t
.Fatalf("Open directory: %v", err
)
548 readDirExpect
:= func(n
, want
int, wantErr error
) {
549 fi
, err
:= d
.Readdir(n
)
551 t
.Fatalf("Readdir of %d got error %v, want %v", n
, err
, wantErr
)
553 if g
, e
:= len(fi
), want
; g
!= e
{
554 t
.Errorf("Readdir of %d got %d files, want %d", n
, g
, e
)
558 readDirNamesExpect
:= func(n
, want
int, wantErr error
) {
559 fi
, err
:= d
.Readdirnames(n
)
561 t
.Fatalf("Readdirnames of %d got error %v, want %v", n
, err
, wantErr
)
563 if g
, e
:= len(fi
), want
; g
!= e
{
564 t
.Errorf("Readdirnames of %d got %d files, want %d", n
, g
, e
)
568 for _
, fn
:= range []func(int, int, error
){readDirExpect
, readDirNamesExpect
} {
569 // Test the slurp case
575 // Slurp with -1 instead
582 // Test the bounded case
586 fn(105, 102, nil) // and tests buffer >100 case
592 func touch(t
*testing
.T
, name
string) {
593 f
, err
:= Create(name
)
597 if err
:= f
.Close(); err
!= nil {
602 func TestReaddirStatFailures(t
*testing
.T
) {
603 switch runtime
.GOOS
{
604 case "windows", "plan9":
605 // Windows and Plan 9 already do this correctly,
606 // but are structured with different syscalls such
607 // that they don't use Lstat, so the hook below for
608 // testing it wouldn't work.
609 t
.Skipf("skipping test on %v", runtime
.GOOS
)
611 dir
, err
:= ioutil
.TempDir("", "")
613 t
.Fatalf("TempDir: %v", err
)
616 touch(t
, filepath
.Join(dir
, "good1"))
617 touch(t
, filepath
.Join(dir
, "x")) // will disappear or have an error
618 touch(t
, filepath
.Join(dir
, "good2"))
622 var xerr error
// error to return for x
623 *LstatP
= func(path
string) (FileInfo
, error
) {
624 if xerr
!= nil && strings
.HasSuffix(path
, "x") {
629 readDir
:= func() ([]FileInfo
, error
) {
637 mustReadDir
:= func(testName
string) []FileInfo
{
638 fis
, err
:= readDir()
640 t
.Fatalf("%s: Readdir: %v", testName
, err
)
644 names
:= func(fis
[]FileInfo
) []string {
645 s
:= make([]string, len(fis
))
646 for i
, fi
:= range fis
{
653 if got
, want
:= names(mustReadDir("initial readdir")),
654 []string{"good1", "good2", "x"}; !reflect
.DeepEqual(got
, want
) {
655 t
.Errorf("initial readdir got %q; want %q", got
, want
)
659 if got
, want
:= names(mustReadDir("with x disappearing")),
660 []string{"good1", "good2"}; !reflect
.DeepEqual(got
, want
) {
661 t
.Errorf("with x disappearing, got %q; want %q", got
, want
)
664 xerr
= errors
.New("some real error")
665 if _
, err
:= readDir(); err
!= xerr
{
666 t
.Errorf("with a non-ErrNotExist error, got error %v; want %v", err
, xerr
)
670 // Readdir on a regular file should fail.
671 func TestReaddirOfFile(t
*testing
.T
) {
672 f
, err
:= ioutil
.TempFile("", "_Go_ReaddirOfFile")
676 defer Remove(f
.Name())
677 f
.Write([]byte("foo"))
679 reg
, err
:= Open(f
.Name())
685 names
, err
:= reg
.Readdirnames(-1)
687 t
.Error("Readdirnames succeeded; want non-nil error")
690 t
.Errorf("unexpected dir names in regular file: %q", names
)
694 func TestHardLink(t
*testing
.T
) {
695 testenv
.MustHaveLink(t
)
698 from
, to
:= "hardlinktestfrom", "hardlinktestto"
699 file
, err
:= Create(to
)
701 t
.Fatalf("open %q failed: %v", to
, err
)
703 if err
= file
.Close(); err
!= nil {
704 t
.Errorf("close %q failed: %v", to
, err
)
708 t
.Fatalf("link %q, %q failed: %v", to
, from
, err
)
711 none
:= "hardlinktestnone"
712 err
= Link(none
, none
)
713 // Check the returned error is well-formed.
714 if lerr
, ok
:= err
.(*LinkError
); !ok || lerr
.Error() == "" {
715 t
.Errorf("link %q, %q failed to return a valid error", none
, none
)
718 tostat
, err
:= Stat(to
)
720 t
.Fatalf("stat %q failed: %v", to
, err
)
722 fromstat
, err
:= Stat(from
)
724 t
.Fatalf("stat %q failed: %v", from
, err
)
726 if !SameFile(tostat
, fromstat
) {
727 t
.Errorf("link %q, %q did not create hard link", to
, from
)
729 // We should not be able to perform the same Link() a second time
731 switch err
:= err
.(type) {
733 if err
.Op
!= "link" {
734 t
.Errorf("Link(%q, %q) err.Op = %q; want %q", to
, from
, err
.Op
, "link")
737 t
.Errorf("Link(%q, %q) err.Old = %q; want %q", to
, from
, err
.Old
, to
)
740 t
.Errorf("Link(%q, %q) err.New = %q; want %q", to
, from
, err
.New
, from
)
742 if !IsExist(err
.Err
) {
743 t
.Errorf("Link(%q, %q) err.Err = %q; want %q", to
, from
, err
.Err
, "file exists error")
746 t
.Errorf("link %q, %q: expected error, got nil", from
, to
)
748 t
.Errorf("link %q, %q: expected %T, got %T %v", from
, to
, new(LinkError
), err
, err
)
752 // chtmpdir changes the working directory to a new temporary directory and
753 // provides a cleanup function.
754 func chtmpdir(t
*testing
.T
) func() {
755 oldwd
, err
:= Getwd()
757 t
.Fatalf("chtmpdir: %v", err
)
759 d
, err
:= ioutil
.TempDir("", "test")
761 t
.Fatalf("chtmpdir: %v", err
)
763 if err
:= Chdir(d
); err
!= nil {
764 t
.Fatalf("chtmpdir: %v", err
)
767 if err
:= Chdir(oldwd
); err
!= nil {
768 t
.Fatalf("chtmpdir: %v", err
)
774 func TestSymlink(t
*testing
.T
) {
775 testenv
.MustHaveSymlink(t
)
778 from
, to
:= "symlinktestfrom", "symlinktestto"
779 file
, err
:= Create(to
)
781 t
.Fatalf("Create(%q) failed: %v", to
, err
)
783 if err
= file
.Close(); err
!= nil {
784 t
.Errorf("Close(%q) failed: %v", to
, err
)
786 err
= Symlink(to
, from
)
788 t
.Fatalf("Symlink(%q, %q) failed: %v", to
, from
, err
)
790 tostat
, err
:= Lstat(to
)
792 t
.Fatalf("Lstat(%q) failed: %v", to
, err
)
794 if tostat
.Mode()&ModeSymlink
!= 0 {
795 t
.Fatalf("Lstat(%q).Mode()&ModeSymlink = %v, want 0", to
, tostat
.Mode()&ModeSymlink
)
797 fromstat
, err
:= Stat(from
)
799 t
.Fatalf("Stat(%q) failed: %v", from
, err
)
801 if !SameFile(tostat
, fromstat
) {
802 t
.Errorf("Symlink(%q, %q) did not create symlink", to
, from
)
804 fromstat
, err
= Lstat(from
)
806 t
.Fatalf("Lstat(%q) failed: %v", from
, err
)
808 if fromstat
.Mode()&ModeSymlink
== 0 {
809 t
.Fatalf("Lstat(%q).Mode()&ModeSymlink = 0, want %v", from
, ModeSymlink
)
811 fromstat
, err
= Stat(from
)
813 t
.Fatalf("Stat(%q) failed: %v", from
, err
)
815 if fromstat
.Name() != from
{
816 t
.Errorf("Stat(%q).Name() = %q, want %q", from
, fromstat
.Name(), from
)
818 if fromstat
.Mode()&ModeSymlink
!= 0 {
819 t
.Fatalf("Stat(%q).Mode()&ModeSymlink = %v, want 0", from
, fromstat
.Mode()&ModeSymlink
)
821 s
, err
:= Readlink(from
)
823 t
.Fatalf("Readlink(%q) failed: %v", from
, err
)
826 t
.Fatalf("Readlink(%q) = %q, want %q", from
, s
, to
)
828 file
, err
= Open(from
)
830 t
.Fatalf("Open(%q) failed: %v", from
, err
)
835 func TestLongSymlink(t
*testing
.T
) {
836 testenv
.MustHaveSymlink(t
)
839 s
:= "0123456789abcdef"
840 // Long, but not too long: a common limit is 255.
841 s
= s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
+ s
842 from
:= "longsymlinktestfrom"
843 err
:= Symlink(s
, from
)
845 t
.Fatalf("symlink %q, %q failed: %v", s
, from
, err
)
847 r
, err
:= Readlink(from
)
849 t
.Fatalf("readlink %q failed: %v", from
, err
)
852 t
.Fatalf("after symlink %q != %q", r
, s
)
856 func TestRename(t
*testing
.T
) {
858 from
, to
:= "renamefrom", "renameto"
860 file
, err
:= Create(from
)
862 t
.Fatalf("open %q failed: %v", from
, err
)
864 if err
= file
.Close(); err
!= nil {
865 t
.Errorf("close %q failed: %v", from
, err
)
867 err
= Rename(from
, to
)
869 t
.Fatalf("rename %q, %q failed: %v", to
, from
, err
)
873 t
.Errorf("stat %q failed: %v", to
, err
)
877 func TestRenameOverwriteDest(t
*testing
.T
) {
879 from
, to
:= "renamefrom", "renameto"
881 toData
:= []byte("to")
882 fromData
:= []byte("from")
884 err
:= ioutil
.WriteFile(to
, toData
, 0777)
886 t
.Fatalf("write file %q failed: %v", to
, err
)
889 err
= ioutil
.WriteFile(from
, fromData
, 0777)
891 t
.Fatalf("write file %q failed: %v", from
, err
)
893 err
= Rename(from
, to
)
895 t
.Fatalf("rename %q, %q failed: %v", to
, from
, err
)
900 t
.Errorf("from file %q still exists", from
)
902 if err
!= nil && !IsNotExist(err
) {
903 t
.Fatalf("stat from: %v", err
)
905 toFi
, err
:= Stat(to
)
907 t
.Fatalf("stat %q failed: %v", to
, err
)
909 if toFi
.Size() != int64(len(fromData
)) {
910 t
.Errorf(`"to" size = %d; want %d (old "from" size)`, toFi
.Size(), len(fromData
))
914 func TestRenameFailed(t
*testing
.T
) {
916 from
, to
:= "renamefrom", "renameto"
918 err
:= Rename(from
, to
)
919 switch err
:= err
.(type) {
921 if err
.Op
!= "rename" {
922 t
.Errorf("rename %q, %q: err.Op: want %q, got %q", from
, to
, "rename", err
.Op
)
925 t
.Errorf("rename %q, %q: err.Old: want %q, got %q", from
, to
, from
, err
.Old
)
928 t
.Errorf("rename %q, %q: err.New: want %q, got %q", from
, to
, to
, err
.New
)
931 t
.Errorf("rename %q, %q: expected error, got nil", from
, to
)
933 t
.Errorf("rename %q, %q: expected %T, got %T %v", from
, to
, new(LinkError
), err
, err
)
937 func TestRenameNotExisting(t
*testing
.T
) {
939 from
, to
:= "doesnt-exist", "dest"
943 if err
:= Rename(from
, to
); !IsNotExist(err
) {
944 t
.Errorf("Rename(%q, %q) = %v; want an IsNotExist error", from
, to
, err
)
948 func TestRenameToDirFailed(t
*testing
.T
) {
950 from
, to
:= "renamefrom", "renameto"
955 err
:= Rename(from
, to
)
956 switch err
:= err
.(type) {
958 if err
.Op
!= "rename" {
959 t
.Errorf("rename %q, %q: err.Op: want %q, got %q", from
, to
, "rename", err
.Op
)
962 t
.Errorf("rename %q, %q: err.Old: want %q, got %q", from
, to
, from
, err
.Old
)
965 t
.Errorf("rename %q, %q: err.New: want %q, got %q", from
, to
, to
, err
.New
)
968 t
.Errorf("rename %q, %q: expected error, got nil", from
, to
)
970 t
.Errorf("rename %q, %q: expected %T, got %T %v", from
, to
, new(LinkError
), err
, err
)
974 func TestRenameCaseDifference(pt
*testing
.T
) {
975 from
, to
:= "renameFROM", "RENAMEfrom"
980 {"dir", func() error
{
981 return Mkdir(from
, 0777)
983 {"file", func() error
{
984 fd
, err
:= Create(from
)
992 for _
, test
:= range tests
{
993 pt
.Run(test
.name
, func(t
*testing
.T
) {
996 if err
:= test
.create(); err
!= nil {
997 t
.Fatalf("failed to create test file: %s", err
)
1000 if _
, err
:= Stat(to
); err
!= nil {
1001 // Sanity check that the underlying filesystem is not case sensitive.
1002 if IsNotExist(err
) {
1003 t
.Skipf("case sensitive filesystem")
1005 t
.Fatalf("stat %q, got: %q", to
, err
)
1008 if err
:= Rename(from
, to
); err
!= nil {
1009 t
.Fatalf("unexpected error when renaming from %q to %q: %s", from
, to
, err
)
1012 fd
, err
:= Open(".")
1014 t
.Fatalf("Open .: %s", err
)
1017 // Stat does not return the real case of the file (it returns what the called asked for)
1018 // So we have to use readdir to get the real name of the file.
1019 dirNames
, err
:= fd
.Readdirnames(-1)
1021 t
.Fatalf("readdirnames: %s", err
)
1024 if dirNamesLen
:= len(dirNames
); dirNamesLen
!= 1 {
1025 t
.Fatalf("unexpected dirNames len, got %q, want %q", dirNamesLen
, 1)
1028 if dirNames
[0] != to
{
1029 t
.Errorf("unexpected name, got %q, want %q", dirNames
[0], to
)
1035 func exec(t
*testing
.T
, dir
, cmd
string, args
[]string, expect
string) {
1038 t
.Fatalf("Pipe: %v", err
)
1041 attr
:= &ProcAttr
{Dir
: dir
, Files
: []*File
{nil, w
, Stderr
}}
1042 p
, err
:= StartProcess(cmd
, args
, attr
)
1044 t
.Fatalf("StartProcess: %v", err
)
1050 output
:= b
.String()
1052 fi1
, _
:= Stat(strings
.TrimSpace(output
))
1053 fi2
, _
:= Stat(expect
)
1054 if !SameFile(fi1
, fi2
) {
1055 t
.Errorf("exec %q returned %q wanted %q",
1056 strings
.Join(append([]string{cmd
}, args
...), " "), output
, expect
)
1061 func TestStartProcess(t
*testing
.T
) {
1062 testenv
.MustHaveExec(t
)
1066 switch runtime
.GOOS
{
1068 t
.Skip("android doesn't have /bin/pwd")
1070 cmd
= Getenv("COMSPEC")
1071 dir
= Getenv("SystemRoot")
1072 args
= []string{"/c", "cd"}
1075 cmd
, err
= osexec
.LookPath("pwd")
1077 t
.Fatalf("Can't find pwd: %v", err
)
1081 t
.Logf("Testing with %v", cmd
)
1083 cmddir
, cmdbase
:= filepath
.Split(cmd
)
1084 args
= append([]string{cmdbase
}, args
...)
1085 // Test absolute executable path.
1086 exec(t
, dir
, cmd
, args
, dir
)
1087 // Test relative executable path.
1088 exec(t
, cmddir
, cmdbase
, args
, cmddir
)
1091 func checkMode(t
*testing
.T
, path
string, mode FileMode
) {
1092 dir
, err
:= Stat(path
)
1094 t
.Fatalf("Stat %q (looking for mode %#o): %s", path
, mode
, err
)
1096 if dir
.Mode()&0777 != mode
{
1097 t
.Errorf("Stat %q: mode %#o want %#o", path
, dir
.Mode(), mode
)
1101 func TestChmod(t
*testing
.T
) {
1102 // Chmod is not supported under windows.
1103 if runtime
.GOOS
== "windows" {
1106 f
:= newFile("TestChmod", t
)
1107 defer Remove(f
.Name())
1110 if err
:= Chmod(f
.Name(), 0456); err
!= nil {
1111 t
.Fatalf("chmod %s 0456: %s", f
.Name(), err
)
1113 checkMode(t
, f
.Name(), 0456)
1115 if err
:= f
.Chmod(0123); err
!= nil {
1116 t
.Fatalf("chmod %s 0123: %s", f
.Name(), err
)
1118 checkMode(t
, f
.Name(), 0123)
1121 func checkSize(t
*testing
.T
, f
*File
, size
int64) {
1122 dir
, err
:= f
.Stat()
1124 t
.Fatalf("Stat %q (looking for size %d): %s", f
.Name(), size
, err
)
1126 if dir
.Size() != size
{
1127 t
.Errorf("Stat %q: size %d want %d", f
.Name(), dir
.Size(), size
)
1131 func TestFTruncate(t
*testing
.T
) {
1132 f
:= newFile("TestFTruncate", t
)
1133 defer Remove(f
.Name())
1137 f
.Write([]byte("hello, world\n"))
1142 checkSize(t
, f
, 1024)
1145 _
, err
:= f
.Write([]byte("surprise!"))
1147 checkSize(t
, f
, 13+9) // wrote at offset past where hello, world was.
1151 func TestTruncate(t
*testing
.T
) {
1152 f
:= newFile("TestTruncate", t
)
1153 defer Remove(f
.Name())
1157 f
.Write([]byte("hello, world\n"))
1159 Truncate(f
.Name(), 10)
1161 Truncate(f
.Name(), 1024)
1162 checkSize(t
, f
, 1024)
1163 Truncate(f
.Name(), 0)
1165 _
, err
:= f
.Write([]byte("surprise!"))
1167 checkSize(t
, f
, 13+9) // wrote at offset past where hello, world was.
1171 // Use TempDir (via newFile) to make sure we're on a local file system,
1172 // so that timings are not distorted by latency and caching.
1173 // On NFS, timings can be off due to caching of meta-data on
1174 // NFS servers (Issue 848).
1175 func TestChtimes(t
*testing
.T
) {
1176 f
:= newFile("TestChtimes", t
)
1177 defer Remove(f
.Name())
1179 f
.Write([]byte("hello, world\n"))
1182 testChtimes(t
, f
.Name())
1185 // Use TempDir (via newDir) to make sure we're on a local file system,
1186 // so that timings are not distorted by latency and caching.
1187 // On NFS, timings can be off due to caching of meta-data on
1188 // NFS servers (Issue 848).
1189 func TestChtimesDir(t
*testing
.T
) {
1190 name
:= newDir("TestChtimes", t
)
1191 defer RemoveAll(name
)
1193 testChtimes(t
, name
)
1196 func testChtimes(t
*testing
.T
, name
string) {
1197 st
, err
:= Stat(name
)
1199 t
.Fatalf("Stat %s: %s", name
, err
)
1203 // Move access and modification time back a second
1204 at
:= Atime(preStat
)
1205 mt
:= preStat
.ModTime()
1206 err
= Chtimes(name
, at
.Add(-time
.Second
), mt
.Add(-time
.Second
))
1208 t
.Fatalf("Chtimes %s: %s", name
, err
)
1211 st
, err
= Stat(name
)
1213 t
.Fatalf("second Stat %s: %s", name
, err
)
1217 pat
:= Atime(postStat
)
1218 pmt
:= postStat
.ModTime()
1219 if !pat
.Before(at
) {
1220 switch runtime
.GOOS
{
1222 // Mtime is the time of the last change of
1223 // content. Similarly, atime is set whenever
1224 // the contents are accessed; also, it is set
1225 // whenever mtime is set.
1227 mounts
, _
:= ioutil
.ReadFile("/proc/mounts")
1228 if strings
.Contains(string(mounts
), "noatime") {
1229 t
.Logf("AccessTime didn't go backwards, but see a filesystem mounted noatime; ignoring. Issue 19293.")
1231 t
.Logf("AccessTime didn't go backwards; was=%v, after=%v (Ignoring on NetBSD, assuming noatime, Issue 19293)", at
, pat
)
1234 t
.Errorf("AccessTime didn't go backwards; was=%v, after=%v", at
, pat
)
1238 if !pmt
.Before(mt
) {
1239 t
.Errorf("ModTime didn't go backwards; was=%v, after=%v", mt
, pmt
)
1243 func TestChdirAndGetwd(t
*testing
.T
) {
1244 // TODO(brainman): file.Chdir() is not implemented on windows.
1245 if runtime
.GOOS
== "windows" {
1248 fd
, err
:= Open(".")
1250 t
.Fatalf("Open .: %s", err
)
1252 // These are chosen carefully not to be symlinks on a Mac
1253 // (unlike, say, /var, /etc), except /tmp, which we handle below.
1254 dirs
:= []string{"/", "/usr/bin", "/tmp"}
1255 // /usr/bin does not usually exist on Plan 9 or Android.
1256 switch runtime
.GOOS
{
1258 dirs
= []string{"/system/bin"}
1260 dirs
= []string{"/", "/usr"}
1262 switch runtime
.GOARCH
{
1263 case "arm", "arm64":
1265 for _
, d
:= range []string{"d1", "d2"} {
1266 dir
, err
:= ioutil
.TempDir("", d
)
1268 t
.Fatalf("TempDir: %v", err
)
1270 // Expand symlinks so path equality tests work.
1271 dir
, err
= filepath
.EvalSymlinks(dir
)
1273 t
.Fatalf("EvalSymlinks: %v", err
)
1275 dirs
= append(dirs
, dir
)
1279 oldwd
:= Getenv("PWD")
1280 for mode
:= 0; mode
< 2; mode
++ {
1281 for _
, d
:= range dirs
{
1285 fd1
, err1
:= Open(d
)
1287 t
.Errorf("Open %s: %s", d
, err1
)
1294 Setenv("PWD", "/tmp")
1296 pwd
, err1
:= Getwd()
1297 Setenv("PWD", oldwd
)
1300 // We changed the current directory and cannot go back.
1301 // Don't let the tests continue; they'll scribble
1302 // all over some other directory.
1303 fmt
.Fprintf(Stderr
, "fchdir back to dot failed: %s\n", err2
)
1308 t
.Fatalf("Chdir %s: %s", d
, err
)
1312 t
.Fatalf("Getwd in %s: %s", d
, err1
)
1316 t
.Fatalf("Getwd returned %q want %q", pwd
, d
)
1323 // Test that Chdir+Getwd is program-wide.
1324 func TestProgWideChdir(t
*testing
.T
) {
1326 c
:= make(chan bool)
1327 cpwd
:= make(chan string)
1328 for i
:= 0; i
< N
; i
++ {
1330 // Lock half the goroutines in their own operating system
1331 // thread to exercise more scheduler possibilities.
1333 // On Plan 9, after calling LockOSThread, the goroutines
1334 // run on different processes which don't share the working
1335 // directory. This used to be an issue because Go expects
1336 // the working directory to be program-wide.
1338 runtime
.LockOSThread()
1343 t
.Errorf("Getwd on goroutine %d: %v", i
, err
)
1349 oldwd
, err
:= Getwd()
1351 t
.Fatalf("Getwd: %v", err
)
1353 d
, err
:= ioutil
.TempDir("", "test")
1355 t
.Fatalf("TempDir: %v", err
)
1358 if err
:= Chdir(oldwd
); err
!= nil {
1359 t
.Fatalf("Chdir: %v", err
)
1363 if err
:= Chdir(d
); err
!= nil {
1364 t
.Fatalf("Chdir: %v", err
)
1366 // OS X sets TMPDIR to a symbolic link.
1367 // So we resolve our working directory again before the test.
1370 t
.Fatalf("Getwd: %v", err
)
1373 for i
:= 0; i
< N
; i
++ {
1376 t
.Errorf("Getwd returned %q; want %q", pwd
, d
)
1381 func TestSeek(t
*testing
.T
) {
1382 f
:= newFile("TestSeek", t
)
1383 defer Remove(f
.Name())
1386 const data
= "hello, world\n"
1387 io
.WriteString(f
, data
)
1395 {0, io
.SeekCurrent
, int64(len(data
))},
1396 {0, io
.SeekStart
, 0},
1397 {5, io
.SeekStart
, 5},
1398 {0, io
.SeekEnd
, int64(len(data
))},
1399 {0, io
.SeekStart
, 0},
1400 {-1, io
.SeekEnd
, int64(len(data
)) - 1},
1401 {1 << 33, io
.SeekStart
, 1 << 33},
1402 {1 << 33, io
.SeekEnd
, 1<<33 + int64(len(data
))},
1404 // Issue 21681, Windows 4G-1, etc:
1405 {1<<32 - 1, io
.SeekStart
, 1<<32 - 1},
1406 {0, io
.SeekCurrent
, 1<<32 - 1},
1407 {2<<32 - 1, io
.SeekStart
, 2<<32 - 1},
1408 {0, io
.SeekCurrent
, 2<<32 - 1},
1410 for i
, tt
:= range tests
{
1411 if runtime
.GOOS
== "hurd" && tt
.out
> 1<<32 {
1412 t
.Logf("skipping test case #%d on Hurd: file too large", i
)
1415 off
, err
:= f
.Seek(tt
.in
, tt
.whence
)
1416 if off
!= tt
.out || err
!= nil {
1417 if e
, ok
:= err
.(*PathError
); ok
&& e
.Err
== syscall
.EINVAL
&& tt
.out
> 1<<32 && runtime
.GOOS
== "linux" {
1418 mounts
, _
:= ioutil
.ReadFile("/proc/mounts")
1419 if strings
.Contains(string(mounts
), "reiserfs") {
1420 // Reiserfs rejects the big seeks.
1421 t
.Skipf("skipping test known to fail on reiserfs; https://golang.org/issue/91")
1424 t
.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i
, tt
.in
, tt
.whence
, off
, err
, tt
.out
)
1429 func TestSeekError(t
*testing
.T
) {
1430 switch runtime
.GOOS
{
1432 t
.Skipf("skipping test on %v", runtime
.GOOS
)
1439 _
, err
= r
.Seek(0, 0)
1441 t
.Fatal("Seek on pipe should fail")
1443 if perr
, ok
:= err
.(*PathError
); !ok || perr
.Err
!= syscall
.ESPIPE
{
1444 t
.Errorf("Seek returned error %v, want &PathError{Err: syscall.ESPIPE}", err
)
1446 _
, err
= w
.Seek(0, 0)
1448 t
.Fatal("Seek on pipe should fail")
1450 if perr
, ok
:= err
.(*PathError
); !ok || perr
.Err
!= syscall
.ESPIPE
{
1451 t
.Errorf("Seek returned error %v, want &PathError{Err: syscall.ESPIPE}", err
)
1455 type openErrorTest
struct {
1461 var openErrorTests
= []openErrorTest
{
1463 sfdir
+ "/no-such-file",
1473 sfdir
+ "/" + sfname
+ "/no-such-file",
1479 func TestOpenError(t
*testing
.T
) {
1480 for _
, tt
:= range openErrorTests
{
1481 f
, err
:= OpenFile(tt
.path
, tt
.mode
, 0)
1483 t
.Errorf("Open(%q, %d) succeeded", tt
.path
, tt
.mode
)
1487 perr
, ok
:= err
.(*PathError
)
1489 t
.Errorf("Open(%q, %d) returns error of %T type; want *PathError", tt
.path
, tt
.mode
, err
)
1491 if perr
.Err
!= tt
.error
{
1492 if runtime
.GOOS
== "plan9" {
1493 syscallErrStr
:= perr
.Err
.Error()
1494 expectedErrStr
:= strings
.Replace(tt
.error
.Error(), "file ", "", 1)
1495 if !strings
.HasSuffix(syscallErrStr
, expectedErrStr
) {
1496 // Some Plan 9 file servers incorrectly return
1497 // EACCES rather than EISDIR when a directory is
1498 // opened for write.
1499 if tt
.error
== syscall
.EISDIR
&& strings
.HasSuffix(syscallErrStr
, syscall
.EACCES
.Error()) {
1502 t
.Errorf("Open(%q, %d) = _, %q; want suffix %q", tt
.path
, tt
.mode
, syscallErrStr
, expectedErrStr
)
1506 if runtime
.GOOS
== "dragonfly" {
1507 // DragonFly incorrectly returns EACCES rather
1508 // EISDIR when a directory is opened for write.
1509 if tt
.error
== syscall
.EISDIR
&& perr
.Err
== syscall
.EACCES
{
1513 t
.Errorf("Open(%q, %d) = _, %q; want %q", tt
.path
, tt
.mode
, perr
.Err
.Error(), tt
.error
.Error())
1518 func TestOpenNoName(t
*testing
.T
) {
1521 t
.Fatal(`Open("") succeeded`)
1526 func runBinHostname(t
*testing
.T
) string {
1527 // Run /bin/hostname and collect output.
1533 const path
= "/bin/hostname"
1534 argv
:= []string{"hostname"}
1535 if runtime
.GOOS
== "aix" {
1536 argv
= []string{"hostname", "-s"}
1538 p
, err
:= StartProcess(path
, argv
, &ProcAttr
{Files
: []*File
{nil, w
, Stderr
}})
1540 if _
, err
:= Stat(path
); IsNotExist(err
) {
1541 t
.Skipf("skipping test; test requires %s but it does not exist", path
)
1551 t
.Fatalf("run hostname Wait: %v", err
)
1555 t
.Errorf("expected an error from Kill running 'hostname'")
1557 output
:= b
.String()
1558 if n
:= len(output
); n
> 0 && output
[n
-1] == '\n' {
1559 output
= output
[0 : n
-1]
1562 t
.Fatalf("/bin/hostname produced no output")
1568 func testWindowsHostname(t
*testing
.T
, hostname
string) {
1569 cmd
:= osexec
.Command("hostname")
1570 out
, err
:= cmd
.CombinedOutput()
1572 t
.Fatalf("Failed to execute hostname command: %v %s", err
, out
)
1574 want
:= strings
.Trim(string(out
), "\r\n")
1575 if hostname
!= want
{
1576 t
.Fatalf("Hostname() = %q != system hostname of %q", hostname
, want
)
1580 func TestHostname(t
*testing
.T
) {
1581 hostname
, err
:= Hostname()
1586 t
.Fatal("Hostname returned empty string and no error")
1588 if strings
.Contains(hostname
, "\x00") {
1589 t
.Fatalf("unexpected zero byte in hostname: %q", hostname
)
1592 // There is no other way to fetch hostname on windows, but via winapi.
1593 // On Plan 9 it can be taken from #c/sysname as Hostname() does.
1594 switch runtime
.GOOS
{
1595 case "android", "plan9":
1596 // No /bin/hostname to verify against.
1599 testWindowsHostname(t
, hostname
)
1603 testenv
.MustHaveExec(t
)
1605 // Check internal Hostname() against the output of /bin/hostname.
1606 // Allow that the internal Hostname returns a Fully Qualified Domain Name
1607 // and the /bin/hostname only returns the first component
1608 want
:= runBinHostname(t
)
1609 if hostname
!= want
{
1610 i
:= strings
.Index(hostname
, ".")
1611 if i
< 0 || hostname
[0:i
] != want
{
1612 t
.Errorf("Hostname() = %q, want %q", hostname
, want
)
1617 func TestReadAt(t
*testing
.T
) {
1618 f
:= newFile("TestReadAt", t
)
1619 defer Remove(f
.Name())
1622 const data
= "hello, world\n"
1623 io
.WriteString(f
, data
)
1625 b
:= make([]byte, 5)
1626 n
, err
:= f
.ReadAt(b
, 7)
1627 if err
!= nil || n
!= len(b
) {
1628 t
.Fatalf("ReadAt 7: %d, %v", n
, err
)
1630 if string(b
) != "world" {
1631 t
.Fatalf("ReadAt 7: have %q want %q", string(b
), "world")
1635 // Verify that ReadAt doesn't affect seek offset.
1636 // In the Plan 9 kernel, there used to be a bug in the implementation of
1637 // the pread syscall, where the channel offset was erroneously updated after
1638 // calling pread on a file.
1639 func TestReadAtOffset(t
*testing
.T
) {
1640 f
:= newFile("TestReadAtOffset", t
)
1641 defer Remove(f
.Name())
1644 const data
= "hello, world\n"
1645 io
.WriteString(f
, data
)
1648 b
:= make([]byte, 5)
1650 n
, err
:= f
.ReadAt(b
, 7)
1651 if err
!= nil || n
!= len(b
) {
1652 t
.Fatalf("ReadAt 7: %d, %v", n
, err
)
1654 if string(b
) != "world" {
1655 t
.Fatalf("ReadAt 7: have %q want %q", string(b
), "world")
1659 if err
!= nil || n
!= len(b
) {
1660 t
.Fatalf("Read: %d, %v", n
, err
)
1662 if string(b
) != "hello" {
1663 t
.Fatalf("Read: have %q want %q", string(b
), "hello")
1667 // Verify that ReadAt doesn't allow negative offset.
1668 func TestReadAtNegativeOffset(t
*testing
.T
) {
1669 f
:= newFile("TestReadAtNegativeOffset", t
)
1670 defer Remove(f
.Name())
1673 const data
= "hello, world\n"
1674 io
.WriteString(f
, data
)
1677 b
:= make([]byte, 5)
1679 n
, err
:= f
.ReadAt(b
, -10)
1681 const wantsub
= "negative offset"
1682 if !strings
.Contains(fmt
.Sprint(err
), wantsub
) || n
!= 0 {
1683 t
.Errorf("ReadAt(-10) = %v, %v; want 0, ...%q...", n
, err
, wantsub
)
1687 func TestWriteAt(t
*testing
.T
) {
1688 f
:= newFile("TestWriteAt", t
)
1689 defer Remove(f
.Name())
1692 const data
= "hello, world\n"
1693 io
.WriteString(f
, data
)
1695 n
, err
:= f
.WriteAt([]byte("WORLD"), 7)
1696 if err
!= nil || n
!= 5 {
1697 t
.Fatalf("WriteAt 7: %d, %v", n
, err
)
1700 b
, err
:= ioutil
.ReadFile(f
.Name())
1702 t
.Fatalf("ReadFile %s: %v", f
.Name(), err
)
1704 if string(b
) != "hello, WORLD\n" {
1705 t
.Fatalf("after write: have %q want %q", string(b
), "hello, WORLD\n")
1709 // Verify that WriteAt doesn't allow negative offset.
1710 func TestWriteAtNegativeOffset(t
*testing
.T
) {
1711 f
:= newFile("TestWriteAtNegativeOffset", t
)
1712 defer Remove(f
.Name())
1715 n
, err
:= f
.WriteAt([]byte("WORLD"), -10)
1717 const wantsub
= "negative offset"
1718 if !strings
.Contains(fmt
.Sprint(err
), wantsub
) || n
!= 0 {
1719 t
.Errorf("WriteAt(-10) = %v, %v; want 0, ...%q...", n
, err
, wantsub
)
1723 // Verify that WriteAt doesn't work in append mode.
1724 func TestWriteAtInAppendMode(t
*testing
.T
) {
1726 f
, err
:= OpenFile("write_at_in_append_mode.txt", O_APPEND|O_CREATE
, 0666)
1728 t
.Fatalf("OpenFile: %v", err
)
1732 _
, err
= f
.WriteAt([]byte(""), 1)
1733 if err
!= ErrWriteAtInAppendMode
{
1734 t
.Fatalf("f.WriteAt returned %v, expected %v", err
, ErrWriteAtInAppendMode
)
1738 func writeFile(t
*testing
.T
, fname
string, flag
int, text
string) string {
1739 f
, err
:= OpenFile(fname
, flag
, 0666)
1741 t
.Fatalf("Open: %v", err
)
1743 n
, err
:= io
.WriteString(f
, text
)
1745 t
.Fatalf("WriteString: %d, %v", n
, err
)
1748 data
, err
:= ioutil
.ReadFile(fname
)
1750 t
.Fatalf("ReadFile: %v", err
)
1755 func TestAppend(t
*testing
.T
) {
1757 const f
= "append.txt"
1758 s
:= writeFile(t
, f
, O_CREATE|O_TRUNC|O_RDWR
, "new")
1760 t
.Fatalf("writeFile: have %q want %q", s
, "new")
1762 s
= writeFile(t
, f
, O_APPEND|O_RDWR
, "|append")
1763 if s
!= "new|append" {
1764 t
.Fatalf("writeFile: have %q want %q", s
, "new|append")
1766 s
= writeFile(t
, f
, O_CREATE|O_APPEND|O_RDWR
, "|append")
1767 if s
!= "new|append|append" {
1768 t
.Fatalf("writeFile: have %q want %q", s
, "new|append|append")
1772 t
.Fatalf("Remove: %v", err
)
1774 s
= writeFile(t
, f
, O_CREATE|O_APPEND|O_RDWR
, "new&append")
1775 if s
!= "new&append" {
1776 t
.Fatalf("writeFile: after append have %q want %q", s
, "new&append")
1778 s
= writeFile(t
, f
, O_CREATE|O_RDWR
, "old")
1779 if s
!= "old&append" {
1780 t
.Fatalf("writeFile: after create have %q want %q", s
, "old&append")
1782 s
= writeFile(t
, f
, O_CREATE|O_TRUNC|O_RDWR
, "new")
1784 t
.Fatalf("writeFile: after truncate have %q want %q", s
, "new")
1788 func TestStatDirWithTrailingSlash(t
*testing
.T
) {
1789 // Create new temporary directory and arrange to clean it up.
1790 path
, err
:= ioutil
.TempDir("", "/_TestStatDirWithSlash_")
1792 t
.Fatalf("TempDir: %s", err
)
1794 defer RemoveAll(path
)
1796 // Stat of path should succeed.
1799 t
.Fatalf("stat %s failed: %s", path
, err
)
1802 // Stat of path+"/" should succeed too.
1806 t
.Fatalf("stat %s failed: %s", path
, err
)
1810 func TestNilProcessStateString(t
*testing
.T
) {
1811 var ps
*ProcessState
1814 t
.Errorf("(*ProcessState)(nil).String() = %q, want %q", s
, "<nil>")
1818 func TestSameFile(t
*testing
.T
) {
1820 fa
, err
:= Create("a")
1822 t
.Fatalf("Create(a): %v", err
)
1825 fb
, err
:= Create("b")
1827 t
.Fatalf("Create(b): %v", err
)
1831 ia1
, err
:= Stat("a")
1833 t
.Fatalf("Stat(a): %v", err
)
1835 ia2
, err
:= Stat("a")
1837 t
.Fatalf("Stat(a): %v", err
)
1839 if !SameFile(ia1
, ia2
) {
1840 t
.Errorf("files should be same")
1843 ib
, err
:= Stat("b")
1845 t
.Fatalf("Stat(b): %v", err
)
1847 if SameFile(ia1
, ib
) {
1848 t
.Errorf("files should be different")
1852 func testDevNullFileInfo(t
*testing
.T
, statname
, devNullName
string, fi FileInfo
, ignoreCase
bool) {
1853 pre
:= fmt
.Sprintf("%s(%q): ", statname
, devNullName
)
1854 name
:= filepath
.Base(devNullName
)
1856 if strings
.ToUpper(fi
.Name()) != strings
.ToUpper(name
) {
1857 t
.Errorf(pre
+"wrong file name have %v want %v", fi
.Name(), name
)
1860 if fi
.Name() != name
{
1861 t
.Errorf(pre
+"wrong file name have %v want %v", fi
.Name(), name
)
1865 t
.Errorf(pre
+"wrong file size have %d want 0", fi
.Size())
1867 if fi
.Mode()&ModeDevice
== 0 {
1868 t
.Errorf(pre
+"wrong file mode %q: ModeDevice is not set", fi
.Mode())
1870 if fi
.Mode()&ModeCharDevice
== 0 {
1871 t
.Errorf(pre
+"wrong file mode %q: ModeCharDevice is not set", fi
.Mode())
1873 if fi
.Mode().IsRegular() {
1874 t
.Errorf(pre
+"wrong file mode %q: IsRegular returns true", fi
.Mode())
1878 func testDevNullFile(t
*testing
.T
, devNullName
string, ignoreCase
bool) {
1879 f
, err
:= Open(devNullName
)
1881 t
.Fatalf("Open(%s): %v", devNullName
, err
)
1887 t
.Fatalf("Stat(%s): %v", devNullName
, err
)
1889 testDevNullFileInfo(t
, "f.Stat", devNullName
, fi
, ignoreCase
)
1891 fi
, err
= Stat(devNullName
)
1893 t
.Fatalf("Stat(%s): %v", devNullName
, err
)
1895 testDevNullFileInfo(t
, "Stat", devNullName
, fi
, ignoreCase
)
1898 func TestDevNullFile(t
*testing
.T
) {
1899 testDevNullFile(t
, DevNull
, false)
1902 var testLargeWrite
= flag
.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output")
1904 func TestLargeWriteToConsole(t
*testing
.T
) {
1905 if !*testLargeWrite
{
1906 t
.Skip("skipping console-flooding test; enable with -large_write")
1908 b
:= make([]byte, 32000)
1913 n
, err
:= Stdout
.Write(b
)
1915 t
.Fatalf("Write to os.Stdout failed: %v", err
)
1918 t
.Errorf("Write to os.Stdout should return %d; got %d", len(b
), n
)
1920 n
, err
= Stderr
.Write(b
)
1922 t
.Fatalf("Write to os.Stderr failed: %v", err
)
1925 t
.Errorf("Write to os.Stderr should return %d; got %d", len(b
), n
)
1929 func TestStatDirModeExec(t
*testing
.T
) {
1932 path
, err
:= ioutil
.TempDir("", "go-build")
1934 t
.Fatalf("Failed to create temp directory: %v", err
)
1936 defer RemoveAll(path
)
1938 if err
:= Chmod(path
, 0777); err
!= nil {
1939 t
.Fatalf("Chmod %q 0777: %v", path
, err
)
1942 dir
, err
:= Stat(path
)
1944 t
.Fatalf("Stat %q (looking for mode %#o): %s", path
, mode
, err
)
1946 if dir
.Mode()&mode
!= mode
{
1947 t
.Errorf("Stat %q: mode %#o want %#o", path
, dir
.Mode()&mode
, mode
)
1951 func TestStatStdin(t
*testing
.T
) {
1952 switch runtime
.GOOS
{
1953 case "android", "plan9":
1954 t
.Skipf("%s doesn't have /bin/sh", runtime
.GOOS
)
1957 testenv
.MustHaveExec(t
)
1959 if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
1960 st
, err
:= Stdin
.Stat()
1962 t
.Fatalf("Stat failed: %v", err
)
1964 fmt
.Println(st
.Mode() & ModeNamedPipe
)
1968 fi
, err
:= Stdin
.Stat()
1972 switch mode
:= fi
.Mode(); {
1973 case mode
&ModeCharDevice
!= 0 && mode
&ModeDevice
!= 0:
1974 case mode
&ModeNamedPipe
!= 0:
1976 t
.Fatalf("unexpected Stdin mode (%v), want ModeCharDevice or ModeNamedPipe", mode
)
1980 if runtime
.GOOS
== "windows" {
1981 cmd
= osexec
.Command("cmd", "/c", "echo output | "+Args
[0]+" -test.run=TestStatStdin")
1983 cmd
= osexec
.Command("/bin/sh", "-c", "echo output | "+Args
[0]+" -test.run=TestStatStdin")
1985 cmd
.Env
= append(Environ(), "GO_WANT_HELPER_PROCESS=1")
1987 output
, err
:= cmd
.CombinedOutput()
1989 t
.Fatalf("Failed to spawn child process: %v %q", err
, string(output
))
1992 // result will be like "prw-rw-rw"
1993 if len(output
) < 1 || output
[0] != 'p' {
1994 t
.Fatalf("Child process reports stdin is not pipe '%v'", string(output
))
1998 func TestStatRelativeSymlink(t
*testing
.T
) {
1999 testenv
.MustHaveSymlink(t
)
2001 tmpdir
, err
:= ioutil
.TempDir("", "TestStatRelativeSymlink")
2005 defer RemoveAll(tmpdir
)
2007 target
:= filepath
.Join(tmpdir
, "target")
2008 f
, err
:= Create(target
)
2019 link
:= filepath
.Join(tmpdir
, "link")
2020 err
= Symlink(filepath
.Base(target
), link
)
2025 st1
, err
:= Stat(link
)
2030 if !SameFile(st
, st1
) {
2031 t
.Error("Stat doesn't follow relative symlink")
2034 if runtime
.GOOS
== "windows" {
2036 err
= Symlink(target
[len(filepath
.VolumeName(target
)):], link
)
2041 st1
, err
:= Stat(link
)
2046 if !SameFile(st
, st1
) {
2047 t
.Error("Stat doesn't follow relative symlink")
2052 func TestReadAtEOF(t
*testing
.T
) {
2053 f
:= newFile("TestReadAtEOF", t
)
2054 defer Remove(f
.Name())
2057 _
, err
:= f
.ReadAt(make([]byte, 10), 0)
2062 t
.Fatalf("ReadAt succeeded")
2064 t
.Fatalf("ReadAt failed: %s", err
)
2068 func TestLongPath(t
*testing
.T
) {
2069 tmpdir
:= newDir("TestLongPath", t
)
2070 defer func(d
string) {
2071 if err
:= RemoveAll(d
); err
!= nil {
2072 t
.Fatalf("RemoveAll failed: %v", err
)
2076 // Test the boundary of 247 and fewer bytes (normal) and 248 and more bytes (adjusted).
2077 sizes
:= []int{247, 248, 249, 400}
2078 for len(tmpdir
) < 400 {
2079 tmpdir
+= "/dir3456789"
2081 for _
, sz
:= range sizes
{
2082 t
.Run(fmt
.Sprintf("length=%d", sz
), func(t
*testing
.T
) {
2083 sizedTempDir
:= tmpdir
[:sz
-1] + "x" // Ensure it does not end with a slash.
2085 // The various sized runs are for this call to trigger the boundary
2087 if err
:= MkdirAll(sizedTempDir
, 0755); err
!= nil {
2088 t
.Fatalf("MkdirAll failed: %v", err
)
2090 data
:= []byte("hello world\n")
2091 if err
:= ioutil
.WriteFile(sizedTempDir
+"/foo.txt", data
, 0644); err
!= nil {
2092 t
.Fatalf("ioutil.WriteFile() failed: %v", err
)
2094 if err
:= Rename(sizedTempDir
+"/foo.txt", sizedTempDir
+"/bar.txt"); err
!= nil {
2095 t
.Fatalf("Rename failed: %v", err
)
2097 mtime
:= time
.Now().Truncate(time
.Minute
)
2098 if err
:= Chtimes(sizedTempDir
+"/bar.txt", mtime
, mtime
); err
!= nil {
2099 t
.Fatalf("Chtimes failed: %v", err
)
2101 names
:= []string{"bar.txt"}
2102 if testenv
.HasSymlink() {
2103 if err
:= Symlink(sizedTempDir
+"/bar.txt", sizedTempDir
+"/symlink.txt"); err
!= nil {
2104 t
.Fatalf("Symlink failed: %v", err
)
2106 names
= append(names
, "symlink.txt")
2108 if testenv
.HasLink() {
2109 if err
:= Link(sizedTempDir
+"/bar.txt", sizedTempDir
+"/link.txt"); err
!= nil {
2110 t
.Fatalf("Link failed: %v", err
)
2112 names
= append(names
, "link.txt")
2114 for _
, wantSize
:= range []int64{int64(len(data
)), 0} {
2115 for _
, name
:= range names
{
2116 path
:= sizedTempDir
+ "/" + name
2117 dir
, err
:= Stat(path
)
2119 t
.Fatalf("Stat(%q) failed: %v", path
, err
)
2121 filesize
:= size(path
, t
)
2122 if dir
.Size() != filesize || filesize
!= wantSize
{
2123 t
.Errorf("Size(%q) is %d, len(ReadFile()) is %d, want %d", path
, dir
.Size(), filesize
, wantSize
)
2125 err
= Chmod(path
, dir
.Mode())
2127 t
.Fatalf("Chmod(%q) failed: %v", path
, err
)
2130 if err
:= Truncate(sizedTempDir
+"/bar.txt", 0); err
!= nil {
2131 t
.Fatalf("Truncate failed: %v", err
)
2138 func testKillProcess(t
*testing
.T
, processKiller
func(p
*Process
)) {
2139 testenv
.MustHaveExec(t
)
2141 // Re-exec the test binary itself to emulate "sleep 1".
2142 cmd
:= osexec
.Command(Args
[0], "-test.run", "TestSleep")
2145 t
.Fatalf("Failed to start test process: %v", err
)
2148 time
.Sleep(100 * time
.Millisecond
)
2149 processKiller(cmd
.Process
)
2153 t
.Errorf("Test process succeeded, but expected to fail")
2157 // TestSleep emulates "sleep 1". It is a helper for testKillProcess, so we
2158 // don't have to rely on an external "sleep" command being available.
2159 func TestSleep(t
*testing
.T
) {
2160 if testing
.Short() {
2161 t
.Skip("Skipping in short mode")
2163 time
.Sleep(time
.Second
)
2166 func TestKillStartProcess(t
*testing
.T
) {
2167 testKillProcess(t
, func(p
*Process
) {
2170 t
.Fatalf("Failed to kill test process: %v", err
)
2175 func TestGetppid(t
*testing
.T
) {
2176 if runtime
.GOOS
== "plan9" {
2177 // TODO: golang.org/issue/8206
2178 t
.Skipf("skipping test on plan9; see issue 8206")
2181 testenv
.MustHaveExec(t
)
2183 if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
2184 fmt
.Print(Getppid())
2188 cmd
:= osexec
.Command(Args
[0], "-test.run=TestGetppid")
2189 cmd
.Env
= append(Environ(), "GO_WANT_HELPER_PROCESS=1")
2191 // verify that Getppid() from the forked process reports our process id
2192 output
, err
:= cmd
.CombinedOutput()
2194 t
.Fatalf("Failed to spawn child process: %v %q", err
, string(output
))
2197 childPpid
:= string(output
)
2198 ourPid
:= fmt
.Sprintf("%d", Getpid())
2199 if childPpid
!= ourPid
{
2200 t
.Fatalf("Child process reports parent process id '%v', expected '%v'", childPpid
, ourPid
)
2204 func TestKillFindProcess(t
*testing
.T
) {
2205 testKillProcess(t
, func(p
*Process
) {
2206 p2
, err
:= FindProcess(p
.Pid
)
2208 t
.Fatalf("Failed to find test process: %v", err
)
2212 t
.Fatalf("Failed to kill test process: %v", err
)
2217 var nilFileMethodTests
= []struct {
2221 {"Chdir", func(f
*File
) error
{ return f
.Chdir() }},
2222 {"Close", func(f
*File
) error
{ return f
.Close() }},
2223 {"Chmod", func(f
*File
) error
{ return f
.Chmod(0) }},
2224 {"Chown", func(f
*File
) error
{ return f
.Chown(0, 0) }},
2225 {"Read", func(f
*File
) error
{ _
, err
:= f
.Read(make([]byte, 0)); return err
}},
2226 {"ReadAt", func(f
*File
) error
{ _
, err
:= f
.ReadAt(make([]byte, 0), 0); return err
}},
2227 {"Readdir", func(f
*File
) error
{ _
, err
:= f
.Readdir(1); return err
}},
2228 {"Readdirnames", func(f
*File
) error
{ _
, err
:= f
.Readdirnames(1); return err
}},
2229 {"Seek", func(f
*File
) error
{ _
, err
:= f
.Seek(0, io
.SeekStart
); return err
}},
2230 {"Stat", func(f
*File
) error
{ _
, err
:= f
.Stat(); return err
}},
2231 {"Sync", func(f
*File
) error
{ return f
.Sync() }},
2232 {"Truncate", func(f
*File
) error
{ return f
.Truncate(0) }},
2233 {"Write", func(f
*File
) error
{ _
, err
:= f
.Write(make([]byte, 0)); return err
}},
2234 {"WriteAt", func(f
*File
) error
{ _
, err
:= f
.WriteAt(make([]byte, 0), 0); return err
}},
2235 {"WriteString", func(f
*File
) error
{ _
, err
:= f
.WriteString(""); return err
}},
2238 // Test that all File methods give ErrInvalid if the receiver is nil.
2239 func TestNilFileMethods(t
*testing
.T
) {
2240 for _
, tt
:= range nilFileMethodTests
{
2243 if got
!= ErrInvalid
{
2244 t
.Errorf("%v should fail when f is nil; got %v", tt
.name
, got
)
2249 func mkdirTree(t
*testing
.T
, root
string, level
, max
int) {
2254 for i
:= 'a'; i
< 'c'; i
++ {
2255 dir
:= filepath
.Join(root
, string(i
))
2256 if err
:= Mkdir(dir
, 0700); err
!= nil {
2259 mkdirTree(t
, dir
, level
, max
)
2263 // Test that simultaneous RemoveAll do not report an error.
2264 // As long as it gets removed, we should be happy.
2265 func TestRemoveAllRace(t
*testing
.T
) {
2266 if runtime
.GOOS
== "windows" {
2267 // Windows has very strict rules about things like
2268 // removing directories while someone else has
2269 // them open. The racing doesn't work out nicely
2270 // like it does on Unix.
2271 t
.Skip("skipping on windows")
2274 n
:= runtime
.GOMAXPROCS(16)
2275 defer runtime
.GOMAXPROCS(n
)
2276 root
, err
:= ioutil
.TempDir("", "issue")
2280 mkdirTree(t
, root
, 1, 6)
2281 hold
:= make(chan struct{})
2282 var wg sync
.WaitGroup
2283 for i
:= 0; i
< 4; i
++ {
2288 err
:= RemoveAll(root
)
2290 t
.Errorf("unexpected error: %T, %q", err
, err
)
2294 close(hold
) // let workers race to remove root
2298 // Test that reading from a pipe doesn't use up a thread.
2299 func TestPipeThreads(t
*testing
.T
) {
2300 switch runtime
.GOOS
{
2302 t
.Skip("skipping on FreeBSD; issue 19093")
2303 case "illumos", "solaris":
2304 t
.Skip("skipping on Solaris and illumos; issue 19111")
2306 t
.Skip("skipping on Windows; issue 19098")
2308 t
.Skip("skipping on Plan 9; does not support runtime poller")
2310 t
.Skip("skipping on js; no support for os.Pipe")
2315 // OpenBSD has a low default for max number of files.
2316 if runtime
.GOOS
== "openbsd" {
2320 r
:= make([]*File
, threads
)
2321 w
:= make([]*File
, threads
)
2322 for i
:= 0; i
< threads
; i
++ {
2323 rp
, wp
, err
:= Pipe()
2325 for j
:= 0; j
< i
; j
++ {
2335 defer debug
.SetMaxThreads(debug
.SetMaxThreads(threads
/ 2))
2337 creading
:= make(chan bool, threads
)
2338 cdone
:= make(chan bool, threads
)
2339 for i
:= 0; i
< threads
; i
++ {
2343 if _
, err
:= r
[i
].Read(b
[:]); err
!= nil {
2346 if err
:= r
[i
].Close(); err
!= nil {
2353 for i
:= 0; i
< threads
; i
++ {
2357 // If we are still alive, it means that the 100 goroutines did
2358 // not require 100 threads.
2360 for i
:= 0; i
< threads
; i
++ {
2361 if _
, err
:= w
[i
].Write([]byte{0}); err
!= nil {
2364 if err
:= w
[i
].Close(); err
!= nil {
2371 func testDoubleCloseError(t
*testing
.T
, path
string) {
2372 file
, err
:= Open(path
)
2376 if err
:= file
.Close(); err
!= nil {
2377 t
.Fatalf("unexpected error from Close: %v", err
)
2379 if err
:= file
.Close(); err
== nil {
2380 t
.Error("second Close did not fail")
2381 } else if pe
, ok
:= err
.(*PathError
); !ok
{
2382 t
.Errorf("second Close returned unexpected error type %T; expected os.PathError", pe
)
2383 } else if pe
.Err
!= ErrClosed
{
2384 t
.Errorf("second Close returned %q, wanted %q", err
, ErrClosed
)
2386 t
.Logf("second close returned expected error %q", err
)
2390 func TestDoubleCloseError(t
*testing
.T
) {
2391 testDoubleCloseError(t
, filepath
.Join(sfdir
, sfname
))
2392 testDoubleCloseError(t
, sfdir
)
2395 func TestUserHomeDir(t
*testing
.T
) {
2396 dir
, err
:= UserHomeDir()
2397 if dir
== "" && err
== nil {
2398 t
.Fatal("UserHomeDir returned an empty string but no error")
2401 t
.Skipf("UserHomeDir failed: %v", err
)
2403 fi
, err
:= Stat(dir
)
2408 t
.Fatalf("dir %s is not directory; type = %v", dir
, fi
.Mode())
2412 func TestDirSeek(t
*testing
.T
) {
2413 if runtime
.GOOS
== "windows" {
2414 testenv
.SkipFlaky(t
, 36019)
2424 dirnames1
, err
:= f
.Readdirnames(0)
2429 ret
, err
:= f
.Seek(0, 0)
2434 t
.Fatalf("seek result not zero: %d", ret
)
2437 dirnames2
, err
:= f
.Readdirnames(0)
2443 if len(dirnames1
) != len(dirnames2
) {
2444 t
.Fatalf("listings have different lengths: %d and %d\n", len(dirnames1
), len(dirnames2
))
2446 for i
, n1
:= range dirnames1
{
2449 t
.Fatalf("different name i=%d n1=%s n2=%s\n", i
, n1
, n2
)
2454 // Test that opening a file does not change its permissions. Issue 38225.
2455 func TestOpenFileKeepsPermissions(t
*testing
.T
) {
2457 dir
, err
:= ioutil
.TempDir("", "TestOpenFileKeepsPermissions")
2461 defer RemoveAll(dir
)
2462 name
:= filepath
.Join(dir
, "x")
2463 f
, err
:= Create(name
)
2467 if err
:= f
.Close(); err
!= nil {
2470 f
, err
= OpenFile(name
, O_WRONLY|O_CREATE|O_TRUNC
, 0)
2474 if fi
, err
:= f
.Stat(); err
!= nil {
2476 } else if fi
.Mode()&0222 == 0 {
2477 t
.Errorf("f.Stat.Mode after OpenFile is %v, should be writable", fi
.Mode())
2479 if err
:= f
.Close(); err
!= nil {
2482 if fi
, err
:= Stat(name
); err
!= nil {
2484 } else if fi
.Mode()&0222 == 0 {
2485 t
.Errorf("Stat after OpenFile is %v, should be writable", fi
.Mode())