mirror of
https://github.com/golang/go
synced 2024-09-30 06:14:31 -06:00
internal/fastwalk: attempt Symlink tests on Windows
Windows does actually support symlinks, but older versions of Windows only support symlinks when running as an administrator. Newer versions of Windows support symlinks for all users. Instead of skipping based on GOOS, first try the Symlink operation. If it succeeds, we can proceed with the test; otherwise, we can try to write a regular file to determine whether the problem was the symlink operation itself or the destination path. For golang/go#38772 Change-Id: Idaa9592011473de7f514b889859e420a84db6d01 Reviewed-on: https://go-review.googlesource.com/c/tools/+/234537 Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
parent
91d71f6c2f
commit
2b542361a4
@ -40,6 +40,8 @@ func testFastWalk(t *testing.T, files map[string]string, callback func(path stri
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tempdir)
|
||||
|
||||
symlinks := map[string]string{}
|
||||
for path, contents := range files {
|
||||
file := filepath.Join(tempdir, "/src", path)
|
||||
if err := os.MkdirAll(filepath.Dir(file), 0755); err != nil {
|
||||
@ -47,7 +49,7 @@ func testFastWalk(t *testing.T, files map[string]string, callback func(path stri
|
||||
}
|
||||
var err error
|
||||
if strings.HasPrefix(contents, "LINK:") {
|
||||
err = os.Symlink(strings.TrimPrefix(contents, "LINK:"), file)
|
||||
symlinks[file] = filepath.FromSlash(strings.TrimPrefix(contents, "LINK:"))
|
||||
} else {
|
||||
err = ioutil.WriteFile(file, []byte(contents), 0644)
|
||||
}
|
||||
@ -55,21 +57,38 @@ func testFastWalk(t *testing.T, files map[string]string, callback func(path stri
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Create symlinks after all other files. Otherwise, directory symlinks on
|
||||
// Windows are unusable (see https://golang.org/issue/39183).
|
||||
for file, dst := range symlinks {
|
||||
err = os.Symlink(dst, file)
|
||||
if err != nil {
|
||||
if writeErr := ioutil.WriteFile(file, []byte(dst), 0644); writeErr == nil {
|
||||
// Couldn't create symlink, but could write the file.
|
||||
// Probably this filesystem doesn't support symlinks.
|
||||
// (Perhaps we are on an older Windows and not running as administrator.)
|
||||
t.Skipf("skipping because symlinks appear to be unsupported: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
got := map[string]os.FileMode{}
|
||||
var mu sync.Mutex
|
||||
if err := fastwalk.Walk(tempdir, func(path string, typ os.FileMode) error {
|
||||
err = fastwalk.Walk(tempdir, func(path string, typ os.FileMode) error {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if !strings.HasPrefix(path, tempdir) {
|
||||
t.Fatalf("bogus prefix on %q, expect %q", path, tempdir)
|
||||
t.Errorf("bogus prefix on %q, expect %q", path, tempdir)
|
||||
}
|
||||
key := filepath.ToSlash(strings.TrimPrefix(path, tempdir))
|
||||
if old, dup := got[key]; dup {
|
||||
t.Fatalf("callback called twice for key %q: %v -> %v", key, old, typ)
|
||||
t.Errorf("callback called twice for key %q: %v -> %v", key, old, typ)
|
||||
}
|
||||
got[key] = typ
|
||||
return callback(path, typ)
|
||||
}); err != nil {
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("callback returned: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
@ -116,26 +135,25 @@ func TestFastWalk_LongFileName(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFastWalk_Symlink(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "windows", "plan9":
|
||||
t.Skipf("skipping on %s", runtime.GOOS)
|
||||
}
|
||||
testFastWalk(t, map[string]string{
|
||||
"foo/foo.go": "one",
|
||||
"bar/bar.go": "LINK:../foo.go",
|
||||
"symdir": "LINK:foo",
|
||||
"foo/foo.go": "one",
|
||||
"bar/bar.go": "LINK:../foo/foo.go",
|
||||
"symdir": "LINK:foo",
|
||||
"broken/broken.go": "LINK:../nonexistent",
|
||||
},
|
||||
func(path string, typ os.FileMode) error {
|
||||
return nil
|
||||
},
|
||||
map[string]os.FileMode{
|
||||
"": os.ModeDir,
|
||||
"/src": os.ModeDir,
|
||||
"/src/bar": os.ModeDir,
|
||||
"/src/bar/bar.go": os.ModeSymlink,
|
||||
"/src/foo": os.ModeDir,
|
||||
"/src/foo/foo.go": 0,
|
||||
"/src/symdir": os.ModeSymlink,
|
||||
"": os.ModeDir,
|
||||
"/src": os.ModeDir,
|
||||
"/src/bar": os.ModeDir,
|
||||
"/src/bar/bar.go": os.ModeSymlink,
|
||||
"/src/foo": os.ModeDir,
|
||||
"/src/foo/foo.go": 0,
|
||||
"/src/symdir": os.ModeSymlink,
|
||||
"/src/broken": os.ModeDir,
|
||||
"/src/broken/broken.go": os.ModeSymlink,
|
||||
})
|
||||
}
|
||||
|
||||
@ -195,11 +213,6 @@ func TestFastWalk_SkipFiles(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFastWalk_TraverseSymlink(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "windows", "plan9":
|
||||
t.Skipf("skipping on %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
testFastWalk(t, map[string]string{
|
||||
"foo/foo.go": "one",
|
||||
"bar/bar.go": "two",
|
||||
|
Loading…
Reference in New Issue
Block a user