github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/worker/metrics/spool/metrics_test.go (about) 1 // Copyright 2012-2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package spool_test 5 6 import ( 7 "path/filepath" 8 "runtime" 9 "time" 10 11 "github.com/juju/testing" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 corecharm "gopkg.in/juju/charm.v6-unstable" 15 "gopkg.in/juju/names.v2" 16 17 "github.com/juju/juju/worker/metrics/spool" 18 "github.com/juju/juju/worker/uniter/runner/jujuc" 19 ) 20 21 type metricsBatchSuite struct { 22 } 23 24 var _ = gc.Suite(&metricsBatchSuite{}) 25 26 func (s *metricsBatchSuite) TestAPIMetricBatch(c *gc.C) { 27 batches := []spool.MetricBatch{{ 28 CharmURL: "local:trusty/test-charm", 29 UUID: "test-uuid", 30 Created: time.Now(), 31 Metrics: []jujuc.Metric{ 32 { 33 Key: "test-key-1", 34 Value: "test-value-1", 35 Time: time.Now(), 36 }, { 37 Key: "test-key-2", 38 Value: "test-value-2", 39 Time: time.Now(), 40 }, 41 }, 42 }, { 43 CharmURL: "local:trusty/test-charm", 44 UUID: "test-uuid", 45 Created: time.Now(), 46 Metrics: []jujuc.Metric{}, 47 }, 48 } 49 for _, batch := range batches { 50 apiBatch := spool.APIMetricBatch(batch) 51 c.Assert(apiBatch.Batch.UUID, gc.DeepEquals, batch.UUID) 52 c.Assert(apiBatch.Batch.CharmURL, gc.DeepEquals, batch.CharmURL) 53 c.Assert(apiBatch.Batch.Created, gc.DeepEquals, batch.Created) 54 c.Assert(len(apiBatch.Batch.Metrics), gc.Equals, len(batch.Metrics)) 55 for i, metric := range batch.Metrics { 56 c.Assert(metric.Key, gc.DeepEquals, apiBatch.Batch.Metrics[i].Key) 57 c.Assert(metric.Value, gc.DeepEquals, apiBatch.Batch.Metrics[i].Value) 58 c.Assert(metric.Time, gc.DeepEquals, apiBatch.Batch.Metrics[i].Time) 59 } 60 } 61 } 62 63 func osDependentSockPath(c *gc.C) string { 64 sockPath := filepath.Join(c.MkDir(), "test.sock") 65 if runtime.GOOS == "windows" { 66 return `\\.\pipe` + sockPath[2:] 67 } 68 return sockPath 69 } 70 71 // testPaths implements Paths for tests that do touch the filesystem. 72 type testPaths struct { 73 tools string 74 charm string 75 socket string 76 metricsspool string 77 } 78 79 func newTestPaths(c *gc.C) testPaths { 80 return testPaths{ 81 tools: c.MkDir(), 82 charm: c.MkDir(), 83 socket: osDependentSockPath(c), 84 metricsspool: c.MkDir(), 85 } 86 } 87 88 func (p testPaths) GetMetricsSpoolDir() string { 89 return p.metricsspool 90 } 91 92 func (p testPaths) GetToolsDir() string { 93 return p.tools 94 } 95 96 func (p testPaths) GetCharmDir() string { 97 return p.charm 98 } 99 100 func (p testPaths) GetJujucSocket() string { 101 return p.socket 102 } 103 104 type metricsRecorderSuite struct { 105 testing.IsolationSuite 106 107 paths testPaths 108 unitTag string 109 } 110 111 var _ = gc.Suite(&metricsRecorderSuite{}) 112 113 func (s *metricsRecorderSuite) SetUpTest(c *gc.C) { 114 s.IsolationSuite.SetUpTest(c) 115 s.paths = newTestPaths(c) 116 s.unitTag = names.NewUnitTag("test-unit/0").String() 117 } 118 119 func (s *metricsRecorderSuite) TestInit(c *gc.C) { 120 w, err := spool.NewJSONMetricRecorder( 121 spool.MetricRecorderConfig{ 122 SpoolDir: s.paths.GetMetricsSpoolDir(), 123 Metrics: map[string]corecharm.Metric{"pings": corecharm.Metric{}}, 124 CharmURL: "local:precise/wordpress", 125 UnitTag: s.unitTag, 126 }) 127 c.Assert(err, jc.ErrorIsNil) 128 c.Assert(w, gc.NotNil) 129 err = w.AddMetric("pings", "5", time.Now()) 130 c.Assert(err, jc.ErrorIsNil) 131 err = w.Close() 132 c.Assert(err, jc.ErrorIsNil) 133 134 r, err := spool.NewJSONMetricReader(s.paths.GetMetricsSpoolDir()) 135 c.Assert(err, jc.ErrorIsNil) 136 batches, err := r.Read() 137 c.Assert(err, jc.ErrorIsNil) 138 c.Assert(batches, gc.HasLen, 1) 139 batch := batches[0] 140 c.Assert(batch.CharmURL, gc.Equals, "local:precise/wordpress") 141 c.Assert(batch.UUID, gc.Not(gc.Equals), "") 142 c.Assert(batch.Metrics, gc.HasLen, 1) 143 c.Assert(batch.Metrics[0].Key, gc.Equals, "pings") 144 c.Assert(batch.Metrics[0].Value, gc.Equals, "5") 145 c.Assert(batch.UnitTag, gc.Equals, s.unitTag) 146 147 err = r.Close() 148 c.Assert(err, jc.ErrorIsNil) 149 } 150 151 func (s *metricsRecorderSuite) TestMetricValidation(c *gc.C) { 152 tests := []struct { 153 about string 154 key string 155 value string 156 expectedError string 157 }{{ 158 about: "metric not declared", 159 key: "pings", 160 value: "5", 161 expectedError: `metric key "pings" not declared by the charm`, 162 }, { 163 about: "non float metrics", 164 key: "pongs", 165 value: "abcd", 166 expectedError: `invalid value type: expected float, got "abcd"`, 167 }, { 168 about: "negative value", 169 key: "pongs", 170 value: "-5.0", 171 expectedError: `invalid value: value must be greater or equal to zero, got -5.0`, 172 }, { 173 about: "large value", 174 key: "pongs", 175 value: "1234567890123456789012345678901234567890", 176 expectedError: `metric value is too large`, 177 }, 178 } 179 180 for _, test := range tests { 181 w, err := spool.NewJSONMetricRecorder( 182 spool.MetricRecorderConfig{ 183 SpoolDir: s.paths.GetMetricsSpoolDir(), 184 Metrics: map[string]corecharm.Metric{ 185 "juju-units": corecharm.Metric{}, 186 "pongs": corecharm.Metric{ 187 Type: corecharm.MetricTypeAbsolute, 188 }, 189 }, 190 CharmURL: "local:precise/wordpress", 191 UnitTag: s.unitTag, 192 }) 193 c.Assert(err, jc.ErrorIsNil) 194 c.Assert(w, gc.NotNil) 195 196 c.Logf("running test: %s", test.about) 197 err = w.AddMetric(test.key, test.value, time.Now()) 198 if test.expectedError != "" { 199 c.Assert(err, gc.ErrorMatches, test.expectedError) 200 err = w.Close() 201 c.Assert(err, jc.ErrorIsNil) 202 203 r, err := spool.NewJSONMetricReader(s.paths.GetMetricsSpoolDir()) 204 c.Assert(err, jc.ErrorIsNil) 205 batches, err := r.Read() 206 c.Assert(err, jc.ErrorIsNil) 207 c.Assert(batches, gc.HasLen, 0) 208 } else { 209 c.Assert(err, jc.ErrorIsNil) 210 err = w.Close() 211 c.Assert(err, jc.ErrorIsNil) 212 } 213 } 214 } 215 216 type metricsReaderSuite struct { 217 paths testPaths 218 unitTag string 219 220 w *spool.JSONMetricRecorder 221 } 222 223 var _ = gc.Suite(&metricsReaderSuite{}) 224 225 func (s *metricsReaderSuite) SetUpTest(c *gc.C) { 226 s.paths = newTestPaths(c) 227 s.unitTag = names.NewUnitTag("test-unit/0").String() 228 229 var err error 230 s.w, err = spool.NewJSONMetricRecorder( 231 spool.MetricRecorderConfig{ 232 SpoolDir: s.paths.GetMetricsSpoolDir(), 233 Metrics: map[string]corecharm.Metric{"pings": corecharm.Metric{}}, 234 CharmURL: "local:precise/wordpress", 235 UnitTag: s.unitTag, 236 }) 237 238 c.Assert(err, jc.ErrorIsNil) 239 err = s.w.AddMetric("pings", "5", time.Now()) 240 c.Assert(err, jc.ErrorIsNil) 241 err = s.w.Close() 242 c.Assert(err, jc.ErrorIsNil) 243 } 244 245 func (s *metricsReaderSuite) TestTwoSimultaneousReaders(c *gc.C) { 246 r, err := spool.NewJSONMetricReader(s.paths.GetMetricsSpoolDir()) 247 c.Assert(err, jc.ErrorIsNil) 248 249 r2, err := spool.NewJSONMetricReader(c.MkDir()) 250 c.Assert(err, jc.ErrorIsNil) 251 c.Assert(r2, gc.NotNil) 252 err = r2.Close() 253 c.Assert(err, jc.ErrorIsNil) 254 err = r.Close() 255 c.Assert(err, jc.ErrorIsNil) 256 257 } 258 259 func (s *metricsReaderSuite) TestUnblockedReaders(c *gc.C) { 260 r, err := spool.NewJSONMetricReader(s.paths.GetMetricsSpoolDir()) 261 c.Assert(err, jc.ErrorIsNil) 262 err = r.Close() 263 c.Assert(err, jc.ErrorIsNil) 264 265 r2, err := spool.NewJSONMetricReader(s.paths.GetMetricsSpoolDir()) 266 c.Assert(err, jc.ErrorIsNil) 267 c.Assert(r2, gc.NotNil) 268 err = r2.Close() 269 c.Assert(err, jc.ErrorIsNil) 270 } 271 272 func (s *metricsReaderSuite) TestRemoval(c *gc.C) { 273 r, err := spool.NewJSONMetricReader(s.paths.GetMetricsSpoolDir()) 274 c.Assert(err, jc.ErrorIsNil) 275 276 batches, err := r.Read() 277 c.Assert(err, jc.ErrorIsNil) 278 for _, batch := range batches { 279 err := r.Remove(batch.UUID) 280 c.Assert(err, jc.ErrorIsNil) 281 } 282 err = r.Close() 283 c.Assert(err, jc.ErrorIsNil) 284 285 batches, err = r.Read() 286 c.Assert(err, jc.ErrorIsNil) 287 c.Assert(batches, gc.HasLen, 0) 288 err = r.Close() 289 c.Assert(err, jc.ErrorIsNil) 290 }