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 5package os_test 6 7import ( 8 "internal/testenv" 9 . "os" 10 "path/filepath" 11 "runtime" 12 "syscall" 13 "testing" 14) 15 16var isReadonlyError = func(error) bool { return false } 17 18func 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 77func TestMkdirAllWithSymlink(t *testing.T) { 78 testenv.MustHaveSymlink(t) 79 80 tmpDir := t.TempDir() 81 dir := tmpDir + "/dir" 82 if err := Mkdir(dir, 0755); err != nil { 83 t.Fatalf("Mkdir %s: %s", dir, err) 84 } 85 86 link := tmpDir + "/link" 87 if err := Symlink("dir", link); err != nil { 88 t.Fatalf("Symlink %s: %s", link, err) 89 } 90 91 path := link + "/foo" 92 if err := MkdirAll(path, 0755); err != nil { 93 t.Errorf("MkdirAll %q: %s", path, err) 94 } 95} 96 97func TestMkdirAllAtSlash(t *testing.T) { 98 switch runtime.GOOS { 99 case "android", "plan9", "windows": 100 t.Skipf("skipping on %s", runtime.GOOS) 101 case "darwin", "ios": 102 switch runtime.GOARCH { 103 case "arm64": 104 t.Skipf("skipping on darwin/arm64, mkdir returns EPERM") 105 } 106 } 107 RemoveAll("/_go_os_test") 108 const dir = "/_go_os_test/dir" 109 err := MkdirAll(dir, 0777) 110 if err != nil { 111 pathErr, ok := err.(*PathError) 112 // common for users not to be able to write to / 113 if ok && (pathErr.Err == syscall.EACCES || isReadonlyError(pathErr.Err)) { 114 t.Skipf("could not create %v: %v", dir, err) 115 } 116 t.Fatalf(`MkdirAll "/_go_os_test/dir": %v, %s`, err, pathErr.Err) 117 } 118 RemoveAll("/_go_os_test") 119} 120