// 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) } } }