github.com/d4l3k/go@v0.0.0-20151015000803-65fc379daeda/src/os/path_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  	"io/ioutil"
     9  	. "os"
    10  	"path/filepath"
    11  	"runtime"
    12  	"syscall"
    13  	"testing"
    14  )
    15  
    16  var isReadonlyError = func(error) bool { return false }
    17  
    18  func TestMkdirAll(t *testing.T) {
    19  	tmpDir := TempDir()
    20  	path := tmpDir + "/_TestMkdirAll_/dir/./dir2"
    21  	err := MkdirAll(path, 0777)
    22  	if err != nil {
    23  		t.Fatalf("MkdirAll %q: %s", path, err)
    24  	}
    25  	defer RemoveAll(tmpDir + "/_TestMkdirAll_")
    26  
    27  	// Already exists, should succeed.
    28  	err = MkdirAll(path, 0777)
    29  	if err != nil {
    30  		t.Fatalf("MkdirAll %q (second time): %s", path, err)
    31  	}
    32  
    33  	// Make file.
    34  	fpath := path + "/file"
    35  	f, err := Create(fpath)
    36  	if err != nil {
    37  		t.Fatalf("create %q: %s", fpath, err)
    38  	}
    39  	defer f.Close()
    40  
    41  	// Can't make directory named after file.
    42  	err = MkdirAll(fpath, 0777)
    43  	if err == nil {
    44  		t.Fatalf("MkdirAll %q: no error", fpath)
    45  	}
    46  	perr, ok := err.(*PathError)
    47  	if !ok {
    48  		t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err)
    49  	}
    50  	if filepath.Clean(perr.Path) != filepath.Clean(fpath) {
    51  		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, filepath.Clean(perr.Path), filepath.Clean(fpath))
    52  	}
    53  
    54  	// Can't make subdirectory of file.
    55  	ffpath := fpath + "/subdir"
    56  	err = MkdirAll(ffpath, 0777)
    57  	if err == nil {
    58  		t.Fatalf("MkdirAll %q: no error", ffpath)
    59  	}
    60  	perr, ok = err.(*PathError)
    61  	if !ok {
    62  		t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err)
    63  	}
    64  	if filepath.Clean(perr.Path) != filepath.Clean(fpath) {
    65  		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, filepath.Clean(perr.Path), filepath.Clean(fpath))
    66  	}
    67  
    68  	if runtime.GOOS == "windows" {
    69  		path := tmpDir + `\_TestMkdirAll_\dir\.\dir2\`
    70  		err := MkdirAll(path, 0777)
    71  		if err != nil {
    72  			t.Fatalf("MkdirAll %q: %s", path, err)
    73  		}
    74  	}
    75  }
    76  
    77  func TestRemoveAll(t *testing.T) {
    78  	tmpDir := TempDir()
    79  	// Work directory.
    80  	path := tmpDir + "/_TestRemoveAll_"
    81  	fpath := path + "/file"
    82  	dpath := path + "/dir"
    83  
    84  	// Make directory with 1 file and remove.
    85  	if err := MkdirAll(path, 0777); err != nil {
    86  		t.Fatalf("MkdirAll %q: %s", path, err)
    87  	}
    88  	fd, err := Create(fpath)
    89  	if err != nil {
    90  		t.Fatalf("create %q: %s", fpath, err)
    91  	}
    92  	fd.Close()
    93  	if err = RemoveAll(path); err != nil {
    94  		t.Fatalf("RemoveAll %q (first): %s", path, err)
    95  	}
    96  	if _, err = Lstat(path); err == nil {
    97  		t.Fatalf("Lstat %q succeeded after RemoveAll (first)", path)
    98  	}
    99  
   100  	// Make directory with file and subdirectory and remove.
   101  	if err = MkdirAll(dpath, 0777); err != nil {
   102  		t.Fatalf("MkdirAll %q: %s", dpath, err)
   103  	}
   104  	fd, err = Create(fpath)
   105  	if err != nil {
   106  		t.Fatalf("create %q: %s", fpath, err)
   107  	}
   108  	fd.Close()
   109  	fd, err = Create(dpath + "/file")
   110  	if err != nil {
   111  		t.Fatalf("create %q: %s", fpath, err)
   112  	}
   113  	fd.Close()
   114  	if err = RemoveAll(path); err != nil {
   115  		t.Fatalf("RemoveAll %q (second): %s", path, err)
   116  	}
   117  	if _, err := Lstat(path); err == nil {
   118  		t.Fatalf("Lstat %q succeeded after RemoveAll (second)", path)
   119  	}
   120  
   121  	// Determine if we should run the following test.
   122  	testit := true
   123  	if runtime.GOOS == "windows" {
   124  		// Chmod is not supported under windows.
   125  		testit = false
   126  	} else {
   127  		// Test fails as root.
   128  		testit = Getuid() != 0
   129  	}
   130  	if testit {
   131  		// Make directory with file and subdirectory and trigger error.
   132  		if err = MkdirAll(dpath, 0777); err != nil {
   133  			t.Fatalf("MkdirAll %q: %s", dpath, err)
   134  		}
   135  
   136  		for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} {
   137  			fd, err = Create(s)
   138  			if err != nil {
   139  				t.Fatalf("create %q: %s", s, err)
   140  			}
   141  			fd.Close()
   142  		}
   143  		if err = Chmod(dpath, 0); err != nil {
   144  			t.Fatalf("Chmod %q 0: %s", dpath, err)
   145  		}
   146  
   147  		// No error checking here: either RemoveAll
   148  		// will or won't be able to remove dpath;
   149  		// either way we want to see if it removes fpath
   150  		// and path/zzz.  Reasons why RemoveAll might
   151  		// succeed in removing dpath as well include:
   152  		//	* running as root
   153  		//	* running on a file system without permissions (FAT)
   154  		RemoveAll(path)
   155  		Chmod(dpath, 0777)
   156  
   157  		for _, s := range []string{fpath, path + "/zzz"} {
   158  			if _, err = Lstat(s); err == nil {
   159  				t.Fatalf("Lstat %q succeeded after partial RemoveAll", s)
   160  			}
   161  		}
   162  	}
   163  	if err = RemoveAll(path); err != nil {
   164  		t.Fatalf("RemoveAll %q after partial RemoveAll: %s", path, err)
   165  	}
   166  	if _, err = Lstat(path); err == nil {
   167  		t.Fatalf("Lstat %q succeeded after RemoveAll (final)", path)
   168  	}
   169  }
   170  
   171  func TestMkdirAllWithSymlink(t *testing.T) {
   172  	switch runtime.GOOS {
   173  	case "nacl", "plan9":
   174  		t.Skipf("skipping on %s", runtime.GOOS)
   175  	case "windows":
   176  		if !supportsSymlinks {
   177  			t.Skipf("skipping on %s", runtime.GOOS)
   178  		}
   179  	}
   180  
   181  	tmpDir, err := ioutil.TempDir("", "TestMkdirAllWithSymlink-")
   182  	if err != nil {
   183  		t.Fatal(err)
   184  	}
   185  	defer RemoveAll(tmpDir)
   186  
   187  	dir := tmpDir + "/dir"
   188  	err = Mkdir(dir, 0755)
   189  	if err != nil {
   190  		t.Fatalf("Mkdir %s: %s", dir, err)
   191  	}
   192  
   193  	link := tmpDir + "/link"
   194  	err = Symlink("dir", link)
   195  	if err != nil {
   196  		t.Fatalf("Symlink %s: %s", link, err)
   197  	}
   198  
   199  	path := link + "/foo"
   200  	err = MkdirAll(path, 0755)
   201  	if err != nil {
   202  		t.Errorf("MkdirAll %q: %s", path, err)
   203  	}
   204  }
   205  
   206  func TestMkdirAllAtSlash(t *testing.T) {
   207  	switch runtime.GOOS {
   208  	case "android", "plan9", "windows":
   209  		t.Skipf("skipping on %s", runtime.GOOS)
   210  	case "darwin":
   211  		switch runtime.GOARCH {
   212  		case "arm", "arm64":
   213  			t.Skipf("skipping on darwin/%s, mkdir returns EPERM", runtime.GOARCH)
   214  		}
   215  	}
   216  	RemoveAll("/_go_os_test")
   217  	const dir = "/_go_os_test/dir"
   218  	err := MkdirAll(dir, 0777)
   219  	if err != nil {
   220  		pathErr, ok := err.(*PathError)
   221  		// common for users not to be able to write to /
   222  		if ok && (pathErr.Err == syscall.EACCES || isReadonlyError(pathErr.Err)) {
   223  			t.Skipf("could not create %v: %v", dir, err)
   224  		}
   225  		t.Fatalf(`MkdirAll "/_go_os_test/dir": %v, %s`, err, pathErr.Err)
   226  	}
   227  	RemoveAll("/_go_os_test")
   228  }