github.com/m3db/m3@v1.5.0/src/query/api/v1/handler/namespace/common_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 namespace 22 23 import ( 24 "errors" 25 "fmt" 26 "testing" 27 "time" 28 29 "github.com/m3db/m3/src/cluster/kv" 30 nsproto "github.com/m3db/m3/src/dbnode/generated/proto/namespace" 31 "github.com/m3db/m3/src/dbnode/namespace" 32 "github.com/m3db/m3/src/dbnode/retention" 33 "github.com/m3db/m3/src/x/ident" 34 xtest "github.com/m3db/m3/src/x/test" 35 36 "github.com/golang/mock/gomock" 37 "github.com/stretchr/testify/assert" 38 "github.com/stretchr/testify/require" 39 ) 40 41 func init() { 42 namespace.RegisterExtendedOptionsConverter("testExtendedOptions", xtest.ConvertToTestExtendedOptions) 43 } 44 45 type storeOptionsMatcher struct { 46 zone string 47 namespace string 48 environment string 49 } 50 51 func (s storeOptionsMatcher) Matches(x interface{}) bool { 52 opts := x.(kv.OverrideOptions) 53 if s.zone != "" && s.zone != opts.Zone() { 54 return false 55 } 56 if s.namespace != "" && s.namespace != opts.Namespace() { 57 return false 58 } 59 if s.environment != "" && s.environment != opts.Environment() { 60 return false 61 } 62 return true 63 } 64 65 func (s storeOptionsMatcher) String() string { 66 return fmt.Sprintf("checks that zone=%s, namespace=%s, environment=%s", s.zone, s.namespace, s.environment) 67 } 68 69 func newStoreOptionsMatcher(zone, namespace, environment string) gomock.Matcher { 70 return storeOptionsMatcher{ 71 zone: zone, 72 namespace: namespace, 73 environment: environment, 74 } 75 } 76 77 func TestMetadata(t *testing.T) { 78 ctrl := gomock.NewController(t) 79 defer ctrl.Finish() 80 81 mockKV := kv.NewMockStore(ctrl) 82 require.NotNil(t, mockKV) 83 84 // Test KV get error 85 mockKV.EXPECT().Get(M3DBNodeNamespacesKey).Return(nil, errors.New("unable to get key")) 86 meta, version, err := Metadata(mockKV) 87 assert.Nil(t, meta) 88 assert.Equal(t, -1, version) 89 assert.EqualError(t, err, "unable to get key") 90 91 // Test empty namespace 92 mockKV.EXPECT().Get(M3DBNodeNamespacesKey).Return(nil, kv.ErrNotFound) 93 meta, version, err = Metadata(mockKV) 94 assert.NotNil(t, meta) 95 assert.Equal(t, 0, version) 96 assert.Len(t, meta, 0) 97 assert.NoError(t, err) 98 99 registry := nsproto.Registry{ 100 Namespaces: map[string]*nsproto.NamespaceOptions{ 101 "metrics-ns1": { 102 BootstrapEnabled: true, 103 FlushEnabled: true, 104 WritesToCommitLog: false, 105 CleanupEnabled: false, 106 RepairEnabled: false, 107 RetentionOptions: &nsproto.RetentionOptions{ 108 RetentionPeriodNanos: 200000000000, 109 BlockSizeNanos: 100000000000, 110 BufferFutureNanos: 3000000000, 111 BufferPastNanos: 4000000000, 112 BlockDataExpiry: true, 113 BlockDataExpiryAfterNotAccessPeriodNanos: 5000000000, 114 }, 115 }, 116 "metrics-ns2": { 117 BootstrapEnabled: true, 118 FlushEnabled: true, 119 WritesToCommitLog: true, 120 CleanupEnabled: true, 121 RepairEnabled: false, 122 RetentionOptions: &nsproto.RetentionOptions{ 123 RetentionPeriodNanos: 400000000000, 124 BlockSizeNanos: 300000000000, 125 BufferFutureNanos: 8000000000, 126 BufferPastNanos: 9000000000, 127 BlockDataExpiry: false, 128 BlockDataExpiryAfterNotAccessPeriodNanos: 10000000000, 129 }, 130 }, 131 }, 132 } 133 mockMetaValue := kv.NewMockValue(ctrl) 134 mockMetaValue.EXPECT().Unmarshal(gomock.Not(nil)).Return(nil).SetArg(0, registry) 135 mockMetaValue.EXPECT().Version().Return(0) 136 137 // Test namespaces 138 mockKV.EXPECT().Get(M3DBNodeNamespacesKey).Return(mockMetaValue, nil) 139 meta, version, err = Metadata(mockKV) 140 assert.NotNil(t, meta) 141 assert.Equal(t, 0, version) 142 assert.Len(t, meta, 2) 143 assert.NoError(t, err) 144 } 145 146 func TestValidateAggregationOptionsUniqueResolutionAndRetention(t *testing.T) { 147 // Validate that non-unique (resolution, retention) fails. 148 dsOpts := namespace.NewDownsampleOptions(true) 149 attrs, err := namespace.NewAggregatedAttributes(5*time.Minute, dsOpts) 150 require.NoError(t, err) 151 152 agg := namespace.NewAggregatedAggregation(attrs) 153 aggOpts := namespace.NewAggregationOptions(). 154 SetAggregations([]namespace.Aggregation{agg}) 155 156 nsOpts := namespace.NewOptions(). 157 SetAggregationOptions(aggOpts). 158 SetRetentionOptions(retention.NewOptions(). 159 SetRetentionPeriod(24 * time.Hour)) 160 161 md1, err := namespace.NewMetadata(ident.StringID("ns1"), nsOpts) 162 require.NoError(t, err) 163 164 md2, err := namespace.NewMetadata(ident.StringID("ns2"), nsOpts) 165 require.NoError(t, err) 166 167 err = validateNamespaceAggregationOptions([]namespace.Metadata{md1, md2}) 168 require.Error(t, err) 169 170 // Validate that unique (resolution, retention) is fine. 171 nsOpts2 := namespace.NewOptions(). 172 SetAggregationOptions(aggOpts). 173 SetRetentionOptions(retention.NewOptions(). 174 SetRetentionPeriod(48 * time.Hour)) 175 176 md2, err = namespace.NewMetadata(ident.StringID("ns2"), nsOpts2) 177 require.NoError(t, err) 178 179 err = validateNamespaceAggregationOptions([]namespace.Metadata{md1, md2}) 180 require.NoError(t, err) 181 }