github.com/m3db/m3@v1.5.0/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  }