github.com/m3db/m3@v1.5.0/src/integration/resources/inprocess/dbnode_test.go (about) 1 // +build test_harness 2 // Copyright (c) 2021 Uber Technologies, Inc. 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 package inprocess 23 24 import ( 25 "testing" 26 "time" 27 28 "github.com/stretchr/testify/assert" 29 "github.com/stretchr/testify/require" 30 31 "github.com/m3db/m3/src/dbnode/generated/thrift/rpc" 32 "github.com/m3db/m3/src/integration/resources" 33 "github.com/m3db/m3/src/m3ninx/idx" 34 "github.com/m3db/m3/src/query/generated/proto/admin" 35 "github.com/m3db/m3/src/x/checked" 36 "github.com/m3db/m3/src/x/ident" 37 "github.com/m3db/m3/src/x/pool" 38 "github.com/m3db/m3/src/x/serialize" 39 ) 40 41 func TestNewDBNodeNoSetup(t *testing.T) { 42 dbnode, err := NewDBNodeFromYAML(defaultDBNodeConfig, DBNodeOptions{Start: true}) 43 require.NoError(t, err) 44 45 require.NoError(t, dbnode.Close()) 46 47 // Restart and shutdown again to test restarting 48 dbnode, err = NewDBNodeFromYAML(defaultDBNodeConfig, DBNodeOptions{Start: true}) 49 require.NoError(t, err) 50 51 require.NoError(t, dbnode.Close()) 52 } 53 54 func TestDBNode(t *testing.T) { 55 dbnode, _, closer := setupNodeAndCoordinator(t) 56 defer closer() 57 58 testHealth(t, dbnode) 59 testWaitForBootstrap(t, dbnode) 60 testWriteFetchRoundtrip(t, dbnode) 61 testWriteTaggedFetchTaggedRoundtrip(t, dbnode) 62 } 63 64 func testHealth(t *testing.T, dbnode resources.Node) { 65 res, err := dbnode.Health() 66 require.NoError(t, err) 67 68 require.True(t, res.Ok) 69 } 70 71 func testWaitForBootstrap(t *testing.T, dbnode resources.Node) { 72 res, err := dbnode.Health() 73 require.NoError(t, err) 74 75 require.Equal(t, true, res.Bootstrapped) 76 } 77 78 func testWriteFetchRoundtrip(t *testing.T, dbnode resources.Node) { 79 var ( 80 id = "foo" 81 ts = time.Now() 82 val = 1.0 83 ) 84 req := &rpc.WriteRequest{ 85 NameSpace: resources.UnaggName, 86 ID: id, 87 Datapoint: &rpc.Datapoint{ 88 Timestamp: ts.Unix(), 89 Value: val, 90 }, 91 } 92 require.NoError(t, dbnode.WritePoint(req)) 93 94 freq := &rpc.FetchRequest{ 95 RangeStart: ts.Add(-1 * time.Minute).Unix(), 96 RangeEnd: ts.Add(1 * time.Minute).Unix(), 97 NameSpace: resources.UnaggName, 98 ID: id, 99 } 100 res, err := dbnode.Fetch(freq) 101 require.NoError(t, err) 102 103 require.Equal(t, 1, len(res.Datapoints)) 104 require.Equal(t, rpc.Datapoint{ 105 Timestamp: ts.Unix(), 106 Value: val, 107 }, *res.Datapoints[0]) 108 } 109 110 func testWriteTaggedFetchTaggedRoundtrip(t *testing.T, dbnode resources.Node) { 111 var ( 112 id = "fooTagged" 113 ts = time.Now() 114 val = 1.0 115 ) 116 req := &rpc.WriteTaggedRequest{ 117 NameSpace: resources.UnaggName, 118 ID: id, 119 Datapoint: &rpc.Datapoint{ 120 Timestamp: ts.UnixNano(), 121 TimestampTimeType: rpc.TimeType_UNIX_NANOSECONDS, 122 Value: val, 123 }, 124 Tags: []*rpc.Tag{ 125 {Name: "__name__", Value: id}, 126 {Name: "job", Value: "bar"}, 127 }, 128 } 129 require.NoError(t, dbnode.WriteTaggedPoint(req)) 130 131 query := idx.NewTermQuery([]byte("job"), []byte("bar")) 132 encoded, err := idx.Marshal(query) 133 require.NoError(t, err) 134 135 freq := &rpc.FetchTaggedRequest{ 136 RangeStart: ts.Add(-1 * time.Minute).UnixNano(), 137 RangeEnd: ts.Add(1 * time.Minute).UnixNano(), 138 NameSpace: []byte(resources.UnaggName), 139 RangeTimeType: rpc.TimeType_UNIX_NANOSECONDS, 140 FetchData: true, 141 Query: encoded, 142 } 143 res, err := dbnode.FetchTagged(freq) 144 require.NoError(t, err) 145 146 require.Equal(t, 1, len(res.Elements)) 147 require.Equal(t, id, string(res.Elements[0].ID)) 148 require.Equal(t, resources.UnaggName, string(res.Elements[0].NameSpace)) 149 150 // Validate Tags 151 testTagDecoderPool := serialize.NewTagDecoderPool( 152 serialize.NewTagDecoderOptions(serialize.TagDecoderOptionsConfig{}), 153 pool.NewObjectPoolOptions()) 154 testTagDecoderPool.Init() 155 156 dec := testTagDecoderPool.Get() 157 dec.Reset(checked.NewBytes(res.Elements[0].EncodedTags, nil)) 158 159 require.True(t, dec.Next()) 160 validateTag(t, dec.Current(), "__name__", id) 161 require.True(t, dec.Next()) 162 validateTag(t, dec.Current(), "job", "bar") 163 require.False(t, dec.Next()) 164 } 165 166 func validateTag(t *testing.T, tag ident.Tag, name string, value string) { 167 require.Equal(t, name, tag.Name.String()) 168 require.Equal(t, value, tag.Value.String()) 169 } 170 171 func setupNodeAndCoordinator(t *testing.T) (resources.Node, resources.Coordinator, func()) { 172 dbnode, err := NewDBNodeFromYAML(defaultDBNodeConfig, DBNodeOptions{ 173 GenerateHostID: true, 174 Start: true, 175 }) 176 require.NoError(t, err) 177 178 coord, err := NewCoordinatorFromYAML(defaultCoordConfig, CoordinatorOptions{Start: true}) 179 require.NoError(t, err) 180 181 require.NoError(t, coord.WaitForNamespace("")) 182 183 host, err := dbnode.HostDetails(9000) 184 require.NoError(t, err) 185 186 _, err = coord.CreateDatabase(admin.DatabaseCreateRequest{ 187 Type: "cluster", 188 NamespaceName: resources.UnaggName, 189 RetentionTime: "1h", 190 NumShards: 4, 191 ReplicationFactor: 1, 192 Hosts: []*admin.Host{host}, 193 }) 194 require.NoError(t, err) 195 196 require.NoError(t, coord.WaitForShardsReady()) 197 require.NoError(t, coord.WaitForClusterReady()) 198 199 return dbnode, coord, func() { 200 assert.NoError(t, coord.Close()) 201 assert.NoError(t, dbnode.Close()) 202 } 203 } 204 205 const defaultDBNodeConfig = ` 206 db: 207 writeNewSeriesAsync: false 208 `