github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/runner/jujuc/add-metric_test.go (about)

     1  // Copyright 2012-2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package jujuc_test
     5  
     6  import (
     7  	"sort"
     8  	"time"
     9  
    10  	"github.com/juju/cmd/v3"
    11  	"github.com/juju/cmd/v3/cmdtesting"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/worker/uniter/runner/jujuc"
    16  )
    17  
    18  type AddMetricSuite struct {
    19  	ContextSuite
    20  }
    21  
    22  var _ = gc.Suite(&AddMetricSuite{})
    23  
    24  func (s *AddMetricSuite) TestHelp(c *gc.C) {
    25  	hctx := s.GetHookContext(c, -1, "")
    26  	com, err := jujuc.NewCommand(hctx, "add-metric")
    27  	c.Assert(err, jc.ErrorIsNil)
    28  	ctx := cmdtesting.Context(c)
    29  	code := cmd.Main(jujuc.NewJujucCommandWrappedForTest(com), ctx, []string{"--help"})
    30  	c.Assert(code, gc.Equals, 0)
    31  	c.Assert(bufferString(ctx.Stdout), gc.Equals, `
    32  Usage: add-metric [options] key1=value1 [key2=value2 ...]
    33  
    34  Summary:
    35  add metrics
    36  
    37  Options:
    38  -l, --labels (= "")
    39      labels to be associated with metric values
    40  `[1:])
    41  	c.Assert(bufferString(ctx.Stderr), gc.Equals, "")
    42  }
    43  
    44  func (s *AddMetricSuite) TestAddMetric(c *gc.C) {
    45  	testCases := []struct {
    46  		about         string
    47  		cmd           []string
    48  		canAddMetrics bool
    49  		result        int
    50  		stdout        string
    51  		stderr        string
    52  		expect        []jujuc.Metric
    53  	}{
    54  		{
    55  			"add single metric",
    56  			[]string{"add-metric", "key=50"},
    57  			true,
    58  			0,
    59  			"",
    60  			"",
    61  			[]jujuc.Metric{{Key: "key", Value: "50", Time: time.Now()}},
    62  		}, {
    63  			"no parameters error",
    64  			[]string{"add-metric"},
    65  			true,
    66  			2,
    67  			"",
    68  			"ERROR no metrics specified\n",
    69  			nil,
    70  		}, {
    71  			"invalid argument format",
    72  			[]string{"add-metric", "key"},
    73  			true,
    74  			2,
    75  			"",
    76  			"ERROR invalid metrics: expected \"key=value\", got \"key\"\n",
    77  			nil,
    78  		}, {
    79  			"invalid argument format",
    80  			[]string{"add-metric", "=key"},
    81  			true,
    82  			2,
    83  			"",
    84  			"ERROR invalid metrics: expected \"key=value\", got \"=key\"\n",
    85  			nil,
    86  		}, {
    87  			"invalid argument format, whitespace key",
    88  			[]string{"add-metric", " =value"},
    89  			true,
    90  			2,
    91  			"",
    92  			"ERROR invalid metrics: expected \"key=value\", got \"=value\"\n",
    93  			nil,
    94  		}, {
    95  			"invalid argument format, whitespace key and value",
    96  			[]string{"add-metric", " \t =  \n"},
    97  			true,
    98  			2,
    99  			"",
   100  			"ERROR invalid metrics: expected \"key=value\", got \"=\"\n",
   101  			nil,
   102  		}, {
   103  			"invalid argument format, whitespace value",
   104  			[]string{"add-metric", " key =  "},
   105  			true,
   106  			2,
   107  			"",
   108  			"ERROR invalid metrics: expected \"key=value\", got \"key=\"\n",
   109  			nil,
   110  		}, {
   111  			"multiple metrics",
   112  			[]string{"add-metric", "key=60", "key2=50.4"},
   113  			true,
   114  			0,
   115  			"",
   116  			"",
   117  			[]jujuc.Metric{{
   118  				Key:   "key",
   119  				Value: "60",
   120  				Time:  time.Now(),
   121  			}, {
   122  				Key:   "key2",
   123  				Value: "50.4",
   124  				Time:  time.Now(),
   125  			}},
   126  		}, {
   127  			"multiple metrics, matching keys",
   128  			[]string{"add-metric", "key=60", "key=50.4"},
   129  			true,
   130  			2,
   131  			"",
   132  			"ERROR invalid metrics: key \"key\" specified more than once\n",
   133  			nil,
   134  		}, {
   135  			"newline in metric value",
   136  			[]string{"add-metric", "key=60\n", "key2\t=\t30", "\tkey3 =\t15"},
   137  			true,
   138  			0,
   139  			"",
   140  			"",
   141  			[]jujuc.Metric{{
   142  				Key: "key", Value: "60", Time: time.Now(),
   143  			}, {
   144  				Key: "key2", Value: "30", Time: time.Now(),
   145  			}, {
   146  				Key: "key3", Value: "15", Time: time.Now(),
   147  			}},
   148  		}, {
   149  			"can't add metrics",
   150  			[]string{"add-metric", "key=60", "key2=50.4"},
   151  			false,
   152  			1,
   153  			"",
   154  			"ERROR cannot record metric: metrics disabled\n",
   155  			nil,
   156  		}, {
   157  			"cannot add builtin metric",
   158  			[]string{"add-metric", "juju-key=50"},
   159  			true,
   160  			1,
   161  			"",
   162  			"ERROR juju-key uses a reserved prefix\n",
   163  			nil,
   164  		}, {
   165  			"invalid label format",
   166  			[]string{"add-metric", "--labels", "foo", "key=1"},
   167  			true,
   168  			2,
   169  			"",
   170  			"ERROR invalid labels: expected \"key=value\", got \"foo\"\n",
   171  			nil,
   172  		}, {
   173  			"invalid label format",
   174  			[]string{"add-metric", "--labels", "=bar", "key=1"},
   175  			true,
   176  			2,
   177  			"",
   178  			"ERROR invalid labels: expected \"key=value\", got \"=bar\"\n",
   179  			nil,
   180  		}, {
   181  			"invalid label format, whitespace key",
   182  			[]string{"add-metric", "--labels", " =bar", "key=1"},
   183  			true,
   184  			2,
   185  			"",
   186  			"ERROR invalid labels: expected \"key=value\", got \"=bar\"\n",
   187  			nil,
   188  		}, {
   189  			"invalid label format, whitespace key and value",
   190  			[]string{"add-metric", "--labels", " \t =  \n", "key=1"},
   191  			true,
   192  			2,
   193  			"",
   194  			"ERROR invalid labels: expected \"key=value\", got \"=\"\n",
   195  			nil,
   196  		}, {
   197  			"invalid label format, whitespace value",
   198  			[]string{"add-metric", "--labels", " foo =  ", "key=1"},
   199  			true,
   200  			2,
   201  			"",
   202  			"ERROR invalid labels: expected \"key=value\", got \"foo=\"\n",
   203  			nil,
   204  		}, {
   205  			"add single metric with label",
   206  			[]string{"add-metric", "--labels", "foo=bar", "key=50"},
   207  			true,
   208  			0,
   209  			"",
   210  			"",
   211  			[]jujuc.Metric{{
   212  				Key: "key", Value: "50", Time: time.Now(),
   213  				Labels: map[string]string{"foo": "bar"},
   214  			}},
   215  		}, {
   216  			"add single metric with labels",
   217  			[]string{"add-metric", "--labels", "foo=bar,baz=quux", "key=510"},
   218  			true,
   219  			0,
   220  			"",
   221  			"",
   222  			[]jujuc.Metric{{
   223  				Key: "key", Value: "510", Time: time.Now(),
   224  				Labels: map[string]string{"foo": "bar", "baz": "quux"},
   225  			}},
   226  		}, {
   227  			"add single metric with labels, whitespace",
   228  			[]string{"add-metric", "--labels", " foo = bar, baz = quux ", "key=510"},
   229  			true,
   230  			0,
   231  			"",
   232  			"",
   233  			[]jujuc.Metric{{
   234  				Key: "key", Value: "510", Time: time.Now(),
   235  				Labels: map[string]string{"foo": "bar", "baz": "quux"},
   236  			}},
   237  		}, {
   238  			"add multiple metrics with labels",
   239  			[]string{"add-metric", "--labels", "foo=bar,baz=quux", "a=1", "b=2"},
   240  			true,
   241  			0,
   242  			"",
   243  			"",
   244  			[]jujuc.Metric{{
   245  				Key: "a", Value: "1", Time: time.Now(),
   246  				Labels: map[string]string{"foo": "bar", "baz": "quux"},
   247  			}, {
   248  				Key: "b", Value: "2", Time: time.Now(),
   249  				Labels: map[string]string{"foo": "bar", "baz": "quux"},
   250  			}},
   251  		}, {
   252  			"can't add metrics with labels",
   253  			[]string{"add-metric", "--labels", "foo=bar", "key=60", "key2=50.4"},
   254  			false,
   255  			1,
   256  			"",
   257  			"ERROR cannot record metric: metrics disabled\n",
   258  			nil,
   259  		}, {
   260  			"cannot add builtin metric with labels",
   261  			[]string{"add-metric", "--labels", "foo=bar", "juju-key=50"},
   262  			true,
   263  			1,
   264  			"",
   265  			"ERROR juju-key uses a reserved prefix\n",
   266  			nil,
   267  		}}
   268  	for i, t := range testCases {
   269  		c.Logf("test %d: %s", i, t.about)
   270  		hctx := s.GetHookContext(c, -1, "")
   271  		hctx.canAddMetrics = t.canAddMetrics
   272  		com, err := jujuc.NewCommand(hctx, t.cmd[0])
   273  		c.Assert(err, jc.ErrorIsNil)
   274  		ctx := cmdtesting.Context(c)
   275  		ret := cmd.Main(jujuc.NewJujucCommandWrappedForTest(com), ctx, t.cmd[1:])
   276  		c.Check(ret, gc.Equals, t.result)
   277  		c.Check(bufferString(ctx.Stdout), gc.Equals, t.stdout)
   278  		c.Check(bufferString(ctx.Stderr), gc.Equals, t.stderr)
   279  		c.Check(hctx.metrics, gc.HasLen, len(t.expect))
   280  		if len(hctx.metrics) != len(t.expect) {
   281  			continue
   282  		}
   283  
   284  		sort.Sort(SortedMetrics(hctx.metrics))
   285  		sort.Sort(SortedMetrics(t.expect))
   286  
   287  		for i, expected := range t.expect {
   288  			c.Check(expected.Key, gc.Equals, hctx.metrics[i].Key)
   289  			c.Check(expected.Value, gc.Equals, hctx.metrics[i].Value)
   290  			c.Check(expected.Labels, gc.DeepEquals, hctx.metrics[i].Labels)
   291  		}
   292  	}
   293  }
   294  
   295  type SortedMetrics []jujuc.Metric
   296  
   297  func (m SortedMetrics) Len() int           { return len(m) }
   298  func (m SortedMetrics) Swap(i, j int)      { m[i], m[j] = m[j], m[i] }
   299  func (m SortedMetrics) Less(i, j int) bool { return m[i].Key < m[j].Key }