github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/os/os_test.go (about) 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 "sort" 21 "strings" 22 "sync" 23 "syscall" 24 "testing" 25 "time" 26 ) 27 28 var supportsSymlinks = true 29 30 var dot = []string{ 31 "dir_unix.go", 32 "env.go", 33 "error.go", 34 "file.go", 35 "os_test.go", 36 "types.go", 37 "stat_darwin.go", 38 "stat_linux.go", 39 } 40 41 type sysDir struct { 42 name string 43 files []string 44 } 45 46 var sysdir = func() *sysDir { 47 switch runtime.GOOS { 48 case "android": 49 return &sysDir{ 50 "/system/framework", 51 []string{ 52 "ext.jar", 53 "framework.jar", 54 }, 55 } 56 case "darwin": 57 switch runtime.GOARCH { 58 case "arm", "arm64": 59 wd, err := syscall.Getwd() 60 if err != nil { 61 wd = err.Error() 62 } 63 return &sysDir{ 64 filepath.Join(wd, "..", ".."), 65 []string{ 66 "ResourceRules.plist", 67 "Info.plist", 68 }, 69 } 70 } 71 case "windows": 72 return &sysDir{ 73 Getenv("SystemRoot") + "\\system32\\drivers\\etc", 74 []string{ 75 "networks", 76 "protocol", 77 "services", 78 }, 79 } 80 case "plan9": 81 return &sysDir{ 82 "/lib/ndb", 83 []string{ 84 "common", 85 "local", 86 }, 87 } 88 } 89 return &sysDir{ 90 "/etc", 91 []string{ 92 "group", 93 "hosts", 94 "passwd", 95 }, 96 } 97 }() 98 99 func size(name string, t *testing.T) int64 { 100 file, err := Open(name) 101 if err != nil { 102 t.Fatal("open failed:", err) 103 } 104 defer file.Close() 105 var buf [100]byte 106 len := 0 107 for { 108 n, e := file.Read(buf[0:]) 109 len += n 110 if e == io.EOF { 111 break 112 } 113 if e != nil { 114 t.Fatal("read failed:", err) 115 } 116 } 117 return int64(len) 118 } 119 120 func equal(name1, name2 string) (r bool) { 121 switch runtime.GOOS { 122 case "windows": 123 r = strings.ToLower(name1) == strings.ToLower(name2) 124 default: 125 r = name1 == name2 126 } 127 return 128 } 129 130 // localTmp returns a local temporary directory not on NFS. 131 func localTmp() string { 132 switch runtime.GOOS { 133 case "android", "windows": 134 return TempDir() 135 case "darwin": 136 switch runtime.GOARCH { 137 case "arm", "arm64": 138 return TempDir() 139 } 140 } 141 return "/tmp" 142 } 143 144 func newFile(testName string, t *testing.T) (f *File) { 145 f, err := ioutil.TempFile(localTmp(), "_Go_"+testName) 146 if err != nil { 147 t.Fatalf("TempFile %s: %s", testName, err) 148 } 149 return 150 } 151 152 func newDir(testName string, t *testing.T) (name string) { 153 name, err := ioutil.TempDir(localTmp(), "_Go_"+testName) 154 if err != nil { 155 t.Fatalf("TempDir %s: %s", testName, err) 156 } 157 return 158 } 159 160 var sfdir = sysdir.name 161 var sfname = sysdir.files[0] 162 163 func TestStat(t *testing.T) { 164 path := sfdir + "/" + sfname 165 dir, err := Stat(path) 166 if err != nil { 167 t.Fatal("stat failed:", err) 168 } 169 if !equal(sfname, dir.Name()) { 170 t.Error("name should be ", sfname, "; is", dir.Name()) 171 } 172 filesize := size(path, t) 173 if dir.Size() != filesize { 174 t.Error("size should be", filesize, "; is", dir.Size()) 175 } 176 } 177 178 func TestFstat(t *testing.T) { 179 path := sfdir + "/" + sfname 180 file, err1 := Open(path) 181 if err1 != nil { 182 t.Fatal("open failed:", err1) 183 } 184 defer file.Close() 185 dir, err2 := file.Stat() 186 if err2 != nil { 187 t.Fatal("fstat failed:", err2) 188 } 189 if !equal(sfname, dir.Name()) { 190 t.Error("name should be ", sfname, "; is", dir.Name()) 191 } 192 filesize := size(path, t) 193 if dir.Size() != filesize { 194 t.Error("size should be", filesize, "; is", dir.Size()) 195 } 196 } 197 198 func TestLstat(t *testing.T) { 199 path := sfdir + "/" + sfname 200 dir, err := Lstat(path) 201 if err != nil { 202 t.Fatal("lstat failed:", err) 203 } 204 if !equal(sfname, dir.Name()) { 205 t.Error("name should be ", sfname, "; is", dir.Name()) 206 } 207 filesize := size(path, t) 208 if dir.Size() != filesize { 209 t.Error("size should be", filesize, "; is", dir.Size()) 210 } 211 } 212 213 // Read with length 0 should not return EOF. 214 func TestRead0(t *testing.T) { 215 path := sfdir + "/" + sfname 216 f, err := Open(path) 217 if err != nil { 218 t.Fatal("open failed:", err) 219 } 220 defer f.Close() 221 222 b := make([]byte, 0) 223 n, err := f.Read(b) 224 if n != 0 || err != nil { 225 t.Errorf("Read(0) = %d, %v, want 0, nil", n, err) 226 } 227 b = make([]byte, 100) 228 n, err = f.Read(b) 229 if n <= 0 || err != nil { 230 t.Errorf("Read(100) = %d, %v, want >0, nil", n, err) 231 } 232 } 233 234 func testReaddirnames(dir string, contents []string, t *testing.T) { 235 file, err := Open(dir) 236 if err != nil { 237 t.Fatalf("open %q failed: %v", dir, err) 238 } 239 defer file.Close() 240 s, err2 := file.Readdirnames(-1) 241 if err2 != nil { 242 t.Fatalf("readdirnames %q failed: %v", dir, err2) 243 } 244 for _, m := range contents { 245 found := false 246 for _, n := range s { 247 if n == "." || n == ".." { 248 t.Errorf("got %s in directory", n) 249 } 250 if equal(m, n) { 251 if found { 252 t.Error("present twice:", m) 253 } 254 found = true 255 } 256 } 257 if !found { 258 t.Error("could not find", m) 259 } 260 } 261 } 262 263 func testReaddir(dir string, contents []string, t *testing.T) { 264 file, err := Open(dir) 265 if err != nil { 266 t.Fatalf("open %q failed: %v", dir, err) 267 } 268 defer file.Close() 269 s, err2 := file.Readdir(-1) 270 if err2 != nil { 271 t.Fatalf("readdir %q failed: %v", dir, err2) 272 } 273 for _, m := range contents { 274 found := false 275 for _, n := range s { 276 if equal(m, n.Name()) { 277 if found { 278 t.Error("present twice:", m) 279 } 280 found = true 281 } 282 } 283 if !found { 284 t.Error("could not find", m) 285 } 286 } 287 } 288 289 func TestReaddirnames(t *testing.T) { 290 testReaddirnames(".", dot, t) 291 testReaddirnames(sysdir.name, sysdir.files, t) 292 } 293 294 func TestReaddir(t *testing.T) { 295 testReaddir(".", dot, t) 296 testReaddir(sysdir.name, sysdir.files, t) 297 } 298 299 func benchmarkReaddirname(path string, b *testing.B) { 300 var nentries int 301 for i := 0; i < b.N; i++ { 302 f, err := Open(path) 303 if err != nil { 304 b.Fatalf("open %q failed: %v", path, err) 305 } 306 ns, err := f.Readdirnames(-1) 307 f.Close() 308 if err != nil { 309 b.Fatalf("readdirnames %q failed: %v", path, err) 310 } 311 nentries = len(ns) 312 } 313 b.Logf("benchmarkReaddirname %q: %d entries", path, nentries) 314 } 315 316 func benchmarkReaddir(path string, b *testing.B) { 317 var nentries int 318 for i := 0; i < b.N; i++ { 319 f, err := Open(path) 320 if err != nil { 321 b.Fatalf("open %q failed: %v", path, err) 322 } 323 fs, err := f.Readdir(-1) 324 f.Close() 325 if err != nil { 326 b.Fatalf("readdir %q failed: %v", path, err) 327 } 328 nentries = len(fs) 329 } 330 b.Logf("benchmarkReaddir %q: %d entries", path, nentries) 331 } 332 333 func BenchmarkReaddirname(b *testing.B) { 334 benchmarkReaddirname(".", b) 335 } 336 337 func BenchmarkReaddir(b *testing.B) { 338 benchmarkReaddir(".", b) 339 } 340 341 // Read the directory one entry at a time. 342 func smallReaddirnames(file *File, length int, t *testing.T) []string { 343 names := make([]string, length) 344 count := 0 345 for { 346 d, err := file.Readdirnames(1) 347 if err == io.EOF { 348 break 349 } 350 if err != nil { 351 t.Fatalf("readdirnames %q failed: %v", file.Name(), err) 352 } 353 if len(d) == 0 { 354 t.Fatalf("readdirnames %q returned empty slice and no error", file.Name()) 355 } 356 names[count] = d[0] 357 count++ 358 } 359 return names[0:count] 360 } 361 362 // Check that reading a directory one entry at a time gives the same result 363 // as reading it all at once. 364 func TestReaddirnamesOneAtATime(t *testing.T) { 365 // big directory that doesn't change often. 366 dir := "/usr/bin" 367 switch runtime.GOOS { 368 case "android": 369 dir = "/system/bin" 370 case "darwin": 371 switch runtime.GOARCH { 372 case "arm", "arm64": 373 wd, err := Getwd() 374 if err != nil { 375 t.Fatal(err) 376 } 377 dir = wd 378 } 379 case "plan9": 380 dir = "/bin" 381 case "windows": 382 dir = Getenv("SystemRoot") + "\\system32" 383 } 384 file, err := Open(dir) 385 if err != nil { 386 t.Fatalf("open %q failed: %v", dir, err) 387 } 388 defer file.Close() 389 all, err1 := file.Readdirnames(-1) 390 if err1 != nil { 391 t.Fatalf("readdirnames %q failed: %v", dir, err1) 392 } 393 file1, err2 := Open(dir) 394 if err2 != nil { 395 t.Fatalf("open %q failed: %v", dir, err2) 396 } 397 defer file1.Close() 398 small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up 399 if len(small) < len(all) { 400 t.Fatalf("len(small) is %d, less than %d", len(small), len(all)) 401 } 402 for i, n := range all { 403 if small[i] != n { 404 t.Errorf("small read %q mismatch: %v", small[i], n) 405 } 406 } 407 } 408 409 func TestReaddirNValues(t *testing.T) { 410 if testing.Short() { 411 t.Skip("test.short; skipping") 412 } 413 dir, err := ioutil.TempDir("", "") 414 if err != nil { 415 t.Fatalf("TempDir: %v", err) 416 } 417 defer RemoveAll(dir) 418 for i := 1; i <= 105; i++ { 419 f, err := Create(filepath.Join(dir, fmt.Sprintf("%d", i))) 420 if err != nil { 421 t.Fatalf("Create: %v", err) 422 } 423 f.Write([]byte(strings.Repeat("X", i))) 424 f.Close() 425 } 426 427 var d *File 428 openDir := func() { 429 var err error 430 d, err = Open(dir) 431 if err != nil { 432 t.Fatalf("Open directory: %v", err) 433 } 434 } 435 436 readDirExpect := func(n, want int, wantErr error) { 437 fi, err := d.Readdir(n) 438 if err != wantErr { 439 t.Fatalf("Readdir of %d got error %v, want %v", n, err, wantErr) 440 } 441 if g, e := len(fi), want; g != e { 442 t.Errorf("Readdir of %d got %d files, want %d", n, g, e) 443 } 444 } 445 446 readDirNamesExpect := func(n, want int, wantErr error) { 447 fi, err := d.Readdirnames(n) 448 if err != wantErr { 449 t.Fatalf("Readdirnames of %d got error %v, want %v", n, err, wantErr) 450 } 451 if g, e := len(fi), want; g != e { 452 t.Errorf("Readdirnames of %d got %d files, want %d", n, g, e) 453 } 454 } 455 456 for _, fn := range []func(int, int, error){readDirExpect, readDirNamesExpect} { 457 // Test the slurp case 458 openDir() 459 fn(0, 105, nil) 460 fn(0, 0, nil) 461 d.Close() 462 463 // Slurp with -1 instead 464 openDir() 465 fn(-1, 105, nil) 466 fn(-2, 0, nil) 467 fn(0, 0, nil) 468 d.Close() 469 470 // Test the bounded case 471 openDir() 472 fn(1, 1, nil) 473 fn(2, 2, nil) 474 fn(105, 102, nil) // and tests buffer >100 case 475 fn(3, 0, io.EOF) 476 d.Close() 477 } 478 } 479 480 func touch(t *testing.T, name string) { 481 f, err := Create(name) 482 if err != nil { 483 t.Fatal(err) 484 } 485 if err := f.Close(); err != nil { 486 t.Fatal(err) 487 } 488 } 489 490 func TestReaddirStatFailures(t *testing.T) { 491 switch runtime.GOOS { 492 case "windows", "plan9": 493 // Windows and Plan 9 already do this correctly, 494 // but are structured with different syscalls such 495 // that they don't use Lstat, so the hook below for 496 // testing it wouldn't work. 497 t.Skipf("skipping test on %v", runtime.GOOS) 498 } 499 dir, err := ioutil.TempDir("", "") 500 if err != nil { 501 t.Fatalf("TempDir: %v", err) 502 } 503 defer RemoveAll(dir) 504 touch(t, filepath.Join(dir, "good1")) 505 touch(t, filepath.Join(dir, "x")) // will disappear or have an error 506 touch(t, filepath.Join(dir, "good2")) 507 defer func() { 508 *LstatP = Lstat 509 }() 510 var xerr error // error to return for x 511 *LstatP = func(path string) (FileInfo, error) { 512 if xerr != nil && strings.HasSuffix(path, "x") { 513 return nil, xerr 514 } 515 return Lstat(path) 516 } 517 readDir := func() ([]FileInfo, error) { 518 d, err := Open(dir) 519 if err != nil { 520 t.Fatal(err) 521 } 522 defer d.Close() 523 return d.Readdir(-1) 524 } 525 mustReadDir := func(testName string) []FileInfo { 526 fis, err := readDir() 527 if err != nil { 528 t.Fatalf("%s: Readdir: %v", testName, err) 529 } 530 return fis 531 } 532 names := func(fis []FileInfo) []string { 533 s := make([]string, len(fis)) 534 for i, fi := range fis { 535 s[i] = fi.Name() 536 } 537 sort.Strings(s) 538 return s 539 } 540 541 if got, want := names(mustReadDir("inital readdir")), 542 []string{"good1", "good2", "x"}; !reflect.DeepEqual(got, want) { 543 t.Errorf("initial readdir got %q; want %q", got, want) 544 } 545 546 xerr = ErrNotExist 547 if got, want := names(mustReadDir("with x disappearing")), 548 []string{"good1", "good2"}; !reflect.DeepEqual(got, want) { 549 t.Errorf("with x disappearing, got %q; want %q", got, want) 550 } 551 552 xerr = errors.New("some real error") 553 if _, err := readDir(); err != xerr { 554 t.Errorf("with a non-ErrNotExist error, got error %v; want %v", err, xerr) 555 } 556 } 557 558 // Readdir on a regular file should fail. 559 func TestReaddirOfFile(t *testing.T) { 560 f, err := ioutil.TempFile("", "_Go_ReaddirOfFile") 561 if err != nil { 562 t.Fatal(err) 563 } 564 defer Remove(f.Name()) 565 f.Write([]byte("foo")) 566 f.Close() 567 reg, err := Open(f.Name()) 568 if err != nil { 569 t.Fatal(err) 570 } 571 defer reg.Close() 572 573 names, err := reg.Readdirnames(-1) 574 if err == nil { 575 t.Error("Readdirnames succeeded; want non-nil error") 576 } 577 if len(names) > 0 { 578 t.Errorf("unexpected dir names in regular file: %q", names) 579 } 580 } 581 582 func TestHardLink(t *testing.T) { 583 if runtime.GOOS == "plan9" { 584 t.Skip("skipping on plan9, hardlinks not supported") 585 } 586 defer chtmpdir(t)() 587 from, to := "hardlinktestfrom", "hardlinktestto" 588 Remove(from) // Just in case. 589 file, err := Create(to) 590 if err != nil { 591 t.Fatalf("open %q failed: %v", to, err) 592 } 593 defer Remove(to) 594 if err = file.Close(); err != nil { 595 t.Errorf("close %q failed: %v", to, err) 596 } 597 err = Link(to, from) 598 if err != nil { 599 t.Fatalf("link %q, %q failed: %v", to, from, err) 600 } 601 602 none := "hardlinktestnone" 603 err = Link(none, none) 604 // Check the returned error is well-formed. 605 if lerr, ok := err.(*LinkError); !ok || lerr.Error() == "" { 606 t.Errorf("link %q, %q failed to return a valid error", none, none) 607 } 608 609 defer Remove(from) 610 tostat, err := Stat(to) 611 if err != nil { 612 t.Fatalf("stat %q failed: %v", to, err) 613 } 614 fromstat, err := Stat(from) 615 if err != nil { 616 t.Fatalf("stat %q failed: %v", from, err) 617 } 618 if !SameFile(tostat, fromstat) { 619 t.Errorf("link %q, %q did not create hard link", to, from) 620 } 621 } 622 623 // chtmpdir changes the working directory to a new temporary directory and 624 // provides a cleanup function. Used when PWD is read-only. 625 func chtmpdir(t *testing.T) func() { 626 if runtime.GOOS != "darwin" || (runtime.GOARCH != "arm" && runtime.GOARCH != "arm64") { 627 return func() {} // only needed on darwin/arm{,64} 628 } 629 oldwd, err := Getwd() 630 if err != nil { 631 t.Fatalf("chtmpdir: %v", err) 632 } 633 d, err := ioutil.TempDir("", "test") 634 if err != nil { 635 t.Fatalf("chtmpdir: %v", err) 636 } 637 if err := Chdir(d); err != nil { 638 t.Fatalf("chtmpdir: %v", err) 639 } 640 return func() { 641 if err := Chdir(oldwd); err != nil { 642 t.Fatalf("chtmpdir: %v", err) 643 } 644 RemoveAll(d) 645 } 646 } 647 648 func TestSymlink(t *testing.T) { 649 switch runtime.GOOS { 650 case "android", "nacl", "plan9": 651 t.Skipf("skipping on %s", runtime.GOOS) 652 case "windows": 653 if !supportsSymlinks { 654 t.Skipf("skipping on %s", runtime.GOOS) 655 } 656 } 657 defer chtmpdir(t)() 658 from, to := "symlinktestfrom", "symlinktestto" 659 Remove(from) // Just in case. 660 file, err := Create(to) 661 if err != nil { 662 t.Fatalf("open %q failed: %v", to, err) 663 } 664 defer Remove(to) 665 if err = file.Close(); err != nil { 666 t.Errorf("close %q failed: %v", to, err) 667 } 668 err = Symlink(to, from) 669 if err != nil { 670 t.Fatalf("symlink %q, %q failed: %v", to, from, err) 671 } 672 defer Remove(from) 673 tostat, err := Lstat(to) 674 if err != nil { 675 t.Fatalf("stat %q failed: %v", to, err) 676 } 677 if tostat.Mode()&ModeSymlink != 0 { 678 t.Fatalf("stat %q claims to have found a symlink", to) 679 } 680 fromstat, err := Stat(from) 681 if err != nil { 682 t.Fatalf("stat %q failed: %v", from, err) 683 } 684 if !SameFile(tostat, fromstat) { 685 t.Errorf("symlink %q, %q did not create symlink", to, from) 686 } 687 fromstat, err = Lstat(from) 688 if err != nil { 689 t.Fatalf("lstat %q failed: %v", from, err) 690 } 691 if fromstat.Mode()&ModeSymlink == 0 { 692 t.Fatalf("symlink %q, %q did not create symlink", to, from) 693 } 694 fromstat, err = Stat(from) 695 if err != nil { 696 t.Fatalf("stat %q failed: %v", from, err) 697 } 698 if fromstat.Mode()&ModeSymlink != 0 { 699 t.Fatalf("stat %q did not follow symlink", from) 700 } 701 s, err := Readlink(from) 702 if err != nil { 703 t.Fatalf("readlink %q failed: %v", from, err) 704 } 705 if s != to { 706 t.Fatalf("after symlink %q != %q", s, to) 707 } 708 file, err = Open(from) 709 if err != nil { 710 t.Fatalf("open %q failed: %v", from, err) 711 } 712 file.Close() 713 } 714 715 func TestLongSymlink(t *testing.T) { 716 switch runtime.GOOS { 717 case "android", "plan9", "nacl": 718 t.Skipf("skipping on %s", runtime.GOOS) 719 case "windows": 720 if !supportsSymlinks { 721 t.Skipf("skipping on %s", runtime.GOOS) 722 } 723 } 724 defer chtmpdir(t)() 725 s := "0123456789abcdef" 726 // Long, but not too long: a common limit is 255. 727 s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s 728 from := "longsymlinktestfrom" 729 Remove(from) // Just in case. 730 err := Symlink(s, from) 731 if err != nil { 732 t.Fatalf("symlink %q, %q failed: %v", s, from, err) 733 } 734 defer Remove(from) 735 r, err := Readlink(from) 736 if err != nil { 737 t.Fatalf("readlink %q failed: %v", from, err) 738 } 739 if r != s { 740 t.Fatalf("after symlink %q != %q", r, s) 741 } 742 } 743 744 func TestRename(t *testing.T) { 745 defer chtmpdir(t)() 746 from, to := "renamefrom", "renameto" 747 // Ensure we are not testing the overwrite case here. 748 Remove(from) 749 Remove(to) 750 751 file, err := Create(from) 752 if err != nil { 753 t.Fatalf("open %q failed: %v", from, err) 754 } 755 if err = file.Close(); err != nil { 756 t.Errorf("close %q failed: %v", from, err) 757 } 758 err = Rename(from, to) 759 if err != nil { 760 t.Fatalf("rename %q, %q failed: %v", to, from, err) 761 } 762 defer Remove(to) 763 _, err = Stat(to) 764 if err != nil { 765 t.Errorf("stat %q failed: %v", to, err) 766 } 767 } 768 769 func TestRenameOverwriteDest(t *testing.T) { 770 if runtime.GOOS == "plan9" { 771 t.Skip("skipping on plan9") 772 } 773 defer chtmpdir(t)() 774 from, to := "renamefrom", "renameto" 775 // Just in case. 776 Remove(from) 777 Remove(to) 778 779 toData := []byte("to") 780 fromData := []byte("from") 781 782 err := ioutil.WriteFile(to, toData, 0777) 783 if err != nil { 784 t.Fatalf("write file %q failed: %v", to, err) 785 } 786 787 err = ioutil.WriteFile(from, fromData, 0777) 788 if err != nil { 789 t.Fatalf("write file %q failed: %v", from, err) 790 } 791 err = Rename(from, to) 792 if err != nil { 793 t.Fatalf("rename %q, %q failed: %v", to, from, err) 794 } 795 defer Remove(to) 796 797 _, err = Stat(from) 798 if err == nil { 799 t.Errorf("from file %q still exists", from) 800 } 801 if err != nil && !IsNotExist(err) { 802 t.Fatalf("stat from: %v", err) 803 } 804 toFi, err := Stat(to) 805 if err != nil { 806 t.Fatalf("stat %q failed: %v", to, err) 807 } 808 if toFi.Size() != int64(len(fromData)) { 809 t.Errorf(`"to" size = %d; want %d (old "from" size)`, toFi.Size(), len(fromData)) 810 } 811 } 812 813 func TestRenameFailed(t *testing.T) { 814 defer chtmpdir(t)() 815 from, to := "renamefrom", "renameto" 816 // Ensure we are not testing the overwrite case here. 817 Remove(from) 818 Remove(to) 819 820 err := Rename(from, to) 821 switch err := err.(type) { 822 case *LinkError: 823 if err.Op != "rename" { 824 t.Errorf("rename %q, %q: err.Op: want %q, got %q", from, to, "rename", err.Op) 825 } 826 if err.Old != from { 827 t.Errorf("rename %q, %q: err.Old: want %q, got %q", from, to, from, err.Old) 828 } 829 if err.New != to { 830 t.Errorf("rename %q, %q: err.New: want %q, got %q", from, to, to, err.New) 831 } 832 case nil: 833 t.Errorf("rename %q, %q: expected error, got nil", from, to) 834 835 // cleanup whatever was placed in "renameto" 836 Remove(to) 837 default: 838 t.Errorf("rename %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err) 839 } 840 } 841 842 func exec(t *testing.T, dir, cmd string, args []string, expect string) { 843 r, w, err := Pipe() 844 if err != nil { 845 t.Fatalf("Pipe: %v", err) 846 } 847 defer r.Close() 848 attr := &ProcAttr{Dir: dir, Files: []*File{nil, w, Stderr}} 849 p, err := StartProcess(cmd, args, attr) 850 if err != nil { 851 t.Fatalf("StartProcess: %v", err) 852 } 853 w.Close() 854 855 var b bytes.Buffer 856 io.Copy(&b, r) 857 output := b.String() 858 859 fi1, _ := Stat(strings.TrimSpace(output)) 860 fi2, _ := Stat(expect) 861 if !SameFile(fi1, fi2) { 862 t.Errorf("exec %q returned %q wanted %q", 863 strings.Join(append([]string{cmd}, args...), " "), output, expect) 864 } 865 p.Wait() 866 } 867 868 func TestStartProcess(t *testing.T) { 869 testenv.MustHaveExec(t) 870 871 var dir, cmd string 872 var args []string 873 switch runtime.GOOS { 874 case "android": 875 t.Skip("android doesn't have /bin/pwd") 876 case "windows": 877 cmd = Getenv("COMSPEC") 878 dir = Getenv("SystemRoot") 879 args = []string{"/c", "cd"} 880 default: 881 cmd = "/bin/pwd" 882 dir = "/" 883 args = []string{} 884 } 885 cmddir, cmdbase := filepath.Split(cmd) 886 args = append([]string{cmdbase}, args...) 887 // Test absolute executable path. 888 exec(t, dir, cmd, args, dir) 889 // Test relative executable path. 890 exec(t, cmddir, cmdbase, args, cmddir) 891 } 892 893 func checkMode(t *testing.T, path string, mode FileMode) { 894 dir, err := Stat(path) 895 if err != nil { 896 t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err) 897 } 898 if dir.Mode()&0777 != mode { 899 t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode(), mode) 900 } 901 } 902 903 func TestChmod(t *testing.T) { 904 // Chmod is not supported under windows. 905 if runtime.GOOS == "windows" { 906 return 907 } 908 f := newFile("TestChmod", t) 909 defer Remove(f.Name()) 910 defer f.Close() 911 912 if err := Chmod(f.Name(), 0456); err != nil { 913 t.Fatalf("chmod %s 0456: %s", f.Name(), err) 914 } 915 checkMode(t, f.Name(), 0456) 916 917 if err := f.Chmod(0123); err != nil { 918 t.Fatalf("chmod %s 0123: %s", f.Name(), err) 919 } 920 checkMode(t, f.Name(), 0123) 921 } 922 923 func checkSize(t *testing.T, f *File, size int64) { 924 dir, err := f.Stat() 925 if err != nil { 926 t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err) 927 } 928 if dir.Size() != size { 929 t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size) 930 } 931 } 932 933 func TestFTruncate(t *testing.T) { 934 f := newFile("TestFTruncate", t) 935 defer Remove(f.Name()) 936 defer f.Close() 937 938 checkSize(t, f, 0) 939 f.Write([]byte("hello, world\n")) 940 checkSize(t, f, 13) 941 f.Truncate(10) 942 checkSize(t, f, 10) 943 f.Truncate(1024) 944 checkSize(t, f, 1024) 945 f.Truncate(0) 946 checkSize(t, f, 0) 947 _, err := f.Write([]byte("surprise!")) 948 if err == nil { 949 checkSize(t, f, 13+9) // wrote at offset past where hello, world was. 950 } 951 } 952 953 func TestTruncate(t *testing.T) { 954 f := newFile("TestTruncate", t) 955 defer Remove(f.Name()) 956 defer f.Close() 957 958 checkSize(t, f, 0) 959 f.Write([]byte("hello, world\n")) 960 checkSize(t, f, 13) 961 Truncate(f.Name(), 10) 962 checkSize(t, f, 10) 963 Truncate(f.Name(), 1024) 964 checkSize(t, f, 1024) 965 Truncate(f.Name(), 0) 966 checkSize(t, f, 0) 967 _, err := f.Write([]byte("surprise!")) 968 if err == nil { 969 checkSize(t, f, 13+9) // wrote at offset past where hello, world was. 970 } 971 } 972 973 // Use TempDir (via newFile) to make sure we're on a local file system, 974 // so that timings are not distorted by latency and caching. 975 // On NFS, timings can be off due to caching of meta-data on 976 // NFS servers (Issue 848). 977 func TestChtimes(t *testing.T) { 978 f := newFile("TestChtimes", t) 979 defer Remove(f.Name()) 980 981 f.Write([]byte("hello, world\n")) 982 f.Close() 983 984 testChtimes(t, f.Name()) 985 } 986 987 // Use TempDir (via newDir) to make sure we're on a local file system, 988 // so that timings are not distorted by latency and caching. 989 // On NFS, timings can be off due to caching of meta-data on 990 // NFS servers (Issue 848). 991 func TestChtimesDir(t *testing.T) { 992 name := newDir("TestChtimes", t) 993 defer RemoveAll(name) 994 995 testChtimes(t, name) 996 } 997 998 func testChtimes(t *testing.T, name string) { 999 st, err := Stat(name) 1000 if err != nil { 1001 t.Fatalf("Stat %s: %s", name, err) 1002 } 1003 preStat := st 1004 1005 // Move access and modification time back a second 1006 at := Atime(preStat) 1007 mt := preStat.ModTime() 1008 err = Chtimes(name, at.Add(-time.Second), mt.Add(-time.Second)) 1009 if err != nil { 1010 t.Fatalf("Chtimes %s: %s", name, err) 1011 } 1012 1013 st, err = Stat(name) 1014 if err != nil { 1015 t.Fatalf("second Stat %s: %s", name, err) 1016 } 1017 postStat := st 1018 1019 /* Plan 9, NaCl: 1020 Mtime is the time of the last change of content. Similarly, atime is set whenever the 1021 contents are accessed; also, it is set whenever mtime is set. 1022 */ 1023 pat := Atime(postStat) 1024 pmt := postStat.ModTime() 1025 if !pat.Before(at) && runtime.GOOS != "plan9" && runtime.GOOS != "nacl" { 1026 t.Errorf("AccessTime didn't go backwards; was=%d, after=%d", at, pat) 1027 } 1028 1029 if !pmt.Before(mt) { 1030 t.Errorf("ModTime didn't go backwards; was=%d, after=%d", mt, pmt) 1031 } 1032 } 1033 1034 func TestChdirAndGetwd(t *testing.T) { 1035 // TODO(brainman): file.Chdir() is not implemented on windows. 1036 if runtime.GOOS == "windows" { 1037 return 1038 } 1039 fd, err := Open(".") 1040 if err != nil { 1041 t.Fatalf("Open .: %s", err) 1042 } 1043 // These are chosen carefully not to be symlinks on a Mac 1044 // (unlike, say, /var, /etc), except /tmp, which we handle below. 1045 dirs := []string{"/", "/usr/bin", "/tmp"} 1046 // /usr/bin does not usually exist on Plan 9 or Android. 1047 switch runtime.GOOS { 1048 case "android": 1049 dirs = []string{"/", "/system/bin"} 1050 case "plan9": 1051 dirs = []string{"/", "/usr"} 1052 case "darwin": 1053 switch runtime.GOARCH { 1054 case "arm", "arm64": 1055 d1, err := ioutil.TempDir("", "d1") 1056 if err != nil { 1057 t.Fatalf("TempDir: %v", err) 1058 } 1059 d2, err := ioutil.TempDir("", "d2") 1060 if err != nil { 1061 t.Fatalf("TempDir: %v", err) 1062 } 1063 dirs = []string{d1, d2} 1064 } 1065 } 1066 oldwd := Getenv("PWD") 1067 for mode := 0; mode < 2; mode++ { 1068 for _, d := range dirs { 1069 if mode == 0 { 1070 err = Chdir(d) 1071 } else { 1072 fd1, err := Open(d) 1073 if err != nil { 1074 t.Errorf("Open %s: %s", d, err) 1075 continue 1076 } 1077 err = fd1.Chdir() 1078 fd1.Close() 1079 } 1080 if d == "/tmp" { 1081 Setenv("PWD", "/tmp") 1082 } 1083 pwd, err1 := Getwd() 1084 Setenv("PWD", oldwd) 1085 err2 := fd.Chdir() 1086 if err2 != nil { 1087 // We changed the current directory and cannot go back. 1088 // Don't let the tests continue; they'll scribble 1089 // all over some other directory. 1090 fmt.Fprintf(Stderr, "fchdir back to dot failed: %s\n", err2) 1091 Exit(1) 1092 } 1093 if err != nil { 1094 fd.Close() 1095 t.Fatalf("Chdir %s: %s", d, err) 1096 } 1097 if err1 != nil { 1098 fd.Close() 1099 t.Fatalf("Getwd in %s: %s", d, err1) 1100 } 1101 if pwd != d { 1102 fd.Close() 1103 t.Fatalf("Getwd returned %q want %q", pwd, d) 1104 } 1105 } 1106 } 1107 fd.Close() 1108 } 1109 1110 // Test that Chdir+Getwd is program-wide. 1111 func TestProgWideChdir(t *testing.T) { 1112 const N = 10 1113 c := make(chan bool) 1114 cpwd := make(chan string) 1115 for i := 0; i < N; i++ { 1116 go func(i int) { 1117 // Lock half the goroutines in their own operating system 1118 // thread to exercise more scheduler possibilities. 1119 if i%2 == 1 { 1120 // On Plan 9, after calling LockOSThread, the goroutines 1121 // run on different processes which don't share the working 1122 // directory. This used to be an issue because Go expects 1123 // the working directory to be program-wide. 1124 // See issue 9428. 1125 runtime.LockOSThread() 1126 } 1127 <-c 1128 pwd, err := Getwd() 1129 if err != nil { 1130 t.Errorf("Getwd on goroutine %d: %v", i, err) 1131 return 1132 } 1133 cpwd <- pwd 1134 }(i) 1135 } 1136 oldwd, err := Getwd() 1137 if err != nil { 1138 t.Fatalf("Getwd: %v", err) 1139 } 1140 d, err := ioutil.TempDir("", "test") 1141 if err != nil { 1142 t.Fatalf("TempDir: %v", err) 1143 } 1144 defer func() { 1145 if err := Chdir(oldwd); err != nil { 1146 t.Fatalf("Chdir: %v", err) 1147 } 1148 RemoveAll(d) 1149 }() 1150 if err := Chdir(d); err != nil { 1151 t.Fatalf("Chdir: %v", err) 1152 } 1153 // OS X sets TMPDIR to a symbolic link. 1154 // So we resolve our working directory again before the test. 1155 d, err = Getwd() 1156 if err != nil { 1157 t.Fatalf("Getwd: %v", err) 1158 } 1159 close(c) 1160 for i := 0; i < N; i++ { 1161 pwd := <-cpwd 1162 if pwd != d { 1163 t.Errorf("Getwd returned %q; want %q", pwd, d) 1164 } 1165 } 1166 } 1167 1168 func TestSeek(t *testing.T) { 1169 f := newFile("TestSeek", t) 1170 defer Remove(f.Name()) 1171 defer f.Close() 1172 1173 const data = "hello, world\n" 1174 io.WriteString(f, data) 1175 1176 type test struct { 1177 in int64 1178 whence int 1179 out int64 1180 } 1181 var tests = []test{ 1182 {0, 1, int64(len(data))}, 1183 {0, 0, 0}, 1184 {5, 0, 5}, 1185 {0, 2, int64(len(data))}, 1186 {0, 0, 0}, 1187 {-1, 2, int64(len(data)) - 1}, 1188 {1 << 33, 0, 1 << 33}, 1189 {1 << 33, 2, 1<<33 + int64(len(data))}, 1190 } 1191 for i, tt := range tests { 1192 off, err := f.Seek(tt.in, tt.whence) 1193 if off != tt.out || err != nil { 1194 if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 { 1195 // Reiserfs rejects the big seeks. 1196 // https://golang.org/issue/91 1197 break 1198 } 1199 t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out) 1200 } 1201 } 1202 } 1203 1204 type openErrorTest struct { 1205 path string 1206 mode int 1207 error error 1208 } 1209 1210 var openErrorTests = []openErrorTest{ 1211 { 1212 sfdir + "/no-such-file", 1213 O_RDONLY, 1214 syscall.ENOENT, 1215 }, 1216 { 1217 sfdir, 1218 O_WRONLY, 1219 syscall.EISDIR, 1220 }, 1221 { 1222 sfdir + "/" + sfname + "/no-such-file", 1223 O_WRONLY, 1224 syscall.ENOTDIR, 1225 }, 1226 } 1227 1228 func TestOpenError(t *testing.T) { 1229 for _, tt := range openErrorTests { 1230 f, err := OpenFile(tt.path, tt.mode, 0) 1231 if err == nil { 1232 t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode) 1233 f.Close() 1234 continue 1235 } 1236 perr, ok := err.(*PathError) 1237 if !ok { 1238 t.Errorf("Open(%q, %d) returns error of %T type; want *PathError", tt.path, tt.mode, err) 1239 } 1240 if perr.Err != tt.error { 1241 if runtime.GOOS == "plan9" { 1242 syscallErrStr := perr.Err.Error() 1243 expectedErrStr := strings.Replace(tt.error.Error(), "file ", "", 1) 1244 if !strings.HasSuffix(syscallErrStr, expectedErrStr) { 1245 // Some Plan 9 file servers incorrectly return 1246 // EACCES rather than EISDIR when a directory is 1247 // opened for write. 1248 if tt.error == syscall.EISDIR && strings.HasSuffix(syscallErrStr, syscall.EACCES.Error()) { 1249 continue 1250 } 1251 t.Errorf("Open(%q, %d) = _, %q; want suffix %q", tt.path, tt.mode, syscallErrStr, expectedErrStr) 1252 } 1253 continue 1254 } 1255 if runtime.GOOS == "dragonfly" { 1256 // DragonFly incorrectly returns EACCES rather 1257 // EISDIR when a directory is opened for write. 1258 if tt.error == syscall.EISDIR && perr.Err == syscall.EACCES { 1259 continue 1260 } 1261 } 1262 t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, perr.Err.Error(), tt.error.Error()) 1263 } 1264 } 1265 } 1266 1267 func TestOpenNoName(t *testing.T) { 1268 f, err := Open("") 1269 if err == nil { 1270 t.Fatal(`Open("") succeeded`) 1271 f.Close() 1272 } 1273 } 1274 1275 func run(t *testing.T, cmd []string) string { 1276 // Run /bin/hostname and collect output. 1277 r, w, err := Pipe() 1278 if err != nil { 1279 t.Fatal(err) 1280 } 1281 defer r.Close() 1282 p, err := StartProcess("/bin/hostname", []string{"hostname"}, &ProcAttr{Files: []*File{nil, w, Stderr}}) 1283 if err != nil { 1284 t.Fatal(err) 1285 } 1286 w.Close() 1287 1288 var b bytes.Buffer 1289 io.Copy(&b, r) 1290 _, err = p.Wait() 1291 if err != nil { 1292 t.Fatalf("run hostname Wait: %v", err) 1293 } 1294 err = p.Kill() 1295 if err == nil { 1296 t.Errorf("expected an error from Kill running 'hostname'") 1297 } 1298 output := b.String() 1299 if n := len(output); n > 0 && output[n-1] == '\n' { 1300 output = output[0 : n-1] 1301 } 1302 if output == "" { 1303 t.Fatalf("%v produced no output", cmd) 1304 } 1305 1306 return output 1307 } 1308 1309 func testWindowsHostname(t *testing.T) { 1310 hostname, err := Hostname() 1311 if err != nil { 1312 t.Fatal(err) 1313 } 1314 cmd := osexec.Command("hostname") 1315 out, err := cmd.CombinedOutput() 1316 if err != nil { 1317 t.Fatalf("Failed to execute hostname command: %v %s", err, out) 1318 } 1319 want := strings.Trim(string(out), "\r\n") 1320 if hostname != want { 1321 t.Fatalf("Hostname() = %q, want %q", hostname, want) 1322 } 1323 } 1324 1325 func TestHostname(t *testing.T) { 1326 // There is no other way to fetch hostname on windows, but via winapi. 1327 // On Plan 9 it can be taken from #c/sysname as Hostname() does. 1328 switch runtime.GOOS { 1329 case "android", "plan9": 1330 t.Skipf("%s doesn't have /bin/hostname", runtime.GOOS) 1331 case "windows": 1332 testWindowsHostname(t) 1333 return 1334 } 1335 1336 testenv.MustHaveExec(t) 1337 1338 // Check internal Hostname() against the output of /bin/hostname. 1339 // Allow that the internal Hostname returns a Fully Qualified Domain Name 1340 // and the /bin/hostname only returns the first component 1341 hostname, err := Hostname() 1342 if err != nil { 1343 t.Fatalf("%v", err) 1344 } 1345 want := run(t, []string{"/bin/hostname"}) 1346 if hostname != want { 1347 i := strings.Index(hostname, ".") 1348 if i < 0 || hostname[0:i] != want { 1349 t.Errorf("Hostname() = %q, want %q", hostname, want) 1350 } 1351 } 1352 } 1353 1354 func TestReadAt(t *testing.T) { 1355 f := newFile("TestReadAt", t) 1356 defer Remove(f.Name()) 1357 defer f.Close() 1358 1359 const data = "hello, world\n" 1360 io.WriteString(f, data) 1361 1362 b := make([]byte, 5) 1363 n, err := f.ReadAt(b, 7) 1364 if err != nil || n != len(b) { 1365 t.Fatalf("ReadAt 7: %d, %v", n, err) 1366 } 1367 if string(b) != "world" { 1368 t.Fatalf("ReadAt 7: have %q want %q", string(b), "world") 1369 } 1370 } 1371 1372 func TestWriteAt(t *testing.T) { 1373 f := newFile("TestWriteAt", t) 1374 defer Remove(f.Name()) 1375 defer f.Close() 1376 1377 const data = "hello, world\n" 1378 io.WriteString(f, data) 1379 1380 n, err := f.WriteAt([]byte("WORLD"), 7) 1381 if err != nil || n != 5 { 1382 t.Fatalf("WriteAt 7: %d, %v", n, err) 1383 } 1384 1385 b, err := ioutil.ReadFile(f.Name()) 1386 if err != nil { 1387 t.Fatalf("ReadFile %s: %v", f.Name(), err) 1388 } 1389 if string(b) != "hello, WORLD\n" { 1390 t.Fatalf("after write: have %q want %q", string(b), "hello, WORLD\n") 1391 } 1392 } 1393 1394 func writeFile(t *testing.T, fname string, flag int, text string) string { 1395 f, err := OpenFile(fname, flag, 0666) 1396 if err != nil { 1397 t.Fatalf("Open: %v", err) 1398 } 1399 n, err := io.WriteString(f, text) 1400 if err != nil { 1401 t.Fatalf("WriteString: %d, %v", n, err) 1402 } 1403 f.Close() 1404 data, err := ioutil.ReadFile(fname) 1405 if err != nil { 1406 t.Fatalf("ReadFile: %v", err) 1407 } 1408 return string(data) 1409 } 1410 1411 func TestAppend(t *testing.T) { 1412 defer chtmpdir(t)() 1413 const f = "append.txt" 1414 defer Remove(f) 1415 s := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new") 1416 if s != "new" { 1417 t.Fatalf("writeFile: have %q want %q", s, "new") 1418 } 1419 s = writeFile(t, f, O_APPEND|O_RDWR, "|append") 1420 if s != "new|append" { 1421 t.Fatalf("writeFile: have %q want %q", s, "new|append") 1422 } 1423 s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "|append") 1424 if s != "new|append|append" { 1425 t.Fatalf("writeFile: have %q want %q", s, "new|append|append") 1426 } 1427 err := Remove(f) 1428 if err != nil { 1429 t.Fatalf("Remove: %v", err) 1430 } 1431 s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "new&append") 1432 if s != "new&append" { 1433 t.Fatalf("writeFile: after append have %q want %q", s, "new&append") 1434 } 1435 s = writeFile(t, f, O_CREATE|O_RDWR, "old") 1436 if s != "old&append" { 1437 t.Fatalf("writeFile: after create have %q want %q", s, "old&append") 1438 } 1439 s = writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new") 1440 if s != "new" { 1441 t.Fatalf("writeFile: after truncate have %q want %q", s, "new") 1442 } 1443 } 1444 1445 func TestStatDirWithTrailingSlash(t *testing.T) { 1446 // Create new temporary directory and arrange to clean it up. 1447 path, err := ioutil.TempDir("", "/_TestStatDirWithSlash_") 1448 if err != nil { 1449 t.Fatalf("TempDir: %s", err) 1450 } 1451 defer RemoveAll(path) 1452 1453 // Stat of path should succeed. 1454 _, err = Stat(path) 1455 if err != nil { 1456 t.Fatalf("stat %s failed: %s", path, err) 1457 } 1458 1459 // Stat of path+"/" should succeed too. 1460 path += "/" 1461 _, err = Stat(path) 1462 if err != nil { 1463 t.Fatalf("stat %s failed: %s", path, err) 1464 } 1465 } 1466 1467 func TestNilProcessStateString(t *testing.T) { 1468 var ps *ProcessState 1469 s := ps.String() 1470 if s != "<nil>" { 1471 t.Errorf("(*ProcessState)(nil).String() = %q, want %q", s, "<nil>") 1472 } 1473 } 1474 1475 func TestSameFile(t *testing.T) { 1476 defer chtmpdir(t)() 1477 fa, err := Create("a") 1478 if err != nil { 1479 t.Fatalf("Create(a): %v", err) 1480 } 1481 defer Remove(fa.Name()) 1482 fa.Close() 1483 fb, err := Create("b") 1484 if err != nil { 1485 t.Fatalf("Create(b): %v", err) 1486 } 1487 defer Remove(fb.Name()) 1488 fb.Close() 1489 1490 ia1, err := Stat("a") 1491 if err != nil { 1492 t.Fatalf("Stat(a): %v", err) 1493 } 1494 ia2, err := Stat("a") 1495 if err != nil { 1496 t.Fatalf("Stat(a): %v", err) 1497 } 1498 if !SameFile(ia1, ia2) { 1499 t.Errorf("files should be same") 1500 } 1501 1502 ib, err := Stat("b") 1503 if err != nil { 1504 t.Fatalf("Stat(b): %v", err) 1505 } 1506 if SameFile(ia1, ib) { 1507 t.Errorf("files should be different") 1508 } 1509 } 1510 1511 func TestDevNullFile(t *testing.T) { 1512 f, err := Open(DevNull) 1513 if err != nil { 1514 t.Fatalf("Open(%s): %v", DevNull, err) 1515 } 1516 defer f.Close() 1517 fi, err := f.Stat() 1518 if err != nil { 1519 t.Fatalf("Stat(%s): %v", DevNull, err) 1520 } 1521 name := filepath.Base(DevNull) 1522 if fi.Name() != name { 1523 t.Fatalf("wrong file name have %v want %v", fi.Name(), name) 1524 } 1525 if fi.Size() != 0 { 1526 t.Fatalf("wrong file size have %d want 0", fi.Size()) 1527 } 1528 } 1529 1530 var testLargeWrite = flag.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output") 1531 1532 func TestLargeWriteToConsole(t *testing.T) { 1533 if !*testLargeWrite { 1534 t.Skip("skipping console-flooding test; enable with -large_write") 1535 } 1536 b := make([]byte, 32000) 1537 for i := range b { 1538 b[i] = '.' 1539 } 1540 b[len(b)-1] = '\n' 1541 n, err := Stdout.Write(b) 1542 if err != nil { 1543 t.Fatalf("Write to os.Stdout failed: %v", err) 1544 } 1545 if n != len(b) { 1546 t.Errorf("Write to os.Stdout should return %d; got %d", len(b), n) 1547 } 1548 n, err = Stderr.Write(b) 1549 if err != nil { 1550 t.Fatalf("Write to os.Stderr failed: %v", err) 1551 } 1552 if n != len(b) { 1553 t.Errorf("Write to os.Stderr should return %d; got %d", len(b), n) 1554 } 1555 } 1556 1557 func TestStatDirModeExec(t *testing.T) { 1558 const mode = 0111 1559 1560 path, err := ioutil.TempDir("", "go-build") 1561 if err != nil { 1562 t.Fatalf("Failed to create temp directory: %v", err) 1563 } 1564 defer RemoveAll(path) 1565 1566 if err := Chmod(path, 0777); err != nil { 1567 t.Fatalf("Chmod %q 0777: %v", path, err) 1568 } 1569 1570 dir, err := Stat(path) 1571 if err != nil { 1572 t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err) 1573 } 1574 if dir.Mode()&mode != mode { 1575 t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode()&mode, mode) 1576 } 1577 } 1578 1579 func TestReadAtEOF(t *testing.T) { 1580 f := newFile("TestReadAtEOF", t) 1581 defer Remove(f.Name()) 1582 defer f.Close() 1583 1584 _, err := f.ReadAt(make([]byte, 10), 0) 1585 switch err { 1586 case io.EOF: 1587 // all good 1588 case nil: 1589 t.Fatalf("ReadAt succeeded") 1590 default: 1591 t.Fatalf("ReadAt failed: %s", err) 1592 } 1593 } 1594 1595 func testKillProcess(t *testing.T, processKiller func(p *Process)) { 1596 testenv.MustHaveExec(t) 1597 1598 // Re-exec the test binary itself to emulate "sleep 1". 1599 cmd := osexec.Command(Args[0], "-test.run", "TestSleep") 1600 err := cmd.Start() 1601 if err != nil { 1602 t.Fatalf("Failed to start test process: %v", err) 1603 } 1604 go func() { 1605 time.Sleep(100 * time.Millisecond) 1606 processKiller(cmd.Process) 1607 }() 1608 err = cmd.Wait() 1609 if err == nil { 1610 t.Errorf("Test process succeeded, but expected to fail") 1611 } 1612 } 1613 1614 // TestSleep emulates "sleep 1". It is a helper for testKillProcess, so we 1615 // don't have to rely on an external "sleep" command being available. 1616 func TestSleep(t *testing.T) { 1617 if testing.Short() { 1618 t.Skip("Skipping in short mode") 1619 } 1620 time.Sleep(time.Second) 1621 } 1622 1623 func TestKillStartProcess(t *testing.T) { 1624 testKillProcess(t, func(p *Process) { 1625 err := p.Kill() 1626 if err != nil { 1627 t.Fatalf("Failed to kill test process: %v", err) 1628 } 1629 }) 1630 } 1631 1632 func TestGetppid(t *testing.T) { 1633 if runtime.GOOS == "plan9" { 1634 // TODO: golang.org/issue/8206 1635 t.Skipf("skipping test on plan9; see issue 8206") 1636 } 1637 1638 testenv.MustHaveExec(t) 1639 1640 if Getenv("GO_WANT_HELPER_PROCESS") == "1" { 1641 fmt.Print(Getppid()) 1642 Exit(0) 1643 } 1644 1645 cmd := osexec.Command(Args[0], "-test.run=TestGetppid") 1646 cmd.Env = append(Environ(), "GO_WANT_HELPER_PROCESS=1") 1647 1648 // verify that Getppid() from the forked process reports our process id 1649 output, err := cmd.CombinedOutput() 1650 if err != nil { 1651 t.Fatalf("Failed to spawn child process: %v %q", err, string(output)) 1652 } 1653 1654 childPpid := string(output) 1655 ourPid := fmt.Sprintf("%d", Getpid()) 1656 if childPpid != ourPid { 1657 t.Fatalf("Child process reports parent process id '%v', expected '%v'", childPpid, ourPid) 1658 } 1659 } 1660 1661 func TestKillFindProcess(t *testing.T) { 1662 testKillProcess(t, func(p *Process) { 1663 p2, err := FindProcess(p.Pid) 1664 if err != nil { 1665 t.Fatalf("Failed to find test process: %v", err) 1666 } 1667 err = p2.Kill() 1668 if err != nil { 1669 t.Fatalf("Failed to kill test process: %v", err) 1670 } 1671 }) 1672 } 1673 1674 var nilFileMethodTests = []struct { 1675 name string 1676 f func(*File) error 1677 }{ 1678 {"Chdir", func(f *File) error { return f.Chdir() }}, 1679 {"Close", func(f *File) error { return f.Close() }}, 1680 {"Chmod", func(f *File) error { return f.Chmod(0) }}, 1681 {"Chown", func(f *File) error { return f.Chown(0, 0) }}, 1682 {"Read", func(f *File) error { _, err := f.Read(make([]byte, 0)); return err }}, 1683 {"ReadAt", func(f *File) error { _, err := f.ReadAt(make([]byte, 0), 0); return err }}, 1684 {"Readdir", func(f *File) error { _, err := f.Readdir(1); return err }}, 1685 {"Readdirnames", func(f *File) error { _, err := f.Readdirnames(1); return err }}, 1686 {"Seek", func(f *File) error { _, err := f.Seek(0, 0); return err }}, 1687 {"Stat", func(f *File) error { _, err := f.Stat(); return err }}, 1688 {"Sync", func(f *File) error { return f.Sync() }}, 1689 {"Truncate", func(f *File) error { return f.Truncate(0) }}, 1690 {"Write", func(f *File) error { _, err := f.Write(make([]byte, 0)); return err }}, 1691 {"WriteAt", func(f *File) error { _, err := f.WriteAt(make([]byte, 0), 0); return err }}, 1692 {"WriteString", func(f *File) error { _, err := f.WriteString(""); return err }}, 1693 } 1694 1695 // Test that all File methods give ErrInvalid if the receiver is nil. 1696 func TestNilFileMethods(t *testing.T) { 1697 for _, tt := range nilFileMethodTests { 1698 var file *File 1699 got := tt.f(file) 1700 if got != ErrInvalid { 1701 t.Errorf("%v should fail when f is nil; got %v", tt.name, got) 1702 } 1703 } 1704 } 1705 1706 func mkdirTree(t *testing.T, root string, level, max int) { 1707 if level >= max { 1708 return 1709 } 1710 level++ 1711 for i := 'a'; i < 'c'; i++ { 1712 dir := filepath.Join(root, string(i)) 1713 if err := Mkdir(dir, 0700); err != nil { 1714 t.Fatal(err) 1715 } 1716 mkdirTree(t, dir, level, max) 1717 } 1718 } 1719 1720 // Test that simultaneous RemoveAll do not report an error. 1721 // As long as it gets removed, we should be happy. 1722 func TestRemoveAllRace(t *testing.T) { 1723 if runtime.GOOS == "windows" { 1724 // Windows has very strict rules about things like 1725 // removing directories while someone else has 1726 // them open. The racing doesn't work out nicely 1727 // like it does on Unix. 1728 t.Skip("skipping on windows") 1729 } 1730 1731 n := runtime.GOMAXPROCS(16) 1732 defer runtime.GOMAXPROCS(n) 1733 root, err := ioutil.TempDir("", "issue") 1734 if err != nil { 1735 t.Fatal(err) 1736 } 1737 mkdirTree(t, root, 1, 6) 1738 hold := make(chan struct{}) 1739 var wg sync.WaitGroup 1740 for i := 0; i < 4; i++ { 1741 wg.Add(1) 1742 go func() { 1743 defer wg.Done() 1744 <-hold 1745 err := RemoveAll(root) 1746 if err != nil { 1747 t.Errorf("unexpected error: %T, %q", err, err) 1748 } 1749 }() 1750 } 1751 close(hold) // let workers race to remove root 1752 wg.Wait() 1753 }