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