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
|
// SPDX-License-Identifier: GPL-3.0-or-later
package config
import (
"reflect"
"strings"
"testing"
"time"
)
func TestParseMain(t *testing.T) {
t.Setenv("HOME", "/home/u")
src := `;; comment
(include "downloads" "docs")
(log "~/state/krino.log")
(defaults (min-age 5m) (case strict))
`
m, errs := ParseMain("krino.conf", []byte(src))
if len(errs) > 0 {
t.Fatal(errs)
}
if !reflect.DeepEqual(m.Include, []string{"downloads", "docs"}) {
t.Errorf("Include = %q", m.Include)
}
if m.IncludePos["docs"].Line != 2 {
t.Errorf("docs at %+v", m.IncludePos["docs"])
}
if m.Log != "/home/u/state/krino.log" {
t.Errorf("Log = %q", m.Log)
}
if r := m.Defaults.Over(Builtin()); r.MinAge != 5*time.Minute || r.Case != CaseStrict {
t.Errorf("defaults = %+v", r)
}
if m.IncludeNode == nil || src[m.IncludeNode.End.Offset-1] != ')' {
t.Errorf("IncludeNode = %+v", m.IncludeNode)
}
}
func TestParseMainEmptyInclude(t *testing.T) {
m, errs := ParseMain("k", []byte("(include)"))
if len(errs) > 0 || len(m.Include) != 0 || m.IncludeNode == nil {
t.Fatalf("m = %+v, errs = %v", m, errs)
}
}
func TestParseMainErrors(t *testing.T) {
tests := []struct{ src, want string }{
{`(include downloads)`, `k:1:10: include takes directory names in quotes, like "downloads"; got downloads`},
{`(include "a/b")`, `k:1:10: bad directory name "a/b": use letters, digits, '.', '_' and '-'`},
{`(include "check")`, `k:1:10: "check" is a krino command; choose another name`},
{`(include "a" "a")`, `k:1:14: "a" included twice`},
{`(include "a") (include "b")`, `k:1:15: include given twice (first at line 1)`},
{`(log)`, `k:1:1: log takes one path in quotes, like (log "~/.local/state/krino/krino.log")`},
{`(log "rel/x")`, `k:1:6: log path must be absolute or start with ~`},
{`(defaults (recursive maybe))`, `k:1:22: recursive is yes or no, not maybe`},
{`(defaults (rule "x"))`, `k:1:11: defaults holds settings like (min-age 2m); got (rule "x")`},
{`(inlcude "a")`, `k:1:1: unknown form (inlcude ...); krino.conf has include, log, defaults and exclude`},
{`include`, `k:1:1: expected a form like (include ...), got include`},
{`(include "a"`, `k:1:1: "(" never closed: (include "a")`},
}
for _, tt := range tests {
_, errs := ParseMain("k", []byte(tt.src))
if len(errs) != 1 || errs[0].Error() != tt.want {
t.Errorf("%s:\n got %v\n want %s", tt.src, errs, tt.want)
}
}
}
// TestParseMainExclude: krino.conf may hold (exclude ...) forms, which
// apply to every directory.
func TestParseMainExclude(t *testing.T) {
m, errs := ParseMain("krino.conf", []byte("(include \"a\")\n(exclude (type iso))\n(exclude (name \"[.]asc$\"))\n"))
if len(errs) != 0 {
t.Fatal(errs)
}
if len(m.Excludes) != 2 || m.Excludes[0].Text != "(exclude (type iso))" {
t.Fatalf("Excludes = %+v", m.Excludes)
}
if _, errs := ParseMain("krino.conf", []byte("(exclude)")); len(errs) != 1 || !strings.Contains(errs[0].Msg, "(exclude) needs a condition") {
t.Errorf("(exclude): errs %v", errs)
}
}
|