github.com/brass-software/os@v0.0.0-20240129060254-960f457a5dea/path_windows_test.go (about) 1 // Copyright 2016 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/syscall/windows" 10 "internal/testenv" 11 "os" 12 "path/filepath" 13 "strings" 14 "syscall" 15 "testing" 16 ) 17 18 func TestFixLongPath(t *testing.T) { 19 if os.CanUseLongPaths { 20 return 21 } 22 t.Parallel() 23 24 // 248 is long enough to trigger the longer-than-248 checks in 25 // fixLongPath, but short enough not to make a path component 26 // longer than 255, which is illegal on Windows. (which 27 // doesn't really matter anyway, since this is purely a string 28 // function we're testing, and it's not actually being used to 29 // do a system call) 30 veryLong := "l" + strings.Repeat("o", 248) + "ng" 31 for _, test := range []struct{ in, want string }{ 32 // Short; unchanged: 33 {`C:\short.txt`, `C:\short.txt`}, 34 {`C:\`, `C:\`}, 35 {`C:`, `C:`}, 36 // The "long" substring is replaced by a looooooong 37 // string which triggers the rewriting. Except in the 38 // cases below where it doesn't. 39 {`C:\long\foo.txt`, `\\?\C:\long\foo.txt`}, 40 {`C:/long/foo.txt`, `\\?\C:\long\foo.txt`}, 41 {`C:\long\foo\\bar\.\baz\\`, `\\?\C:\long\foo\bar\baz`}, 42 {`\\unc\path`, `\\unc\path`}, 43 {`long.txt`, `long.txt`}, 44 {`C:long.txt`, `C:long.txt`}, 45 {`c:\long\..\bar\baz`, `c:\long\..\bar\baz`}, 46 {`\\?\c:\long\foo.txt`, `\\?\c:\long\foo.txt`}, 47 {`\\?\c:\long/foo.txt`, `\\?\c:\long/foo.txt`}, 48 } { 49 in := strings.ReplaceAll(test.in, "long", veryLong) 50 want := strings.ReplaceAll(test.want, "long", veryLong) 51 if got := os.FixLongPath(in); got != want { 52 got = strings.ReplaceAll(got, veryLong, "long") 53 t.Errorf("fixLongPath(%q) = %q; want %q", test.in, got, test.want) 54 } 55 } 56 } 57 58 func TestMkdirAllLongPath(t *testing.T) { 59 t.Parallel() 60 61 tmpDir := t.TempDir() 62 path := tmpDir 63 for i := 0; i < 100; i++ { 64 path += `\another-path-component` 65 } 66 if err := os.MkdirAll(path, 0777); err != nil { 67 t.Fatalf("MkdirAll(%q) failed; %v", path, err) 68 } 69 if err := os.RemoveAll(tmpDir); err != nil { 70 t.Fatalf("RemoveAll(%q) failed; %v", tmpDir, err) 71 } 72 } 73 74 func TestMkdirAllExtendedLength(t *testing.T) { 75 t.Parallel() 76 tmpDir := t.TempDir() 77 78 const prefix = `\\?\` 79 if len(tmpDir) < 4 || tmpDir[:4] != prefix { 80 fullPath, err := syscall.FullPath(tmpDir) 81 if err != nil { 82 t.Fatalf("FullPath(%q) fails: %v", tmpDir, err) 83 } 84 tmpDir = prefix + fullPath 85 } 86 path := tmpDir + `\dir\` 87 if err := os.MkdirAll(path, 0777); err != nil { 88 t.Fatalf("MkdirAll(%q) failed: %v", path, err) 89 } 90 91 path = path + `.\dir2` 92 if err := os.MkdirAll(path, 0777); err == nil { 93 t.Fatalf("MkdirAll(%q) should have failed, but did not", path) 94 } 95 } 96 97 func TestOpenRootSlash(t *testing.T) { 98 t.Parallel() 99 100 tests := []string{ 101 `/`, 102 `\`, 103 } 104 105 for _, test := range tests { 106 dir, err := os.Open(test) 107 if err != nil { 108 t.Fatalf("Open(%q) failed: %v", test, err) 109 } 110 dir.Close() 111 } 112 } 113 114 func testMkdirAllAtRoot(t *testing.T, root string) { 115 // Create a unique-enough directory name in root. 116 base := fmt.Sprintf("%s-%d", t.Name(), os.Getpid()) 117 path := filepath.Join(root, base) 118 if err := os.MkdirAll(path, 0777); err != nil { 119 t.Fatalf("MkdirAll(%q) failed: %v", path, err) 120 } 121 // Clean up 122 if err := os.RemoveAll(path); err != nil { 123 t.Fatal(err) 124 } 125 } 126 127 func TestMkdirAllExtendedLengthAtRoot(t *testing.T) { 128 if testenv.Builder() == "" { 129 t.Skipf("skipping non-hermetic test outside of Go builders") 130 } 131 132 const prefix = `\\?\` 133 vol := filepath.VolumeName(t.TempDir()) + `\` 134 if len(vol) < 4 || vol[:4] != prefix { 135 vol = prefix + vol 136 } 137 testMkdirAllAtRoot(t, vol) 138 } 139 140 func TestMkdirAllVolumeNameAtRoot(t *testing.T) { 141 if testenv.Builder() == "" { 142 t.Skipf("skipping non-hermetic test outside of Go builders") 143 } 144 145 vol, err := syscall.UTF16PtrFromString(filepath.VolumeName(t.TempDir()) + `\`) 146 if err != nil { 147 t.Fatal(err) 148 } 149 const maxVolNameLen = 50 150 var buf [maxVolNameLen]uint16 151 err = windows.GetVolumeNameForVolumeMountPoint(vol, &buf[0], maxVolNameLen) 152 if err != nil { 153 t.Fatal(err) 154 } 155 volName := syscall.UTF16ToString(buf[:]) 156 testMkdirAllAtRoot(t, volName) 157 }