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  }