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

Configure Feed

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

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