aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-14 23:58:43 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-14 23:58:43 +0200
commit67ada0b5bc25cb6cff3ab780d82cb0bfe64e4968 (patch)
treee05598d93c71af19be946b3cb0d4e80688596c24 /internal
parent04f46bf180cf506ceadb76b5afacf9c02700cc65 (diff)
downloadkrino-67ada0b5bc25cb6cff3ab780d82cb0bfe64e4968.tar.gz
krino-67ada0b5bc25cb6cff3ab780d82cb0bfe64e4968.zip
tests: apply error exits 1 and w stops krino through the real command; undo projection occupied half
Diffstat (limited to 'internal')
-rw-r--r--internal/engine/undo_identity_test.go53
1 files changed, 53 insertions, 0 deletions
diff --git a/internal/engine/undo_identity_test.go b/internal/engine/undo_identity_test.go
index f42c5da..01f57d8 100644
--- a/internal/engine/undo_identity_test.go
+++ b/internal/engine/undo_identity_test.go
@@ -572,3 +572,56 @@ func TestUndoRunWithADamagedLineIsStillAnUndo(t *testing.T) {
t.Errorf("PlanUndo(undo run with a damaged line) = %v; want refused as an undo", err)
}
}
+
+// TestUndoOverwriteThenMove: a move that replaced an existing file and was
+// then moved on is undone whole - the moved file goes back, and the file it
+// replaced is restored to the path the later reversal vacates (triage 34m).
+func TestUndoOverwriteThenMove(t *testing.T) {
+ e, run, h, logPath := appliedRun(t, map[string]map[string]string{"dl": {"a.pdf": "one", "Out/a.pdf": "old"}},
+ map[string]string{"dl": "(path \"~/dl\")\n(ignore \"Out/\")\n(recursive yes)\n(rule \"r\" (on-conflict overwrite) (move \"Out\") (move \"Out2\"))\n"})
+ if b, _ := os.ReadFile(filepath.Join(h, "dl", "Out2", "a.pdf")); string(b) != "one" {
+ t.Fatalf("setup: the chain did not run as planned")
+ }
+ up, err := e.PlanUndo(run)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, f := range up.Files {
+ if f.Refused != "" {
+ t.Fatalf("%s refused: %s (%+v)", f.File, f.Refused, f.Steps)
+ }
+ }
+ j, err := journal.Open(logPath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer j.Close()
+ if _, err := e.ApplyUndo(context.Background(), up, j, journal.NewRunID(time.Now())); err != nil {
+ t.Fatal(err)
+ }
+ for rel, want := range map[string]string{"a.pdf": "one", "Out/a.pdf": "old"} {
+ if b, err := os.ReadFile(filepath.Join(h, "dl", rel)); err != nil || string(b) != want {
+ t.Errorf("%s after undo: %q, %v; want %q", rel, b, err, want)
+ }
+ }
+}
+
+// TestProjectionSeesAPathAnEarlierStepWillFill: a path not on disk yet that
+// a queued reversal will put a file at is occupied for the steps after it,
+// and free again once a later one moves that file on (triage 34m: the
+// "occupied" half of the projection had no test that could fail).
+func TestProjectionSeesAPathAnEarlierStepWillFill(t *testing.T) {
+ x := filepath.Join(t.TempDir(), "x.pdf")
+ p := newUndoProjection()
+ if p.occupiedNow(x) {
+ t.Fatal("an empty path reads as occupied")
+ }
+ p.record(UndoStep{Action: "undo-move", Src: x + ".elsewhere", Dst: x})
+ if !p.occupiedNow(x) {
+ t.Error("a path a queued undo-move fills reads as free")
+ }
+ p.record(UndoStep{Action: "undo-rename", Src: x, Dst: x + ".back"})
+ if p.occupiedNow(x) {
+ t.Error("a path a later reversal vacates still reads as occupied")
+ }
+}