github.com/m3db/m3@v1.5.0/src/m3ninx/index/segment/builder/multi_segments_builder_test.go (about) 1 // Copyright (c) 2020 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 "sort" 26 "strconv" 27 "testing" 28 29 "github.com/golang/mock/gomock" 30 "github.com/stretchr/testify/require" 31 32 "github.com/m3db/m3/src/m3ninx/doc" 33 "github.com/m3db/m3/src/m3ninx/index" 34 "github.com/m3db/m3/src/m3ninx/index/segment" 35 "github.com/m3db/m3/src/m3ninx/postings" 36 ) 37 38 // TestMultiSegmentsBuilderSortedBySizeDescending ensures that segments in the 39 // multi segments builder are in descending order by size for optimal compaction. 40 func TestMultiSegmentsBuilderSortedBySizeDescending(t *testing.T) { 41 ctrl := gomock.NewController(t) 42 defer ctrl.Finish() 43 44 b := NewBuilderFromSegments(NewOptions()).(*builderFromSegments) 45 46 numSegments := 5 47 segs := make([]segment.Segment, 0, numSegments) 48 for i := 1; i <= numSegments; i++ { 49 pi := postings.NewMockIterator(ctrl) 50 gomock.InOrder( 51 pi.EXPECT().Next().Return(true), 52 pi.EXPECT().Current().Return(postings.ID(0)), 53 pi.EXPECT().Next().Return(false), 54 pi.EXPECT().Close().Return(nil), 55 ) 56 r := segment.NewMockReader(ctrl) 57 it := index.NewIDDocIterator(r, pi) 58 gomock.InOrder( 59 r.EXPECT().AllDocs().Return(it, nil), 60 r.EXPECT().Metadata(postings.ID(0)).Return(doc.Metadata{ 61 ID: []byte("foo" + strconv.Itoa(i)), 62 Fields: []doc.Field{ 63 { 64 Name: []byte("bar"), 65 Value: []byte("baz"), 66 }, 67 }, 68 }, nil), 69 r.EXPECT().Close().Return(nil), 70 ) 71 72 seg := segment.NewMockSegment(ctrl) 73 seg.EXPECT().Reader().Return(r, nil) 74 seg.EXPECT().Size().Return(int64(i * 10)).AnyTimes() 75 seg.EXPECT().TermsIterable().Return(nil) 76 segs = append(segs, seg) 77 } 78 require.NoError(t, b.AddSegments(segs)) 79 80 // Sort segments in descending order by size. 81 sort.Slice(segs, func(i, j int) bool { 82 return segs[i].Size() > segs[j].Size() 83 }) 84 85 actualSegs := make([]segment.Segment, 0, numSegments) 86 for _, segMD := range b.segments { 87 actualSegs = append(actualSegs, segMD.segment) 88 } 89 90 for i, segMD := range b.segments { 91 actualSize := segMD.segment.Size() 92 require.Equal(t, segs[i].Size(), actualSize) 93 94 if i > 0 { 95 // Check that offset is going up. 96 actualPrevOffset := b.segments[i-1].offset 97 actualCurrOffset := b.segments[i].offset 98 require.True(t, actualCurrOffset > actualPrevOffset, 99 fmt.Sprintf("expected=(actualCurrOffset > actualPrevOffset)\n"+ 100 "actual=(actualCurrOffset=%d, actualPrevOffset=%d)\n", 101 actualCurrOffset, actualPrevOffset)) 102 } 103 } 104 }