github.com/m3db/m3@v1.5.0/src/metrics/policy/policy_test.go (about) 1 // Copyright (c) 2017 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 policy 22 23 import ( 24 "testing" 25 "time" 26 27 "github.com/m3db/m3/src/metrics/aggregation" 28 "github.com/m3db/m3/src/metrics/generated/proto/aggregationpb" 29 "github.com/m3db/m3/src/metrics/generated/proto/policypb" 30 "github.com/m3db/m3/src/x/test/testmarshal" 31 xtime "github.com/m3db/m3/src/x/time" 32 33 "github.com/stretchr/testify/require" 34 yaml "gopkg.in/yaml.v2" 35 ) 36 37 func TestPolicyString(t *testing.T) { 38 inputs := []struct { 39 p Policy 40 expected string 41 }{ 42 {p: NewPolicy(NewStoragePolicy(10*time.Second, xtime.Second, time.Hour), aggregation.DefaultID), expected: "10s:1h"}, 43 {p: NewPolicy(NewStoragePolicy(time.Minute, xtime.Minute, 12*time.Hour), aggregation.MustCompressTypes(aggregation.Mean, aggregation.P999)), expected: "1m:12h|Mean,P999"}, 44 {p: NewPolicy(NewStoragePolicy(time.Minute, xtime.Minute, 12*time.Hour), aggregation.MustCompressTypes(aggregation.Mean)), expected: "1m:12h|Mean"}, 45 } 46 for _, input := range inputs { 47 require.Equal(t, input.expected, input.p.String()) 48 } 49 } 50 51 func TestPolicyMarshalling(t *testing.T) { 52 inputs := []struct { 53 notCanonical bool 54 str string 55 expected Policy 56 }{ 57 { 58 str: "1s:1h", 59 expected: NewPolicy(NewStoragePolicy(time.Second, xtime.Second, time.Hour), aggregation.DefaultID), 60 }, 61 { 62 str: "10s:1d|Mean", 63 expected: NewPolicy(NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour), aggregation.MustCompressTypes(aggregation.Mean)), 64 }, 65 { 66 notCanonical: true, 67 str: "60s:24h|Mean,Count", 68 expected: NewPolicy(NewStoragePolicy(60*time.Second, xtime.Minute, 24*time.Hour), aggregation.MustCompressTypes(aggregation.Mean, aggregation.Count)), 69 }, 70 { 71 notCanonical: true, 72 str: "1m:1d|Count,Mean", 73 expected: NewPolicy(NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour), aggregation.MustCompressTypes(aggregation.Mean, aggregation.Count)), 74 }, 75 { 76 str: "1m:1d|Mean,Count", 77 expected: NewPolicy(NewStoragePolicy(time.Minute, xtime.Minute, 24*time.Hour), aggregation.MustCompressTypes(aggregation.Mean, aggregation.Count)), 78 }, 79 { 80 notCanonical: true, 81 str: "1s@1s:1h|P999,P9999", 82 expected: NewPolicy(NewStoragePolicy(time.Second, xtime.Second, time.Hour), aggregation.MustCompressTypes(aggregation.P999, aggregation.P9999)), 83 }, 84 } 85 86 t.Run("roundtrips", func(t *testing.T) { 87 examples := make([]Policy, 0, len(inputs)) 88 for _, ex := range inputs { 89 examples = append(examples, ex.expected) 90 } 91 92 testmarshal.TestMarshalersRoundtrip(t, examples, []testmarshal.Marshaler{testmarshal.TextMarshaler, testmarshal.JSONMarshaler, testmarshal.YAMLMarshaler}) 93 }) 94 95 t.Run("marshals/text", func(t *testing.T) { 96 for _, input := range inputs { 97 if input.notCanonical { 98 continue 99 } 100 testmarshal.Require(t, testmarshal.AssertMarshals(t, testmarshal.TextMarshaler, input.expected, []byte(input.str))) 101 } 102 }) 103 104 t.Run("unmarshals/text", func(t *testing.T) { 105 for _, input := range inputs { 106 testmarshal.Require(t, testmarshal.AssertUnmarshals(t, testmarshal.TextMarshaler, input.expected, []byte(input.str))) 107 } 108 }) 109 110 t.Run("unmarshals/yaml", func(t *testing.T) { 111 for _, input := range inputs { 112 testmarshal.Require(t, testmarshal.AssertUnmarshals(t, testmarshal.YAMLMarshaler, input.expected, []byte(input.str))) 113 } 114 }) 115 } 116 117 func TestPolicyUnmarshalYAMLErrors(t *testing.T) { 118 inputs := []string{ 119 "|", 120 "|Mean", 121 "1s:1h|", 122 "1s:1h||", 123 "1s:1h|P99|", 124 "1s:1h|P", 125 "1s:1h|Meann", 126 "1s:1h|Mean,", 127 } 128 for _, input := range inputs { 129 var p Policy 130 require.Error(t, yaml.Unmarshal([]byte(input), &p)) 131 } 132 } 133 134 func TestNewPoliciesFromProto(t *testing.T) { 135 input := []*policypb.Policy{ 136 &policypb.Policy{ 137 StoragePolicy: &policypb.StoragePolicy{ 138 Resolution: policypb.Resolution{ 139 WindowSize: int64(10 * time.Second), 140 Precision: int64(time.Second), 141 }, 142 Retention: policypb.Retention{ 143 Period: int64(24 * time.Hour), 144 }, 145 }, 146 AggregationTypes: []aggregationpb.AggregationType{ 147 aggregationpb.AggregationType_MEAN, 148 aggregationpb.AggregationType_P999, 149 }, 150 }, 151 &policypb.Policy{ 152 StoragePolicy: &policypb.StoragePolicy{ 153 Resolution: policypb.Resolution{ 154 WindowSize: int64(time.Minute), 155 Precision: int64(time.Minute), 156 }, 157 Retention: policypb.Retention{ 158 Period: int64(240 * time.Hour), 159 }, 160 }, 161 AggregationTypes: []aggregationpb.AggregationType{ 162 aggregationpb.AggregationType_MEAN, 163 aggregationpb.AggregationType_P9999, 164 }, 165 }, 166 } 167 168 res, err := NewPoliciesFromProto(input) 169 require.NoError(t, err) 170 require.Equal(t, []Policy{ 171 NewPolicy(NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour), aggregation.MustCompressTypes(aggregation.Mean, aggregation.P999)), 172 NewPolicy(NewStoragePolicy(time.Minute, xtime.Minute, 240*time.Hour), aggregation.MustCompressTypes(aggregation.Mean, aggregation.P9999)), 173 }, res) 174 } 175 176 func TestParsePolicyIntoProto(t *testing.T) { 177 inputs := []struct { 178 str string 179 expected *policypb.Policy 180 }{ 181 { 182 str: "1s:1h", 183 expected: &policypb.Policy{ 184 StoragePolicy: &policypb.StoragePolicy{ 185 Resolution: policypb.Resolution{ 186 WindowSize: time.Second.Nanoseconds(), 187 Precision: time.Second.Nanoseconds(), 188 }, 189 Retention: policypb.Retention{ 190 Period: time.Hour.Nanoseconds(), 191 }, 192 }, 193 }, 194 }, 195 { 196 str: "1s:1h|Mean", 197 expected: &policypb.Policy{ 198 StoragePolicy: &policypb.StoragePolicy{ 199 Resolution: policypb.Resolution{ 200 WindowSize: time.Second.Nanoseconds(), 201 Precision: time.Second.Nanoseconds(), 202 }, 203 Retention: policypb.Retention{ 204 Period: time.Hour.Nanoseconds(), 205 }, 206 }, 207 AggregationTypes: []aggregationpb.AggregationType{aggregationpb.AggregationType_MEAN}, 208 }, 209 }, 210 { 211 str: "60s:24h|Mean,Count", 212 expected: &policypb.Policy{ 213 StoragePolicy: &policypb.StoragePolicy{ 214 Resolution: policypb.Resolution{ 215 WindowSize: time.Minute.Nanoseconds(), 216 Precision: time.Minute.Nanoseconds(), 217 }, 218 Retention: policypb.Retention{ 219 Period: 24 * time.Hour.Nanoseconds(), 220 }, 221 }, 222 AggregationTypes: []aggregationpb.AggregationType{aggregationpb.AggregationType_MEAN, aggregationpb.AggregationType_COUNT}, 223 }, 224 }, 225 { 226 str: "1m:1d|Count,Mean", 227 expected: &policypb.Policy{ 228 StoragePolicy: &policypb.StoragePolicy{ 229 Resolution: policypb.Resolution{ 230 WindowSize: time.Minute.Nanoseconds(), 231 Precision: time.Minute.Nanoseconds(), 232 }, 233 Retention: policypb.Retention{ 234 Period: 24 * time.Hour.Nanoseconds(), 235 }, 236 }, 237 AggregationTypes: []aggregationpb.AggregationType{aggregationpb.AggregationType_MEAN, aggregationpb.AggregationType_COUNT}, 238 }, 239 }, 240 { 241 str: "1m@1s:1h|P999,P9999", 242 expected: &policypb.Policy{ 243 StoragePolicy: &policypb.StoragePolicy{ 244 Resolution: policypb.Resolution{ 245 WindowSize: time.Minute.Nanoseconds(), 246 Precision: time.Second.Nanoseconds(), 247 }, 248 Retention: policypb.Retention{ 249 Period: time.Hour.Nanoseconds(), 250 }, 251 }, 252 AggregationTypes: []aggregationpb.AggregationType{aggregationpb.AggregationType_P999, aggregationpb.AggregationType_P9999}, 253 }, 254 }, 255 } 256 257 for _, input := range inputs { 258 p, err := ParsePolicy(input.str) 259 require.NoError(t, err) 260 261 sp, err := p.Proto() 262 require.NoError(t, err) 263 require.Equal(t, input.expected, sp, input.str) 264 } 265 }