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