ajhahn.de
← eeco
Go 111 lines
package workflow

import (
	"os"
	"path/filepath"
	"testing"
)

func TestLeakGuard_CleanTrackedTree(t *testing.T) {
	cfg := newCfg(t)
	writeRepoFile(t, cfg.RepoRoot, "main.go", "package main\nfunc main(){}\n")
	writeRepoFile(t, cfg.RepoRoot, ".gitignore", "/.eeco/\n")
	gitInit(t, cfg.RepoRoot)
	res, err := leakGuard{}.Run(Env{Config: cfg})
	if err != nil {
		t.Fatal(err)
	}
	if res.Code != CodeClean {
		t.Fatalf("clean repo -> %d (%s) %+v", res.Code, res.Summary, res.Findings)
	}
}

func TestLeakGuard_FlagsTrailerInTrackedFile(t *testing.T) {
	cfg := newCfg(t)
	trailer := fragCoAB + ": A <a@b>"
	writeRepoFile(t, cfg.RepoRoot, "CHANGELOG.md", "release notes\n"+trailer+"\n")
	gitInit(t, cfg.RepoRoot)
	res, err := leakGuard{}.Run(Env{Config: cfg})
	if err != nil {
		t.Fatal(err)
	}
	if res.Code != CodeFinding {
		t.Fatalf("tracked trailer -> %d, want %d (%+v)", res.Code, CodeFinding, res.Findings)
	}
}

func TestLeakGuard_FlagsWorkspacePathLeak(t *testing.T) {
	cfg := newCfg(t)
	// Build the engine path from fragments so this tracked test source
	// never carries a contiguous workspace-engine path for the gate to
	// (correctly) flag against eeco itself.
	eng := cfg.WorkspaceName + "/state/"
	writeRepoFile(t, cfg.RepoRoot, "notes.txt", "debug dump from "+eng+"queue.md here\n")
	gitInit(t, cfg.RepoRoot)
	res, err := leakGuard{}.Run(Env{Config: cfg})
	if err != nil {
		t.Fatal(err)
	}
	if res.Code != CodeFinding {
		t.Fatalf("workspace path leak -> %d, want %d", res.Code, CodeFinding)
	}
}

func TestLeakGuard_GitignoreEntryExempt(t *testing.T) {
	cfg := newCfg(t)
	// The .gitignore workspace line is the documented intended change;
	// it must never be reported as a leak — even an engine-path-shaped
	// line here is exempt. Fragment-built for the reason above.
	ws := cfg.WorkspaceName
	writeRepoFile(t, cfg.RepoRoot, ".gitignore", "/"+ws+"/\n"+ws+"/state/\n")
	gitInit(t, cfg.RepoRoot)
	res, err := leakGuard{}.Run(Env{Config: cfg})
	if err != nil {
		t.Fatal(err)
	}
	if res.Code != CodeClean {
		t.Fatalf(".gitignore flagged: %+v", res.Findings)
	}
}

func TestLeakGuard_IgnoresUntrackedFile(t *testing.T) {
	cfg := newCfg(t)
	writeRepoFile(t, cfg.RepoRoot, "tracked.txt", "fine\n")
	gitInit(t, cfg.RepoRoot)
	// Written after `git add`: untracked, so it cannot enter history.
	writeRepoFile(t, cfg.RepoRoot, "untracked.txt", fragCoAB+": X <x@y>\n")
	res, err := leakGuard{}.Run(Env{Config: cfg})
	if err != nil {
		t.Fatal(err)
	}
	if res.Code != CodeClean {
		t.Fatalf("untracked file gated the commit: %+v", res.Findings)
	}
}

func TestLeakGuard_ScansCommitMessage(t *testing.T) {
	cfg := newCfg(t)
	writeRepoFile(t, cfg.RepoRoot, "f.txt", "ok\n")
	gitInit(t, cfg.RepoRoot)
	msg := "feat: a change\n\n" + fragCoAB + ": Tool <t@x>\n"
	if err := os.WriteFile(filepath.Join(cfg.RepoRoot, ".git", "COMMIT_EDITMSG"), []byte(msg), 0o644); err != nil {
		t.Fatal(err)
	}
	res, err := leakGuard{}.Run(Env{Config: cfg})
	if err != nil {
		t.Fatal(err)
	}
	if res.Code != CodeFinding {
		t.Fatalf("commit-message trailer -> %d, want %d", res.Code, CodeFinding)
	}
	var sawMsg bool
	for _, f := range res.Findings {
		if f.Path == "COMMIT_EDITMSG" {
			sawMsg = true
		}
	}
	if !sawMsg {
		t.Errorf("commit message not attributed in findings: %+v", res.Findings)
	}
}