aboutsummaryrefslogtreecommitdiff
path: root/gui/internal/model/sort_test.go
blob: 0b3a01dba46ba8e4f011e90ad9aaa25e7e6a6bab (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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)
		}
	}
}