diff options
Diffstat (limited to 'cmd/krino/sort_test.go')
| -rw-r--r-- | cmd/krino/sort_test.go | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/cmd/krino/sort_test.go b/cmd/krino/sort_test.go index e482f44..fa9a7ca 100644 --- a/cmd/krino/sort_test.go +++ b/cmd/krino/sort_test.go @@ -110,3 +110,66 @@ func TestAllSkippedDirectoryReportsZeroAndLogsNothing(t *testing.T) { t.Errorf("journal gained entries for a directory with nothing to act on:\n%s", data) } } + +// TestPermanentDeleteOfDuplicatesUnderOverlappingDirKeepsACopy drives the +// whole run end to end on the shape where a (duplicate "DIR") overlaps the +// scanned tree: a recursive root holding Archive/x.pdf and a loose, older +// x-copy.pdf with the same bytes, and a rule that permanently deletes +// duplicates of anything under Archive. Whatever the verdicts, applying +// the plan must leave the content on disk; the expected outcome is that +// the archived copy stays and only the loose one goes. +func TestPermanentDeleteOfDuplicatesUnderOverlappingDirKeepsACopy(t *testing.T) { + h := home(t) + dl := filepath.Join(h, "dl") + content := []byte("%PDF acme statement") + archived := filepath.Join(dl, "Archive", "x.pdf") + loose := filepath.Join(dl, "x-copy.pdf") + old := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC) + for p, mt := range map[string]time.Time{archived: old.Add(time.Hour), loose: old} { + if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(p, content, 0o644); err != nil { + t.Fatal(err) + } + if err := os.Chtimes(p, mt, mt); err != nil { + t.Fatal(err) + } + } + if code, _, errOut := runCLI(t, "init"); code != 0 { + t.Fatal(errOut) + } + if code, _, errOut := runCLI(t, "new", "dl", dl); code != 0 { + t.Fatal(errOut) + } + rules := "(path \"~/dl\")\n(recursive yes)\n(min-age 0s)\n" + + "(rule \"dups\" (when (duplicate \"Archive\")) (delete permanent))\n" + if err := os.WriteFile(filepath.Join(h, ".config", "krino", "dirs", "dl.conf"), []byte(rules), 0o644); err != nil { + t.Fatal(err) + } + + code, out, errOut := runCLI(t, "-y") + + var copies []string + err := filepath.WalkDir(dl, func(p string, d os.DirEntry, err error) error { + if err != nil || !d.Type().IsRegular() { + return err + } + if b, err := os.ReadFile(p); err == nil && string(b) == string(content) { + copies = append(copies, p) + } + return nil + }) + if err != nil { + t.Fatal(err) + } + if len(copies) == 0 { + t.Fatalf("every copy was deleted (exit %d)\nstdout:\n%s\nstderr:\n%s", code, out, errOut) + } + if code != 0 { + t.Fatalf("run: %d %s", code, errOut) + } + if len(copies) != 1 || copies[0] != archived { + t.Errorf("copies left = %v, want only %s", copies, archived) + } +} |
