github.com/m3db/m3@v1.5.0/src/dbnode/storage/block/block_proto_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 block 22 23 import ( 24 "testing" 25 "time" 26 27 "github.com/golang/mock/gomock" 28 "github.com/m3db/m3/src/dbnode/namespace" 29 "github.com/m3db/m3/src/dbnode/testdata/prototest" 30 "github.com/m3db/m3/src/dbnode/ts" 31 "github.com/m3db/m3/src/dbnode/x/xio" 32 "github.com/m3db/m3/src/x/ident" 33 xtime "github.com/m3db/m3/src/x/time" 34 35 "github.com/stretchr/testify/require" 36 ) 37 38 var ( 39 testNamespace = ident.StringID("block_test_ns") 40 testSchemaHistory = prototest.NewSchemaHistory() 41 testSchema = prototest.NewMessageDescriptor(testSchemaHistory) 42 testSchemaDesc = namespace.GetTestSchemaDescr(testSchema) 43 testProtoMessages = prototest.NewProtoTestMessages(testSchema) 44 ) 45 46 // TestDatabaseBlockMergeProto lazily merges two blocks and verifies that the correct 47 // data is returned. 48 func TestDatabaseBlockMergeProto(t *testing.T) { 49 ctrl := gomock.NewController(t) 50 defer ctrl.Finish() 51 52 // Test proto messages 53 piter := prototest.NewProtoMessageIterator(testProtoMessages) 54 55 // Test data 56 curr := xtime.Now() 57 data := []ts.Datapoint{ 58 { 59 TimestampNanos: curr, 60 Value: 0, 61 }, 62 { 63 TimestampNanos: curr.Add(time.Second), 64 Value: 0, 65 }, 66 } 67 durations := []time.Duration{ 68 time.Minute, 69 time.Hour, 70 } 71 72 testNamespaceCtx := namespace.Context{ 73 ID: testNamespace, 74 Schema: testSchemaDesc, 75 } 76 77 // Setup encoding pools. 78 blockOpts := NewOptions(). 79 SetReaderIteratorPool(prototest.ProtoPools.ReaderIterPool). 80 SetEncoderPool(prototest.ProtoPools.EncoderPool). 81 SetMultiReaderIteratorPool(prototest.ProtoPools.MultiReaderIterPool) 82 83 // Create the two blocks we plan to merge 84 encoder := blockOpts.EncoderPool().Get() 85 86 encoder.Reset(data[0].TimestampNanos, 10, testSchemaDesc) 87 encoder.Encode(data[0], xtime.Second, piter.Next()) 88 seg := encoder.Discard() 89 block1 := NewDatabaseBlock(data[0].TimestampNanos, durations[0], seg, blockOpts, testNamespaceCtx).(*dbBlock) 90 91 encoder.Reset(data[1].TimestampNanos, 10, testSchemaDesc) 92 encoder.Encode(data[1], xtime.Second, piter.Next()) 93 seg = encoder.Discard() 94 block2 := NewDatabaseBlock(data[1].TimestampNanos, durations[1], seg, blockOpts, testNamespaceCtx).(*dbBlock) 95 96 // Lazily merge the two blocks 97 block1.Merge(block2) 98 99 // BlockSize should not change 100 require.Equal(t, durations[0], block1.BlockSize()) 101 102 // Try and read the data back and verify it looks good 103 depCtx := block1.opts.ContextPool().Get() 104 stream, err := block1.Stream(depCtx) 105 require.NoError(t, err) 106 seg, err = stream.Segment() 107 require.NoError(t, err) 108 reader := xio.NewSegmentReader(seg) 109 iter := blockOpts.ReaderIteratorPool().Get() 110 iter.Reset(reader, testSchemaDesc) 111 112 piter.Reset() 113 i := 0 114 for iter.Next() { 115 dp, _, annotation := iter.Current() 116 require.True(t, data[i].Equal(dp)) 117 prototest.RequireEqual(t, testSchema, piter.Next(), annotation) 118 i++ 119 } 120 require.NoError(t, iter.Err()) 121 require.Equal(t, 2, i) 122 123 // Make sure the checksum was updated 124 mergedChecksum, err := block1.Checksum() 125 require.NoError(t, err) 126 require.Equal(t, seg.CalculateChecksum(), mergedChecksum) 127 128 depCtx.BlockingClose() 129 block1.Close() 130 block2.Close() 131 }