diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-09-14 14:08:36 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-09-14 14:08:36 +0200 |
| commit | 1d3f2d1e4c59867024470d3444e12698b7ebb22e (patch) | |
| tree | 4fa14f455c72f9b206a680dcc1b0f4c1f3708158 /cmd/krino/exclude_test.go | |
| parent | 07c24054cab965800983ef40f53a05c2db131ede (diff) | |
| download | krino-0.0.4.tar.gz krino-0.0.4.zip | |
0.0.4: max-size, exclude forms, --min-agev0.0.4
Diffstat (limited to 'cmd/krino/exclude_test.go')
| -rw-r--r-- | cmd/krino/exclude_test.go | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/cmd/krino/exclude_test.go b/cmd/krino/exclude_test.go new file mode 100644 index 0000000..2e9ff2a --- /dev/null +++ b/cmd/krino/exclude_test.go @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package main + +import ( + "os" + "path/filepath" + "strings" + "testing" + "time" + + "krino/internal/engine" + "krino/internal/scan" +) + +// excludeFixture makes ~/dl with an old a.iso, an old keep.txt and a fresh +// new.txt, a krino.conf excluding iso files everywhere, and dl's own rules: +// exclude names starting with "draft", move everything else to Out. +func excludeFixture(t *testing.T) string { + t.Helper() + h := home(t) + dl := filepath.Join(h, "dl") + old := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC) + for name, mt := range map[string]time.Time{"a.iso": old, "keep.txt": old, "draft.txt": old, "new.txt": time.Now()} { + p := filepath.Join(dl, name) + if err := os.MkdirAll(dl, 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(p, []byte("x"), 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) + } + cfg := filepath.Join(h, ".config", "krino") + mainConf, err := os.ReadFile(filepath.Join(cfg, "krino.conf")) + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(cfg, "krino.conf"), append(mainConf, []byte("\n(exclude (type iso))\n")...), 0o644); err != nil { + t.Fatal(err) + } + rules := "(path \"~/dl\")\n(exclude (name \"^draft\"))\n(rule \"all\" (move \"Out\"))\n" + if err := os.WriteFile(filepath.Join(cfg, "dirs", "dl.conf"), []byte(rules), 0o644); err != nil { + t.Fatal(err) + } + return h +} + +// TestMinAgeFlagOverridesTheSetting: --min-age changes "too new" for one +// run, in either position, and a bad value is a usage error before anything +// is read. +func TestMinAgeFlagOverridesTheSetting(t *testing.T) { + excludeFixture(t) + _, out, _ := runCLI(t, "-n") + if strings.Contains(out, "new.txt") || !strings.Contains(out, "1 too new") { + t.Errorf("without the flag new.txt should be too new:\n%s", out) + } + for _, args := range [][]string{{"--min-age", "0", "-n"}, {"-n", "--min-age", "0s"}} { + code, out, errOut := runCLI(t, args...) + if code != 0 || !strings.Contains(out, " new.txt\n") || strings.Contains(out, "too new") { + t.Errorf("%v: exit %d, new.txt should be planned:\n%s\n%s", args, code, out, errOut) + } + } + code, _, errOut := runCLI(t, "--min-age", "soon", "-n") + if code != 2 || !strings.Contains(errOut, "--min-age") { + t.Errorf("--min-age soon: exit %d, stderr %q; want 2 naming --min-age", code, errOut) + } +} + +// TestVerboseListsExcludedFiles: with -v, the plan lists each excluded file +// with the exclude that set it aside; the counts line counts them. +func TestVerboseListsExcludedFiles(t *testing.T) { + excludeFixture(t) + code, out, errOut := runCLI(t, "-n", "-v") + if code != 0 { + t.Fatalf("exit %d: %s", code, errOut) + } + for _, want := range []string{ + "2 excluded", + "\nexcluded\n a.iso (exclude (type iso))\n draft.txt (exclude (name \"^draft\"))\n", + } { + if !strings.Contains(out, want) { + t.Errorf("output lacks %q:\n%s", want, out) + } + } +} + +// TestCheckListsExclusions: check shows each directory's exclusions, the +// krino.conf ones first, before its rules. +func TestCheckListsExclusions(t *testing.T) { + excludeFixture(t) + code, out, errOut := runCLI(t, "check") + if code != 0 { + t.Fatalf("exit %d: %s", code, errOut) + } + want := " (exclude (type iso))\n (exclude (name \"^draft\"))\n 1 all" + if !strings.Contains(out, want) { + t.Errorf("check output lacks %q:\n%s", want, out) + } +} + +// TestExplainShowsExclusion: explain says which exclude sets the file +// aside and traces every exclude. +func TestExplainShowsExclusion(t *testing.T) { + h := excludeFixture(t) + code, out, errOut := runCLI(t, "explain", filepath.Join(h, "dl", "a.iso")) + if code != 0 { + t.Fatalf("exit %d: %s", code, errOut) + } + for _, want := range []string{ + "krino would set this file aside: (exclude (type iso))\n", + "(exclude (type iso)): MATCH\n", + "(exclude (name \"^draft\")): no\n", + } { + if !strings.Contains(out, want) { + t.Errorf("explain output lacks %q:\n%s", want, out) + } + } +} + +// TestSkipSummaryCountsTooBig: a file skipped for max-size is counted as +// too big in the "not acted on" line. +func TestSkipSummaryCountsTooBig(t *testing.T) { + r := &engine.Result{Skipped: []scan.Skipped{{Rel: "big.iso", Reason: scan.TooBig}}} + if got := skipSummaryLine(r, nil, false); !strings.Contains(got, "1 too big") { + t.Errorf("line = %q, want 1 too big", got) + } +} |
