fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

Select the types of activity you want to include in your feed.

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