github.com/m3db/m3@v1.5.0/src/dbnode/integration/roundtrip_test.go (about) 1 // Copyright (c) 2016 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 integration 22 23 import ( 24 "testing" 25 "time" 26 27 "github.com/m3db/m3/src/dbnode/integration/generate" 28 "github.com/m3db/m3/src/dbnode/namespace" 29 "github.com/m3db/m3/src/dbnode/testdata/prototest" 30 xtime "github.com/m3db/m3/src/x/time" 31 32 "github.com/stretchr/testify/assert" 33 "github.com/stretchr/testify/require" 34 ) 35 36 type setTestOptions func(t *testing.T, testOpts TestOptions) TestOptions 37 38 func TestRoundtrip(t *testing.T) { 39 testRoundtrip(t, nil, nil) 40 } 41 42 func TestProtoRoundtrip(t *testing.T) { 43 testRoundtrip(t, setProtoTestOptions, setProtoTestInputConfig) 44 } 45 46 func setProtoTestInputConfig(inputData []generate.BlockConfig) { 47 for i := 0; i < len(inputData); i++ { 48 inputData[i].AnnGen = testProtoIter 49 } 50 } 51 52 func setProtoTestOptions(t *testing.T, testOpts TestOptions) TestOptions { 53 var namespaces []namespace.Metadata 54 for _, nsMeta := range testOpts.Namespaces() { 55 nsOpts := nsMeta.Options().SetSchemaHistory(testSchemaHistory) 56 md, err := namespace.NewMetadata(nsMeta.ID(), nsOpts) 57 require.NoError(t, err) 58 namespaces = append(namespaces, md) 59 } 60 return testOpts.SetProtoEncoding(true). 61 SetNamespaces(namespaces). 62 SetAssertTestDataEqual(assertProtoDataEqual) 63 } 64 65 func assertProtoDataEqual(t *testing.T, expected, actual []generate.TestValue) bool { 66 if len(expected) != len(actual) { 67 return false 68 } 69 for i := 0; i < len(expected); i++ { 70 if !assert.Equal(t, expected[i].TimestampNanos, actual[i].TimestampNanos) { 71 return false 72 } 73 if !assert.Equal(t, expected[i].Value, actual[i].Value) { 74 return false 75 } 76 if !prototest.ProtoEqual(testSchema, expected[i].Annotation, actual[i].Annotation) { 77 return false 78 } 79 } 80 return true 81 } 82 83 func testRoundtrip(t *testing.T, setTestOpts setTestOptions, updateInputConfig generate.UpdateBlockConfig) { 84 // if testing.Short() { 85 // t.SkipNow() // Just skip if we're doing a short run 86 // } 87 // Test setup 88 testOpts := NewTestOptions(t). 89 SetTickMinimumInterval(time.Second). 90 SetUseTChannelClientForReading(false). 91 SetUseTChannelClientForWriting(false) 92 if setTestOpts != nil { 93 testOpts = setTestOpts(t, testOpts) 94 } 95 testSetup, err := NewTestSetup(t, testOpts, nil) 96 require.NoError(t, err) 97 defer testSetup.Close() 98 99 // Input data setup 100 blockSize := namespace.NewOptions().RetentionOptions().BlockSize() 101 now := testSetup.NowFn()() 102 inputData := []generate.BlockConfig{ 103 {IDs: []string{"foo", "bar"}, NumPoints: 100, Start: now}, 104 {IDs: []string{"foo", "baz"}, NumPoints: 50, Start: now.Add(blockSize)}, 105 } 106 if updateInputConfig != nil { 107 updateInputConfig(inputData) 108 } 109 110 // Start the server 111 log := testSetup.StorageOpts().InstrumentOptions().Logger() 112 log.Debug("round trip test") 113 require.NoError(t, testSetup.StartServer()) 114 log.Debug("server is now up") 115 116 // Stop the server 117 defer func() { 118 require.NoError(t, testSetup.StopServer()) 119 log.Debug("server is now down") 120 }() 121 122 // Write test data 123 seriesMaps := make(map[xtime.UnixNano]generate.SeriesBlock) 124 for _, input := range inputData { 125 testSetup.SetNowFn(input.Start) 126 testData := generate.Block(input) 127 seriesMaps[input.Start] = testData 128 require.NoError(t, testSetup.WriteBatch(testNamespaces[0], testData)) 129 } 130 log.Debug("test data is now written") 131 132 // Advance time and sleep for a long enough time so data blocks are sealed during ticking 133 testSetup.SetNowFn(testSetup.NowFn()().Add(blockSize * 2)) 134 testSetup.SleepFor10xTickMinimumInterval() 135 136 // Verify in-memory data match what we've written 137 verifySeriesMaps(t, testSetup, testNamespaces[0], seriesMaps) 138 139 // Verify in-memory data again just to be sure the data can be read multiple times without issues 140 verifySeriesMaps(t, testSetup, testNamespaces[0], seriesMaps) 141 }