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