153 lines
4.4 KiB
Go
153 lines
4.4 KiB
Go
package osvfs
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/microsoft/typescript-go/internal/tspath"
|
|
"gotest.tools/v3/assert"
|
|
)
|
|
|
|
func TestSymlinkRealpath(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
targetFile, linkFile := setupSymlinks(t)
|
|
|
|
gotContents, err := os.ReadFile(linkFile)
|
|
assert.NilError(t, err)
|
|
assert.Equal(t, string(gotContents), "hello")
|
|
|
|
fs := FS()
|
|
|
|
targetRealpath := fs.Realpath(tspath.NormalizePath(targetFile))
|
|
linkRealpath := fs.Realpath(tspath.NormalizePath(linkFile))
|
|
|
|
if targetRealpath != linkRealpath {
|
|
t.Errorf("expected realpath of target and link to be equal, got %q and %q", targetRealpath, linkRealpath)
|
|
cmd := exec.Command("node", "-e", `console.log({ native: fs.realpathSync.native(process.argv[1]), node: fs.realpathSync(process.argv[1]) })`, linkFile)
|
|
out, err := cmd.CombinedOutput()
|
|
assert.NilError(t, err)
|
|
t.Logf("node: %s", out)
|
|
}
|
|
}
|
|
|
|
func setupSymlinks(tb testing.TB) (targetFile, linkFile string) {
|
|
tb.Helper()
|
|
|
|
tmp := tb.TempDir()
|
|
|
|
target := filepath.Join(tmp, "target")
|
|
targetFile = filepath.Join(target, "file")
|
|
|
|
link := filepath.Join(tmp, "link")
|
|
linkFile = filepath.Join(link, "file")
|
|
|
|
assert.NilError(tb, os.MkdirAll(target, 0o777))
|
|
assert.NilError(tb, os.WriteFile(targetFile, []byte("hello"), 0o666))
|
|
|
|
mklink(tb, target, link, true)
|
|
|
|
return targetFile, linkFile
|
|
}
|
|
|
|
func BenchmarkRealpath(b *testing.B) {
|
|
targetFile, linkFile := setupSymlinks(b)
|
|
|
|
fs := FS()
|
|
normalizedTargetFile := tspath.NormalizePath(targetFile)
|
|
normalizedLinkFile := tspath.NormalizePath(linkFile)
|
|
|
|
b.Run("target", func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
|
|
for b.Loop() {
|
|
fs.Realpath(normalizedTargetFile)
|
|
}
|
|
})
|
|
|
|
b.Run("link", func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
|
|
for b.Loop() {
|
|
fs.Realpath(normalizedLinkFile)
|
|
}
|
|
})
|
|
|
|
// Simulate a deep node_modules path to show scaling with depth.
|
|
deepDir := b.TempDir()
|
|
for _, seg := range []string{"project", "node_modules", "@scope", "package", "node_modules", "dep", "lib", "dist", "esm", "internal", "utils"} {
|
|
deepDir = filepath.Join(deepDir, seg)
|
|
}
|
|
assert.NilError(b, os.MkdirAll(deepDir, 0o777))
|
|
deepFile := filepath.Join(deepDir, "index.js")
|
|
assert.NilError(b, os.WriteFile(deepFile, []byte("module.exports = {}"), 0o666))
|
|
normalizedDeepFile := tspath.NormalizePath(deepFile)
|
|
|
|
b.Run("deep", func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
|
|
for b.Loop() {
|
|
fs.Realpath(normalizedDeepFile)
|
|
}
|
|
})
|
|
|
|
b.Run("deep_evalSymlinks", func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
deepNative := filepath.FromSlash(normalizedDeepFile)
|
|
|
|
for b.Loop() {
|
|
filepath.EvalSymlinks(deepNative) //nolint:errcheck
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestGetAccessibleEntries(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tmp := t.TempDir()
|
|
target := filepath.Join(tmp, "target")
|
|
link := filepath.Join(tmp, "link")
|
|
|
|
assert.NilError(t, os.MkdirAll(target, 0o777))
|
|
assert.NilError(t, os.MkdirAll(link, 0o777))
|
|
|
|
targetFile1 := filepath.Join(target, "file1")
|
|
targetFile2 := filepath.Join(target, "file2")
|
|
|
|
assert.NilError(t, os.WriteFile(targetFile1, []byte("hello"), 0o666))
|
|
assert.NilError(t, os.WriteFile(targetFile2, []byte("world"), 0o666))
|
|
|
|
targetDir1 := filepath.Join(target, "dir1")
|
|
targetDir2 := filepath.Join(target, "dir2")
|
|
|
|
assert.NilError(t, os.MkdirAll(targetDir1, 0o777))
|
|
assert.NilError(t, os.MkdirAll(targetDir2, 0o777))
|
|
|
|
mklink(t, targetFile1, filepath.Join(link, "file1"), false)
|
|
mklink(t, targetFile2, filepath.Join(link, "file2"), false)
|
|
mklink(t, targetDir1, filepath.Join(link, "dir1"), true)
|
|
mklink(t, targetDir2, filepath.Join(link, "dir2"), true)
|
|
|
|
fs := FS()
|
|
|
|
entries := fs.GetAccessibleEntries(tspath.NormalizePath(link))
|
|
|
|
assert.DeepEqual(t, entries.Directories, []string{"dir1", "dir2"})
|
|
assert.DeepEqual(t, entries.Files, []string{"file1", "file2"})
|
|
assert.Check(t, entries.Symlinks != nil, "expected Symlinks to be set for directory with symlinks")
|
|
assert.Equal(t, len(entries.Symlinks), 4)
|
|
for _, name := range []string{"file1", "file2", "dir1", "dir2"} {
|
|
_, ok := entries.Symlinks[name]
|
|
assert.Check(t, ok, "expected %q to be in Symlinks", name)
|
|
}
|
|
|
|
// Non-symlink directory should have empty Symlinks.
|
|
entries = fs.GetAccessibleEntries(tspath.NormalizePath(target))
|
|
assert.DeepEqual(t, entries.Directories, []string{"dir1", "dir2"})
|
|
assert.DeepEqual(t, entries.Files, []string{"file1", "file2"})
|
|
assert.Check(t, entries.Symlinks != nil, "expected Symlinks to be non-nil for directory without symlinks")
|
|
assert.Equal(t, len(entries.Symlinks), 0)
|
|
}
|