github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/m3ninx/index/segment/mem/reader_test.go (about) 1 // Copyright (c) 2018 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 mem 22 23 import ( 24 re "regexp" 25 "testing" 26 27 "github.com/m3db/m3/src/m3ninx/doc" 28 "github.com/m3db/m3/src/m3ninx/index" 29 "github.com/m3db/m3/src/m3ninx/postings" 30 "github.com/m3db/m3/src/m3ninx/postings/roaring" 31 32 "github.com/golang/mock/gomock" 33 "github.com/stretchr/testify/require" 34 ) 35 36 func TestReaderMatchExact(t *testing.T) { 37 mockCtrl := gomock.NewController(t) 38 defer mockCtrl.Finish() 39 40 maxID := postings.ID(55) 41 42 name, value := []byte("apple"), []byte("red") 43 postingsList := roaring.NewPostingsList() 44 require.NoError(t, postingsList.Insert(postings.ID(42))) 45 require.NoError(t, postingsList.Insert(postings.ID(50))) 46 require.NoError(t, postingsList.Insert(postings.ID(57))) 47 48 segment := NewMockReadableSegment(mockCtrl) 49 gomock.InOrder( 50 segment.EXPECT().matchTerm(name, value).Return(postingsList, nil), 51 ) 52 53 reader := newReader(segment, readerDocRange{0, maxID}, postings.NewPool(nil, roaring.NewPostingsList)) 54 55 actual, err := reader.MatchTerm(name, value) 56 require.NoError(t, err) 57 require.True(t, postingsList.Equal(actual)) 58 59 require.NoError(t, reader.Close()) 60 } 61 62 func TestReaderMatchRegex(t *testing.T) { 63 mockCtrl := gomock.NewController(t) 64 defer mockCtrl.Finish() 65 66 maxID := postings.ID(55) 67 68 name, regexp := []byte("apple"), []byte("r.*") 69 compiled := re.MustCompile(string(regexp)) 70 postingsList := roaring.NewPostingsList() 71 require.NoError(t, postingsList.Insert(postings.ID(42))) 72 require.NoError(t, postingsList.Insert(postings.ID(50))) 73 require.NoError(t, postingsList.Insert(postings.ID(57))) 74 75 segment := NewMockReadableSegment(mockCtrl) 76 gomock.InOrder( 77 segment.EXPECT().matchRegexp(name, compiled).Return(postingsList, nil), 78 ) 79 80 reader := newReader(segment, readerDocRange{0, maxID}, postings.NewPool(nil, roaring.NewPostingsList)) 81 actual, err := reader.MatchRegexp(name, index.CompiledRegex{Simple: compiled}) 82 require.NoError(t, err) 83 require.True(t, postingsList.Equal(actual)) 84 85 require.NoError(t, reader.Close()) 86 } 87 88 func TestReaderMatchAll(t *testing.T) { 89 mockCtrl := gomock.NewController(t) 90 defer mockCtrl.Finish() 91 92 var ( 93 minID = postings.ID(42) 94 maxID = postings.ID(47) 95 ) 96 97 postingsList := roaring.NewPostingsList() 98 require.NoError(t, postingsList.Insert(postings.ID(42))) 99 require.NoError(t, postingsList.Insert(postings.ID(43))) 100 require.NoError(t, postingsList.Insert(postings.ID(44))) 101 require.NoError(t, postingsList.Insert(postings.ID(45))) 102 require.NoError(t, postingsList.Insert(postings.ID(46))) 103 104 reader := newReader(nil, readerDocRange{minID, maxID}, postings.NewPool(nil, roaring.NewPostingsList)) 105 106 actual, err := reader.MatchAll() 107 require.NoError(t, err) 108 require.True(t, postingsList.Equal(actual)) 109 110 require.NoError(t, reader.Close()) 111 } 112 113 func TestReaderDocs(t *testing.T) { 114 mockCtrl := gomock.NewController(t) 115 defer mockCtrl.Finish() 116 117 maxID := postings.ID(50) 118 docs := []doc.Metadata{ 119 { 120 Fields: []doc.Field{ 121 { 122 Name: []byte("apple"), 123 Value: []byte("red"), 124 }, 125 }, 126 }, 127 { 128 Fields: []doc.Field{ 129 { 130 Name: []byte("banana"), 131 Value: []byte("yellow"), 132 }, 133 }, 134 }, 135 } 136 137 segment := NewMockReadableSegment(mockCtrl) 138 gomock.InOrder( 139 segment.EXPECT().getDoc(postings.ID(42)).Return(docs[0], nil), 140 segment.EXPECT().getDoc(postings.ID(47)).Return(docs[1], nil), 141 ) 142 143 postingsList := roaring.NewPostingsList() 144 require.NoError(t, postingsList.Insert(postings.ID(42))) 145 require.NoError(t, postingsList.Insert(postings.ID(47))) 146 require.NoError(t, postingsList.Insert(postings.ID(57))) // IDs past maxID should be ignored. 147 148 reader := newReader(segment, readerDocRange{0, maxID}, postings.NewPool(nil, roaring.NewPostingsList)) 149 150 iter, err := reader.MetadataIterator(postingsList) 151 require.NoError(t, err) 152 153 actualDocs := make([]doc.Metadata, 0, len(docs)) 154 for iter.Next() { 155 actualDocs = append(actualDocs, iter.Current()) 156 } 157 158 require.NoError(t, iter.Err()) 159 require.NoError(t, iter.Close()) 160 161 require.Equal(t, docs, actualDocs) 162 163 require.NoError(t, reader.Close()) 164 } 165 166 func TestReaderAllDocs(t *testing.T) { 167 mockCtrl := gomock.NewController(t) 168 defer mockCtrl.Finish() 169 170 maxID := postings.ID(2) 171 docs := []doc.Metadata{ 172 { 173 Fields: []doc.Field{ 174 { 175 Name: []byte("apple"), 176 Value: []byte("red"), 177 }, 178 }, 179 }, 180 { 181 Fields: []doc.Field{ 182 { 183 Name: []byte("banana"), 184 Value: []byte("yellow"), 185 }, 186 }, 187 }, 188 } 189 190 segment := NewMockReadableSegment(mockCtrl) 191 gomock.InOrder( 192 segment.EXPECT().getDoc(postings.ID(0)).Return(docs[0], nil), 193 segment.EXPECT().getDoc(postings.ID(1)).Return(docs[1], nil), 194 ) 195 196 reader := newReader(segment, readerDocRange{0, maxID}, postings.NewPool(nil, roaring.NewPostingsList)) 197 iter, err := reader.AllDocs() 198 require.NoError(t, err) 199 200 actualDocs := make([]doc.Metadata, 0, len(docs)) 201 for iter.Next() { 202 actualDocs = append(actualDocs, iter.Current()) 203 } 204 205 require.NoError(t, iter.Err()) 206 require.NoError(t, iter.Close()) 207 208 require.Equal(t, docs, actualDocs) 209 210 require.NoError(t, reader.Close()) 211 }