github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/x/xio/block_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 xio 22 23 import ( 24 "fmt" 25 "testing" 26 "time" 27 28 "github.com/golang/mock/gomock" 29 "github.com/stretchr/testify/assert" 30 "github.com/stretchr/testify/require" 31 32 "github.com/m3db/m3/src/dbnode/ts" 33 "github.com/m3db/m3/src/x/checked" 34 xtime "github.com/m3db/m3/src/x/time" 35 ) 36 37 var ( 38 start = xtime.Now().Truncate(time.Minute) 39 blockSize = time.Minute 40 errTest = fmt.Errorf("err") 41 ) 42 43 func buildBlock(t *testing.T) (BlockReader, *MockSegmentReader) { 44 ctrl := gomock.NewController(t) 45 defer ctrl.Finish() 46 reader := NewMockSegmentReader(ctrl) 47 return BlockReader{reader, start, blockSize}, reader 48 } 49 50 func TestCloneBlock(t *testing.T) { 51 ctrl := gomock.NewController(t) 52 defer ctrl.Finish() 53 54 seg := ts.Segment{} 55 56 reader := NewMockSegmentReader(ctrl) 57 reader.EXPECT().Read64().Return(uint64(0), byte(0), errTest).Times(1) 58 reader.EXPECT().Read64().Return(uint64(123456), byte(10), nil).Times(1) 59 reader.EXPECT().Reset(seg).Return().Times(1) 60 61 clonedReader := NewMockSegmentReader(ctrl) 62 clonedReader.EXPECT().Read64().Return(uint64(1337), byte(2), nil).Times(1) 63 64 reader.EXPECT().Clone(nil).Return(clonedReader, nil).Times(1) 65 66 b := BlockReader{ 67 SegmentReader: reader, 68 Start: start, 69 BlockSize: blockSize, 70 } 71 72 word, n, err := b.Read64() 73 require.Equal(t, uint64(0), word) 74 require.Equal(t, byte(0), n) 75 require.Equal(t, errTest, err) 76 77 word, n, err = b.Read64() 78 require.Equal(t, uint64(123456), word) 79 require.Equal(t, byte(10), n) 80 require.NoError(t, err) 81 82 b2, err := b.CloneBlock(nil) 83 require.NoError(t, err) 84 85 startReset := start.Add(time.Hour) 86 blockSizeReset := time.Hour * 5 87 88 b.ResetWindowed(seg, startReset, blockSizeReset) 89 require.Equal(t, b.Start, startReset) 90 require.Equal(t, b.BlockSize, blockSizeReset) 91 92 require.Equal(t, b2.Start, start) 93 require.Equal(t, b2.BlockSize, blockSize) 94 95 word, n, err = b2.Read64() 96 97 require.Equal(t, uint64(1337), word) 98 require.Equal(t, byte(2), n) 99 require.NoError(t, err) 100 } 101 102 func TestBlockReaderStartEnd(t *testing.T) { 103 br, _ := buildBlock(t) 104 assert.Equal(t, br.Start, start) 105 assert.Equal(t, br.BlockSize, blockSize) 106 } 107 108 func TestBlockReaderClone(t *testing.T) { 109 br, sr := buildBlock(t) 110 sr.EXPECT().Clone(nil).Return(nil, errTest).Times(1) 111 r, err := br.Clone(nil) 112 require.Nil(t, r) 113 require.Equal(t, err, errTest) 114 115 sr.EXPECT().Clone(nil).Return(sr, nil).Times(1) 116 r, err = br.Clone(nil) 117 require.NoError(t, err) 118 119 require.Equal(t, r, sr) 120 require.Equal(t, br.Start, start) 121 require.Equal(t, br.BlockSize, blockSize) 122 } 123 124 func TestBlockReaderRead(t *testing.T) { 125 br, sr := buildBlock(t) 126 127 sr.EXPECT().Read64().Return(uint64(0), byte(0), errTest).Times(1) 128 word, n, err := br.Read64() 129 require.Equal(t, uint64(0), word) 130 require.Equal(t, byte(0), n) 131 require.Equal(t, err, errTest) 132 133 sr.EXPECT().Read64().Return(uint64(100), byte(1), nil).Times(1) 134 word, n, err = br.Read64() 135 require.Equal(t, uint64(100), word) 136 require.Equal(t, byte(1), n) 137 require.NoError(t, err) 138 } 139 140 func TestBlockReaderFinalize(t *testing.T) { 141 br, sr := buildBlock(t) 142 sr.EXPECT().Finalize().Times(1) 143 br.Finalize() 144 } 145 146 func TestBlockReaderSegment(t *testing.T) { 147 br, sr := buildBlock(t) 148 segment := ts.Segment{} 149 sr.EXPECT().Segment().Return(segment, errTest).Times(1) 150 _, err := br.Segment() 151 require.Equal(t, err, errTest) 152 153 sr.EXPECT().Segment().Return(segment, nil).Times(1) 154 seg, err := br.Segment() 155 require.Equal(t, seg, segment) 156 require.NoError(t, err) 157 } 158 159 func TestBlockReaderReset(t *testing.T) { 160 br, sr := buildBlock(t) 161 segment := ts.Segment{} 162 sr.EXPECT().Reset(segment).Times(1) 163 br.Reset(segment) 164 } 165 166 func TestBlockReaderResetWindowed(t *testing.T) { 167 br, sr := buildBlock(t) 168 segment := ts.Segment{} 169 sr.EXPECT().Reset(segment).Times(1) 170 startReset := start.Add(time.Hour) 171 blockSizeReset := time.Hour * 5 172 br.ResetWindowed(segment, startReset, blockSizeReset) 173 require.Equal(t, br.Start, startReset) 174 require.Equal(t, br.BlockSize, blockSizeReset) 175 } 176 177 func TestBlockIsEmpty(t *testing.T) { 178 assert.True(t, EmptyBlockReader.IsEmpty()) 179 assert.True(t, BlockReader{}.IsEmpty()) 180 181 assert.False(t, BlockReader{ 182 Start: start, 183 }.IsEmpty()) 184 assert.False(t, BlockReader{ 185 BlockSize: blockSize, 186 }.IsEmpty()) 187 188 block, reader := buildBlock(t) 189 assert.False(t, BlockReader{ 190 SegmentReader: reader, 191 }.IsEmpty()) 192 assert.False(t, block.IsEmpty()) 193 } 194 195 func TestBlockIsNotEmpty(t *testing.T) { 196 assert.False(t, EmptyBlockReader.IsNotEmpty()) 197 assert.False(t, BlockReader{}.IsNotEmpty()) 198 199 assert.True(t, BlockReader{ 200 Start: start, 201 }.IsNotEmpty()) 202 assert.True(t, BlockReader{ 203 BlockSize: blockSize, 204 }.IsNotEmpty()) 205 206 block, reader := buildBlock(t) 207 assert.True(t, BlockReader{ 208 SegmentReader: reader, 209 }.IsNotEmpty()) 210 assert.True(t, block.IsNotEmpty()) 211 } 212 213 func TestFilterEmptyBlockReadersSliceOfSlicesInPlace(t *testing.T) { 214 var ( 215 head = checked.NewBytes([]byte("some-data"), checked.NewBytesOptions()) 216 segment = ts.NewSegment(head, nil, 0, 0) 217 segmentReader = NewSegmentReader(segment) 218 ) 219 notEmpty := BlockReader{ 220 SegmentReader: segmentReader, 221 } 222 223 noneEmpty := []BlockReader{notEmpty} 224 someEmpty := []BlockReader{notEmpty, EmptyBlockReader} 225 allEmpty := []BlockReader{EmptyBlockReader} 226 unfiltered := [][]BlockReader{noneEmpty, someEmpty, allEmpty} 227 filtered, err := FilterEmptyBlockReadersSliceOfSlicesInPlace(unfiltered) 228 require.NoError(t, err) 229 require.Equal(t, 2, len(filtered)) 230 require.Equal(t, 1, len(filtered[0])) 231 require.Equal(t, 1, len(filtered[1])) 232 } 233 234 func TestFilterEmptyBlockReadersInPlace(t *testing.T) { 235 var ( 236 head = checked.NewBytes([]byte("some-data"), checked.NewBytesOptions()) 237 segment = ts.NewSegment(head, nil, 0, 0) 238 segmentReader = NewSegmentReader(segment) 239 ) 240 notEmpty := BlockReader{ 241 SegmentReader: segmentReader, 242 } 243 244 unfiltered := []BlockReader{notEmpty, EmptyBlockReader} 245 filtered, err := FilterEmptyBlockReadersInPlace(unfiltered) 246 require.NoError(t, err) 247 require.Equal(t, 1, len(filtered)) 248 }