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

Configure Feed

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

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