forked from sourcegraph/zoekt
-
Notifications
You must be signed in to change notification settings - Fork 1
/
limit_test.go
163 lines (148 loc) · 4.52 KB
/
limit_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package zoekt
import (
"bytes"
"fmt"
"testing"
"github.com/google/go-cmp/cmp"
)
func TestLimitMatches(t *testing.T) {
cases := []struct {
// Represents a SearchResult with three dimensions:
// 1. outer slice is `Files`
// 2. inner slice is `{Chunk,Line}Matches`
// 3. value is the length of `Ranges`/`LineFragments`
in [][]int
limit int
expected [][]int
}{{
in: [][]int{{1, 1, 1}},
limit: 1,
expected: [][]int{{1}},
}, {
in: [][]int{{1, 1, 1}},
limit: 3,
expected: [][]int{{1, 1, 1}},
}, {
in: [][]int{{1, 1, 1}},
limit: 4,
expected: [][]int{{1, 1, 1}},
}, {
in: [][]int{{2, 2, 2}},
limit: 4,
expected: [][]int{{2, 2}},
}, {
in: [][]int{{2, 2, 2}},
limit: 3,
expected: [][]int{{2, 1}},
}, {
in: [][]int{{2, 2, 2}},
limit: 1,
expected: [][]int{{1}},
}, {
in: [][]int{{1}, {1}},
limit: 2,
expected: [][]int{{1}, {1}},
}, {
in: [][]int{{1}, {1}},
limit: 1,
expected: [][]int{{1}},
}, {
in: [][]int{{1}, {1, 3}},
limit: 4,
expected: [][]int{{1}, {1, 2}},
}, {
in: [][]int{{1}, {2, 2}, {3, 3, 3}},
limit: 4,
expected: [][]int{{1}, {2, 1}},
}}
for _, tc := range cases {
t.Run("ChunkMatches", func(t *testing.T) {
// Generate a ChunkMatch suitable for testing `LimitChunkMatches`.
generateChunkMatch := func(numRanges, lineNumber int) (ChunkMatch, int) {
cm := ChunkMatch{SymbolInfo: make([]*Symbol, numRanges)}
// To simplify testing, we generate Content and the associated
// Ranges with fixed logic: each ChunkMatch has 1 line of
// context, and each Range spans two lines. It'd probably be
// better to do some kind of property-based testing, but this is
// alright.
// 1 line of context.
cm.Content = append(cm.Content, []byte("context\n")...)
for i := 0; i < numRanges; i += 1 {
cm.Ranges = append(cm.Ranges, Range{
// We only provide LineNumber as that's all that's
// relevant.
Start: Location{LineNumber: uint32(lineNumber + (2 * i) + 1)},
End: Location{LineNumber: uint32(lineNumber + (2 * i) + 2)},
})
cm.Content = append(cm.Content, []byte(fmt.Sprintf("range%dStart\nrange%dEnd\n", i, i))...)
}
// 1 line of context. Content in zoekt notably just does not
// contain a trailing newline.
cm.Content = append(cm.Content, []byte("context")...)
// Next Chunk starts two lines past the number of lines we just
// added.
return cm, lineNumber + (2 * numRanges) + 4
}
res := SearchResult{}
for _, file := range tc.in {
fm := FileMatch{}
lineNumber := 0
for _, numRanges := range file {
var cm ChunkMatch
cm, lineNumber = generateChunkMatch(numRanges, lineNumber)
fm.ChunkMatches = append(fm.ChunkMatches, cm)
}
res.Files = append(res.Files, fm)
}
res.Files = SortAndTruncateFiles(res.Files, &SearchOptions{
MaxMatchDisplayCount: tc.limit,
ChunkMatches: true,
})
var got [][]int
for _, fm := range res.Files {
var matches []int
for _, cm := range fm.ChunkMatches {
if len(cm.Ranges) != len(cm.SymbolInfo) {
t.Errorf("Expected Ranges and SymbolInfo to be the same size, but got %d and %d", len(cm.Ranges), len(cm.SymbolInfo))
}
// Using the logic from generateChunkMatch.
expectedNewlines := 1 + (len(cm.Ranges) * 2)
actualNewlines := bytes.Count(cm.Content, []byte("\n"))
if actualNewlines != expectedNewlines {
t.Errorf("Expected Content to have %d newlines but got %d", expectedNewlines, actualNewlines)
}
matches = append(matches, len(cm.Ranges))
}
got = append(got, matches)
}
if !cmp.Equal(tc.expected, got) {
t.Errorf("Expected %v but got %v", tc.expected, got)
}
})
t.Run("LineMatches", func(t *testing.T) {
res := SearchResult{}
for _, file := range tc.in {
fm := FileMatch{}
for _, numFragments := range file {
fm.LineMatches = append(fm.LineMatches, LineMatch{LineFragments: make([]LineFragmentMatch, numFragments)})
}
res.Files = append(res.Files, fm)
}
res.Files = SortAndTruncateFiles(res.Files, &SearchOptions{
MaxMatchDisplayCount: tc.limit,
ChunkMatches: false,
})
var got [][]int
for _, fm := range res.Files {
var matches []int
for _, lm := range fm.LineMatches {
matches = append(matches, len(lm.LineFragments))
}
got = append(got, matches)
}
if !cmp.Equal(tc.expected, got) {
t.Errorf("Expected %v but got %v", tc.expected, got)
}
})
}
}