diff options
Diffstat (limited to 'internal/engine/explain_test.go')
| -rw-r--r-- | internal/engine/explain_test.go | 83 |
1 files changed, 79 insertions, 4 deletions
diff --git a/internal/engine/explain_test.go b/internal/engine/explain_test.go index 4d304f9..83011c5 100644 --- a/internal/engine/explain_test.go +++ b/internal/engine/explain_test.go @@ -4,10 +4,12 @@ package engine import ( "context" + "os" "path/filepath" "reflect" "strings" "testing" + "time" "krino/internal/plan" ) @@ -26,7 +28,7 @@ func TestExplainReportsCapturesAndChain(t *testing.T) { if len(errs) > 0 { t.Fatal(errs) } - x, err := e.Explain(context.Background(), filepath.Join(dl, "Screenshot_2026-09-01.png")) + x, err := e.ExplainWithChain(context.Background(), filepath.Join(dl, "Screenshot_2026-09-01.png")) if err != nil { t.Fatal(err) } @@ -38,8 +40,9 @@ func TestExplainReportsCapturesAndChain(t *testing.T) { } } -// TestExplainChainMatchesThePlan: the chain explain reports is the one the -// directory's plan gives the same file, conflicts and skips included. +// TestExplainChainMatchesThePlan: for a file planned on its own, the chain +// is the one the directory's plan gives it, conflicts with files already on +// disk included. func TestExplainChainMatchesThePlan(t *testing.T) { h, dl := excludeTree(t, map[string]string{"a.pdf": "one", "Out/a.pdf": "taken"}) main := writeConfig(t, h, `(include "dl")`, map[string]string{"dl": ` @@ -55,7 +58,7 @@ func TestExplainChainMatchesThePlan(t *testing.T) { if err != nil { t.Fatal(err) } - x, err := e.Explain(context.Background(), filepath.Join(dl, "a.pdf")) + x, err := e.ExplainWithChain(context.Background(), filepath.Join(dl, "a.pdf")) if err != nil { t.Fatal(err) } @@ -63,3 +66,75 @@ func TestExplainChainMatchesThePlan(t *testing.T) { t.Errorf("explain chain %+v\nplan chain %+v", x.Chain, dp.Chains[0].Steps) } } + +// TestExplainChainOnlyWhenAsked: the command line's explain does not build +// the chain (it can hash files to resolve a conflict), and a file no rule +// acts on has none at all (plan 13 review F1, F2). +func TestExplainChainOnlyWhenAsked(t *testing.T) { + h, dl := excludeTree(t, map[string]string{"a.pdf": "one", "keep-b.pdf": "two", "new.pdf": "three"}) + now := time.Now() + os.Chtimes(filepath.Join(dl, "new.pdf"), now, now) + main := writeConfig(t, h, `(include "dl")`, map[string]string{"dl": ` +(path "~/dl") +(exclude (name "^keep-")) +(rule "all" (move "Out")) +`}) + e, errs := Load(main) + if len(errs) > 0 { + t.Fatal(errs) + } + x, err := e.Explain(context.Background(), filepath.Join(dl, "a.pdf")) + if err != nil { + t.Fatal(err) + } + if x.Chain != nil { + t.Errorf("Explain built a chain: %+v", x.Chain) + } + if x, err = e.ExplainWithChain(context.Background(), filepath.Join(dl, "a.pdf")); err != nil || len(x.Chain) != 1 { + t.Fatalf("ExplainWithChain: %+v, %v", x.Chain, err) + } + for _, rel := range []string{"keep-b.pdf", "new.pdf"} { + x, err := e.ExplainWithChain(context.Background(), filepath.Join(dl, rel)) + if err != nil { + t.Fatal(err) + } + if x.Chain != nil { + t.Errorf("%s (%s%s) has a chain: %+v", rel, x.Skip, x.Excluded, x.Chain) + } + } +} + +// TestExplainChainIsThisFileAlone: with two files competing for one name, +// the chain shows what this file alone would do; the plan is where the two +// are resolved against each other (plan 13 review F2). +func TestExplainChainIsThisFileAlone(t *testing.T) { + h, dl := excludeTree(t, map[string]string{"a.pdf": "one", "b.pdf": "two"}) + main := writeConfig(t, h, `(include "dl")`, map[string]string{"dl": ` +(path "~/dl") +(rule "r" (rename "same.pdf")) +`}) + e, errs := Load(main) + if len(errs) > 0 { + t.Fatal(errs) + } + dp, err := e.Plan(context.Background(), e.Dirs[0], plan.NewClaims()) + if err != nil { + t.Fatal(err) + } + var planned string + for _, c := range dp.Chains { + if c.File.Rel == "b.pdf" { + planned = filepath.Base(c.Steps[0].Dst) + } + } + if planned != "same_1.pdf" { + t.Fatalf("the plan gave b.pdf %q; expected the suffix", planned) + } + x, err := e.ExplainWithChain(context.Background(), filepath.Join(dl, "b.pdf")) + if err != nil { + t.Fatal(err) + } + if got := filepath.Base(x.Chain[0].Dst); got != "same.pdf" { + t.Errorf("chain for b.pdf alone = %q, want same.pdf (the plan resolves the clash with a.pdf)", got) + } +} |
