vendor tsgo
This commit is contained in:
185
tools/tsgo/internal/nativepath/symlink_windows_test.go
Normal file
185
tools/tsgo/internal/nativepath/symlink_windows_test.go
Normal file
@@ -0,0 +1,185 @@
|
||||
package nativepath
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestIsSymlinkOrReparsePoint(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tmp := t.TempDir()
|
||||
|
||||
t.Run("regular file", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
file := filepath.Join(tmp, "regular.txt")
|
||||
assert.NilError(t, os.WriteFile(file, []byte("hello"), 0o666))
|
||||
assert.Equal(t, IsSymlinkOrReparsePoint(file), false)
|
||||
})
|
||||
|
||||
t.Run("regular directory", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
dir := filepath.Join(tmp, "regular-dir")
|
||||
assert.NilError(t, os.MkdirAll(dir, 0o777))
|
||||
assert.Equal(t, IsSymlinkOrReparsePoint(dir), false)
|
||||
})
|
||||
|
||||
t.Run("junction point", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
target := filepath.Join(tmp, "junction-target")
|
||||
link := filepath.Join(tmp, "junction-link")
|
||||
assert.NilError(t, os.MkdirAll(target, 0o777))
|
||||
mklink(t, target, link, true)
|
||||
assert.Equal(t, IsSymlinkOrReparsePoint(link), true)
|
||||
})
|
||||
|
||||
t.Run("file symlink", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
target := filepath.Join(tmp, "symlink-target.txt")
|
||||
link := filepath.Join(tmp, "symlink-link.txt")
|
||||
assert.NilError(t, os.WriteFile(target, []byte("hello"), 0o666))
|
||||
mklink(t, target, link, false)
|
||||
assert.Equal(t, IsSymlinkOrReparsePoint(link), true)
|
||||
})
|
||||
|
||||
t.Run("directory symlink", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
target := filepath.Join(tmp, "dir-symlink-target")
|
||||
link := filepath.Join(tmp, "dir-symlink-link")
|
||||
assert.NilError(t, os.MkdirAll(target, 0o777))
|
||||
mklink(t, target, link, false)
|
||||
assert.Equal(t, IsSymlinkOrReparsePoint(link), true)
|
||||
})
|
||||
|
||||
t.Run("nonexistent path", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
nonexistent := filepath.Join(tmp, "does-not-exist")
|
||||
assert.Equal(t, IsSymlinkOrReparsePoint(nonexistent), false)
|
||||
})
|
||||
|
||||
t.Run("empty path", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert.Equal(t, IsSymlinkOrReparsePoint(""), false)
|
||||
})
|
||||
|
||||
t.Run("invalid path with null byte", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert.Equal(t, IsSymlinkOrReparsePoint("invalid\x00path"), false)
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsSymlinkOrReparsePointLongPath(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tmp := t.TempDir()
|
||||
|
||||
// Create a deeply nested path that exceeds 248 characters
|
||||
longPathBase := tmp
|
||||
pathComponent := "very_long_directory_name_to_exceed_max_path_limit_abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
for len(longPathBase) < 250 {
|
||||
longPathBase = filepath.Join(longPathBase, pathComponent)
|
||||
}
|
||||
|
||||
target := filepath.Join(longPathBase, "target")
|
||||
link := filepath.Join(longPathBase, "link")
|
||||
|
||||
// Use \\?\ prefix to enable long path support for mklink
|
||||
longTarget := `\\?\` + target
|
||||
longLink := `\\?\` + link
|
||||
|
||||
assert.NilError(t, os.MkdirAll(longTarget, 0o777))
|
||||
assert.NilError(t, exec.Command("cmd", "/c", "mklink", "/J", longLink, longTarget).Run())
|
||||
|
||||
// With long path support enabled, this should work even for paths >= 248 chars
|
||||
assert.Equal(t, IsSymlinkOrReparsePoint(link), true)
|
||||
}
|
||||
|
||||
func TestIsSymlinkOrReparsePointNestedInSymlink(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tmp := t.TempDir()
|
||||
|
||||
// Create a structure: target/inner-target, link -> target, then check link/inner-link
|
||||
target := filepath.Join(tmp, "target")
|
||||
innerTarget := filepath.Join(target, "inner-target")
|
||||
assert.NilError(t, os.MkdirAll(innerTarget, 0o777))
|
||||
|
||||
link := filepath.Join(tmp, "link")
|
||||
mklink(t, target, link, true)
|
||||
|
||||
// Create a junction inside the target
|
||||
innerLink := filepath.Join(target, "inner-link")
|
||||
mklink(t, innerTarget, innerLink, true)
|
||||
|
||||
// Check the junction through the symlink path
|
||||
nestedPath := filepath.Join(link, "inner-link")
|
||||
assert.Equal(t, IsSymlinkOrReparsePoint(nestedPath), true)
|
||||
}
|
||||
|
||||
func TestIsSymlinkOrReparsePointRelativePath(t *testing.T) { //nolint:paralleltest // Cannot use t.Parallel() with t.Chdir()
|
||||
tmp := t.TempDir()
|
||||
t.Chdir(tmp)
|
||||
|
||||
target := "target-rel"
|
||||
link := "link-rel"
|
||||
assert.NilError(t, os.MkdirAll(target, 0o777))
|
||||
mklink(t, target, link, true)
|
||||
|
||||
assert.Equal(t, IsSymlinkOrReparsePoint(link), true)
|
||||
assert.Equal(t, IsSymlinkOrReparsePoint(target), false)
|
||||
}
|
||||
|
||||
func BenchmarkIsSymlinkOrJunction(b *testing.B) {
|
||||
tmp := b.TempDir()
|
||||
|
||||
regularFile := filepath.Join(tmp, "regular.txt")
|
||||
assert.NilError(b, os.WriteFile(regularFile, []byte("hello"), 0o666))
|
||||
|
||||
target := filepath.Join(tmp, "target")
|
||||
link := filepath.Join(tmp, "link")
|
||||
assert.NilError(b, os.MkdirAll(target, 0o777))
|
||||
assert.NilError(b, exec.Command("cmd", "/c", "mklink", "/J", link, target).Run())
|
||||
|
||||
b.Run("regular file", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
IsSymlinkOrReparsePoint(regularFile)
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("junction", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for b.Loop() {
|
||||
IsSymlinkOrReparsePoint(link)
|
||||
}
|
||||
})
|
||||
|
||||
b.Run("nonexistent", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
nonexistent := filepath.Join(tmp, "does-not-exist")
|
||||
for b.Loop() {
|
||||
IsSymlinkOrReparsePoint(nonexistent)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func mklink(tb testing.TB, target, link string, isDir bool) {
|
||||
tb.Helper()
|
||||
|
||||
if isDir {
|
||||
assert.NilError(tb, exec.Command("cmd", "/c", "mklink", "/J", link, target).Run())
|
||||
} else {
|
||||
err := os.Symlink(target, link)
|
||||
if err != nil && strings.Contains(err.Error(), "A required privilege is not held by the client") {
|
||||
tb.Log(err)
|
||||
tb.Skip("file symlink support is not enabled without elevation or developer mode")
|
||||
}
|
||||
assert.NilError(tb, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user