diff options
Diffstat (limited to 'internal/cond')
| -rw-r--r-- | internal/cond/eval.go | 17 | ||||
| -rw-r--r-- | internal/cond/eval_test.go | 14 |
2 files changed, 27 insertions, 4 deletions
diff --git a/internal/cond/eval.go b/internal/cond/eval.go index 3cec110..b0ee828 100644 --- a/internal/cond/eval.go +++ b/internal/cond/eval.go @@ -33,6 +33,11 @@ type Result struct { Captures []string // submatches of the first true, non-negated name test: [0] whole match, [1:] groups Reasons []string // what made it true, e.g. `type pdf`, `content "acme ltd"`, `name "\bacme\b"` Warnings []string // e.g. `content unreadable: needs pdftotext, not installed` + + // Unreadable is true when evaluation reached a content test that could + // not read the file. The test counts as false; an exclude uses this to + // hold anyway (review M11). + Unreadable bool } // Trace is the full evaluation of every node, for krino explain. @@ -47,9 +52,10 @@ type Trace struct { // first true, non-negated name test, and warnings de-duplicated in // first-seen order. type evalCtx struct { - captures []string - warned map[string]bool - warnings []string + captures []string + warned map[string]bool + warnings []string + unreadable bool } // warn records msg unless it has already been recorded. @@ -75,7 +81,7 @@ func (c *Cond) Eval(f Facts) Result { } ctx := &evalCtx{} match, reasons := c.eval(c.root, f, ctx, false) - return Result{Match: match, Captures: ctx.captures, Reasons: reasons, Warnings: ctx.warnings} + return Result{Match: match, Captures: ctx.captures, Reasons: reasons, Warnings: ctx.warnings, Unreadable: ctx.unreadable} } // eval evaluates one node against f, short-circuiting and/or in child @@ -122,6 +128,9 @@ func (c *Cond) eval(n *node, f Facts, ctx *evalCtx, negated bool) (bool, []strin ok, reason, warn, caps := c.evalLeaf(n, f) if warn != "" { ctx.warn(warn) + if n.kind == kContent { + ctx.unreadable = true + } } if !ok { return false, nil diff --git a/internal/cond/eval_test.go b/internal/cond/eval_test.go index 8891de7..88612ac 100644 --- a/internal/cond/eval_test.go +++ b/internal/cond/eval_test.go @@ -226,3 +226,17 @@ func TestNegatedCombinatorReason(t *testing.T) { t.Errorf("negated leaf = %+v, want its own label unchanged: %q", r, "not matched") } } + +// TestEvalReportsUnreadableContent: Result.Unreadable says a content test +// was reached and could not read the file - what lets an exclude fail +// closed (review M11) - and stays false when evaluation never reached the +// content test. +func TestEvalReportsUnreadableContent(t *testing.T) { + f := &fake{name: "a.pdf", rawErr: errors.New("larger than max-read")} + if r := eval(t, `(and (type pdf) (content "x"))`, Options{}, f); r.Match || !r.Unreadable { + t.Errorf("reached: Match %v Unreadable %v; want false, true", r.Match, r.Unreadable) + } + if r := eval(t, `(or (name "^a") (content "x"))`, Options{}, f); !r.Match || r.Unreadable { + t.Errorf("not reached: Match %v Unreadable %v; want true, false", r.Match, r.Unreadable) + } +} |
