github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/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  	"flag"
    10  	"fmt"
    11  	"io"
    12  	"io/ioutil"
    13  	. "os"
    14  	osexec "os/exec"
    15  	"path/filepath"
    16  	"runtime"
    17  	"strings"
    18  	"syscall"
    19  	"testing"
    20  	"text/template"
    21  	"time"
    22  )
    23  
    24  var dot = []string{
    25  	"dir_unix.go",
    26  	"env.go",
    27  	"error.go",
    28  	"file.go",
    29  	"os_test.go",
    30  	"types.go",
    31  	"stat_darwin.go",
    32  	"stat_linux.go",
    33  }
    34  
    35  type sysDir struct {
    36  	name  string
    37  	files []string
    38  }
    39  
    40  var sysdir = func() (sd *sysDir) {
    41  	switch runtime.GOOS {
    42  	case "windows":
    43  		sd = &sysDir{
    44  			Getenv("SystemRoot") + "\\system32\\drivers\\etc",
    45  			[]string{
    46  				"networks",
    47  				"protocol",
    48  				"services",
    49  			},
    50  		}
    51  	case "plan9":
    52  		sd = &sysDir{
    53  			"/lib/ndb",
    54  			[]string{
    55  				"common",
    56  				"local",
    57  			},
    58  		}
    59  	default:
    60  		sd = &sysDir{
    61  			"/etc",
    62  			[]string{
    63  				"group",
    64  				"hosts",
    65  				"passwd",
    66  			},
    67  		}
    68  	}
    69  	return
    70  }()
    71  
    72  func size(name string, t *testing.T) int64 {
    73  	file, err := Open(name)
    74  	if err != nil {
    75  		t.Fatal("open failed:", err)
    76  	}
    77  	defer file.Close()
    78  	var buf [100]byte
    79  	len := 0
    80  	for {
    81  		n, e := file.Read(buf[0:])
    82  		len += n
    83  		if e == io.EOF {
    84  			break
    85  		}
    86  		if e != nil {
    87  			t.Fatal("read failed:", err)
    88  		}
    89  	}
    90  	return int64(len)
    91  }
    92  
    93  func equal(name1, name2 string) (r bool) {
    94  	switch runtime.GOOS {
    95  	case "windows":
    96  		r = strings.ToLower(name1) == strings.ToLower(name2)
    97  	default:
    98  		r = name1 == name2
    99  	}
   100  	return
   101  }
   102  
   103  func newFile(testName string, t *testing.T) (f *File) {
   104  	// Use a local file system, not NFS.
   105  	// On Unix, override $TMPDIR in case the user
   106  	// has it set to an NFS-mounted directory.
   107  	dir := ""
   108  	if runtime.GOOS != "windows" {
   109  		dir = "/tmp"
   110  	}
   111  	f, err := ioutil.TempFile(dir, "_Go_"+testName)
   112  	if err != nil {
   113  		t.Fatalf("open %s: %s", testName, err)
   114  	}
   115  	return
   116  }
   117  
   118  var sfdir = sysdir.name
   119  var sfname = sysdir.files[0]
   120  
   121  func TestStat(t *testing.T) {
   122  	path := sfdir + "/" + sfname
   123  	dir, err := Stat(path)
   124  	if err != nil {
   125  		t.Fatal("stat failed:", err)
   126  	}
   127  	if !equal(sfname, dir.Name()) {
   128  		t.Error("name should be ", sfname, "; is", dir.Name())
   129  	}
   130  	filesize := size(path, t)
   131  	if dir.Size() != filesize {
   132  		t.Error("size should be", filesize, "; is", dir.Size())
   133  	}
   134  }
   135  
   136  func TestFstat(t *testing.T) {
   137  	path := sfdir + "/" + sfname
   138  	file, err1 := Open(path)
   139  	if err1 != nil {
   140  		t.Fatal("open failed:", err1)
   141  	}
   142  	defer file.Close()
   143  	dir, err2 := file.Stat()
   144  	if err2 != nil {
   145  		t.Fatal("fstat failed:", err2)
   146  	}
   147  	if !equal(sfname, dir.Name()) {
   148  		t.Error("name should be ", sfname, "; is", dir.Name())
   149  	}
   150  	filesize := size(path, t)
   151  	if dir.Size() != filesize {
   152  		t.Error("size should be", filesize, "; is", dir.Size())
   153  	}
   154  }
   155  
   156  func TestLstat(t *testing.T) {
   157  	path := sfdir + "/" + sfname
   158  	dir, err := Lstat(path)
   159  	if err != nil {
   160  		t.Fatal("lstat failed:", err)
   161  	}
   162  	if !equal(sfname, dir.Name()) {
   163  		t.Error("name should be ", sfname, "; is", dir.Name())
   164  	}
   165  	filesize := size(path, t)
   166  	if dir.Size() != filesize {
   167  		t.Error("size should be", filesize, "; is", dir.Size())
   168  	}
   169  }
   170  
   171  // Read with length 0 should not return EOF.
   172  func TestRead0(t *testing.T) {
   173  	path := sfdir + "/" + sfname
   174  	f, err := Open(path)
   175  	if err != nil {
   176  		t.Fatal("open failed:", err)
   177  	}
   178  	defer f.Close()
   179  
   180  	b := make([]byte, 0)
   181  	n, err := f.Read(b)
   182  	if n != 0 || err != nil {
   183  		t.Errorf("Read(0) = %d, %v, want 0, nil", n, err)
   184  	}
   185  	b = make([]byte, 100)
   186  	n, err = f.Read(b)
   187  	if n <= 0 || err != nil {
   188  		t.Errorf("Read(100) = %d, %v, want >0, nil", n, err)
   189  	}
   190  }
   191  
   192  func testReaddirnames(dir string, contents []string, t *testing.T) {
   193  	file, err := Open(dir)
   194  	if err != nil {
   195  		t.Fatalf("open %q failed: %v", dir, err)
   196  	}
   197  	defer file.Close()
   198  	s, err2 := file.Readdirnames(-1)
   199  	if err2 != nil {
   200  		t.Fatalf("readdirnames %q failed: %v", dir, err2)
   201  	}
   202  	for _, m := range contents {
   203  		found := false
   204  		for _, n := range s {
   205  			if n == "." || n == ".." {
   206  				t.Errorf("got %s in directory", n)
   207  			}
   208  			if equal(m, n) {
   209  				if found {
   210  					t.Error("present twice:", m)
   211  				}
   212  				found = true
   213  			}
   214  		}
   215  		if !found {
   216  			t.Error("could not find", m)
   217  		}
   218  	}
   219  }
   220  
   221  func testReaddir(dir string, contents []string, t *testing.T) {
   222  	file, err := Open(dir)
   223  	if err != nil {
   224  		t.Fatalf("open %q failed: %v", dir, err)
   225  	}
   226  	defer file.Close()
   227  	s, err2 := file.Readdir(-1)
   228  	if err2 != nil {
   229  		t.Fatalf("readdir %q failed: %v", dir, err2)
   230  	}
   231  	for _, m := range contents {
   232  		found := false
   233  		for _, n := range s {
   234  			if equal(m, n.Name()) {
   235  				if found {
   236  					t.Error("present twice:", m)
   237  				}
   238  				found = true
   239  			}
   240  		}
   241  		if !found {
   242  			t.Error("could not find", m)
   243  		}
   244  	}
   245  }
   246  
   247  func TestReaddirnames(t *testing.T) {
   248  	testReaddirnames(".", dot, t)
   249  	testReaddirnames(sysdir.name, sysdir.files, t)
   250  }
   251  
   252  func TestReaddir(t *testing.T) {
   253  	testReaddir(".", dot, t)
   254  	testReaddir(sysdir.name, sysdir.files, t)
   255  }
   256  
   257  // Read the directory one entry at a time.
   258  func smallReaddirnames(file *File, length int, t *testing.T) []string {
   259  	names := make([]string, length)
   260  	count := 0
   261  	for {
   262  		d, err := file.Readdirnames(1)
   263  		if err == io.EOF {
   264  			break
   265  		}
   266  		if err != nil {
   267  			t.Fatalf("readdirnames %q failed: %v", file.Name(), err)
   268  		}
   269  		if len(d) == 0 {
   270  			t.Fatalf("readdirnames %q returned empty slice and no error", file.Name())
   271  		}
   272  		names[count] = d[0]
   273  		count++
   274  	}
   275  	return names[0:count]
   276  }
   277  
   278  // Check that reading a directory one entry at a time gives the same result
   279  // as reading it all at once.
   280  func TestReaddirnamesOneAtATime(t *testing.T) {
   281  	// big directory that doesn't change often.
   282  	dir := "/usr/bin"
   283  	switch runtime.GOOS {
   284  	case "windows":
   285  		dir = Getenv("SystemRoot") + "\\system32"
   286  	case "plan9":
   287  		dir = "/bin"
   288  	}
   289  	file, err := Open(dir)
   290  	if err != nil {
   291  		t.Fatalf("open %q failed: %v", dir, err)
   292  	}
   293  	defer file.Close()
   294  	all, err1 := file.Readdirnames(-1)
   295  	if err1 != nil {
   296  		t.Fatalf("readdirnames %q failed: %v", dir, err1)
   297  	}
   298  	file1, err2 := Open(dir)
   299  	if err2 != nil {
   300  		t.Fatalf("open %q failed: %v", dir, err2)
   301  	}
   302  	defer file1.Close()
   303  	small := smallReaddirnames(file1, len(all)+100, t) // +100 in case we screw up
   304  	if len(small) < len(all) {
   305  		t.Fatalf("len(small) is %d, less than %d", len(small), len(all))
   306  	}
   307  	for i, n := range all {
   308  		if small[i] != n {
   309  			t.Errorf("small read %q mismatch: %v", small[i], n)
   310  		}
   311  	}
   312  }
   313  
   314  func TestReaddirNValues(t *testing.T) {
   315  	if testing.Short() {
   316  		t.Skip("test.short; skipping")
   317  	}
   318  	dir, err := ioutil.TempDir("", "")
   319  	if err != nil {
   320  		t.Fatalf("TempDir: %v", err)
   321  	}
   322  	defer RemoveAll(dir)
   323  	for i := 1; i <= 105; i++ {
   324  		f, err := Create(filepath.Join(dir, fmt.Sprintf("%d", i)))
   325  		if err != nil {
   326  			t.Fatalf("Create: %v", err)
   327  		}
   328  		f.Write([]byte(strings.Repeat("X", i)))
   329  		f.Close()
   330  	}
   331  
   332  	var d *File
   333  	openDir := func() {
   334  		var err error
   335  		d, err = Open(dir)
   336  		if err != nil {
   337  			t.Fatalf("Open directory: %v", err)
   338  		}
   339  	}
   340  
   341  	readDirExpect := func(n, want int, wantErr error) {
   342  		fi, err := d.Readdir(n)
   343  		if err != wantErr {
   344  			t.Fatalf("Readdir of %d got error %v, want %v", n, err, wantErr)
   345  		}
   346  		if g, e := len(fi), want; g != e {
   347  			t.Errorf("Readdir of %d got %d files, want %d", n, g, e)
   348  		}
   349  	}
   350  
   351  	readDirNamesExpect := func(n, want int, wantErr error) {
   352  		fi, err := d.Readdirnames(n)
   353  		if err != wantErr {
   354  			t.Fatalf("Readdirnames of %d got error %v, want %v", n, err, wantErr)
   355  		}
   356  		if g, e := len(fi), want; g != e {
   357  			t.Errorf("Readdirnames of %d got %d files, want %d", n, g, e)
   358  		}
   359  	}
   360  
   361  	for _, fn := range []func(int, int, error){readDirExpect, readDirNamesExpect} {
   362  		// Test the slurp case
   363  		openDir()
   364  		fn(0, 105, nil)
   365  		fn(0, 0, nil)
   366  		d.Close()
   367  
   368  		// Slurp with -1 instead
   369  		openDir()
   370  		fn(-1, 105, nil)
   371  		fn(-2, 0, nil)
   372  		fn(0, 0, nil)
   373  		d.Close()
   374  
   375  		// Test the bounded case
   376  		openDir()
   377  		fn(1, 1, nil)
   378  		fn(2, 2, nil)
   379  		fn(105, 102, nil) // and tests buffer >100 case
   380  		fn(3, 0, io.EOF)
   381  		d.Close()
   382  	}
   383  }
   384  
   385  func TestHardLink(t *testing.T) {
   386  	// Hardlinks are not supported under windows or Plan 9.
   387  	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
   388  		return
   389  	}
   390  	from, to := "hardlinktestfrom", "hardlinktestto"
   391  	Remove(from) // Just in case.
   392  	file, err := Create(to)
   393  	if err != nil {
   394  		t.Fatalf("open %q failed: %v", to, err)
   395  	}
   396  	defer Remove(to)
   397  	if err = file.Close(); err != nil {
   398  		t.Errorf("close %q failed: %v", to, err)
   399  	}
   400  	err = Link(to, from)
   401  	if err != nil {
   402  		t.Fatalf("link %q, %q failed: %v", to, from, err)
   403  	}
   404  	defer Remove(from)
   405  	tostat, err := Stat(to)
   406  	if err != nil {
   407  		t.Fatalf("stat %q failed: %v", to, err)
   408  	}
   409  	fromstat, err := Stat(from)
   410  	if err != nil {
   411  		t.Fatalf("stat %q failed: %v", from, err)
   412  	}
   413  	if !SameFile(tostat, fromstat) {
   414  		t.Errorf("link %q, %q did not create hard link", to, from)
   415  	}
   416  }
   417  
   418  func TestSymLink(t *testing.T) {
   419  	// Symlinks are not supported under windows or Plan 9.
   420  	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
   421  		return
   422  	}
   423  	from, to := "symlinktestfrom", "symlinktestto"
   424  	Remove(from) // Just in case.
   425  	file, err := Create(to)
   426  	if err != nil {
   427  		t.Fatalf("open %q failed: %v", to, err)
   428  	}
   429  	defer Remove(to)
   430  	if err = file.Close(); err != nil {
   431  		t.Errorf("close %q failed: %v", to, err)
   432  	}
   433  	err = Symlink(to, from)
   434  	if err != nil {
   435  		t.Fatalf("symlink %q, %q failed: %v", to, from, err)
   436  	}
   437  	defer Remove(from)
   438  	tostat, err := Lstat(to)
   439  	if err != nil {
   440  		t.Fatalf("stat %q failed: %v", to, err)
   441  	}
   442  	if tostat.Mode()&ModeSymlink != 0 {
   443  		t.Fatalf("stat %q claims to have found a symlink", to)
   444  	}
   445  	fromstat, err := Stat(from)
   446  	if err != nil {
   447  		t.Fatalf("stat %q failed: %v", from, err)
   448  	}
   449  	if !SameFile(tostat, fromstat) {
   450  		t.Errorf("symlink %q, %q did not create symlink", to, from)
   451  	}
   452  	fromstat, err = Lstat(from)
   453  	if err != nil {
   454  		t.Fatalf("lstat %q failed: %v", from, err)
   455  	}
   456  	if fromstat.Mode()&ModeSymlink == 0 {
   457  		t.Fatalf("symlink %q, %q did not create symlink", to, from)
   458  	}
   459  	fromstat, err = Stat(from)
   460  	if err != nil {
   461  		t.Fatalf("stat %q failed: %v", from, err)
   462  	}
   463  	if fromstat.Mode()&ModeSymlink != 0 {
   464  		t.Fatalf("stat %q did not follow symlink", from)
   465  	}
   466  	s, err := Readlink(from)
   467  	if err != nil {
   468  		t.Fatalf("readlink %q failed: %v", from, err)
   469  	}
   470  	if s != to {
   471  		t.Fatalf("after symlink %q != %q", s, to)
   472  	}
   473  	file, err = Open(from)
   474  	if err != nil {
   475  		t.Fatalf("open %q failed: %v", from, err)
   476  	}
   477  	file.Close()
   478  }
   479  
   480  func TestLongSymlink(t *testing.T) {
   481  	// Symlinks are not supported under windows or Plan 9.
   482  	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
   483  		return
   484  	}
   485  	s := "0123456789abcdef"
   486  	// Long, but not too long: a common limit is 255.
   487  	s = s + s + s + s + s + s + s + s + s + s + s + s + s + s + s
   488  	from := "longsymlinktestfrom"
   489  	Remove(from) // Just in case.
   490  	err := Symlink(s, from)
   491  	if err != nil {
   492  		t.Fatalf("symlink %q, %q failed: %v", s, from, err)
   493  	}
   494  	defer Remove(from)
   495  	r, err := Readlink(from)
   496  	if err != nil {
   497  		t.Fatalf("readlink %q failed: %v", from, err)
   498  	}
   499  	if r != s {
   500  		t.Fatalf("after symlink %q != %q", r, s)
   501  	}
   502  }
   503  
   504  func TestRename(t *testing.T) {
   505  	from, to := "renamefrom", "renameto"
   506  	Remove(to) // Just in case.
   507  	file, err := Create(from)
   508  	if err != nil {
   509  		t.Fatalf("open %q failed: %v", to, err)
   510  	}
   511  	if err = file.Close(); err != nil {
   512  		t.Errorf("close %q failed: %v", to, err)
   513  	}
   514  	err = Rename(from, to)
   515  	if err != nil {
   516  		t.Fatalf("rename %q, %q failed: %v", to, from, err)
   517  	}
   518  	defer Remove(to)
   519  	_, err = Stat(to)
   520  	if err != nil {
   521  		t.Errorf("stat %q failed: %v", to, err)
   522  	}
   523  }
   524  
   525  func exec(t *testing.T, dir, cmd string, args []string, expect string) {
   526  	r, w, err := Pipe()
   527  	if err != nil {
   528  		t.Fatalf("Pipe: %v", err)
   529  	}
   530  	defer r.Close()
   531  	attr := &ProcAttr{Dir: dir, Files: []*File{nil, w, Stderr}}
   532  	p, err := StartProcess(cmd, args, attr)
   533  	if err != nil {
   534  		t.Fatalf("StartProcess: %v", err)
   535  	}
   536  	w.Close()
   537  
   538  	var b bytes.Buffer
   539  	io.Copy(&b, r)
   540  	output := b.String()
   541  
   542  	fi1, _ := Stat(strings.TrimSpace(output))
   543  	fi2, _ := Stat(expect)
   544  	if !SameFile(fi1, fi2) {
   545  		t.Errorf("exec %q returned %q wanted %q",
   546  			strings.Join(append([]string{cmd}, args...), " "), output, expect)
   547  	}
   548  	p.Wait()
   549  }
   550  
   551  func TestStartProcess(t *testing.T) {
   552  	var dir, cmd string
   553  	var args []string
   554  	if runtime.GOOS == "windows" {
   555  		cmd = Getenv("COMSPEC")
   556  		dir = Getenv("SystemRoot")
   557  		args = []string{"/c", "cd"}
   558  	} else {
   559  		cmd = "/bin/pwd"
   560  		dir = "/"
   561  		args = []string{}
   562  	}
   563  	cmddir, cmdbase := filepath.Split(cmd)
   564  	args = append([]string{cmdbase}, args...)
   565  	// Test absolute executable path.
   566  	exec(t, dir, cmd, args, dir)
   567  	// Test relative executable path.
   568  	exec(t, cmddir, cmdbase, args, cmddir)
   569  }
   570  
   571  func checkMode(t *testing.T, path string, mode FileMode) {
   572  	dir, err := Stat(path)
   573  	if err != nil {
   574  		t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
   575  	}
   576  	if dir.Mode()&0777 != mode {
   577  		t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode(), mode)
   578  	}
   579  }
   580  
   581  func TestChmod(t *testing.T) {
   582  	// Chmod is not supported under windows.
   583  	if runtime.GOOS == "windows" {
   584  		return
   585  	}
   586  	f := newFile("TestChmod", t)
   587  	defer Remove(f.Name())
   588  	defer f.Close()
   589  
   590  	if err := Chmod(f.Name(), 0456); err != nil {
   591  		t.Fatalf("chmod %s 0456: %s", f.Name(), err)
   592  	}
   593  	checkMode(t, f.Name(), 0456)
   594  
   595  	if err := f.Chmod(0123); err != nil {
   596  		t.Fatalf("chmod %s 0123: %s", f.Name(), err)
   597  	}
   598  	checkMode(t, f.Name(), 0123)
   599  }
   600  
   601  func checkSize(t *testing.T, f *File, size int64) {
   602  	dir, err := f.Stat()
   603  	if err != nil {
   604  		t.Fatalf("Stat %q (looking for size %d): %s", f.Name(), size, err)
   605  	}
   606  	if dir.Size() != size {
   607  		t.Errorf("Stat %q: size %d want %d", f.Name(), dir.Size(), size)
   608  	}
   609  }
   610  
   611  func TestFTruncate(t *testing.T) {
   612  	f := newFile("TestFTruncate", t)
   613  	defer Remove(f.Name())
   614  	defer f.Close()
   615  
   616  	checkSize(t, f, 0)
   617  	f.Write([]byte("hello, world\n"))
   618  	checkSize(t, f, 13)
   619  	f.Truncate(10)
   620  	checkSize(t, f, 10)
   621  	f.Truncate(1024)
   622  	checkSize(t, f, 1024)
   623  	f.Truncate(0)
   624  	checkSize(t, f, 0)
   625  	f.Write([]byte("surprise!"))
   626  	checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
   627  }
   628  
   629  func TestTruncate(t *testing.T) {
   630  	f := newFile("TestTruncate", t)
   631  	defer Remove(f.Name())
   632  	defer f.Close()
   633  
   634  	checkSize(t, f, 0)
   635  	f.Write([]byte("hello, world\n"))
   636  	checkSize(t, f, 13)
   637  	Truncate(f.Name(), 10)
   638  	checkSize(t, f, 10)
   639  	Truncate(f.Name(), 1024)
   640  	checkSize(t, f, 1024)
   641  	Truncate(f.Name(), 0)
   642  	checkSize(t, f, 0)
   643  	f.Write([]byte("surprise!"))
   644  	checkSize(t, f, 13+9) // wrote at offset past where hello, world was.
   645  }
   646  
   647  // Use TempDir() to make sure we're on a local file system,
   648  // so that timings are not distorted by latency and caching.
   649  // On NFS, timings can be off due to caching of meta-data on
   650  // NFS servers (Issue 848).
   651  func TestChtimes(t *testing.T) {
   652  	f := newFile("TestChtimes", t)
   653  	defer Remove(f.Name())
   654  	defer f.Close()
   655  
   656  	f.Write([]byte("hello, world\n"))
   657  	f.Close()
   658  
   659  	st, err := Stat(f.Name())
   660  	if err != nil {
   661  		t.Fatalf("Stat %s: %s", f.Name(), err)
   662  	}
   663  	preStat := st
   664  
   665  	// Move access and modification time back a second
   666  	at := Atime(preStat)
   667  	mt := preStat.ModTime()
   668  	err = Chtimes(f.Name(), at.Add(-time.Second), mt.Add(-time.Second))
   669  	if err != nil {
   670  		t.Fatalf("Chtimes %s: %s", f.Name(), err)
   671  	}
   672  
   673  	st, err = Stat(f.Name())
   674  	if err != nil {
   675  		t.Fatalf("second Stat %s: %s", f.Name(), err)
   676  	}
   677  	postStat := st
   678  
   679  	/* Plan 9:
   680  		Mtime is the time of the last change of content.  Similarly, atime is set whenever the
   681  	    contents are accessed; also, it is set whenever mtime is set.
   682  	*/
   683  	pat := Atime(postStat)
   684  	pmt := postStat.ModTime()
   685  	if !pat.Before(at) && runtime.GOOS != "plan9" {
   686  		t.Errorf("AccessTime didn't go backwards; was=%d, after=%d", at, pat)
   687  	}
   688  
   689  	if !pmt.Before(mt) {
   690  		t.Errorf("ModTime didn't go backwards; was=%d, after=%d", mt, pmt)
   691  	}
   692  }
   693  
   694  func TestChdirAndGetwd(t *testing.T) {
   695  	// TODO(brainman): file.Chdir() is not implemented on windows.
   696  	if runtime.GOOS == "windows" {
   697  		return
   698  	}
   699  	fd, err := Open(".")
   700  	if err != nil {
   701  		t.Fatalf("Open .: %s", err)
   702  	}
   703  	// These are chosen carefully not to be symlinks on a Mac
   704  	// (unlike, say, /var, /etc, and /tmp).
   705  	dirs := []string{"/", "/usr/bin"}
   706  	// /usr/bin does not usually exist on Plan 9.
   707  	if runtime.GOOS == "plan9" {
   708  		dirs = []string{"/", "/usr"}
   709  	}
   710  	for mode := 0; mode < 2; mode++ {
   711  		for _, d := range dirs {
   712  			if mode == 0 {
   713  				err = Chdir(d)
   714  			} else {
   715  				fd1, err := Open(d)
   716  				if err != nil {
   717  					t.Errorf("Open %s: %s", d, err)
   718  					continue
   719  				}
   720  				err = fd1.Chdir()
   721  				fd1.Close()
   722  			}
   723  			pwd, err1 := Getwd()
   724  			err2 := fd.Chdir()
   725  			if err2 != nil {
   726  				// We changed the current directory and cannot go back.
   727  				// Don't let the tests continue; they'll scribble
   728  				// all over some other directory.
   729  				fmt.Fprintf(Stderr, "fchdir back to dot failed: %s\n", err2)
   730  				Exit(1)
   731  			}
   732  			if err != nil {
   733  				fd.Close()
   734  				t.Fatalf("Chdir %s: %s", d, err)
   735  			}
   736  			if err1 != nil {
   737  				fd.Close()
   738  				t.Fatalf("Getwd in %s: %s", d, err1)
   739  			}
   740  			if pwd != d {
   741  				fd.Close()
   742  				t.Fatalf("Getwd returned %q want %q", pwd, d)
   743  			}
   744  		}
   745  	}
   746  	fd.Close()
   747  }
   748  
   749  func TestSeek(t *testing.T) {
   750  	f := newFile("TestSeek", t)
   751  	defer Remove(f.Name())
   752  	defer f.Close()
   753  
   754  	const data = "hello, world\n"
   755  	io.WriteString(f, data)
   756  
   757  	type test struct {
   758  		in     int64
   759  		whence int
   760  		out    int64
   761  	}
   762  	var tests = []test{
   763  		{0, 1, int64(len(data))},
   764  		{0, 0, 0},
   765  		{5, 0, 5},
   766  		{0, 2, int64(len(data))},
   767  		{0, 0, 0},
   768  		{-1, 2, int64(len(data)) - 1},
   769  		{1 << 33, 0, 1 << 33},
   770  		{1 << 33, 2, 1<<33 + int64(len(data))},
   771  	}
   772  	for i, tt := range tests {
   773  		off, err := f.Seek(tt.in, tt.whence)
   774  		if off != tt.out || err != nil {
   775  			if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 {
   776  				// Reiserfs rejects the big seeks.
   777  				// http://code.google.com/p/go/issues/detail?id=91
   778  				break
   779  			}
   780  			t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out)
   781  		}
   782  	}
   783  }
   784  
   785  type openErrorTest struct {
   786  	path  string
   787  	mode  int
   788  	error error
   789  }
   790  
   791  var openErrorTests = []openErrorTest{
   792  	{
   793  		sfdir + "/no-such-file",
   794  		O_RDONLY,
   795  		syscall.ENOENT,
   796  	},
   797  	{
   798  		sfdir,
   799  		O_WRONLY,
   800  		syscall.EISDIR,
   801  	},
   802  	{
   803  		sfdir + "/" + sfname + "/no-such-file",
   804  		O_WRONLY,
   805  		syscall.ENOTDIR,
   806  	},
   807  }
   808  
   809  func TestOpenError(t *testing.T) {
   810  	for _, tt := range openErrorTests {
   811  		f, err := OpenFile(tt.path, tt.mode, 0)
   812  		if err == nil {
   813  			t.Errorf("Open(%q, %d) succeeded", tt.path, tt.mode)
   814  			f.Close()
   815  			continue
   816  		}
   817  		perr, ok := err.(*PathError)
   818  		if !ok {
   819  			t.Errorf("Open(%q, %d) returns error of %T type; want *PathError", tt.path, tt.mode, err)
   820  		}
   821  		if perr.Err != tt.error {
   822  			if runtime.GOOS == "plan9" {
   823  				syscallErrStr := perr.Err.Error()
   824  				expectedErrStr := strings.Replace(tt.error.Error(), "file ", "", 1)
   825  				if !strings.HasSuffix(syscallErrStr, expectedErrStr) {
   826  					t.Errorf("Open(%q, %d) = _, %q; want suffix %q", tt.path, tt.mode, syscallErrStr, expectedErrStr)
   827  				}
   828  				continue
   829  			}
   830  			if runtime.GOOS == "dragonfly" {
   831  				// DragonFly incorrectly returns EACCES rather
   832  				// EISDIR when a directory is opened for write.
   833  				if tt.error == syscall.EISDIR && perr.Err == syscall.EACCES {
   834  					continue
   835  				}
   836  			}
   837  			t.Errorf("Open(%q, %d) = _, %q; want %q", tt.path, tt.mode, perr.Err.Error(), tt.error.Error())
   838  		}
   839  	}
   840  }
   841  
   842  func TestOpenNoName(t *testing.T) {
   843  	f, err := Open("")
   844  	if err == nil {
   845  		t.Fatal(`Open("") succeeded`)
   846  		f.Close()
   847  	}
   848  }
   849  
   850  func run(t *testing.T, cmd []string) string {
   851  	// Run /bin/hostname and collect output.
   852  	r, w, err := Pipe()
   853  	if err != nil {
   854  		t.Fatal(err)
   855  	}
   856  	defer r.Close()
   857  	p, err := StartProcess("/bin/hostname", []string{"hostname"}, &ProcAttr{Files: []*File{nil, w, Stderr}})
   858  	if err != nil {
   859  		t.Fatal(err)
   860  	}
   861  	w.Close()
   862  
   863  	var b bytes.Buffer
   864  	io.Copy(&b, r)
   865  	_, err = p.Wait()
   866  	if err != nil {
   867  		t.Fatalf("run hostname Wait: %v", err)
   868  	}
   869  	err = p.Kill()
   870  	if err == nil {
   871  		t.Errorf("expected an error from Kill running 'hostname'")
   872  	}
   873  	output := b.String()
   874  	if n := len(output); n > 0 && output[n-1] == '\n' {
   875  		output = output[0 : n-1]
   876  	}
   877  	if output == "" {
   878  		t.Fatalf("%v produced no output", cmd)
   879  	}
   880  
   881  	return output
   882  }
   883  
   884  func TestHostname(t *testing.T) {
   885  	// There is no other way to fetch hostname on windows, but via winapi.
   886  	// On Plan 9 it is can be taken from #c/sysname as Hostname() does.
   887  	if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
   888  		return
   889  	}
   890  
   891  	// Check internal Hostname() against the output of /bin/hostname.
   892  	// Allow that the internal Hostname returns a Fully Qualified Domain Name
   893  	// and the /bin/hostname only returns the first component
   894  	hostname, err := Hostname()
   895  	if err != nil {
   896  		t.Fatalf("%v", err)
   897  	}
   898  	want := run(t, []string{"/bin/hostname"})
   899  	if hostname != want {
   900  		i := strings.Index(hostname, ".")
   901  		if i < 0 || hostname[0:i] != want {
   902  			t.Errorf("Hostname() = %q, want %q", hostname, want)
   903  		}
   904  	}
   905  }
   906  
   907  func TestReadAt(t *testing.T) {
   908  	f := newFile("TestReadAt", t)
   909  	defer Remove(f.Name())
   910  	defer f.Close()
   911  
   912  	const data = "hello, world\n"
   913  	io.WriteString(f, data)
   914  
   915  	b := make([]byte, 5)
   916  	n, err := f.ReadAt(b, 7)
   917  	if err != nil || n != len(b) {
   918  		t.Fatalf("ReadAt 7: %d, %v", n, err)
   919  	}
   920  	if string(b) != "world" {
   921  		t.Fatalf("ReadAt 7: have %q want %q", string(b), "world")
   922  	}
   923  }
   924  
   925  func TestWriteAt(t *testing.T) {
   926  	f := newFile("TestWriteAt", t)
   927  	defer Remove(f.Name())
   928  	defer f.Close()
   929  
   930  	const data = "hello, world\n"
   931  	io.WriteString(f, data)
   932  
   933  	n, err := f.WriteAt([]byte("WORLD"), 7)
   934  	if err != nil || n != 5 {
   935  		t.Fatalf("WriteAt 7: %d, %v", n, err)
   936  	}
   937  
   938  	b, err := ioutil.ReadFile(f.Name())
   939  	if err != nil {
   940  		t.Fatalf("ReadFile %s: %v", f.Name(), err)
   941  	}
   942  	if string(b) != "hello, WORLD\n" {
   943  		t.Fatalf("after write: have %q want %q", string(b), "hello, WORLD\n")
   944  	}
   945  }
   946  
   947  func writeFile(t *testing.T, fname string, flag int, text string) string {
   948  	f, err := OpenFile(fname, flag, 0666)
   949  	if err != nil {
   950  		t.Fatalf("Open: %v", err)
   951  	}
   952  	n, err := io.WriteString(f, text)
   953  	if err != nil {
   954  		t.Fatalf("WriteString: %d, %v", n, err)
   955  	}
   956  	f.Close()
   957  	data, err := ioutil.ReadFile(fname)
   958  	if err != nil {
   959  		t.Fatalf("ReadFile: %v", err)
   960  	}
   961  	return string(data)
   962  }
   963  
   964  func TestAppend(t *testing.T) {
   965  	const f = "append.txt"
   966  	defer Remove(f)
   967  	s := writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
   968  	if s != "new" {
   969  		t.Fatalf("writeFile: have %q want %q", s, "new")
   970  	}
   971  	s = writeFile(t, f, O_APPEND|O_RDWR, "|append")
   972  	if s != "new|append" {
   973  		t.Fatalf("writeFile: have %q want %q", s, "new|append")
   974  	}
   975  	s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "|append")
   976  	if s != "new|append|append" {
   977  		t.Fatalf("writeFile: have %q want %q", s, "new|append|append")
   978  	}
   979  	err := Remove(f)
   980  	if err != nil {
   981  		t.Fatalf("Remove: %v", err)
   982  	}
   983  	s = writeFile(t, f, O_CREATE|O_APPEND|O_RDWR, "new&append")
   984  	if s != "new&append" {
   985  		t.Fatalf("writeFile: after append have %q want %q", s, "new&append")
   986  	}
   987  	s = writeFile(t, f, O_CREATE|O_RDWR, "old")
   988  	if s != "old&append" {
   989  		t.Fatalf("writeFile: after create have %q want %q", s, "old&append")
   990  	}
   991  	s = writeFile(t, f, O_CREATE|O_TRUNC|O_RDWR, "new")
   992  	if s != "new" {
   993  		t.Fatalf("writeFile: after truncate have %q want %q", s, "new")
   994  	}
   995  }
   996  
   997  func TestStatDirWithTrailingSlash(t *testing.T) {
   998  	// Create new temporary directory and arrange to clean it up.
   999  	path, err := ioutil.TempDir("", "/_TestStatDirWithSlash_")
  1000  	if err != nil {
  1001  		t.Fatalf("TempDir: %s", err)
  1002  	}
  1003  	defer RemoveAll(path)
  1004  
  1005  	// Stat of path should succeed.
  1006  	_, err = Stat(path)
  1007  	if err != nil {
  1008  		t.Fatalf("stat %s failed: %s", path, err)
  1009  	}
  1010  
  1011  	// Stat of path+"/" should succeed too.
  1012  	path += "/"
  1013  	_, err = Stat(path)
  1014  	if err != nil {
  1015  		t.Fatalf("stat %s failed: %s", path, err)
  1016  	}
  1017  }
  1018  
  1019  func TestNilProcessStateString(t *testing.T) {
  1020  	var ps *ProcessState
  1021  	s := ps.String()
  1022  	if s != "<nil>" {
  1023  		t.Errorf("(*ProcessState)(nil).String() = %q, want %q", s, "<nil>")
  1024  	}
  1025  }
  1026  
  1027  func TestSameFile(t *testing.T) {
  1028  	fa, err := Create("a")
  1029  	if err != nil {
  1030  		t.Fatalf("Create(a): %v", err)
  1031  	}
  1032  	defer Remove(fa.Name())
  1033  	fa.Close()
  1034  	fb, err := Create("b")
  1035  	if err != nil {
  1036  		t.Fatalf("Create(b): %v", err)
  1037  	}
  1038  	defer Remove(fb.Name())
  1039  	fb.Close()
  1040  
  1041  	ia1, err := Stat("a")
  1042  	if err != nil {
  1043  		t.Fatalf("Stat(a): %v", err)
  1044  	}
  1045  	ia2, err := Stat("a")
  1046  	if err != nil {
  1047  		t.Fatalf("Stat(a): %v", err)
  1048  	}
  1049  	if !SameFile(ia1, ia2) {
  1050  		t.Errorf("files should be same")
  1051  	}
  1052  
  1053  	ib, err := Stat("b")
  1054  	if err != nil {
  1055  		t.Fatalf("Stat(b): %v", err)
  1056  	}
  1057  	if SameFile(ia1, ib) {
  1058  		t.Errorf("files should be different")
  1059  	}
  1060  }
  1061  
  1062  func TestDevNullFile(t *testing.T) {
  1063  	f, err := Open(DevNull)
  1064  	if err != nil {
  1065  		t.Fatalf("Open(%s): %v", DevNull, err)
  1066  	}
  1067  	defer f.Close()
  1068  	fi, err := f.Stat()
  1069  	if err != nil {
  1070  		t.Fatalf("Stat(%s): %v", DevNull, err)
  1071  	}
  1072  	name := filepath.Base(DevNull)
  1073  	if fi.Name() != name {
  1074  		t.Fatalf("wrong file name have %v want %v", fi.Name(), name)
  1075  	}
  1076  	if fi.Size() != 0 {
  1077  		t.Fatalf("wrong file size have %d want 0", fi.Size())
  1078  	}
  1079  }
  1080  
  1081  var testLargeWrite = flag.Bool("large_write", false, "run TestLargeWriteToConsole test that floods console with output")
  1082  
  1083  func TestLargeWriteToConsole(t *testing.T) {
  1084  	if !*testLargeWrite {
  1085  		t.Skip("skipping console-flooding test; enable with -large_write")
  1086  	}
  1087  	b := make([]byte, 32000)
  1088  	for i := range b {
  1089  		b[i] = '.'
  1090  	}
  1091  	b[len(b)-1] = '\n'
  1092  	n, err := Stdout.Write(b)
  1093  	if err != nil {
  1094  		t.Fatalf("Write to os.Stdout failed: %v", err)
  1095  	}
  1096  	if n != len(b) {
  1097  		t.Errorf("Write to os.Stdout should return %d; got %d", len(b), n)
  1098  	}
  1099  	n, err = Stderr.Write(b)
  1100  	if err != nil {
  1101  		t.Fatalf("Write to os.Stderr failed: %v", err)
  1102  	}
  1103  	if n != len(b) {
  1104  		t.Errorf("Write to os.Stderr should return %d; got %d", len(b), n)
  1105  	}
  1106  }
  1107  
  1108  func TestStatDirModeExec(t *testing.T) {
  1109  	const mode = 0111
  1110  
  1111  	path, err := ioutil.TempDir("", "go-build")
  1112  	if err != nil {
  1113  		t.Fatalf("Failed to create temp directory: %v", err)
  1114  	}
  1115  	defer RemoveAll(path)
  1116  
  1117  	if err := Chmod(path, 0777); err != nil {
  1118  		t.Fatalf("Chmod %q 0777: %v", path, err)
  1119  	}
  1120  
  1121  	dir, err := Stat(path)
  1122  	if err != nil {
  1123  		t.Fatalf("Stat %q (looking for mode %#o): %s", path, mode, err)
  1124  	}
  1125  	if dir.Mode()&mode != mode {
  1126  		t.Errorf("Stat %q: mode %#o want %#o", path, dir.Mode()&mode, mode)
  1127  	}
  1128  }
  1129  
  1130  func TestReadAtEOF(t *testing.T) {
  1131  	f := newFile("TestReadAtEOF", t)
  1132  	defer Remove(f.Name())
  1133  	defer f.Close()
  1134  
  1135  	_, err := f.ReadAt(make([]byte, 10), 0)
  1136  	switch err {
  1137  	case io.EOF:
  1138  		// all good
  1139  	case nil:
  1140  		t.Fatalf("ReadAt succeeded")
  1141  	default:
  1142  		t.Fatalf("ReadAt failed: %s", err)
  1143  	}
  1144  }
  1145  
  1146  func testKillProcess(t *testing.T, processKiller func(p *Process)) {
  1147  	dir, err := ioutil.TempDir("", "go-build")
  1148  	if err != nil {
  1149  		t.Fatalf("Failed to create temp directory: %v", err)
  1150  	}
  1151  	defer RemoveAll(dir)
  1152  
  1153  	src := filepath.Join(dir, "main.go")
  1154  	f, err := Create(src)
  1155  	if err != nil {
  1156  		t.Fatalf("Failed to create %v: %v", src, err)
  1157  	}
  1158  	st := template.Must(template.New("source").Parse(`
  1159  package main
  1160  import "time"
  1161  func main() {
  1162  	time.Sleep(time.Second)
  1163  }
  1164  `))
  1165  	err = st.Execute(f, nil)
  1166  	if err != nil {
  1167  		f.Close()
  1168  		t.Fatalf("Failed to execute template: %v", err)
  1169  	}
  1170  	f.Close()
  1171  
  1172  	exe := filepath.Join(dir, "main.exe")
  1173  	output, err := osexec.Command("go", "build", "-o", exe, src).CombinedOutput()
  1174  	if err != nil {
  1175  		t.Fatalf("Failed to build exe %v: %v %v", exe, err, string(output))
  1176  	}
  1177  
  1178  	cmd := osexec.Command(exe)
  1179  	err = cmd.Start()
  1180  	if err != nil {
  1181  		t.Fatalf("Failed to start test process: %v", err)
  1182  	}
  1183  	go func() {
  1184  		time.Sleep(100 * time.Millisecond)
  1185  		processKiller(cmd.Process)
  1186  	}()
  1187  	err = cmd.Wait()
  1188  	if err == nil {
  1189  		t.Errorf("Test process succeeded, but expected to fail")
  1190  	}
  1191  }
  1192  
  1193  func TestKillStartProcess(t *testing.T) {
  1194  	testKillProcess(t, func(p *Process) {
  1195  		err := p.Kill()
  1196  		if err != nil {
  1197  			t.Fatalf("Failed to kill test process: %v", err)
  1198  		}
  1199  	})
  1200  }
  1201  
  1202  func TestKillFindProcess(t *testing.T) {
  1203  	testKillProcess(t, func(p *Process) {
  1204  		p2, err := FindProcess(p.Pid)
  1205  		if err != nil {
  1206  			t.Fatalf("Failed to find test process: %v", err)
  1207  		}
  1208  		err = p2.Kill()
  1209  		if err != nil {
  1210  			t.Fatalf("Failed to kill test process: %v", err)
  1211  		}
  1212  	})
  1213  }