...

Source file src/os/os_test.go

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

View as plain text