(t *testing.T, tc evalTC)
| 21 | const testIterations = 5 |
| 22 | |
| 23 | func testEvaluator(t *testing.T, tc evalTC) { |
| 24 | t.Helper() |
| 25 | |
| 26 | t.Run(tc.query, func(t *testing.T) { |
| 27 | ast, err := Parse(tc.query) |
| 28 | require.NoError(t, err) |
| 29 | |
| 30 | // run tests multiple times to ensure optimizations like regex caching are working |
| 31 | for range testIterations { |
| 32 | // clone input to confirm it doesn't get modified |
| 33 | cloneIn := make([]*Spanset, len(tc.input)) |
| 34 | for i := range tc.input { |
| 35 | cloneIn[i] = tc.input[i].clone() |
| 36 | cloneIn[i].Spans = append([]Span(nil), tc.input[i].Spans...) |
| 37 | } |
| 38 | |
| 39 | actual, err := ast.Pipeline.evaluate(tc.input) |
| 40 | require.NoError(t, err) |
| 41 | |
| 42 | // sort expected/actual spansets. grouping requires this b/c map iteration makes the output |
| 43 | // non-deterministic. |
| 44 | makeSort := func(ss []*Spanset) func(i, j int) bool { |
| 45 | return func(i, j int) bool { |
| 46 | return bytes.Compare(ss[i].Spans[0].ID(), ss[j].Spans[0].ID()) < 0 |
| 47 | } |
| 48 | } |
| 49 | sort.Slice(actual, makeSort(actual)) |
| 50 | sort.Slice(tc.output, makeSort(tc.output)) |
| 51 | |
| 52 | require.Equal(t, tc.output, actual) |
| 53 | require.Equal(t, tc.input, cloneIn) |
| 54 | } |
| 55 | }) |
| 56 | } |
| 57 | |
| 58 | func TestSpansetFilter_matches(t *testing.T) { |
| 59 | tests := []struct { |
no test coverage detected