github.com/m3db/m3@v1.5.0/src/m3ninx/index/segment/builder/multi_segments_terms_iter_test.go (about) 1 // Copyright (c) 2019 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package builder 22 23 import ( 24 "fmt" 25 "strconv" 26 "strings" 27 "testing" 28 29 "github.com/m3db/m3/src/m3ninx/doc" 30 "github.com/m3db/m3/src/m3ninx/index/segment" 31 "github.com/m3db/m3/src/m3ninx/postings" 32 33 "github.com/stretchr/testify/require" 34 ) 35 36 func TestTermsIterFromSegmentsDeduplicates(t *testing.T) { 37 segments := []segment.Segment{ 38 newTestSegmentWithDocs(t, []doc.Metadata{ 39 { 40 ID: []byte("foo"), 41 Fields: []doc.Field{ 42 {Name: []byte("fruit"), Value: []byte("apple")}, 43 {Name: []byte("vegetable"), Value: []byte("carrot")}, 44 }, 45 }, 46 }), 47 newTestSegmentWithDocs(t, []doc.Metadata{ 48 { 49 ID: []byte("bar"), 50 Fields: []doc.Field{ 51 {Name: []byte("fruit"), Value: []byte("apple")}, 52 {Name: []byte("color"), Value: []byte("blue")}, 53 {Name: []byte("alpha"), Value: []byte("1.0")}, 54 }, 55 }, 56 { 57 ID: []byte("foo"), 58 Fields: []doc.Field{ 59 {Name: []byte("fruit"), Value: []byte("apple")}, 60 {Name: []byte("vegetable"), Value: []byte("carrot")}, 61 }, 62 }, 63 { 64 ID: []byte("baz"), 65 Fields: []doc.Field{ 66 {Name: []byte("fruit"), Value: []byte("watermelon")}, 67 {Name: []byte("color"), Value: []byte("green")}, 68 {Name: []byte("alpha"), Value: []byte("0.5")}, 69 }, 70 }, 71 { 72 ID: []byte("bux"), 73 Fields: []doc.Field{ 74 {Name: []byte("fruit"), Value: []byte("watermelon")}, 75 {Name: []byte("color"), Value: []byte("red")}, 76 {Name: []byte("alpha"), Value: []byte("0.1")}, 77 }, 78 }, 79 }), 80 } 81 82 builder := NewBuilderFromSegments(testOptions) 83 builder.Reset() 84 require.NoError(t, builder.AddSegments(segments)) 85 iter, err := builder.Terms([]byte("fruit")) 86 require.NoError(t, err) 87 88 assertTermsPostings(t, builder.Docs(), iter, termPostings{ 89 "apple": []int{0, 1}, 90 "watermelon": []int{2, 3}, 91 }) 92 } 93 94 func assertTermsPostings( 95 t *testing.T, 96 docs []doc.Metadata, 97 iter segment.TermsIterator, 98 expected termPostings, 99 ) { 100 actual := toTermPostings(t, iter) 101 require.Equal(t, expected, actual, 102 fmt.Sprintf("actual terms postings:\n%s", 103 termsPostingsString(docs, actual))) 104 } 105 106 func termsPostingsString(docs []doc.Metadata, tp termPostings) string { 107 str := strings.Builder{} 108 for k, ids := range tp { 109 str.WriteString(k) 110 str.WriteString(":\n") 111 for _, id := range ids { 112 str.WriteString("id=") 113 str.WriteString(strconv.Itoa(id)) 114 str.WriteString(", doc=") 115 116 if id >= len(docs) { 117 msg := fmt.Sprintf("cannot find doc: postingsID=%d, numDocs=%d", id, len(docs)) 118 panic(msg) 119 } 120 121 doc := docs[postings.ID(id)] 122 str.WriteString(doc.String()) 123 str.WriteString("\n") 124 } 125 str.WriteString("\n") 126 } 127 return str.String() 128 }