From c09020c2fb01da24d5befbed78ce3b73b5efbe4c Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Mon, 14 Sep 2026 23:39:37 +0200 Subject: content tests are three-valued: unknown when unreadable or read in part --- internal/cond/eval_test.go | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) (limited to 'internal/cond/eval_test.go') diff --git a/internal/cond/eval_test.go b/internal/cond/eval_test.go index 2e8bcfd..7d796a1 100644 --- a/internal/cond/eval_test.go +++ b/internal/cond/eval_test.go @@ -167,11 +167,11 @@ func TestExplainFormat(t *testing.T) { c, _ := Compile("d.conf", nodes(t, `(type pdf) (or (content "acme ltd") (name "\bacme\b"))`), Options{IgnoreCase: true}) var b strings.Builder c.Explain(f).Format(&b) - want := "no and\n" + + want := "? and\n" + "yes type pdf\n" + - "no or\n" + + "? or\n" + "no name \"\\bacme\\b\"\n" + - "no content \"acme ltd\" (content unreadable: needs pdftotext, not installed)\n" + "? content \"acme ltd\" (content unreadable: needs pdftotext, not installed)\n" if b.String() != want { t.Fatalf("got\n%s\nwant\n%s", b.String(), want) } @@ -257,3 +257,30 @@ func TestCapturesKeepDiacritics(t *testing.T) { t.Errorf("captures with a group that did not take part = %q, want %q", r.Captures, want) } } + +// TestUnreadableContentIsUnknown: a content test that cannot read the file +// is unknown, not false, and and/or/not combine unknowns the way Kleene's +// three-valued logic does: a condition certainly false (or true) whatever +// the text holds is decided, and only one that depends on the text is +// unknown (plan 11, re-review cache F2). A rule matches only a true +// condition; an exclude holds on true or unknown. +func TestUnreadableContentIsUnknown(t *testing.T) { + f := &fake{name: "a.pdf", rawErr: errors.New("larger than max-read")} + cases := []struct { + src string + match, unreadable bool + }{ + {`(and (content "x") (type txt))`, false, false}, + {`(or (content "x") (type pdf))`, true, false}, + {`(not (content "x"))`, false, true}, + {`(and (type pdf) (content "x"))`, false, true}, + {`(or (type txt) (content "x"))`, false, true}, + {`(content "secret") (and (content "other") (type txt))`, false, false}, + {`(not (and (content "x") (type txt)))`, true, false}, + } + for _, c := range cases { + if r := eval(t, c.src, Options{}, f); r.Match != c.match || r.Unreadable != c.unreadable { + t.Errorf("%s: Match %v Unreadable %v; want %v, %v", c.src, r.Match, r.Unreadable, c.match, c.unreadable) + } + } +} -- cgit v1.3