github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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"
    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{
   124  				"pings": {},
   125  				"pongs": {},
   126  			},
   127  			CharmURL: "local:precise/wordpress",
   128  			UnitTag:  s.unitTag,
   129  		})
   130  	c.Assert(err, jc.ErrorIsNil)
   131  	c.Assert(w, gc.NotNil)
   132  	err = w.AddMetric("pings", "5", time.Now(), nil)
   133  	c.Assert(err, jc.ErrorIsNil)
   134  	err = w.AddMetric("pongs", "10", time.Now(), map[string]string{"foo": "bar"})
   135  	c.Assert(err, jc.ErrorIsNil)
   136  	err = w.Close()
   137  	c.Assert(err, jc.ErrorIsNil)
   138  
   139  	r, err := spool.NewJSONMetricReader(s.paths.GetMetricsSpoolDir())
   140  	c.Assert(err, jc.ErrorIsNil)
   141  	batches, err := r.Read()
   142  	c.Assert(err, jc.ErrorIsNil)
   143  	c.Assert(batches, gc.HasLen, 1)
   144  	batch := batches[0]
   145  	c.Assert(batch.CharmURL, gc.Equals, "local:precise/wordpress")
   146  	c.Assert(batch.UUID, gc.Not(gc.Equals), "")
   147  	c.Assert(batch.Metrics, gc.HasLen, 2)
   148  	c.Assert(batch.Metrics[0].Key, gc.Equals, "pings")
   149  	c.Assert(batch.Metrics[0].Value, gc.Equals, "5")
   150  	c.Assert(batch.Metrics[0].Labels, gc.HasLen, 0)
   151  	c.Assert(batch.Metrics[1].Key, gc.Equals, "pongs")
   152  	c.Assert(batch.Metrics[1].Value, gc.Equals, "10")
   153  	c.Assert(batch.Metrics[1].Labels, gc.DeepEquals, map[string]string{"foo": "bar"})
   154  	c.Assert(batch.UnitTag, gc.Equals, s.unitTag)
   155  
   156  	err = r.Close()
   157  	c.Assert(err, jc.ErrorIsNil)
   158  }
   159  
   160  func (s *metricsRecorderSuite) TestMetricValidation(c *gc.C) {
   161  	tests := []struct {
   162  		about         string
   163  		key           string
   164  		value         string
   165  		expectedError string
   166  	}{{
   167  		about:         "metric not declared",
   168  		key:           "pings",
   169  		value:         "5",
   170  		expectedError: `metric key "pings" not declared by the charm`,
   171  	}, {
   172  		about:         "non float metrics",
   173  		key:           "pongs",
   174  		value:         "abcd",
   175  		expectedError: `invalid value type: expected float, got "abcd"`,
   176  	}, {
   177  		about:         "negative value",
   178  		key:           "pongs",
   179  		value:         "-5.0",
   180  		expectedError: `invalid value: value must be greater or equal to zero, got -5.0`,
   181  	}, {
   182  		about:         "large value",
   183  		key:           "pongs",
   184  		value:         "1234567890123456789012345678901234567890",
   185  		expectedError: `metric value is too large`,
   186  	},
   187  	}
   188  
   189  	for _, test := range tests {
   190  		w, err := spool.NewJSONMetricRecorder(
   191  			spool.MetricRecorderConfig{
   192  				SpoolDir: s.paths.GetMetricsSpoolDir(),
   193  				Metrics: map[string]corecharm.Metric{
   194  					"juju-units": {},
   195  					"pongs": {
   196  						Type: corecharm.MetricTypeAbsolute,
   197  					},
   198  				},
   199  				CharmURL: "local:precise/wordpress",
   200  				UnitTag:  s.unitTag,
   201  			})
   202  		c.Assert(err, jc.ErrorIsNil)
   203  		c.Assert(w, gc.NotNil)
   204  
   205  		c.Logf("running test: %s", test.about)
   206  		err = w.AddMetric(test.key, test.value, time.Now(), nil)
   207  		if test.expectedError != "" {
   208  			c.Assert(err, gc.ErrorMatches, test.expectedError)
   209  			err = w.Close()
   210  			c.Assert(err, jc.ErrorIsNil)
   211  
   212  			r, err := spool.NewJSONMetricReader(s.paths.GetMetricsSpoolDir())
   213  			c.Assert(err, jc.ErrorIsNil)
   214  			batches, err := r.Read()
   215  			c.Assert(err, jc.ErrorIsNil)
   216  			c.Assert(batches, gc.HasLen, 0)
   217  		} else {
   218  			c.Assert(err, jc.ErrorIsNil)
   219  			err = w.Close()
   220  			c.Assert(err, jc.ErrorIsNil)
   221  		}
   222  	}
   223  }
   224  
   225  type metricsReaderSuite struct {
   226  	paths   testPaths
   227  	unitTag string
   228  
   229  	w *spool.JSONMetricRecorder
   230  }
   231  
   232  var _ = gc.Suite(&metricsReaderSuite{})
   233  
   234  func (s *metricsReaderSuite) SetUpTest(c *gc.C) {
   235  	s.paths = newTestPaths(c)
   236  	s.unitTag = names.NewUnitTag("test-unit/0").String()
   237  
   238  	var err error
   239  	s.w, err = spool.NewJSONMetricRecorder(
   240  		spool.MetricRecorderConfig{
   241  			SpoolDir: s.paths.GetMetricsSpoolDir(),
   242  			Metrics:  map[string]corecharm.Metric{"pings": {}},
   243  			CharmURL: "local:precise/wordpress",
   244  			UnitTag:  s.unitTag,
   245  		})
   246  
   247  	c.Assert(err, jc.ErrorIsNil)
   248  	err = s.w.AddMetric("pings", "5", time.Now(), nil)
   249  	c.Assert(err, jc.ErrorIsNil)
   250  	err = s.w.Close()
   251  	c.Assert(err, jc.ErrorIsNil)
   252  }
   253  
   254  func (s *metricsReaderSuite) TestTwoSimultaneousReaders(c *gc.C) {
   255  	r, err := spool.NewJSONMetricReader(s.paths.GetMetricsSpoolDir())
   256  	c.Assert(err, jc.ErrorIsNil)
   257  
   258  	r2, err := spool.NewJSONMetricReader(c.MkDir())
   259  	c.Assert(err, jc.ErrorIsNil)
   260  	c.Assert(r2, gc.NotNil)
   261  	err = r2.Close()
   262  	c.Assert(err, jc.ErrorIsNil)
   263  	err = r.Close()
   264  	c.Assert(err, jc.ErrorIsNil)
   265  
   266  }
   267  
   268  func (s *metricsReaderSuite) TestUnblockedReaders(c *gc.C) {
   269  	r, err := spool.NewJSONMetricReader(s.paths.GetMetricsSpoolDir())
   270  	c.Assert(err, jc.ErrorIsNil)
   271  	err = r.Close()
   272  	c.Assert(err, jc.ErrorIsNil)
   273  
   274  	r2, err := spool.NewJSONMetricReader(s.paths.GetMetricsSpoolDir())
   275  	c.Assert(err, jc.ErrorIsNil)
   276  	c.Assert(r2, gc.NotNil)
   277  	err = r2.Close()
   278  	c.Assert(err, jc.ErrorIsNil)
   279  }
   280  
   281  func (s *metricsReaderSuite) TestRemoval(c *gc.C) {
   282  	r, err := spool.NewJSONMetricReader(s.paths.GetMetricsSpoolDir())
   283  	c.Assert(err, jc.ErrorIsNil)
   284  
   285  	batches, err := r.Read()
   286  	c.Assert(err, jc.ErrorIsNil)
   287  	for _, batch := range batches {
   288  		err := r.Remove(batch.UUID)
   289  		c.Assert(err, jc.ErrorIsNil)
   290  	}
   291  	err = r.Close()
   292  	c.Assert(err, jc.ErrorIsNil)
   293  
   294  	batches, err = r.Read()
   295  	c.Assert(err, jc.ErrorIsNil)
   296  	c.Assert(batches, gc.HasLen, 0)
   297  	err = r.Close()
   298  	c.Assert(err, jc.ErrorIsNil)
   299  }