gopkg.in/juju/charm.v6-unstable@v6.0.0-20171026192109-50d0c219b496/metrics_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the LGPLv3, see LICENCE file for details. 3 4 package charm_test 5 6 import ( 7 "sort" 8 "strings" 9 10 gc "gopkg.in/check.v1" 11 12 "gopkg.in/juju/charm.v6-unstable" 13 ) 14 15 // Keys returns a list of all defined metrics keys. 16 func Keys(m *charm.Metrics) []string { 17 result := make([]string, 0, len(m.Metrics)) 18 19 for name := range m.Metrics { 20 result = append(result, name) 21 22 } 23 sort.Strings(result) 24 return result 25 } 26 27 type MetricsSuite struct{} 28 29 var _ = gc.Suite(&MetricsSuite{}) 30 31 func (s *MetricsSuite) TestReadEmpty(c *gc.C) { 32 metrics, err := charm.ReadMetrics(strings.NewReader("")) 33 c.Assert(err, gc.IsNil) 34 c.Assert(metrics, gc.NotNil) 35 } 36 37 func (s *MetricsSuite) TestReadAlmostEmpty(c *gc.C) { 38 metrics, err := charm.ReadMetrics(strings.NewReader(` 39 metrics: 40 `)) 41 c.Assert(err, gc.IsNil) 42 c.Assert(metrics, gc.NotNil) 43 } 44 45 func (s *MetricsSuite) TestNoDescription(c *gc.C) { 46 metrics, err := charm.ReadMetrics(strings.NewReader(` 47 metrics: 48 some-metric: 49 type: gauge 50 `)) 51 c.Assert(err, gc.ErrorMatches, "invalid metrics declaration: metric \"some-metric\" lacks description") 52 c.Assert(metrics, gc.IsNil) 53 } 54 55 func (s *MetricsSuite) TestIncorrectType(c *gc.C) { 56 metrics, err := charm.ReadMetrics(strings.NewReader(` 57 metrics: 58 some-metric: 59 type: not-a-type 60 description: Some description. 61 `)) 62 c.Assert(err, gc.ErrorMatches, "invalid metrics declaration: metric \"some-metric\" has unknown type \"not-a-type\"") 63 c.Assert(metrics, gc.IsNil) 64 } 65 66 func (s *MetricsSuite) TestMultipleDefinition(c *gc.C) { 67 metrics, err := charm.ReadMetrics(strings.NewReader(` 68 metrics: 69 some-metric: 70 type: gauge 71 description: Some description. 72 some-metric: 73 type: absolute 74 description: Some other description. 75 76 `)) 77 c.Assert(err, gc.IsNil) 78 c.Assert(metrics.Metrics, gc.HasLen, 1) 79 c.Assert(metrics.Metrics["some-metric"].Type, gc.Equals, charm.MetricTypeAbsolute) 80 } 81 82 func (s *MetricsSuite) TestIsBuiltinMetric(c *gc.C) { 83 tests := []struct { 84 input string 85 isbuiltin bool 86 }{{ 87 "juju-thing", 88 true, 89 }, { 90 "jujuthing", 91 true, 92 }, { 93 "thing", 94 false, 95 }, 96 } 97 98 for i, test := range tests { 99 c.Logf("test %d isBuiltinMetric(%v) = %v", i, test.input, test.isbuiltin) 100 is := charm.IsBuiltinMetric(test.input) 101 c.Assert(is, gc.Equals, test.isbuiltin) 102 } 103 } 104 105 func (s *MetricsSuite) TestValidYaml(c *gc.C) { 106 metrics, err := charm.ReadMetrics(strings.NewReader(` 107 metrics: 108 blips: 109 type: absolute 110 description: An absolute metric. 111 blops: 112 type: gauge 113 description: A gauge metric. 114 juju-unit-time: 115 `)) 116 c.Assert(err, gc.IsNil) 117 c.Assert(metrics, gc.NotNil) 118 c.Assert(Keys(metrics), gc.DeepEquals, []string{"blips", "blops", "juju-unit-time"}) 119 120 testCases := []struct { 121 about string 122 name string 123 value string 124 err string 125 }{{ 126 about: "valid gauge metric", 127 name: "blops", 128 value: "1", 129 err: "", 130 }, { 131 about: "valid absolute metric", 132 name: "blips", 133 value: "0", 134 err: "", 135 }, { 136 about: "valid gauge metric, float value", 137 name: "blops", 138 value: "0.15", 139 err: "", 140 }, { 141 about: "valid absolute metric, float value", 142 name: "blips", 143 value: "6.015e15", 144 err: "", 145 }, { 146 about: "undeclared metric", 147 name: "undeclared", 148 value: "6.015e15", 149 err: "metric \"undeclared\" not defined", 150 }, { 151 about: "invalid type for gauge metric", 152 name: "blops", 153 value: "true", 154 err: "invalid value type: expected float, got \"true\"", 155 }, { 156 about: "metric value too large", 157 name: "blips", 158 value: "1111111111111111111111111111111", 159 err: "metric value is too large", 160 }, 161 } 162 163 for i, t := range testCases { 164 c.Logf("test %d: %s", i, t.about) 165 err := metrics.ValidateMetric(t.name, t.value) 166 if t.err == "" { 167 c.Check(err, gc.IsNil) 168 } else { 169 c.Check(err, gc.ErrorMatches, t.err) 170 } 171 } 172 173 } 174 175 func (s *MetricsSuite) TestBuiltInMetrics(c *gc.C) { 176 tests := []string{` 177 metrics: 178 some-metric: 179 type: gauge 180 description: Some description. 181 juju-unit-time: 182 type: absolute 183 `, ` 184 metrics: 185 some-metric: 186 type: gauge 187 description: Some description. 188 juju-unit-time: 189 description: Some description 190 `, 191 } 192 for _, test := range tests { 193 c.Logf("%s", test) 194 _, err := charm.ReadMetrics(strings.NewReader(test)) 195 c.Assert(err, gc.ErrorMatches, `metric "juju-unit-time" is using a prefix reserved for built-in metrics: it should not have type or description specification`) 196 } 197 } 198 199 func (s *MetricsSuite) TestValidateValue(c *gc.C) { 200 tests := []struct { 201 value string 202 expectedError string 203 }{{ 204 value: "1234567890", 205 }, { 206 value: "0", 207 }, { 208 value: "abcd", 209 expectedError: `invalid value type: expected float, got "abcd"`, 210 }, { 211 value: "1234567890123456789012345678901234567890", 212 expectedError: "metric value is too large", 213 }, { 214 value: "-42", 215 expectedError: "invalid value: value must be greater or equal to zero, got -42", 216 }, 217 } 218 219 for _, test := range tests { 220 err := charm.ValidateValue(test.value) 221 if test.expectedError != "" { 222 c.Assert(err, gc.ErrorMatches, test.expectedError) 223 } else { 224 c.Assert(err, gc.IsNil) 225 } 226 } 227 } 228 229 func (s *MetricsSuite) TestPlanRequired(c *gc.C) { 230 tests := []struct { 231 about string 232 input string 233 planRequired bool 234 }{{ 235 about: "not specified", 236 input: ` 237 metrics: 238 some-metric: 239 type: gauge 240 description: thing 241 `, 242 planRequired: false, 243 }, { 244 about: "plan optional", 245 input: ` 246 plan: 247 required: false 248 metrics: 249 `, 250 planRequired: false, 251 }, { 252 about: "plan required", 253 input: ` 254 plan: 255 required: true 256 metrics: 257 `, 258 planRequired: true, 259 }, { 260 about: "not set", 261 input: ` 262 plan: 263 metrics: 264 `, 265 planRequired: false, 266 }, 267 } 268 for i, test := range tests { 269 c.Logf("testplanrequired %d: %s", i, test.about) 270 metrics, err := charm.ReadMetrics(strings.NewReader(test.input)) 271 c.Assert(err, gc.IsNil) 272 c.Assert(metrics.PlanRequired(), gc.Equals, test.planRequired) 273 } 274 }