diff options
Diffstat (limited to 'internal/engine/undo_identity_test.go')
| -rw-r--r-- | internal/engine/undo_identity_test.go | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/internal/engine/undo_identity_test.go b/internal/engine/undo_identity_test.go index f9d6307..f42c5da 100644 --- a/internal/engine/undo_identity_test.go +++ b/internal/engine/undo_identity_test.go @@ -492,3 +492,83 @@ func TestUndoRefusesATrashEntryRecordedForAnotherPath(t *testing.T) { t.Errorf("Refused = %q; want the trash entry named as another file's", f.Refused) } } + +// TestFinishedUndoRemovesADirectoryLeftEmpty: a directory made by one file's +// chain and still holding another file is not offered on its own, but once +// that other file's reversal empties it, the undo removes it (plan 10 +// re-check R1). +func TestFinishedUndoRemovesADirectoryLeftEmpty(t *testing.T) { + e, run, h, logPath := appliedRun(t, map[string]map[string]string{"dl": {"a.pdf": "one", "b.pdf": "two"}}, + map[string]string{"dl": "(path \"~/dl\")\n(rule \"r\" (move \"Out\"))\n"}) + out := filepath.Join(h, "dl", "Out") + undo := func(decline string) { + t.Helper() + up, err := e.PlanUndo(run) + if err != nil { + t.Fatal(err) + } + for i := range up.Files { + up.Files[i].Declined = up.Files[i].File == decline + } + 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) + } + } + up, err := e.PlanUndo(run) + if err != nil { + t.Fatal(err) + } + other := "" + for _, f := range up.Files { + made := false + for _, s := range f.Steps { + made = made || s.Action == "undo-mkdir" + } + if !made { + other = f.File + } + } + undo(other) // the file that made Out goes back; the other still holds Out + if _, err := os.Stat(out); err != nil { + t.Fatalf("Out went while %s still held it: %v", other, err) + } + undo("") // the other goes back, leaving Out empty + if _, err := os.Lstat(out); !os.IsNotExist(err) { + t.Errorf("Out is still there after the undo finished: %v", err) + } +} + +// TestUndoRunWithADamagedLineIsStillAnUndo: a damaged line in an undo run's +// log does not make that run look like an ordinary one that can be undone +// (plan 10 re-check R3). +func TestUndoRunWithADamagedLineIsStillAnUndo(t *testing.T) { + e, run, _, logPath := appliedRun(t, map[string]map[string]string{"dl": {"a.pdf": "one"}}, + map[string]string{"dl": "(path \"~/dl\")\n(rule \"r\" (rename \"r-{name}\") (move \"Out\"))\n"}) + up, err := e.PlanUndo(run) + if err != nil { + t.Fatal(err) + } + j, err := journal.Open(logPath) + if err != nil { + t.Fatal(err) + } + undoRun := journal.NewRunID(time.Now().Add(time.Second)) + if _, err := e.ApplyUndo(context.Background(), up, j, undoRun); err != nil { + t.Fatal(err) + } + j.Close() + f, err := os.OpenFile(logPath, os.O_APPEND|os.O_WRONLY, 0) + if err != nil { + t.Fatal(err) + } + f.WriteString(time.Now().UTC().Format(time.RFC3339) + "\t" + undoRun + "\tdl\ta.pdf\t9\tundo-mo\n") + f.Close() + if _, err := e.PlanUndo(undoRun); err == nil || !strings.Contains(err.Error(), "itself an undo") { + t.Errorf("PlanUndo(undo run with a damaged line) = %v; want refused as an undo", err) + } +} |
