Source file src/os/path_windows_test.go

     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  }
   158  

View as plain text