// SPDX-License-Identifier: GPL-3.0-or-later package config import "testing" // FuzzPrintRule: whatever rule text parses, printing it gives text that // parses to the same rule and prints identically, so a GUI that rewrites one // rule never changes what it means. func FuzzPrintRule(f *testing.F) { for _, s := range []string{ `(rule "a" (move "Out"))`, `(rule "b" (when (not (name "^x"))) (copy "~/b") (delete))`, `(rule "c" (when (duplicate "~/d")) (move "Dupes") (stop))`, `(rule "d" (when (and (type pdf) (or (size > 1M) (age < 2d)))) (rename "{stem}-x{ext}"))`, `(rule "e" (case strict) (fold no) (on-conflict overwrite) (copy "X"))`, } { f.Add(s) } f.Fuzz(func(t *testing.T, s string) { dir, errs := ParseDir("dl", "dl.conf", []byte("(path \"/tmp\")\n"+s)) if len(errs) > 0 || len(dir.Rules) != 1 { return } out := PrintRule(dir.Rules[0]) again, errs := ParseDir("dl", "dl.conf", []byte("(path \"/tmp\")\n"+out)) if len(errs) > 0 || len(again.Rules) != 1 { t.Fatalf("printed %q does not parse: %v", out, errs) } if got := PrintRule(again.Rules[0]); got != out { t.Fatalf("printing %q is not stable: %q", out, got) } a, b := dir.Rules[0], again.Rules[0] if a.Name != b.Name || a.HasWhen != b.HasWhen || a.Stop != b.Stop || len(a.Actions) != len(b.Actions) || len(a.When) != len(b.When) { t.Fatalf("printing %q changed the rule: %+v vs %+v", out, a, b) } for i := range a.Actions { if a.Actions[i].Kind != b.Actions[i].Kind || a.Actions[i].Arg != b.Actions[i].Arg { t.Fatalf("printing %q changed action %d: %+v vs %+v", out, i, a.Actions[i], b.Actions[i]) } } }) }