aboutsummaryrefslogtreecommitdiff
path: root/gui/internal/model/sort_test.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-17 10:05:55 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-17 10:05:55 +0200
commit47b6776c2cb9b017ad95acb5aae8e34b8776fc7c (patch)
tree3efb4a2f2c36f4537a3fe1377cfb010fd63072ec /gui/internal/model/sort_test.go
parent0e067e693609589d46f5aa6e161b95cc905987cc (diff)
downloadkrino-47b6776c2cb9b017ad95acb5aae8e34b8776fc7c.tar.gz
krino-47b6776c2cb9b017ad95acb5aae8e34b8776fc7c.zip
gui: sort the plan by name, size, age, action or rule
Diffstat (limited to 'gui/internal/model/sort_test.go')
-rw-r--r--gui/internal/model/sort_test.go95
1 files changed, 95 insertions, 0 deletions
diff --git a/gui/internal/model/sort_test.go b/gui/internal/model/sort_test.go
new file mode 100644
index 0000000..0b3a01d
--- /dev/null
+++ b/gui/internal/model/sort_test.go
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package model
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+ "time"
+)
+
+// names is the rows an order leaves, for the assertions below.
+func names(t *PlanTab, shown []int) []string {
+ var out []string
+ for _, i := range shown {
+ out = append(out, t.Rows[i].Rel)
+ }
+ return out
+}
+
+func same(a []string, b ...string) bool {
+ if len(a) != len(b) {
+ return false
+ }
+ for i := range a {
+ if a[i] != b[i] {
+ return false
+ }
+ }
+ return true
+}
+
+// TestSorted: each order reads the way its label says, and the default
+// leaves the plan as krino made it.
+func TestSorted(t *testing.T) {
+ conf := "(path \"~/dl\")\n" +
+ "(rule \"pdfs\" (when (type pdf)) (move \"Docs\") (stop))\n" +
+ "(rule \"rest\" (move \"Other\"))\n"
+ e, h := sandboxDir(t, conf, map[string]string{
+ "big.pdf": "0123456789abcdef", "small.txt": "x", "middle.pdf": "0123456789",
+ })
+ // Distinct times, so age has something to order by.
+ now := time.Now()
+ for name, ago := range map[string]time.Duration{
+ "big.pdf": 3 * time.Hour, "small.txt": 90 * 24 * time.Hour, "middle.pdf": 24 * time.Hour,
+ } {
+ p := filepath.Join(h, "dl", name)
+ when := now.Add(-ago)
+ if err := os.Chtimes(p, when, when); err != nil {
+ t.Fatal(err)
+ }
+ }
+ tab := planTab(t, e)
+ all := tab.Matching("")
+
+ if got := names(tab, tab.Sorted(all, SortDefault)); len(got) != 3 {
+ t.Fatalf("default = %v", got)
+ }
+ if got := names(tab, tab.Sorted(all, SortName)); !same(got, "big.pdf", "middle.pdf", "small.txt") {
+ t.Errorf("by name = %v", got)
+ }
+ if got := names(tab, tab.Sorted(all, SortSize)); !same(got, "big.pdf", "middle.pdf", "small.txt") {
+ t.Errorf("by size = %v", got)
+ }
+ if got := names(tab, tab.Sorted(all, SortAge)); !same(got, "small.txt", "middle.pdf", "big.pdf") {
+ t.Errorf("by age = %v, want the oldest first", got)
+ }
+ if got := names(tab, tab.Sorted(all, SortRule)); !same(got, "big.pdf", "middle.pdf", "small.txt") {
+ t.Errorf("by rule = %v, want pdfs before rest", got)
+ }
+ // An order krino does not know leaves the plan alone rather than
+ // guessing at one.
+ if got := names(tab, tab.Sorted(all, "nonsense")); !same(got, names(tab, all)...) {
+ t.Errorf("an unknown order changed the list: %v", got)
+ }
+ // Sorting never changes the plan itself.
+ if len(tab.Rows) != 3 || tab.Rows[0].Rel != names(tab, all)[0] {
+ t.Error("the plan's own order changed")
+ }
+}
+
+// TestSortedIsStable: files that compare the same keep the plan's order, so
+// the list does not shuffle under the eye.
+func TestSortedIsStable(t *testing.T) {
+ conf := "(path \"~/dl\")\n(rule \"all\" (move \"Out\"))\n"
+ e, _ := sandboxDir(t, conf, map[string]string{"a.txt": "x", "b.txt": "x", "c.txt": "x"})
+ tab := planTab(t, e)
+ all := tab.Matching("")
+ first := names(tab, tab.Sorted(all, SortSize))
+ for i := 0; i < 5; i++ {
+ if got := names(tab, tab.Sorted(all, SortSize)); !same(got, first...) {
+ t.Fatalf("run %d = %v, want %v", i, got, first)
+ }
+ }
+}