Files
agent-lib/internal/e2e/collide_test.go
T

122 lines
3.6 KiB
Go
Raw Normal View History

package e2e
import (
"os"
"path/filepath"
"testing"
"github.com/m3tam3re/agent-lib/internal/lockfile"
)
func ownSkillFixture(h *harness, t *testing.T) {
t.Helper()
dir := filepath.Join(h.workDir, "skills", "good-skill")
if err := os.MkdirAll(dir, 0o755); err != nil {
t.Fatal(err)
}
os.WriteFile(filepath.Join(dir, "SKILL.md"), []byte("---\nname: Own Good\n---\n"), 0o644)
}
func TestCollisionOwnVsVendored(t *testing.T) {
h := newHarness(t)
ownSkillFixture(h, t)
standardFixture(h, t)
out, err := h.run(t, "vendor", "add", "superpowers", h.upstreamDir)
if err == nil {
t.Fatalf("own-vs-vendored collision must fail:\n%s", out)
}
for _, want := range []string{"collides", "own", "good-skill"} {
if !contains(out, want) {
t.Errorf("error must contain %q:\n%s", want, out)
}
}
if _, err := os.Stat(filepath.Join(h.workDir, "external")); err == nil {
t.Error("collision must abort before any tree mutation")
}
if _, err := os.Stat(filepath.Join(h.workDir, lockfile.FileName)); err == nil {
t.Error("collision must not write a lockfile")
}
}
func TestCollisionVendoredVsVendored(t *testing.T) {
h := newHarness(t)
standardFixture(h, t)
h.mustRun(t, "vendor", "add", "first", h.upstreamDir)
out, err := h.run(t, "vendor", "add", "second", h.upstreamDir)
if err == nil {
t.Fatalf("vendored-vs-vendored collision must fail:\n%s", out)
}
for _, want := range []string{"collides", "first"} {
if !contains(out, want) {
t.Errorf("error must name both parties (%q missing):\n%s", want, out)
}
}
}
func TestCollisionResolvedByRename(t *testing.T) {
h := newHarness(t)
ownSkillFixture(h, t)
standardFixture(h, t)
out := h.mustRun(t, "vendor", "add", "superpowers", h.upstreamDir,
"--rename", "good-skill=superpowers-good-skill")
if !contains(out, "renamed") && !contains(out, "materialized") {
t.Errorf("rename resolution should report success:\n%s", out)
}
renamed := filepath.Join(h.workDir, "external/superpowers/skills/superpowers-good-skill/SKILL.md")
if _, err := os.Stat(renamed); err != nil {
t.Fatal("renamed folder must carry the deployed name")
}
original := filepath.Join(h.workDir, "external/superpowers/skills/good-skill")
if _, err := os.Stat(original); err == nil {
t.Error("upstream folder name must not appear after rename")
}
lock := readFile(t, filepath.Join(h.workDir, lockfile.FileName))
if !contains(lock, `"good-skill": "superpowers-good-skill"`) {
t.Errorf("rename map must be pinned in the lockfile:\n%s", lock)
}
if out := h.mustRun(t, "validate"); !contains(out, "valid") {
t.Errorf("renamed state must validate:\n%s", out)
}
}
func TestCollisionRenameToAnotherCollision(t *testing.T) {
h := newHarness(t)
ownSkillFixture(h, t)
standardFixture(h, t)
out, err := h.run(t, "vendor", "add", "superpowers", h.upstreamDir,
"--rename", "good-skill=broken-skill")
if err == nil {
t.Fatalf("renaming onto an existing deployed name must fail:\n%s", out)
}
if !contains(out, "collides") {
t.Errorf("error must report the collision:\n%s", out)
}
}
func TestValidateDetectsHandEditedCollision(t *testing.T) {
h := newHarness(t)
standardFixture(h, t)
h.mustRun(t, "vendor", "add", "superpowers", h.upstreamDir)
h.mustRun(t, "vendor", "add", "second-source", h.upstreamDir, "--include", "good-skill",
"--rename", "good-skill=second-good")
mutateLockfile(t, h, func(lf *lockfile.Lockfile) {
lf.Sources["second-source"].Renames["good-skill"] = "broken-skill"
})
out, err := h.run(t, "validate")
if err == nil {
t.Fatalf("hand-edited rename collision must fail validation:\n%s", out)
}
if !contains(out, "collision") {
t.Errorf("rule must be reported as collision:\n%s", out)
}
}