Home | History | Annotate | Download | only in os
      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.
      4 
      5 package os_test
      6 
      7 import (
      8 	"bytes"
      9 	"errors"
     10 	"flag"
     11 	"fmt"
     12 	"internal/testenv"
     13 	"io"
     14 	"io/ioutil"
     15 	. "os"
     16 	osexec "os/exec"
     17 	"path/filepath"
     18 	"reflect"
     19 	"runtime"
     20 	"runtime/debug"
     21 	"sort"
     22 	"strings"
     23 	"sync"
     24 	"syscall"
     25 	"testing"
     26 	"time"
     27 )
     28 
     29 var dot = []string{
     30 	"dir_unix.go",
     31 	"env.go",
     32 	"error.go",
     33 	"file.go",
     34 	"os_test.go",
     35 	"types.go",
     36 	"stat_darwin.go",
     37 	"stat_linux.go",
     38 }
     39 
     40 type sysDir struct {
     41 	name  string
     42 	files []string
     43 }
     44 
     45 var sysdir = func() *sysDir {
     46 	switch runtime.GOOS {
     47 	case "android":
     48 		return &sysDir{
     49 			"/system/lib",
     50 			[]string{
     51 				"libmedia.so",
     52 				"libpowermanager.so",
     53 			},
     54 		}
     55 	case "darwin":
     56 		switch runtime.GOARCH {
     57 		case "arm", "arm64":
     58 			wd, err := syscall.Getwd()
     59 			if err != nil {
     60 				wd = err.Error()
     61 			}
     62 			return &sysDir{
     63 				filepath.Join(wd, "..", ".."),
     64 				[]string{
     65 					"ResourceRules.plist",
     66 					"Info.plist",
     67 				},
     68 			}
     69 		}
     70 	case "windows":
     71 		return &sysDir{
     72 			Getenv("SystemRoot") + "\\system32\\drivers\\etc",
     73 			[]string{
     74 				"networks",
     75 				"protocol",
     76 				"services",
     77 			},
     78 		}
     79 	case "plan9":
     80 		return &sysDir{
     81 			"/lib/ndb",
     82 			[]string{
     83 				"common",
     84 				"local",
     85 			},
     86 		}
     87 	}
     88 	return &sysDir{
     89 		"/etc",
     90 		[]string{
     91 			"group",
     92 			"hosts",
     93 			"passwd",
     94 		},
     95 	}
     96 }()
     97 
     98 func size(name string, t *testing.T) int64 {
     99 	file, err := Open(name)
    100 	if err != nil {
    101 		t.Fatal("open failed:", err)
    102 	}
    103 	defer file.Close()
    104 	var buf [100]byte
    105 	len := 0
    106 	for {
    107 		n, e := file.Read(buf[0:])
    108 		len += n
    109 		if e == io.EOF {
    110 			break
    111 		}
    112 		if e != nil {
    113 			t.Fatal("read failed:", e)
    114 		}
    115 	}
    116 	return int64(len)
    117 }
    118 
    119 func equal(name1, name2 string) (r bool) {
    120 	switch runtime.GOOS {
    121 	case "windows":
    122 		r = strings.ToLower(name1) == strings.ToLower(name2)
    123 	default:
    124 		r = name1 == name2
    125 	}
    126 	return
    127 }
    128 
    129 // localTmp returns a local temporary directory not on NFS.
    130 func localTmp() string {
    131 	switch runtime.GOOS {
    132 	case "android", "windows":
    133 		return TempDir()
    134 	case "darwin":
    135 		switch runtime.GOARCH {
    136 		case "arm", "arm64":
    137 			return TempDir()
    138 		}
    139 	}
    140 	return "/tmp"
    141 }
    142 
    143 func newFile(testName string, t *testing.T) (f *File) {
    144 	f, err := ioutil.TempFile(localTmp(), "_Go_"+testName)
    145 	if err != nil {
    146 		t.Fatalf("TempFile %s: %s", testName, err)
    147 	}
    148 	return
    149 }
    150 
    151 func newDir(testName string, t *testing.T) (name string) {
    152 	name, err := ioutil.TempDir(localTmp(), "_Go_"+testName)
    153 	if err != nil {
    154 		t.Fatalf("TempDir %s: %s", testName, err)
    155 	}
    156 	return
    157 }
    158 
    159 var sfdir = sysdir.name
    160 var sfname = sysdir.files[0]
    161 
    162 func TestStat(t *testing.T) {
    163 	path := sfdir + "/" + sfname
    164 	dir, err := Stat(path)
    165 	if err != nil {
    166 		t.Fatal("stat failed:", err)
    167 	}
    168 	if !equal(sfname, dir.Name()) {
    169 		t.Error("name should be ", sfname, "; is", dir.Name())
    170 	}
    171 	filesize := size(path, t)
    172 	if dir.Size() != filesize {
    173 		t.Error("size should be", filesize, "; is", dir.Size())
    174 	}
    175 }
    176 
    177 func TestStatError(t *testing.T) {
    178 	defer chtmpdir(t)()
    179 
    180 	path := "no-such-file"
    181 	Remove(path) // Just in case
    182 
    183 	fi, err := Stat(path)
    184 	if err == nil {
    185 		t.Fatal("got nil, want error")
    186 	}
    187 	if fi != nil {
    188 		t.Errorf("got %v, want nil", fi)
    189 	}
    190 	if perr, ok := err.(*PathError); !ok {
    191 		t.Errorf("got %T, want %T", err, perr)
    192 	}
    193 
    194 	testenv.MustHaveSymlink(t)
    195 
    196 	link := "symlink"
    197 	Remove(link) // Just in case
    198 	err = Symlink(path, link)
    199 	if err != nil {
    200 		t.Fatal(err)
    201 	}
    202 	defer Remove(link)
    203 
    204 	fi, err = Stat(link)
    205 	if err == nil {
    206 		t.Fatal("got nil, want error")
    207 	}
    208 	if fi != nil {
    209 		t.Errorf("got %v, want nil", fi)
    210 	}
    211 	if perr, ok := err.(*PathError); !ok {
    212 		t.Errorf("got %T, want %T", err, perr)
    213 	}
    214 }
    215 
    216 func TestFstat(t *testing.T) {
    217 	path := sfdir + "/" + sfname
    218 	file, err1 := Open(path)
    219 	if err1 != nil {
    220 		t.Fatal("open failed:", err1)
    221 	}
    222 	defer file.Close()
    223 	dir, err2 := file.Stat()
    224 	if err2 != nil {
    225 		t.Fatal("fstat failed:", err2)
    226 	}
    227 	if !equal(sfname, dir.Name()) {
    228 		t.Error("name should be ", sfname, "; is", dir.Name())
    229 	}
    230 	filesize := size(path, t)
    231 	if dir.Size() != filesize {
    232 		t.Error("size should be", filesize, "; is", dir.Size())
    233 	}
    234 }
    235 
    236 func TestLstat(t *testing.T) {
    237 	path := sfdir + "/" + sfname
    238 	dir, err := Lstat(path)
    239 	if err != nil {
    240 		t.Fatal("lstat failed:", err)
    241 	}
    242 	if !equal(sfname, dir.Name()) {
    243 		t.Error("name should be ", sfname, "; is", dir.Name())
    244 	}
    245 	filesize := size(path, t)
    246 	if dir.Size() != filesize {
    247 		t.Error("size should be", filesize, "; is", dir.Size())
    248 	}
    249 }
    250 
    251 // Read with length 0 should not return EOF.
    252 func TestRead0(t *testing.T) {
    253 	path := sfdir + "/" + sfname
    254 	f, err := Open(path)
    255 	if err != nil {
    256 		t.Fatal("open failed:", err)
    257 	}
    258 	defer f.Close()
    259 
    260 	b := make([]byte, 0)
    261 	n, err := f.Read(b)
    262 	if n != 0 || err != nil {
    263 		t.Errorf("Read(0) = %d, %v, want 0, nil", n, err)
    264 	}
    265 	b = make([]byte, 100)
    266 	n, err = f.Read(b)
    267 	if n <= 0 || err != nil {
    268 		t.Errorf("Read(100) = %d, %v, want >0, nil", n, err)
    269 	}
    270 }
    271 
    272 // Reading a closed file should should return ErrClosed error
    273 func TestReadClosed(t *testing.T) {
    274 	path := sfdir + "/" + sfname
    275 	file, err := Open(path)
    276 	if err != nil {
    277 		t.Fatal("open failed:", err)
    278 	}
    279 	file.Close() // close immediately
    280 
    281 	b := make([]byte, 100)
    282 	_, err = file.Read(b)
    283 
    284 	e, ok := err.(*PathError)
    285 	if !ok {
    286 		t.Fatalf("Read: %T(%v), want PathError", e, e)
    287 	}
    288 
    289 	if e.Err != ErrClosed {
    290 		t.Errorf("Read: %v, want PathError(ErrClosed)", e)
    291 	}
    292 }
    293 
    294 func testReaddirnames(dir string, contents []string, t *testing.T) {
    295 	file, err := Open(dir)
    296 	if err != nil {
    297 		t.Fatalf("open %q failed: %v", dir, err)
    298 	}
    299 	defer file.Close()
    300 	s, err2 := file.Readdirnames(-1)
    301 	if err2 != nil {
    302 		t.Fatalf("readdirnames %q failed: %v", dir, err2)
    303 	}
    304 	for _, m := range contents {
    305 		found := false
    306 		for _, n := range s {
    307 			if n == "." || n == ".." {
    308 				t.Errorf("got %s in directory", n)
    309 			}
    310 			if equal(m, n) {
    311 				if found {
    312 					t.Error("present twice:", m)
    313 				}
    314 				found = true
    315 			}
    316 		}
    317 		if !found {
    318 			t.Error("could not find", m)
    319 		}
    320 	}
    321 }
    322 
    323 func testReaddir(dir string, contents []string, t *testing.T) {
    324 	file, err := Open(dir)
    325 	if err != nil {
    326 		t.Fatalf("open %q failed: %v", dir, err)
    327 	}
    328 	defer file.Close()
    329 	s, err2 := file.Readdir(-1)
    330 	if err2 != nil {
    331 		t.Fatalf("readdir %q failed: %v", dir, err2)
    332 	}
    333 	for _, m := range contents {
    334 		found := false
    335 		for _, n := range s {
    336 			if equal(m, n.Name()) {
    337 				if found {
    338 					t.Error("present twice:", m)
    339 				}
    340 				found = true
    341 			}
    342 		}
    343 		if !found {
    344 			t.Error("could not find", m)
    345 		}
    346 	}
    347 }
    348 
    349 func TestReaddirnames(t *testing.T) {
    350 	testReaddirnames(".", dot, t)
    351 	testReaddirnames(sysdir.name, sysdir.files, t)
    352 }
    353 
    354 func TestReaddir(t *testing.T) {
    355 	testReaddir(".", dot, t)
    356 	testReaddir(sysdir.name, sysdir.files, t)
    357 }
    358 
    359 func benchmarkReaddirname(path string, b *testing.B) {
    360 	var nentries int
    361 	for i := 0; i < b.N; i++ {
    362 		f, err := Open(path)
    363 		if err != nil {
    364 			b.Fatalf("open %q failed: %v", path, err)
    365 		}
    366 		ns, err := f.Readdirnames(-1)
    367 		f.Close()
    368 		if err != nil {
    369 			b.Fatalf("readdirnames %q failed: %v", path, err)
    370 		}
    371 		nentries = len(ns)
    372 	}
    373 	b.Logf("benchmarkReaddirname %q: %d entries", path, nentries)
    374 }
    375 
    376 func benchmarkReaddir(path string, b *testing.B) {
    377 	var nentries int
    378 	for i := 0; i < b.N; i++ {
    379 		f, err := Open(path)
    380 		if err != nil {
    381 			b.Fatalf("open %q failed: %v", path, err)
    382 		}
    383 		fs, err := f.Readdir(-1)
    384 		f.Close()
    385 		if err != nil {
    386 			b.Fatalf("readdir %q failed: %v", path, err)
    387 		}
    388 		nentries = len(fs)
    389 	}
    390 	b.Logf("benchmarkReaddir %q: %d entries", path, nentries)
    391 }
    392 
    393 func BenchmarkReaddirname(b *testing.B) {
    394 	benchmarkReaddirname(".", b)
    395 }
    396 
    397 func BenchmarkReaddir(b *testing.B) {
    398 	benchmarkReaddir(".", b)
    399 }
    400 
    401 func benchmarkStat(b *testing.B, path string) {
    402 	b.ResetTimer()
    403 	for i := 0; i < b.N; i++ {
    404 		_, err := Stat(path)
    405 		if err != nil {
    406 			b.Fatalf("Stat(%q) failed: %v", path, err)
    407 		}
    408 	}
    409 }
    410 
    411 func benchmarkLstat(b *testing.B, path string) {
    412 	b.ResetTimer()
    413 	for i := 0; i < b.N; i++ {
    414 		_, err := Lstat(path)
    415 		if err != nil {
    416 			b.Fatalf("Lstat(%q) failed: %v", path, err)
    417 		}
    418 	}
    419 }
    420 
    421 func BenchmarkStatDot(b *testing.B) {
    422 	benchmarkStat(b, ".")
    423 }
    424 
    425 func BenchmarkStatFile(b *testing.B) {
    426 	benchmarkStat(b, filepath.Join(runtime.GOROOT(), "src/os/os_test.go"))
    427 }
    428 
    429 func BenchmarkStatDir(b *testing.B) {
    430 	benchmarkStat(b, filepath.Join(runtime.GOROOT(), "src/os"))
    431 }
    432 
    433 func BenchmarkLstatDot(b *testing.B) {
    434 	benchmarkLstat(b, ".")
    435 }
    436 
    437 func BenchmarkLstatFile(b *testing.B) {
    438 	benchmarkLstat(b, filepath.Join(runtime.GOROOT(), "src/os/os_test.go"))
    439 }
    440 
    441 func BenchmarkLstatDir(b *testing.B) {
    442 	benchmarkLstat(b, filepath.Join(runtime.GOROOT(), "src/os"))
    443 }
    444 
    445 // Read the directory one entry at a time.
    446 func smallReaddirnames(file *File, length int, t *testing.T) []string {
    447 	names := make([]string, length)
    448 	count := 0
    449 	for {
    450 		d, err := file.Readdirnames(1)
    451 		if err == io.EOF {
    452 			break
    453 		}
    454 		if err != nil {
    455 			t.Fatalf("readdirnames %q failed: %v", file.Name(), err)
    456 		}
    457 		if len(d) == 0 {
    458 			t.Fatalf("readdirnames %q returned empty slice and no error", file.Name())
    459 		}
    460 		names[count] = d[0]
    461 		count++
    462 	}
    463 	return names[0:count]
    464 }
    465 
    466 // Check that reading a directory one entry at a time gives the same result
    467 // as reading it all at once.
    468 func TestReaddirnamesOneAtATime(t *testing.T) {
    469 	// big directory that doesn't change often.
    470 	dir := "/usr/bin"
    471 	switch runtime.GOOS {
    472 	case "android":
    473 		dir = "/system/bin"
    474 	case "darwin":
    475 		switch runtime.GOARCH {
    476 		case "arm", "arm64":
    477 			wd, err := Getwd()
    478 			if err != nil {
    479 				t.Fatal(err)
    480 			}
    481 			dir = wd
    482 		}
    483 	case "plan9":
    484 		dir = "/bin"
    485 	case "windows":
    486 		dir = Getenv("SystemRoot") + "\\system32"
    487 	}
    488 	file, err := Open(dir)
    489 	if err != nil {
    490 		t.Fatalf("open %q failed: %v", dir, err)
    491 	}
    492 	defer file.Close()
    493 	all, err1 := file.Readdirnames(-1)
    494 	if err1 != nil {
    495 		t.Fatalf("readdirnames %q failed: %v", dir, err1)
    496 	}
    497 	file1, err2 := Open(dir)
    498 	if err2 != nil {
    499 		t.Fatalf("open %q failed: %v", dir, err2)
    500 	}
    501 	defer file1.Close()
    502 	small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up
    503 	if len(small) < len(all) {
    504 		t.Fatalf("len(small) is %d, less than %d", len(small), len(all))
    505 	}
    506 	for i, n := range all {
    507 		if small[i] != n {
    508 			t.Errorf("small read %q mismatch: %v", small[i], n)
    509 		}
    510 	}
    511 }
    512 
    513 func TestReaddirNValues(t *testing.T) {
    514 	if testing.Short() {
    515 		t.Skip("test.short; skipping")
    516 	}
    517 	dir, err := ioutil.TempDir("", "")
    518 	if err != nil {
    519 		t.Fatalf("TempDir: %v", err)
    520 	}
    521 	defer RemoveAll(dir)
    522 	for i := 1; i <= 105; i++ {
    523 		f, err := Create(filepath.Join(dir, fmt.Sprintf("%d", i)))
    524 		if err != nil {
    525 			t.Fatalf("Create: %v", err)
    526 		}
    527 		f.Write([]byte(strings.Repeat("X", i)))
    528 		f.Close()
    529 	}
    530 
    531 	var d *File
    532 	openDir := func() {
    533 		var err error
    534 		d, err = Open(dir)
    535 		if err != nil {
    536 			t.Fatalf("Open directory: %v", err)
    537 		}
    538 	}
    539 
    540 	readDirExpect := func(n, want int, wantErr error) {
    541 		fi, err := d.Readdir(n)
    542 		if err != wantErr {
    543 			t.Fatalf("Readdir of %d got error %v, want %v", n, err, wantErr)
    544 		}
    545 		if g, e := len(fi), want; g != e {
    546 			t.Errorf("Readdir of %d got %d files, want %d", n, g, e)
    547 		}
    548 	}
    549 
    550 	readDirNamesExpect := func(n, want int, wantErr error) {
    551 		fi, err := d.Readdirnames(n)
    552 		if err != wantErr {
    553 			t.Fatalf("Readdirnames of %d got error %v, want %v", n, err, wantErr)
    554 		}
    555 		if g, e := len(fi), want; g != e {
    556 			t.Errorf("Readdirnames of %d got %d files, want %d", n, g, e)
    557 		}
    558 	}
    559 
    560 	for _, fn := range []func(int, int, error){readDirExpect, readDirNamesExpect} {
    561 		// Test the slurp case
    562 		openDir()
    563 		fn(0, 105, nil)
    564 		fn(0, 0, nil)
    565 		d.Close()
    566 
    567 		// Slurp with -1 instead
    568 		openDir()
    569 		fn(-1, 105, nil)
    570 		fn(-2, 0, nil)
    571 		fn(0, 0, nil)
    572 		d.Close()
    573 
    574 		// Test the bounded case
    575 		openDir()
    576 		fn(1, 1, nil)
    577 		fn(2, 2, nil)
    578 		fn(105, 102, nil) // and tests buffer >100 case
    579 		fn(3, 0, io.EOF)
    580 		d.Close()
    581 	}
    582 }
    583 
    584 func touch(t *testing.T, name string) {
    585 	f, err := Create(name)
    586 	if err != nil {
    587 		t.Fatal(err)
    588 	}
    589 	if err := f.Close(); err != nil {
    590 		t.Fatal(err)
    591 	}
    592 }
    593 
    594 func TestReaddirStatFailures(t *testing.T) {
    595 	switch runtime.GOOS {
    596 	case "windows", "plan9":
    597 		// Windows and Plan 9 already do this correctly,
    598 		// but are structured with different syscalls such
    599 		// that they don't use Lstat, so the hook below for
    600 		// testing it wouldn't work.
    601 		t.Skipf("skipping test on %v", runtime.GOOS)
    602 	}
    603 	dir, err := ioutil.TempDir("", "")
    604 	if err != nil {
    605 		t.Fatalf("TempDir: %v", err)
    606 	}
    607 	defer RemoveAll(dir)
    608 	touch(t, filepath.Join(dir, "good1"))
    609 	touch(t, filepath.Join(dir, "x")) // will disappear or have an error
    610 	touch(t, filepath.Join(dir, "good2"))
    611 	defer func() {
    612 		*LstatP = Lstat
    613 	}()
    614 	var xerr error // error to return for x
    615 	*LstatP = func(path string) (FileInfo, error) {
    616 		if xerr != nil && strings.HasSuffix(path, "x") {
    617 			return nil, xerr
    618 		}
    619 		return Lstat(path)
    620 	}
    621 	readDir := func() ([]FileInfo, error) {
    622 		d, err := Open(dir)
    623 		if err != nil {
    624 			t.Fatal(err)
    625 		}
    626 		defer d.Close()
    627 		return d.Readdir(-1)
    628 	}
    629 	mustReadDir := func(testName string) []FileInfo {
    630 		fis, err := readDir()
    631 		if err != nil {
    632 			t.Fatalf("%s: Readdir: %v", testName, err)
    633 		}
    634 		return fis
    635 	}
    636 	names := func(fis []FileInfo) []string {
    637 		s := make([]string, len(fis))
    638 		for i, fi := range fis {
    639 			s[i] = fi.Name()
    640 		}
    641 		sort.Strings(s)
    642 		return s
    643 	}
    644 
    645 	if got, want := names(mustReadDir("initial readdir")),
    646 		[]string{"good1", "good2", "x"}; !reflect.DeepEqual(got, want) {
    647 		t.Errorf("initial readdir got %q; want %q", got, want)
    648 	}
    649 
    650 	xerr = ErrNotExist
    651 	if got, want := names(mustReadDir("with x disappearing")),
    652 		[]string{"good1", "good2"}; !reflect.DeepEqual(got, want) {
    653 		t.Errorf("with x disappearing, got %q; want %q", got, want)
    654 	}
    655 
    656 	xerr = errors.New("some real error")
    657 	if _, err := readDir(); err != xerr {
    658 		t.Errorf("with a non-ErrNotExist error, got error %v; want %v", err, xerr)
    659 	}
    660 }
    661 
    662 // Readdir on a regular file should fail.
    663 func TestReaddirOfFile(t *testing.T) {
    664 	f, err := ioutil.TempFile("", "_Go_ReaddirOfFile")
    665 	if err != nil {
    666 		t.Fatal(err)
    667 	}
    668 	defer Remove(f.Name())
    669 	f.Write([]byte("foo"))
    670 	f.Close()
    671 	reg, err := Open(f.Name())
    672 	if err != nil {
    673 		t.Fatal(err)
    674 	}
    675 	defer reg.Close()
    676 
    677 	names, err := reg.Readdirnames(-1)
    678 	if err == nil {
    679 		t.Error("Readdirnames succeeded; want non-nil error")
    680 	}
    681 	if len(names) > 0 {
    682 		t.Errorf("unexpected dir names in regular file: %q", names)
    683 	}
    684 }
    685 
    686 func TestHardLink(t *testing.T) {
    687 	testenv.MustHaveLink(t)
    688 
    689 	defer chtmpdir(t)()
    690 	from, to := "hardlinktestfrom", "hardlinktestto"
    691 	Remove(from) // Just in case.
    692 	file, err := Create(to)
    693 	if err != nil {
    694 		t.Fatalf("open %q failed: %v", to, err)
    695 	}
    696 	defer Remove(to)
    697 	if err = file.Close(); err != nil {
    698 		t.Errorf("close %q failed: %v", to, err)
    699 	}
    700 	err = Link(to, from)
    701 	if err != nil {
    702 		t.Fatalf("link %q, %q failed: %v", to, from, err)
    703 	}
    704 
    705 	none := "hardlinktestnone"
    706 	err = Link(none, none)
    707 	// Check the returned error is well-formed.
    708 	if lerr, ok := err.(*LinkError); !ok || lerr.Error() == "" {
    709 		t.Errorf("link %q, %q failed to return a valid error", none, none)
    710 	}
    711 
    712 	defer Remove(from)
    713 	tostat, err := Stat(to)
    714 	if err != nil {
    715 		t.Fatalf("stat %q failed: %v", to, err)
    716 	}
    717 	fromstat, err := Stat(from)
    718 	if err != nil {
    719 		t.Fatalf("stat %q failed: %v", from, err)
    720 	}
    721 	if !SameFile(tostat, fromstat) {
    722 		t.Errorf("link %q, %q did not create hard link", to, from)
    723 	}
    724 	// We should not be able to perform the same Link() a second time
    725 	err = Link(to, from)
    726 	switch err := err.(type) {
    727 	case *LinkError:
    728 		if err.Op != "link" {
    729 			t.Errorf("Link(%q, %q) err.Op = %q; want %q", to, from, err.Op, "link")
    730 		}
    731 		if err.Old != to {
    732 			t.Errorf("Link(%q, %q) err.Old = %q; want %q", to, from, err.Old, to)
    733 		}
    734 		if err.New != from {
    735 			t.Errorf("Link(%q, %q) err.New = %q; want %q", to, from, err.New, from)
    736 		}
    737 		if !IsExist(err.Err) {
    738 			t.Errorf("Link(%q, %q) err.Err = %q; want %q", to, from, err.Err, "file exists error")
    739 		}
    740 	case nil:
    741 		t.Errorf("link %q, %q: expected error, got nil", from, to)
    742 	default:
    743 		t.Errorf("link %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err)
    744 	}
    745 }
    746 
    747 // chtmpdir changes the working directory to a new temporary directory and
    748 // provides a cleanup function. Used when PWD is read-only.
    749 func chtmpdir(t *testing.T) func() {
    750 	if runtime.GOOS != "darwin" || (runtime.GOARCH != "arm" && runtime.GOARCH != "arm64") {
    751 		return func() {} // only needed on darwin/arm{,64}
    752 	}
    753 	oldwd, err := Getwd()
    754 	if err != nil {
    755 		t.Fatalf("chtmpdir: %v", err)
    756 	}
    757 	d, err := ioutil.TempDir("", "test")
    758 	if err != nil {
    759 		t.Fatalf("chtmpdir: %v", err)
    760 	}
    761 	if err := Chdir(d); err != nil {
    762 		t.Fatalf("chtmpdir: %v", err)
    763 	}
    764 	return func() {
    765 		if err := Chdir(oldwd); err != nil {
    766 			t.Fatalf("chtmpdir: %v", err)
    767 		}
    768 		RemoveAll(d)
    769 	}
    770 }
    771 
    772 func TestSymlink(t *testing.T) {
    773 	testenv.MustHaveSymlink(t)
    774 
    775 	defer chtmpdir(t)()
    776 	from, to := "symlinktestfrom", "symlinktestto"
    777 	Remove(from) // Just in case.
    778 	file, err := Create(to)
    779 	if err != nil {
    780 		t.Fatalf("Create(%q) failed: %v", to, err)
    781 	}
    782 	defer Remove(to)
    783 	if err = file.Close(); err != nil {
    784 		t.Errorf("Close(%q) failed: %v", to, err)
    785 	}
    786 	err = Symlink(to, from)
    787 	if err != nil {
    788 		t.Fatalf("Symlink(%q, %q) failed: %v", to, from, err)
    789 	}
    790 	defer Remove(from)
    791 	tostat, err := Lstat(to)
    792 	if err != nil {
    793 		t.Fatalf("Lstat(%q) failed: %v", to, err)
    794 	}
    795 	if tostat.Mode()&ModeSymlink != 0 {
    796 		t.Fatalf("Lstat(%q).Mode()&ModeSymlink = %v, want 0", to, tostat.Mode()&ModeSymlink)
    797 	}
    798 	fromstat, err := Stat(from)
    799 	if err != nil {
    800 		t.Fatalf("Stat(%q) failed: %v", from, err)
    801 	}
    802 	if !SameFile(tostat, fromstat) {
    803 		t.Errorf("Symlink(%q, %q) did not create symlink", to, from)
    804 	}
    805 	fromstat, err = Lstat(from)
    806 	if err != nil {
    807 		t.Fatalf("Lstat(%q) failed: %v", from, err)
    808 	}
    809 	if fromstat.Mode()&ModeSymlink == 0 {
    810 		t.Fatalf("Lstat(%q).Mode()&ModeSymlink = 0, want %v", from, ModeSymlink)
    811 	}
    812 	fromstat, err = Stat(from)
    813 	if err != nil {
    814 		t.Fatalf("Stat(%q) failed: %v", from, err)
    815 	}
    816 	if fromstat.Name() != from {
    817 		t.Errorf("Stat(%q).Name() = %q, want %q", from, fromstat.Name(), from)
    818 	}
    819 	if fromstat.Mode()&ModeSymlink != 0 {
    820 		t.Fatalf("Stat(%q).Mode()&ModeSymlink = %v, want 0", from, fromstat.Mode()&ModeSymlink)
    821 	}
    822 	s, err := Readlink(from)
    823 	if err != nil {
    824 		t.Fatalf("Readlink(%q) failed: %v", from, err)
    825 	}
    826 	if s != to {
    827 		t.Fatalf("Readlink(%q) = %q, want %q", from, s, to)
    828 	}
    829 	file, err = Open(from)
    830 	if err != nil {
    831 		t.Fatalf("Open(%q) failed: %v", from, err)
    832 	}
    833 	file.Close()
    834 }
    835 
    836 func TestLongSymlink(t *testing.T) {
    837 	testenv.MustHaveSymlink(t)
    838 
    839 	defer chtmpdir(t)()
    840 	s := "0123456789abcdef"
    841 	// Long, but not too long: a common limit is 255.
    842 	s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s
    843 	from := "longsymlinktestfrom"
    844 	Remove(from) // Just in case.
    845 	err := Symlink(s, from)
    846 	if err != nil {
    847 		t.Fatalf("symlink %q, %q failed: %v", s, from, err)
    848 	}
    849 	defer Remove(from)
    850 	r, err := Readlink(from)
    851 	if err != nil {
    852 		t.Fatalf("readlink %q failed: %v", from, err)
    853 	}
    854 	if r != s {
    855 		t.Fatalf("after symlink %q != %q", r, s)
    856 	}
    857 }
    858 
    859 func TestRename(t *testing.T) {
    860 	defer chtmpdir(t)()
    861 	from, to := "renamefrom", "renameto"
    862 	// Ensure we are not testing the overwrite case here.
    863 	Remove(from)
    864 	Remove(to)
    865 
    866 	file, err := Create(from)
    867 	if err != nil {
    868 		t.Fatalf("open %q failed: %v", from, err)
    869 	}
    870 	if err = file.Close(); err != nil {
    871 		t.Errorf("close %q failed: %v", from, err)
    872 	}
    873 	err = Rename(from, to)
    874 	if err != nil {
    875 		t.Fatalf("rename %q, %q failed: %v", to, from, err)
    876 	}
    877 	defer Remove(to)
    878 	_, err = Stat(to)
    879 	if err != nil {
    880 		t.Errorf("stat %q failed: %v", to, err)
    881 	}
    882 }
    883 
    884 func TestRenameOverwriteDest(t *testing.T) {
    885 	defer chtmpdir(t)()
    886 	from, to := "renamefrom", "renameto"
    887 	// Just in case.
    888 	Remove(from)
    889 	Remove(to)
    890 
    891 	toData := []byte("to")
    892 	fromData := []byte("from")
    893 
    894 	err := ioutil.WriteFile(to, toData, 0777)
    895 	if err != nil {
    896 		t.Fatalf("write file %q failed: %v", to, err)
    897 	}
    898 
    899 	err = ioutil.WriteFile(from, fromData, 0777)
    900 	if err != nil {
    901 		t.Fatalf("write file %q failed: %v", from, err)
    902 	}
    903 	err = Rename(from, to)
    904 	if err != nil {
    905 		t.Fatalf("rename %q, %q failed: %v", to, from, err)
    906 	}
    907 	defer Remove(to)
    908 
    909 	_, err = Stat(from)
    910 	if err == nil {
    911 		t.Errorf("from file %q still exists", from)
    912 	}
    913 	if err != nil && !IsNotExist(err) {
    914 		t.Fatalf("stat from: %v", err)
    915 	}
    916 	toFi, err := Stat(to)
    917 	if err != nil {
    918 		t.Fatalf("stat %q failed: %v", to, err)
    919 	}
    920 	if toFi.Size() != int64(len(fromData)) {
    921 		t.Errorf(`"to" size = %d; want %d (old "from" size)`, toFi.Size(), len(fromData))
    922 	}
    923 }
    924 
    925 func TestRenameFailed(t *testing.T) {
    926 	defer chtmpdir(t)()
    927 	from, to := "renamefrom", "renameto"
    928 	// Ensure we are not testing the overwrite case here.
    929 	Remove(from)
    930 	Remove(to)
    931 
    932 	err := Rename(from, to)
    933 	switch err := err.(type) {
    934 	case *LinkError:
    935 		if err.Op != "rename" {
    936 			t.Errorf("rename %q, %q: err.Op: want %q, got %q", from, to, "rename", err.Op)
    937 		}
    938 		if err.Old != from {
    939 			t.Errorf("rename %q, %q: err.Old: want %q, got %q", from, to, from, err.Old)
    940 		}
    941 		if err.New != to {
    942 			t.Errorf("rename %q, %q: err.New: want %q, got %q", from, to, to, err.New)
    943 		}
    944 	case nil:
    945 		t.Errorf("rename %q, %q: expected error, got nil", from, to)
    946 
    947 		// cleanup whatever was placed in "renameto"
    948 		Remove(to)
    949 	default:
    950 		t.Errorf("rename %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err)
    951 	}
    952 }
    953 
    954 func TestRenameNotExisting(t *testing.T) {
    955 	defer chtmpdir(t)()
    956 	from, to := "doesnt-exist", "dest"
    957 
    958 	Mkdir(to, 0777)
    959 	defer Remove(to)
    960 
    961 	if err := Rename(from, to); !IsNotExist(err) {
    962 		t.Errorf("Rename(%q, %q) = %v; want an IsNotExist error", from, to, err)
    963 	}
    964 }
    965 
    966 func TestRenameToDirFailed(t *testing.T) {
    967 	defer chtmpdir(t)()
    968 	from, to := "renamefrom", "renameto"
    969 
    970 	Remove(from)
    971 	Remove(to)
    972 	Mkdir(from, 0777)
    973 	Mkdir(to, 0777)
    974 	defer Remove(from)
    975 	defer Remove(to)
    976 
    977 	err := Rename(from, to)
    978 	switch err := err.(type) {
    979 	case *LinkError:
    980 		if err.Op != "rename" {
    981 			t.Errorf("rename %q, %q: err.Op: want %q, got %q", from, to, "rename", err.Op)
    982 		}
    983 		if err.Old != from {
    984 			t.Errorf("rename %q, %q: err.Old: want %q, got %q", from, to, from, err.Old)
    985 		}
    986 		if err.New != to {
    987 			t.Errorf("rename %q, %q: err.New: want %q, got %q", from, to, to, err.New)
    988 		}
    989 	case nil:
    990 		t.Errorf("rename %q, %q: expected error, got nil", from, to)
    991 
    992 		// cleanup whatever was placed in "renameto"
    993 		Remove(to)
    994 	default:
    995 		t.Errorf("rename %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err)
    996 	}
    997 }
    998 
    999 func exec(t *testing.T, dir, cmd string, args []string, expect string) {
   1000 	r, w, err := Pipe()
   1001 	if err != nil {
   1002 		t.Fatalf("Pipe: %v", err)
   1003 	}
   1004 	defer r.Close()
   1005 	attr := &ProcAttr{Dir: dir, Files: []*File{nil, w, Stderr}}
   1006 	p, err := StartProcess(cmd, args, attr)
   1007 	if err != nil {
   1008 		t.Fatalf("StartProcess: %v", err)
   1009 	}
   1010 	w.Close()
   1011 
   1012 	var b bytes.Buffer
   1013 	io.Copy(&b, r)
   1014 	output := b.String()
   1015 
   1016 	fi1, _ := Stat(strings.TrimSpace(output))
   1017 	fi2, _ := Stat(expect)
   1018 	if !SameFile(fi1, fi2) {
   1019 		t.Errorf("exec %q returned %q wanted %q",
   1020 			strings.Join(append([]string{cmd}, args...), " "), output, expect)
   1021 	}
   1022 	p.Wait()
   1023 }
   1024 
   1025 func TestStartProcess(t *testing.T) {
   1026 	testenv.MustHaveExec(t)
   1027 
   1028 	var dir, cmd string
   1029 	var args []string
   1030 	switch runtime.GOOS {
   1031 	case "android":
   1032 		t.Skip("android doesn't have /bin/pwd")
   1033 	case "windows":
   1034 		cmd = Getenv("COMSPEC")
   1035 		dir = Getenv("SystemRoot")
   1036 		args = []string{"/c", "cd"}
   1037 	default:
   1038 		var err error
   1039 		cmd, err = osexec.LookPath("pwd")
   1040 		if err != nil {
   1041 			t.Fatalf("Can't find pwd: %v", err)
   1042 		}
   1043 		dir = "/"
   1044 		args = []string{}
   1045 		t.Logf("Testing with %v", cmd)
   1046 	}
   1047 	cmddir, cmdbase := filepath.Split(cmd)
   1048 	args = append([]string{cmdbase}, args...)
   1049 	// Test absolute executable path.
   1050 	exec(t, dir, cmd, args, dir)
   1051 	// Test relative executable path.
   1052 	exec(t, cmddir, cmdbase, args, cmddir)
   1053 }
   1054 
   1055 func checkMode(t *testing.T, path string, mode FileMode) {
   1056 	dir, err := Stat(path)
   1057 	if err != nil {
   1058 		t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
   1059 	}
   1060 	if dir.Mode()&0777 != mode {
   1061 		t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode(), mode)
   1062 	}
   1063 }
   1064 
   1065 func TestChmod(t *testing.T) {
   1066 	// Chmod is not supported under windows.
   1067 	if runtime.GOOS == "windows" {
   1068 		return
   1069 	}
   1070 	f := newFile("TestChmod", t)
   1071 	defer Remove(f.Name())
   1072 	defer f.Close()
   1073 
   1074 	if err := Chmod(f.Name(), 0456); err != nil {
   1075 		t.Fatalf("chmod %s 0456: %s", f.Name(), err)
   1076 	}
   1077 	checkMode(t, f.Name(), 0456)
   1078 
   1079 	if err := f.Chmod(0123); err != nil {
   1080 		t.Fatalf("chmod %s 0123: %s", f.Name(), err)
   1081 	}
   1082 	checkMode(t, f.Name(), 0123)
   1083 }
   1084 
   1085 func checkSize(t *testing.T, f *File, size int64) {
   1086 	dir, err := f.Stat()
   1087 	if err != nil {
   1088 		t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err)
   1089 	}
   1090 	if dir.Size() != size {
   1091 		t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size)
   1092 	}
   1093 }
   1094 
   1095 func TestFTruncate(t *testing.T) {
   1096 	f := newFile("TestFTruncate", t)
   1097 	defer Remove(f.Name())
   1098 	defer f.Close()
   1099 
   1100 	checkSize(t, f, 0)
   1101 	f.Write([]byte("hello, world\n"))
   1102 	checkSize(t, f, 13)
   1103 	f.Truncate(10)
   1104 	checkSize(t, f, 10)
   1105 	f.Truncate(1024)
   1106 	checkSize(t, f, 1024)
   1107 	f.Truncate(0)
   1108 	checkSize(t, f, 0)
   1109 	_, err := f.Write([]byte("surprise!"))
   1110 	if err == nil {
   1111 		checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
   1112 	}
   1113 }
   1114 
   1115 func TestTruncate(t *testing.T) {
   1116 	f := newFile("TestTruncate", t)
   1117 	defer Remove(f.Name())
   1118 	defer f.Close()
   1119 
   1120 	checkSize(t, f, 0)
   1121 	f.Write([]byte("hello, world\n"))
   1122 	checkSize(t, f, 13)
   1123 	Truncate(f.Name(), 10)
   1124 	checkSize(t, f, 10)
   1125 	Truncate(f.Name(), 1024)
   1126 	checkSize(t, f, 1024)
   1127 	Truncate(f.Name(), 0)
   1128 	checkSize(t, f, 0)
   1129 	_, err := f.Write([]byte("surprise!"))
   1130 	if err == nil {
   1131 		checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
   1132 	}
   1133 }
   1134 
   1135 // Use TempDir (via newFile) to make sure we're on a local file system,
   1136 // so that timings are not distorted by latency and caching.
   1137 // On NFS, timings can be off due to caching of meta-data on
   1138 // NFS servers (Issue 848).
   1139 func TestChtimes(t *testing.T) {
   1140 	f := newFile("TestChtimes", t)
   1141 	defer Remove(f.Name())
   1142 
   1143 	f.Write([]byte("hello, world\n"))
   1144 	f.Close()
   1145 
   1146 	testChtimes(t, f.Name())
   1147 }
   1148 
   1149 // Use TempDir (via newDir) to make sure we're on a local file system,
   1150 // so that timings are not distorted by latency and caching.
   1151 // On NFS, timings can be off due to caching of meta-data on
   1152 // NFS servers (Issue 848).
   1153 func TestChtimesDir(t *testing.T) {
   1154 	name := newDir("TestChtimes", t)
   1155 	defer RemoveAll(name)
   1156 
   1157 	testChtimes(t, name)
   1158 }
   1159 
   1160 func testChtimes(t *testing.T, name string) {
   1161 	st, err := Stat(name)
   1162 	if err != nil {
   1163 		t.Fatalf("Stat %s: %s", name, err)
   1164 	}
   1165 	preStat := st
   1166 
   1167 	// Move access and modification time back a second
   1168 	at := Atime(preStat)
   1169 	mt := preStat.ModTime()
   1170 	err = Chtimes(name, at.Add(-time.Second), mt.Add(-time.Second))
   1171 	if err != nil {
   1172 		t.Fatalf("Chtimes %s: %s", name, err)
   1173 	}
   1174 
   1175 	st, err = Stat(name)
   1176 	if err != nil {
   1177 		t.Fatalf("second Stat %s: %s", name, err)
   1178 	}
   1179 	postStat := st
   1180 
   1181 	pat := Atime(postStat)
   1182 	pmt := postStat.ModTime()
   1183 	if !pat.Before(at) {
   1184 		switch runtime.GOOS {
   1185 		case "plan9", "nacl":
   1186 			// Ignore.
   1187 			// Plan 9, NaCl:
   1188 			// Mtime is the time of the last change of
   1189 			// content.  Similarly, atime is set whenever
   1190 			// the contents are accessed; also, it is set
   1191 			// whenever mtime is set.
   1192 		case "netbsd":
   1193 			mounts, _ := ioutil.ReadFile("/proc/mounts")
   1194 			if strings.Contains(string(mounts), "noatime") {
   1195 				t.Logf("AccessTime didn't go backwards, but see a filesystem mounted noatime; ignoring. Issue 19293.")
   1196 			} else {
   1197 				t.Logf("AccessTime didn't go backwards; was=%v, after=%v (Ignoring on NetBSD, assuming noatime, Issue 19293)", at, pat)
   1198 			}
   1199 		default:
   1200 			t.Errorf("AccessTime didn't go backwards; was=%v, after=%v", at, pat)
   1201 		}
   1202 	}
   1203 
   1204 	if !pmt.Before(mt) {
   1205 		t.Errorf("ModTime didn't go backwards; was=%v, after=%v", mt, pmt)
   1206 	}
   1207 }
   1208 
   1209 func TestChdirAndGetwd(t *testing.T) {
   1210 	// TODO(brainman): file.Chdir() is not implemented on windows.
   1211 	if runtime.GOOS == "windows" {
   1212 		return
   1213 	}
   1214 	fd, err := Open(".")
   1215 	if err != nil {
   1216 		t.Fatalf("Open .: %s", err)
   1217 	}
   1218 	// These are chosen carefully not to be symlinks on a Mac
   1219 	// (unlike, say, /var, /etc), except /tmp, which we handle below.
   1220 	dirs := []string{"/", "/usr/bin", "/tmp"}
   1221 	// /usr/bin does not usually exist on Plan 9 or Android.
   1222 	switch runtime.GOOS {
   1223 	case "android":
   1224 		dirs = []string{"/", "/system/bin"}
   1225 	case "plan9":
   1226 		dirs = []string{"/", "/usr"}
   1227 	case "darwin":
   1228 		switch runtime.GOARCH {
   1229 		case "arm", "arm64":
   1230 			d1, err := ioutil.TempDir("", "d1")
   1231 			if err != nil {
   1232 				t.Fatalf("TempDir: %v", err)
   1233 			}
   1234 			d2, err := ioutil.TempDir("", "d2")
   1235 			if err != nil {
   1236 				t.Fatalf("TempDir: %v", err)
   1237 			}
   1238 			dirs = []string{d1, d2}
   1239 		}
   1240 	}
   1241 	oldwd := Getenv("PWD")
   1242 	for mode := 0; mode < 2; mode++ {
   1243 		for _, d := range dirs {
   1244 			if mode == 0 {
   1245 				err = Chdir(d)
   1246 			} else {
   1247 				fd1, err1 := Open(d)
   1248 				if err1 != nil {
   1249 					t.Errorf("Open %s: %s", d, err1)
   1250 					continue
   1251 				}
   1252 				err = fd1.Chdir()
   1253 				fd1.Close()
   1254 			}
   1255 			if d == "/tmp" {
   1256 				Setenv("PWD", "/tmp")
   1257 			}
   1258 			pwd, err1 := Getwd()
   1259 			Setenv("PWD", oldwd)
   1260 			err2 := fd.Chdir()
   1261 			if err2 != nil {
   1262 				// We changed the current directory and cannot go back.
   1263 				// Don't let the tests continue; they'll scribble
   1264 				// all over some other directory.
   1265 				fmt.Fprintf(Stderr, "fchdir back to dot failed: %s\n", err2)
   1266 				Exit(1)
   1267 			}
   1268 			if err != nil {
   1269 				fd.Close()
   1270 				t.Fatalf("Chdir %s: %s", d, err)
   1271 			}
   1272 			if err1 != nil {
   1273 				fd.Close()
   1274 				t.Fatalf("Getwd in %s: %s", d, err1)
   1275 			}
   1276 			if pwd != d {
   1277 				fd.Close()
   1278 				t.Fatalf("Getwd returned %q want %q", pwd, d)
   1279 			}
   1280 		}
   1281 	}
   1282 	fd.Close()
   1283 }
   1284 
   1285 // Test that Chdir+Getwd is program-wide.
   1286 func TestProgWideChdir(t *testing.T) {
   1287 	const N = 10
   1288 	c := make(chan bool)
   1289 	cpwd := make(chan string)
   1290 	for i := 0; i < N; i++ {
   1291 		go func(i int) {
   1292 			// Lock half the goroutines in their own operating system
   1293 			// thread to exercise more scheduler possibilities.
   1294 			if i%2 == 1 {
   1295 				// On Plan 9, after calling LockOSThread, the goroutines
   1296 				// run on different processes which don't share the working
   1297 				// directory. This used to be an issue because Go expects
   1298 				// the working directory to be program-wide.
   1299 				// See issue 9428.
   1300 				runtime.LockOSThread()
   1301 			}
   1302 			<-c
   1303 			pwd, err := Getwd()
   1304 			if err != nil {
   1305 				t.Errorf("Getwd on goroutine %d: %v", i, err)
   1306 				return
   1307 			}
   1308 			cpwd <- pwd
   1309 		}(i)
   1310 	}
   1311 	oldwd, err := Getwd()
   1312 	if err != nil {
   1313 		t.Fatalf("Getwd: %v", err)
   1314 	}
   1315 	d, err := ioutil.TempDir("", "test")
   1316 	if err != nil {
   1317 		t.Fatalf("TempDir: %v", err)
   1318 	}
   1319 	defer func() {
   1320 		if err := Chdir(oldwd); err != nil {
   1321 			t.Fatalf("Chdir: %v", err)
   1322 		}
   1323 		RemoveAll(d)
   1324 	}()
   1325 	if err := Chdir(d); err != nil {
   1326 		t.Fatalf("Chdir: %v", err)
   1327 	}
   1328 	// OS X sets TMPDIR to a symbolic link.
   1329 	// So we resolve our working directory again before the test.
   1330 	d, err = Getwd()
   1331 	if err != nil {
   1332 		t.Fatalf("Getwd: %v", err)
   1333 	}
   1334 	close(c)
   1335 	for i := 0; i < N; i++ {
   1336 		pwd := <-cpwd
   1337 		if pwd != d {
   1338 			t.Errorf("Getwd returned %q; want %q", pwd, d)
   1339 		}
   1340 	}
   1341 }
   1342 
   1343 func TestSeek(t *testing.T) {
   1344 	f := newFile("TestSeek", t)
   1345 	defer Remove(f.Name())
   1346 	defer f.Close()
   1347 
   1348 	const data = "hello, world\n"
   1349 	io.WriteString(f, data)
   1350 
   1351 	type test struct {
   1352 		in     int64
   1353 		whence int
   1354 		out    int64
   1355 	}
   1356 	var tests = []test{
   1357 		{0, io.SeekCurrent, int64(len(data))},
   1358 		{0, io.SeekStart, 0},
   1359 		{5, io.SeekStart, 5},
   1360 		{0, io.SeekEnd, int64(len(data))},
   1361 		{0, io.SeekStart, 0},
   1362 		{-1, io.SeekEnd, int64(len(data)) - 1},
   1363 		{1 << 33, io.SeekStart, 1 << 33},
   1364 		{1 << 33, io.SeekEnd, 1<<33 + int64(len(data))},
   1365 
   1366 		// Issue 21681, Windows 4G-1, etc:
   1367 		{1<<32 - 1, io.SeekStart, 1<<32 - 1},
   1368 		{0, io.SeekCurrent, 1<<32 - 1},
   1369 		{2<<32 - 1, io.SeekStart, 2<<32 - 1},
   1370 		{0, io.SeekCurrent, 2<<32 - 1},
   1371 	}
   1372 	for i, tt := range tests {
   1373 		if runtime.GOOS == "nacl" && tt.out > 1<<30 {
   1374 			t.Logf("skipping test case #%d on nacl; https://golang.org/issue/21728", i)
   1375 			continue
   1376 		}
   1377 		off, err := f.Seek(tt.in, tt.whence)
   1378 		if off != tt.out || err != nil {
   1379 			if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 && runtime.GOOS == "linux" {
   1380 				mounts, _ := ioutil.ReadFile("/proc/mounts")
   1381 				if strings.Contains(string(mounts), "reiserfs") {
   1382 					// Reiserfs rejects the big seeks.
   1383 					t.Skipf("skipping test known to fail on reiserfs; https://golang.org/issue/91")
   1384 				}
   1385 			}
   1386 			t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
   1387 		}
   1388 	}
   1389 }
   1390 
   1391 func TestSeekError(t *testing.T) {
   1392 	switch runtime.GOOS {
   1393 	case "plan9", "nacl":
   1394 		t.Skipf("skipping test on %v", runtime.GOOS)
   1395 	}
   1396 
   1397 	r, w, err := Pipe()
   1398 	if err != nil {
   1399 		t.Fatal(err)
   1400 	}
   1401 	_, err = r.Seek(0, 0)
   1402 	if err == nil {
   1403 		t.Fatal("Seek on pipe should fail")
   1404 	}
   1405 	if perr, ok := err.(*PathError); !ok || perr.Err != syscall.ESPIPE {
   1406 		t.Errorf("Seek returned error %v, want &PathError{Err: syscall.ESPIPE}", err)
   1407 	}
   1408 	_, err = w.Seek(0, 0)
   1409 	if err == nil {
   1410 		t.Fatal("Seek on pipe should fail")
   1411 	}
   1412 	if perr, ok := err.(*PathError); !ok || perr.Err != syscall.ESPIPE {
   1413 		t.Errorf("Seek returned error %v, want &PathError{Err: syscall.ESPIPE}", err)
   1414 	}
   1415 }
   1416 
   1417 type openErrorTest struct {
   1418 	path  string
   1419 	mode  int
   1420 	error error
   1421 }
   1422 
   1423 var openErrorTests = []openErrorTest{
   1424 	{
   1425 		sfdir + "/no-such-file",
   1426 		O_RDONLY,
   1427 		syscall.ENOENT,
   1428 	},
   1429 	{
   1430 		sfdir,
   1431 		O_WRONLY,
   1432 		syscall.EISDIR,
   1433 	},
   1434 	{
   1435 		sfdir + "/" + sfname + "/no-such-file",
   1436 		O_WRONLY,
   1437 		syscall.ENOTDIR,
   1438 	},
   1439 }
   1440 
   1441 func TestOpenError(t *testing.T) {
   1442 	for _, tt := range openErrorTests {
   1443 		f, err := OpenFile(tt.path, tt.mode, 0)
   1444 		if err == nil {
   1445 			t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode)
   1446 			f.Close()
   1447 			continue
   1448 		}
   1449 		perr, ok := err.(*PathError)
   1450 		if !ok {
   1451 			t.Errorf("Open(%q, %d) returns error of %T type; want *PathError", tt.path, tt.mode, err)
   1452 		}
   1453 		if perr.Err != tt.error {
   1454 			if runtime.GOOS == "plan9" {
   1455 				syscallErrStr := perr.Err.Error()
   1456 				expectedErrStr := strings.Replace(tt.error.Error(), "file ", "", 1)
   1457 				if !strings.HasSuffix(syscallErrStr, expectedErrStr) {
   1458 					// Some Plan 9 file servers incorrectly return
   1459 					// EACCES rather than EISDIR when a directory is
   1460 					// opened for write.
   1461 					if tt.error == syscall.EISDIR && strings.HasSuffix(syscallErrStr, syscall.EACCES.Error()) {
   1462 						continue
   1463 					}
   1464 					t.Errorf("Open(%q, %d) = _, %q; want suffix %q", tt.path, tt.mode, syscallErrStr, expectedErrStr)
   1465 				}
   1466 				continue
   1467 			}
   1468 			if runtime.GOOS == "dragonfly" {
   1469 				// DragonFly incorrectly returns EACCES rather
   1470 				// EISDIR when a directory is opened for write.
   1471 				if tt.error == syscall.EISDIR && perr.Err == syscall.EACCES {
   1472 					continue
   1473 				}
   1474 			}
   1475 			t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, perr.Err.Error(), tt.error.Error())
   1476 		}
   1477 	}
   1478 }
   1479 
   1480 func TestOpenNoName(t *testing.T) {
   1481 	f, err := Open("")
   1482 	if err == nil {
   1483 		t.Fatal(`Open("") succeeded`)
   1484 		f.Close()
   1485 	}
   1486 }
   1487 
   1488 func runBinHostname(t *testing.T) string {
   1489 	// Run /bin/hostname and collect output.
   1490 	r, w, err := Pipe()
   1491 	if err != nil {
   1492 		t.Fatal(err)
   1493 	}
   1494 	defer r.Close()
   1495 	const path = "/bin/hostname"
   1496 	p, err := StartProcess(path, []string{"hostname"}, &ProcAttr{Files: []*File{nil, w, Stderr}})
   1497 	if err != nil {
   1498 		if _, err := Stat(path); IsNotExist(err) {
   1499 			t.Skipf("skipping test; test requires %s but it does not exist", path)
   1500 		}
   1501 		t.Fatal(err)
   1502 	}
   1503 	w.Close()
   1504 
   1505 	var b bytes.Buffer
   1506 	io.Copy(&b, r)
   1507 	_, err = p.Wait()
   1508 	if err != nil {
   1509 		t.Fatalf("run hostname Wait: %v", err)
   1510 	}
   1511 	err = p.Kill()
   1512 	if err == nil {
   1513 		t.Errorf("expected an error from Kill running 'hostname'")
   1514 	}
   1515 	output := b.String()
   1516 	if n := len(output); n > 0 && output[n-1] == '\n' {
   1517 		output = output[0 : n-1]
   1518 	}
   1519 	if output == "" {
   1520 		t.Fatalf("/bin/hostname produced no output")
   1521 	}
   1522 
   1523 	return output
   1524 }
   1525 
   1526 func testWindowsHostname(t *testing.T) {
   1527 	hostname, err := Hostname()
   1528 	if err != nil {
   1529 		t.Fatal(err)
   1530 	}
   1531 	cmd := osexec.Command("hostname")
   1532 	out, err := cmd.CombinedOutput()
   1533 	if err != nil {
   1534 		t.Fatalf("Failed to execute hostname command: %v %s", err, out)
   1535 	}
   1536 	want := strings.Trim(string(out), "\r\n")
   1537 	if hostname != want {
   1538 		t.Fatalf("Hostname() = %q, want %q", hostname, want)
   1539 	}
   1540 }
   1541 
   1542 func TestHostname(t *testing.T) {
   1543 	// There is no other way to fetch hostname on windows, but via winapi.
   1544 	// On Plan 9 it can be taken from #c/sysname as Hostname() does.
   1545 	switch runtime.GOOS {
   1546 	case "android", "plan9":
   1547 		t.Skipf("%s doesn't have /bin/hostname", runtime.GOOS)
   1548 	case "windows":
   1549 		testWindowsHostname(t)
   1550 		return
   1551 	}
   1552 
   1553 	testenv.MustHaveExec(t)
   1554 
   1555 	// Check internal Hostname() against the output of /bin/hostname.
   1556 	// Allow that the internal Hostname returns a Fully Qualified Domain Name
   1557 	// and the /bin/hostname only returns the first component
   1558 	hostname, err := Hostname()
   1559 	if err != nil {
   1560 		t.Fatalf("%v", err)
   1561 	}
   1562 	want := runBinHostname(t)
   1563 	if hostname != want {
   1564 		i := strings.Index(hostname, ".")
   1565 		if i < 0 || hostname[0:i] != want {
   1566 			t.Errorf("Hostname() = %q, want %q", hostname, want)
   1567 		}
   1568 	}
   1569 }
   1570 
   1571 func TestReadAt(t *testing.T) {
   1572 	f := newFile("TestReadAt", t)
   1573 	defer Remove(f.Name())
   1574 	defer f.Close()
   1575 
   1576 	const data = "hello, world\n"
   1577 	io.WriteString(f, data)
   1578 
   1579 	b := make([]byte, 5)
   1580 	n, err := f.ReadAt(b, 7)
   1581 	if err != nil || n != len(b) {
   1582 		t.Fatalf("ReadAt 7: %d, %v", n, err)
   1583 	}
   1584 	if string(b) != "world" {
   1585 		t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
   1586 	}
   1587 }
   1588 
   1589 // Verify that ReadAt doesn't affect seek offset.
   1590 // In the Plan 9 kernel, there used to be a bug in the implementation of
   1591 // the pread syscall, where the channel offset was erroneously updated after
   1592 // calling pread on a file.
   1593 func TestReadAtOffset(t *testing.T) {
   1594 	f := newFile("TestReadAtOffset", t)
   1595 	defer Remove(f.Name())
   1596 	defer f.Close()
   1597 
   1598 	const data = "hello, world\n"
   1599 	io.WriteString(f, data)
   1600 
   1601 	f.Seek(0, 0)
   1602 	b := make([]byte, 5)
   1603 
   1604 	n, err := f.ReadAt(b, 7)
   1605 	if err != nil || n != len(b) {
   1606 		t.Fatalf("ReadAt 7: %d, %v", n, err)
   1607 	}
   1608 	if string(b) != "world" {
   1609 		t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
   1610 	}
   1611 
   1612 	n, err = f.Read(b)
   1613 	if err != nil || n != len(b) {
   1614 		t.Fatalf("Read: %d, %v", n, err)
   1615 	}
   1616 	if string(b) != "hello" {
   1617 		t.Fatalf("Read: have %q want %q", string(b), "hello")
   1618 	}
   1619 }
   1620 
   1621 // Verify that ReadAt doesn't allow negative offset.
   1622 func TestReadAtNegativeOffset(t *testing.T) {
   1623 	f := newFile("TestReadAtNegativeOffset", t)
   1624 	defer Remove(f.Name())
   1625 	defer f.Close()
   1626 
   1627 	const data = "hello, world\n"
   1628 	io.WriteString(f, data)
   1629 
   1630 	f.Seek(0, 0)
   1631 	b := make([]byte, 5)
   1632 
   1633 	n, err := f.ReadAt(b, -10)
   1634 
   1635 	const wantsub = "negative offset"
   1636 	if !strings.Contains(fmt.Sprint(err), wantsub) || n != 0 {
   1637 		t.Errorf("ReadAt(-10) = %v, %v; want 0, ...%q...", n, err, wantsub)
   1638 	}
   1639 }
   1640 
   1641 func TestWriteAt(t *testing.T) {
   1642 	f := newFile("TestWriteAt", t)
   1643 	defer Remove(f.Name())
   1644 	defer f.Close()
   1645 
   1646 	const data = "hello, world\n"
   1647 	io.WriteString(f, data)
   1648 
   1649 	n, err := f.WriteAt([]byte("WORLD"), 7)
   1650 	if err != nil || n != 5 {
   1651 		t.Fatalf("WriteAt 7: %d, %v", n, err)
   1652 	}
   1653 
   1654 	b, err := ioutil.ReadFile(f.Name())
   1655 	if err != nil {
   1656 		t.Fatalf("ReadFile %s: %v", f.Name(), err)
   1657 	}
   1658 	if string(b) != "hello, WORLD\n" {
   1659 		t.Fatalf("after write: have %q want %q", string(b), "hello, WORLD\n")
   1660 	}
   1661 }
   1662 
   1663 // Verify that WriteAt doesn't allow negative offset.
   1664 func TestWriteAtNegativeOffset(t *testing.T) {
   1665 	f := newFile("TestWriteAtNegativeOffset", t)
   1666 	defer Remove(f.Name())
   1667 	defer f.Close()
   1668 
   1669 	n, err := f.WriteAt([]byte("WORLD"), -10)
   1670 
   1671 	const wantsub = "negative offset"
   1672 	if !strings.Contains(fmt.Sprint(err), wantsub) || n != 0 {
   1673 		t.Errorf("WriteAt(-10) = %v, %v; want 0, ...%q...", n, err, wantsub)
   1674 	}
   1675 }
   1676 
   1677 func writeFile(t *testing.T, fname string, flag int, text string) string {
   1678 	f, err := OpenFile(fname, flag, 0666)
   1679 	if err != nil {
   1680 		t.Fatalf("Open: %v", err)
   1681 	}
   1682 	n, err := io.WriteString(f, text)
   1683 	if err != nil {
   1684 		t.Fatalf("WriteString: %d, %v", n, err)
   1685 	}
   1686 	f.Close()
   1687 	data, err := ioutil.ReadFile(fname)
   1688 	if err != nil {
   1689 		t.Fatalf("ReadFile: %v", err)
   1690 	}
   1691 	return string(data)
   1692 }
   1693 
   1694 func TestAppend(t *testing.T) {
   1695 	defer chtmpdir(t)()
   1696 	const f = "append.txt"
   1697 	defer Remove(f)
   1698 	s := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
   1699 	if s != "new" {
   1700 		t.Fatalf("writeFile: have %q want %q", s, "new")
   1701 	}
   1702 	s = writeFile(t, f, O_APPEND|O_RDWR, "|append")
   1703 	if s != "new|append" {
   1704 		t.Fatalf("writeFile: have %q want %q", s, "new|append")
   1705 	}
   1706 	s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "|append")
   1707 	if s != "new|append|append" {
   1708 		t.Fatalf("writeFile: have %q want %q", s, "new|append|append")
   1709 	}
   1710 	err := Remove(f)
   1711 	if err != nil {
   1712 		t.Fatalf("Remove: %v", err)
   1713 	}
   1714 	s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "new&append")
   1715 	if s != "new&append" {
   1716 		t.Fatalf("writeFile: after append have %q want %q", s, "new&append")
   1717 	}
   1718 	s = writeFile(t, f, O_CREATE|O_RDWR, "old")
   1719 	if s != "old&append" {
   1720 		t.Fatalf("writeFile: after create have %q want %q", s, "old&append")
   1721 	}
   1722 	s = writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
   1723 	if s != "new" {
   1724 		t.Fatalf("writeFile: after truncate have %q want %q", s, "new")
   1725 	}
   1726 }
   1727 
   1728 func TestStatDirWithTrailingSlash(t *testing.T) {
   1729 	// Create new temporary directory and arrange to clean it up.
   1730 	path, err := ioutil.TempDir("", "/_TestStatDirWithSlash_")
   1731 	if err != nil {
   1732 		t.Fatalf("TempDir: %s", err)
   1733 	}
   1734 	defer RemoveAll(path)
   1735 
   1736 	// Stat of path should succeed.
   1737 	_, err = Stat(path)
   1738 	if err != nil {
   1739 		t.Fatalf("stat %s failed: %s", path, err)
   1740 	}
   1741 
   1742 	// Stat of path+"/" should succeed too.
   1743 	path += "/"
   1744 	_, err = Stat(path)
   1745 	if err != nil {
   1746 		t.Fatalf("stat %s failed: %s", path, err)
   1747 	}
   1748 }
   1749 
   1750 func TestNilProcessStateString(t *testing.T) {
   1751 	var ps *ProcessState
   1752 	s := ps.String()
   1753 	if s != "<nil>" {
   1754 		t.Errorf("(*ProcessState)(nil).String() = %q, want %q", s, "<nil>")
   1755 	}
   1756 }
   1757 
   1758 func TestSameFile(t *testing.T) {
   1759 	defer chtmpdir(t)()
   1760 	fa, err := Create("a")
   1761 	if err != nil {
   1762 		t.Fatalf("Create(a): %v", err)
   1763 	}
   1764 	defer Remove(fa.Name())
   1765 	fa.Close()
   1766 	fb, err := Create("b")
   1767 	if err != nil {
   1768 		t.Fatalf("Create(b): %v", err)
   1769 	}
   1770 	defer Remove(fb.Name())
   1771 	fb.Close()
   1772 
   1773 	ia1, err := Stat("a")
   1774 	if err != nil {
   1775 		t.Fatalf("Stat(a): %v", err)
   1776 	}
   1777 	ia2, err := Stat("a")
   1778 	if err != nil {
   1779 		t.Fatalf("Stat(a): %v", err)
   1780 	}
   1781 	if !SameFile(ia1, ia2) {
   1782 		t.Errorf("files should be same")
   1783 	}
   1784 
   1785 	ib, err := Stat("b")
   1786 	if err != nil {
   1787 		t.Fatalf("Stat(b): %v", err)
   1788 	}
   1789 	if SameFile(ia1, ib) {
   1790 		t.Errorf("files should be different")
   1791 	}
   1792 }
   1793 
   1794 func TestDevNullFile(t *testing.T) {
   1795 	f, err := Open(DevNull)
   1796 	if err != nil {
   1797 		t.Fatalf("Open(%s): %v", DevNull, err)
   1798 	}
   1799 	defer f.Close()
   1800 	fi, err := f.Stat()
   1801 	if err != nil {
   1802 		t.Fatalf("Stat(%s): %v", DevNull, err)
   1803 	}
   1804 	name := filepath.Base(DevNull)
   1805 	if fi.Name() != name {
   1806 		t.Fatalf("wrong file name have %v want %v", fi.Name(), name)
   1807 	}
   1808 	if fi.Size() != 0 {
   1809 		t.Fatalf("wrong file size have %d want 0", fi.Size())
   1810 	}
   1811 }
   1812 
   1813 var testLargeWrite = flag.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output")
   1814 
   1815 func TestLargeWriteToConsole(t *testing.T) {
   1816 	if !*testLargeWrite {
   1817 		t.Skip("skipping console-flooding test; enable with -large_write")
   1818 	}
   1819 	b := make([]byte, 32000)
   1820 	for i := range b {
   1821 		b[i] = '.'
   1822 	}
   1823 	b[len(b)-1] = '\n'
   1824 	n, err := Stdout.Write(b)
   1825 	if err != nil {
   1826 		t.Fatalf("Write to os.Stdout failed: %v", err)
   1827 	}
   1828 	if n != len(b) {
   1829 		t.Errorf("Write to os.Stdout should return %d; got %d", len(b), n)
   1830 	}
   1831 	n, err = Stderr.Write(b)
   1832 	if err != nil {
   1833 		t.Fatalf("Write to os.Stderr failed: %v", err)
   1834 	}
   1835 	if n != len(b) {
   1836 		t.Errorf("Write to os.Stderr should return %d; got %d", len(b), n)
   1837 	}
   1838 }
   1839 
   1840 func TestStatDirModeExec(t *testing.T) {
   1841 	const mode = 0111
   1842 
   1843 	path, err := ioutil.TempDir("", "go-build")
   1844 	if err != nil {
   1845 		t.Fatalf("Failed to create temp directory: %v", err)
   1846 	}
   1847 	defer RemoveAll(path)
   1848 
   1849 	if err := Chmod(path, 0777); err != nil {
   1850 		t.Fatalf("Chmod %q 0777: %v", path, err)
   1851 	}
   1852 
   1853 	dir, err := Stat(path)
   1854 	if err != nil {
   1855 		t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
   1856 	}
   1857 	if dir.Mode()&mode != mode {
   1858 		t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode()&mode, mode)
   1859 	}
   1860 }
   1861 
   1862 func TestStatStdin(t *testing.T) {
   1863 	switch runtime.GOOS {
   1864 	case "android", "plan9":
   1865 		t.Skipf("%s doesn't have /bin/sh", runtime.GOOS)
   1866 	}
   1867 
   1868 	testenv.MustHaveExec(t)
   1869 
   1870 	if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
   1871 		st, err := Stdin.Stat()
   1872 		if err != nil {
   1873 			t.Fatalf("Stat failed: %v", err)
   1874 		}
   1875 		fmt.Println(st.Mode() & ModeNamedPipe)
   1876 		Exit(0)
   1877 	}
   1878 
   1879 	fi, err := Stdin.Stat()
   1880 	if err != nil {
   1881 		t.Fatal(err)
   1882 	}
   1883 	switch mode := fi.Mode(); {
   1884 	case mode&ModeCharDevice != 0:
   1885 	case mode&ModeNamedPipe != 0:
   1886 	default:
   1887 		t.Fatalf("unexpected Stdin mode (%v), want ModeCharDevice or ModeNamedPipe", mode)
   1888 	}
   1889 
   1890 	var cmd *osexec.Cmd
   1891 	if runtime.GOOS == "windows" {
   1892 		cmd = osexec.Command("cmd", "/c", "echo output | "+Args[0]+" -test.run=TestStatStdin")
   1893 	} else {
   1894 		cmd = osexec.Command("/bin/sh", "-c", "echo output | "+Args[0]+" -test.run=TestStatStdin")
   1895 	}
   1896 	cmd.Env = append(Environ(), "GO_WANT_HELPER_PROCESS=1")
   1897 
   1898 	output, err := cmd.CombinedOutput()
   1899 	if err != nil {
   1900 		t.Fatalf("Failed to spawn child process: %v %q", err, string(output))
   1901 	}
   1902 
   1903 	// result will be like "prw-rw-rw"
   1904 	if len(output) < 1 || output[0] != 'p' {
   1905 		t.Fatalf("Child process reports stdin is not pipe '%v'", string(output))
   1906 	}
   1907 }
   1908 
   1909 func TestStatRelativeSymlink(t *testing.T) {
   1910 	testenv.MustHaveSymlink(t)
   1911 
   1912 	tmpdir, err := ioutil.TempDir("", "TestStatRelativeSymlink")
   1913 	if err != nil {
   1914 		t.Fatal(err)
   1915 	}
   1916 	defer RemoveAll(tmpdir)
   1917 
   1918 	target := filepath.Join(tmpdir, "target")
   1919 	f, err := Create(target)
   1920 	if err != nil {
   1921 		t.Fatal(err)
   1922 	}
   1923 	defer f.Close()
   1924 
   1925 	st, err := f.Stat()
   1926 	if err != nil {
   1927 		t.Fatal(err)
   1928 	}
   1929 
   1930 	link := filepath.Join(tmpdir, "link")
   1931 	err = Symlink(filepath.Base(target), link)
   1932 	if err != nil {
   1933 		t.Fatal(err)
   1934 	}
   1935 
   1936 	st1, err := Stat(link)
   1937 	if err != nil {
   1938 		t.Fatal(err)
   1939 	}
   1940 
   1941 	if !SameFile(st, st1) {
   1942 		t.Error("Stat doesn't follow relative symlink")
   1943 	}
   1944 
   1945 	if runtime.GOOS == "windows" {
   1946 		Remove(link)
   1947 		err = Symlink(target[len(filepath.VolumeName(target)):], link)
   1948 		if err != nil {
   1949 			t.Fatal(err)
   1950 		}
   1951 
   1952 		st1, err := Stat(link)
   1953 		if err != nil {
   1954 			t.Fatal(err)
   1955 		}
   1956 
   1957 		if !SameFile(st, st1) {
   1958 			t.Error("Stat doesn't follow relative symlink")
   1959 		}
   1960 	}
   1961 }
   1962 
   1963 func TestReadAtEOF(t *testing.T) {
   1964 	f := newFile("TestReadAtEOF", t)
   1965 	defer Remove(f.Name())
   1966 	defer f.Close()
   1967 
   1968 	_, err := f.ReadAt(make([]byte, 10), 0)
   1969 	switch err {
   1970 	case io.EOF:
   1971 		// all good
   1972 	case nil:
   1973 		t.Fatalf("ReadAt succeeded")
   1974 	default:
   1975 		t.Fatalf("ReadAt failed: %s", err)
   1976 	}
   1977 }
   1978 
   1979 func TestLongPath(t *testing.T) {
   1980 	tmpdir := newDir("TestLongPath", t)
   1981 	defer func(d string) {
   1982 		if err := RemoveAll(d); err != nil {
   1983 			t.Fatalf("RemoveAll failed: %v", err)
   1984 		}
   1985 	}(tmpdir)
   1986 
   1987 	// Test the boundary of 247 and fewer bytes (normal) and 248 and more bytes (adjusted).
   1988 	sizes := []int{247, 248, 249, 400}
   1989 	for len(tmpdir) < 400 {
   1990 		tmpdir += "/dir3456789"
   1991 	}
   1992 	for _, sz := range sizes {
   1993 		t.Run(fmt.Sprintf("length=%d", sz), func(t *testing.T) {
   1994 			sizedTempDir := tmpdir[:sz-1] + "x" // Ensure it does not end with a slash.
   1995 
   1996 			// The various sized runs are for this call to trigger the boundary
   1997 			// condition.
   1998 			if err := MkdirAll(sizedTempDir, 0755); err != nil {
   1999 				t.Fatalf("MkdirAll failed: %v", err)
   2000 			}
   2001 			data := []byte("hello world\n")
   2002 			if err := ioutil.WriteFile(sizedTempDir+"/foo.txt", data, 0644); err != nil {
   2003 				t.Fatalf("ioutil.WriteFile() failed: %v", err)
   2004 			}
   2005 			if err := Rename(sizedTempDir+"/foo.txt", sizedTempDir+"/bar.txt"); err != nil {
   2006 				t.Fatalf("Rename failed: %v", err)
   2007 			}
   2008 			mtime := time.Now().Truncate(time.Minute)
   2009 			if err := Chtimes(sizedTempDir+"/bar.txt", mtime, mtime); err != nil {
   2010 				t.Fatalf("Chtimes failed: %v", err)
   2011 			}
   2012 			names := []string{"bar.txt"}
   2013 			if testenv.HasSymlink() {
   2014 				if err := Symlink(sizedTempDir+"/bar.txt", sizedTempDir+"/symlink.txt"); err != nil {
   2015 					t.Fatalf("Symlink failed: %v", err)
   2016 				}
   2017 				names = append(names, "symlink.txt")
   2018 			}
   2019 			if testenv.HasLink() {
   2020 				if err := Link(sizedTempDir+"/bar.txt", sizedTempDir+"/link.txt"); err != nil {
   2021 					t.Fatalf("Link failed: %v", err)
   2022 				}
   2023 				names = append(names, "link.txt")
   2024 			}
   2025 			for _, wantSize := range []int64{int64(len(data)), 0} {
   2026 				for _, name := range names {
   2027 					path := sizedTempDir + "/" + name
   2028 					dir, err := Stat(path)
   2029 					if err != nil {
   2030 						t.Fatalf("Stat(%q) failed: %v", path, err)
   2031 					}
   2032 					filesize := size(path, t)
   2033 					if dir.Size() != filesize || filesize != wantSize {
   2034 						t.Errorf("Size(%q) is %d, len(ReadFile()) is %d, want %d", path, dir.Size(), filesize, wantSize)
   2035 					}
   2036 					err = Chmod(path, dir.Mode())
   2037 					if err != nil {
   2038 						t.Fatalf("Chmod(%q) failed: %v", path, err)
   2039 					}
   2040 				}
   2041 				if err := Truncate(sizedTempDir+"/bar.txt", 0); err != nil {
   2042 					t.Fatalf("Truncate failed: %v", err)
   2043 				}
   2044 			}
   2045 		})
   2046 	}
   2047 }
   2048 
   2049 func testKillProcess(t *testing.T, processKiller func(p *Process)) {
   2050 	testenv.MustHaveExec(t)
   2051 
   2052 	// Re-exec the test binary itself to emulate "sleep 1".
   2053 	cmd := osexec.Command(Args[0], "-test.run", "TestSleep")
   2054 	err := cmd.Start()
   2055 	if err != nil {
   2056 		t.Fatalf("Failed to start test process: %v", err)
   2057 	}
   2058 	go func() {
   2059 		time.Sleep(100 * time.Millisecond)
   2060 		processKiller(cmd.Process)
   2061 	}()
   2062 	err = cmd.Wait()
   2063 	if err == nil {
   2064 		t.Errorf("Test process succeeded, but expected to fail")
   2065 	}
   2066 }
   2067 
   2068 // TestSleep emulates "sleep 1". It is a helper for testKillProcess, so we
   2069 // don't have to rely on an external "sleep" command being available.
   2070 func TestSleep(t *testing.T) {
   2071 	if testing.Short() {
   2072 		t.Skip("Skipping in short mode")
   2073 	}
   2074 	time.Sleep(time.Second)
   2075 }
   2076 
   2077 func TestKillStartProcess(t *testing.T) {
   2078 	testKillProcess(t, func(p *Process) {
   2079 		err := p.Kill()
   2080 		if err != nil {
   2081 			t.Fatalf("Failed to kill test process: %v", err)
   2082 		}
   2083 	})
   2084 }
   2085 
   2086 func TestGetppid(t *testing.T) {
   2087 	if runtime.GOOS == "plan9" {
   2088 		// TODO: golang.org/issue/8206
   2089 		t.Skipf("skipping test on plan9; see issue 8206")
   2090 	}
   2091 
   2092 	testenv.MustHaveExec(t)
   2093 
   2094 	if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
   2095 		fmt.Print(Getppid())
   2096 		Exit(0)
   2097 	}
   2098 
   2099 	cmd := osexec.Command(Args[0], "-test.run=TestGetppid")
   2100 	cmd.Env = append(Environ(), "GO_WANT_HELPER_PROCESS=1")
   2101 
   2102 	// verify that Getppid() from the forked process reports our process id
   2103 	output, err := cmd.CombinedOutput()
   2104 	if err != nil {
   2105 		t.Fatalf("Failed to spawn child process: %v %q", err, string(output))
   2106 	}
   2107 
   2108 	childPpid := string(output)
   2109 	ourPid := fmt.Sprintf("%d", Getpid())
   2110 	if childPpid != ourPid {
   2111 		t.Fatalf("Child process reports parent process id '%v', expected '%v'", childPpid, ourPid)
   2112 	}
   2113 }
   2114 
   2115 func TestKillFindProcess(t *testing.T) {
   2116 	testKillProcess(t, func(p *Process) {
   2117 		p2, err := FindProcess(p.Pid)
   2118 		if err != nil {
   2119 			t.Fatalf("Failed to find test process: %v", err)
   2120 		}
   2121 		err = p2.Kill()
   2122 		if err != nil {
   2123 			t.Fatalf("Failed to kill test process: %v", err)
   2124 		}
   2125 	})
   2126 }
   2127 
   2128 var nilFileMethodTests = []struct {
   2129 	name string
   2130 	f    func(*File) error
   2131 }{
   2132 	{"Chdir", func(f *File) error { return f.Chdir() }},
   2133 	{"Close", func(f *File) error { return f.Close() }},
   2134 	{"Chmod", func(f *File) error { return f.Chmod(0) }},
   2135 	{"Chown", func(f *File) error { return f.Chown(0, 0) }},
   2136 	{"Read", func(f *File) error { _, err := f.Read(make([]byte, 0)); return err }},
   2137 	{"ReadAt", func(f *File) error { _, err := f.ReadAt(make([]byte, 0), 0); return err }},
   2138 	{"Readdir", func(f *File) error { _, err := f.Readdir(1); return err }},
   2139 	{"Readdirnames", func(f *File) error { _, err := f.Readdirnames(1); return err }},
   2140 	{"Seek", func(f *File) error { _, err := f.Seek(0, io.SeekStart); return err }},
   2141 	{"Stat", func(f *File) error { _, err := f.Stat(); return err }},
   2142 	{"Sync", func(f *File) error { return f.Sync() }},
   2143 	{"Truncate", func(f *File) error { return f.Truncate(0) }},
   2144 	{"Write", func(f *File) error { _, err := f.Write(make([]byte, 0)); return err }},
   2145 	{"WriteAt", func(f *File) error { _, err := f.WriteAt(make([]byte, 0), 0); return err }},
   2146 	{"WriteString", func(f *File) error { _, err := f.WriteString(""); return err }},
   2147 }
   2148 
   2149 // Test that all File methods give ErrInvalid if the receiver is nil.
   2150 func TestNilFileMethods(t *testing.T) {
   2151 	for _, tt := range nilFileMethodTests {
   2152 		var file *File
   2153 		got := tt.f(file)
   2154 		if got != ErrInvalid {
   2155 			t.Errorf("%v should fail when f is nil; got %v", tt.name, got)
   2156 		}
   2157 	}
   2158 }
   2159 
   2160 func mkdirTree(t *testing.T, root string, level, max int) {
   2161 	if level >= max {
   2162 		return
   2163 	}
   2164 	level++
   2165 	for i := 'a'; i < 'c'; i++ {
   2166 		dir := filepath.Join(root, string(i))
   2167 		if err := Mkdir(dir, 0700); err != nil {
   2168 			t.Fatal(err)
   2169 		}
   2170 		mkdirTree(t, dir, level, max)
   2171 	}
   2172 }
   2173 
   2174 // Test that simultaneous RemoveAll do not report an error.
   2175 // As long as it gets removed, we should be happy.
   2176 func TestRemoveAllRace(t *testing.T) {
   2177 	if runtime.GOOS == "windows" {
   2178 		// Windows has very strict rules about things like
   2179 		// removing directories while someone else has
   2180 		// them open. The racing doesn't work out nicely
   2181 		// like it does on Unix.
   2182 		t.Skip("skipping on windows")
   2183 	}
   2184 
   2185 	n := runtime.GOMAXPROCS(16)
   2186 	defer runtime.GOMAXPROCS(n)
   2187 	root, err := ioutil.TempDir("", "issue")
   2188 	if err != nil {
   2189 		t.Fatal(err)
   2190 	}
   2191 	mkdirTree(t, root, 1, 6)
   2192 	hold := make(chan struct{})
   2193 	var wg sync.WaitGroup
   2194 	for i := 0; i < 4; i++ {
   2195 		wg.Add(1)
   2196 		go func() {
   2197 			defer wg.Done()
   2198 			<-hold
   2199 			err := RemoveAll(root)
   2200 			if err != nil {
   2201 				t.Errorf("unexpected error: %T, %q", err, err)
   2202 			}
   2203 		}()
   2204 	}
   2205 	close(hold) // let workers race to remove root
   2206 	wg.Wait()
   2207 }
   2208 
   2209 // Test that reading from a pipe doesn't use up a thread.
   2210 func TestPipeThreads(t *testing.T) {
   2211 	switch runtime.GOOS {
   2212 	case "freebsd":
   2213 		t.Skip("skipping on FreeBSD; issue 19093")
   2214 	case "solaris":
   2215 		t.Skip("skipping on Solaris; issue 19111")
   2216 	case "windows":
   2217 		t.Skip("skipping on Windows; issue 19098")
   2218 	case "plan9":
   2219 		t.Skip("skipping on Plan 9; does not support runtime poller")
   2220 	}
   2221 
   2222 	threads := 100
   2223 
   2224 	// OpenBSD has a low default for max number of files.
   2225 	if runtime.GOOS == "openbsd" {
   2226 		threads = 50
   2227 	}
   2228 
   2229 	r := make([]*File, threads)
   2230 	w := make([]*File, threads)
   2231 	for i := 0; i < threads; i++ {
   2232 		rp, wp, err := Pipe()
   2233 		if err != nil {
   2234 			for j := 0; j < i; j++ {
   2235 				r[j].Close()
   2236 				w[j].Close()
   2237 			}
   2238 			t.Fatal(err)
   2239 		}
   2240 		r[i] = rp
   2241 		w[i] = wp
   2242 	}
   2243 
   2244 	defer debug.SetMaxThreads(debug.SetMaxThreads(threads / 2))
   2245 
   2246 	creading := make(chan bool, threads)
   2247 	cdone := make(chan bool, threads)
   2248 	for i := 0; i < threads; i++ {
   2249 		go func(i int) {
   2250 			var b [1]byte
   2251 			creading <- true
   2252 			if _, err := r[i].Read(b[:]); err != nil {
   2253 				t.Error(err)
   2254 			}
   2255 			if err := r[i].Close(); err != nil {
   2256 				t.Error(err)
   2257 			}
   2258 			cdone <- true
   2259 		}(i)
   2260 	}
   2261 
   2262 	for i := 0; i < threads; i++ {
   2263 		<-creading
   2264 	}
   2265 
   2266 	// If we are still alive, it means that the 100 goroutines did
   2267 	// not require 100 threads.
   2268 
   2269 	for i := 0; i < threads; i++ {
   2270 		if _, err := w[i].Write([]byte{0}); err != nil {
   2271 			t.Error(err)
   2272 		}
   2273 		if err := w[i].Close(); err != nil {
   2274 			t.Error(err)
   2275 		}
   2276 		<-cdone
   2277 	}
   2278 }
   2279 
   2280 func TestDoubleCloseError(t *testing.T) {
   2281 	path := sfdir + "/" + sfname
   2282 	file, err := Open(path)
   2283 	if err != nil {
   2284 		t.Fatal(err)
   2285 	}
   2286 	if err := file.Close(); err != nil {
   2287 		t.Fatalf("unexpected error from Close: %v", err)
   2288 	}
   2289 	if err := file.Close(); err == nil {
   2290 		t.Error("second Close did not fail")
   2291 	} else if pe, ok := err.(*PathError); !ok {
   2292 		t.Errorf("second Close returned unexpected error type %T; expected os.PathError", pe)
   2293 	} else if pe.Err != ErrClosed {
   2294 		t.Errorf("second Close returned %q, wanted %q", err, ErrClosed)
   2295 	} else {
   2296 		t.Logf("second close returned expected error %q", err)
   2297 	}
   2298 }
   2299