Files
aego/tools/artstudio/release/symlink_path_test.go
sanspie fac6fa35a4
ci-platforms / darwin arm64 smoke (push) Skipped
ci-platforms / windows amd64 smoke (push) Skipped
ci-platforms / darwin amd64 smoke (push) Skipped
github-native / gitea-pending (push) Skipped
github-native / darwin amd64 native (push) Skipped
github-native / linux amd64 native (push) Skipped
github-native / windows amd64 native (push) Skipped
github-native / darwin arm64 native (push) Skipped
github-native / gitea-result (push) Skipped
ci / checks (push) Failing after 7m29s
ci / build (amd64, linux, ubuntu-24.04) (push) Failing after 14m13s
ci / release (push) Skipped
GitHub / windows amd64 native GitHub-hosted native CI: failure
GitHub / darwin arm64 native GitHub-hosted native CI: error
GitHub / darwin amd64 native GitHub-hosted native CI: failure
GitHub / linux amd64 native GitHub-hosted native CI: success
fix: stabilize CI and prepare docs release
Keep recovery copies private on Windows, make cross-platform test fixtures deterministic, and preserve the updated Art and documentation contracts.

Refresh workspace screenshot references for the intentional factory layouts and restore the earlier Russian palette reference after before/after comparison. Keep the existing screenshot tolerances.
2026-11-09 16:24:24 +03:00

101 lines
3.0 KiB
Go

package main
import (
"errors"
"os"
"path/filepath"
"runtime"
"testing"
)
// Resolve only paths belonging to test-owned fixtures. On macOS t.TempDir can
// be under /var, which is itself a symlink to /private/var. Production path
// validation must still reject symlinks rather than resolving caller input.
func physicalFixturePath(t *testing.T, p string) string {
t.Helper()
physical, err := filepath.EvalSymlinks(p)
if err != nil {
t.Fatalf("resolve fixture path %s: %v", p, err)
}
return physical
}
func physicalTempDir(t *testing.T) string {
t.Helper()
return physicalFixturePath(t, t.TempDir())
}
func fixtureSymlink(t *testing.T, target, link string) {
t.Helper()
if err := os.Symlink(target, link); err != nil {
if runtime.GOOS == "windows" {
t.Skipf("symlinks unavailable: %v", err)
}
t.Fatalf("create symlink %s: %v", link, err)
}
}
func requireRefusedSymlink(t *testing.T, p, link string) {
t.Helper()
err := noSymlinkPath(p)
want := "symlink path refused: " + link
if err == nil || err.Error() != want {
t.Fatalf("noSymlinkPath(%q) = %v; want %q", p, err, want)
}
}
func TestNoSymlinkPathChecksEveryComponent(t *testing.T) {
base := physicalTempDir(t)
dir := filepath.Join(base, "real", "child")
if err := os.MkdirAll(dir, 0o755); err != nil {
t.Fatal(err)
}
file := filepath.Join(dir, "file")
if err := os.WriteFile(file, []byte("fixture"), 0o644); err != nil {
t.Fatal(err)
}
if err := noSymlinkPath(file); err != nil {
t.Fatalf("physical fixture refused: %v", err)
}
if err := noSymlinkPath(filepath.Join(base, "missing")); !errors.Is(err, os.ErrNotExist) {
t.Fatalf("missing path = %v; want not-exist error", err)
}
for _, tc := range []struct {
name, target, link string
suffix []string
}{
{"leaf", dir, filepath.Join(base, "leaf"), nil},
{"ancestor", filepath.Join(base, "real"), filepath.Join(base, "ancestor"), []string{"child", "file"}},
{"relative ancestor", "child", filepath.Join(base, "real", "relative"), []string{"file"}},
{"dangling leaf", filepath.Join(base, "missing"), filepath.Join(base, "dangling"), nil},
} {
t.Run(tc.name, func(t *testing.T) {
fixtureSymlink(t, tc.target, tc.link)
p := filepath.Join(append([]string{tc.link}, tc.suffix...)...)
requireRefusedSymlink(t, p, tc.link)
})
}
}
func TestPhysicalFixturePathResolvesOnlyTestOwnedAlias(t *testing.T) {
base := physicalTempDir(t)
physical := filepath.Join(base, "real", "temp")
if err := os.MkdirAll(physical, 0o755); err != nil {
t.Fatal(err)
}
alias := filepath.Join(base, "temp-alias")
fixtureSymlink(t, filepath.Join(base, "real"), alias)
throughAlias := filepath.Join(alias, "temp")
requireRefusedSymlink(t, throughAlias, alias)
if got := physicalFixturePath(t, throughAlias); got != physical {
t.Fatalf("physical fixture path = %q; want %q", got, physical)
} else if err := noSymlinkPath(got); err != nil {
t.Fatalf("resolved fixture path refused: %v", err)
}
link := filepath.Join(physical, "untrusted")
fixtureSymlink(t, base, link)
requireRefusedSymlink(t, link, link)
}