monasca-agent/tests/test_aggregator.py
Joseph Davis 623a4db21f Enable unit tests for py36
Even though there was a py36 test enabled in the gate, the tox.ini
configuration was not actually invoking the unit tests.  This
change sets up the environment to allow tests to run.

As a result, a number of Python3 errors are uncovered and fixed.

Notably:
  Python 3 does not have contextlib.nested, so reformatting using ,
  file() is not in Python 3, so use io.open() instead
  Use six.assertCountEqual(self, in tests

safe_decode:
  subprocess.check_output returns in byte encoding, while default text
type str. safe_decode does the right thing by making sure string are not
bytes in python2 and python3

No ascci encoding:
 python3 defaults to UTF-8 encoding, which is merely an extension to
ascii (default for python2).

test_json_plugin.py:
 the file being opened in binary(wb) mode so python is expecting the
string in bytes.

Some of the refactoring should be revisited after we drop Python 2
support.

Change-Id: I62b46a2509c39201ca015ca7c269b2ea70c376c8
Story: 2005047
Task: 29547
2019-07-18 16:08:09 +02:00

290 lines
12 KiB
Python

# (C) Copyright 2015-2017 Hewlett Packard Enterprise Development Company LP
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import unittest
import six
import monasca_agent.common.aggregator as aggregator
import monasca_agent.common.metrics as metrics_pkg
import monasca_common.validation.metrics as metric_validator
# a few valid characters to test
valid_name_chars = ".'_-"
invalid_name_chars = metric_validator.INVALID_CHARS
# a few valid characters to test
valid_dimension_chars = " .'_-"
invalid_dimension_chars = metric_validator.INVALID_CHARS
class TestMetricsAggregator(unittest.TestCase):
def setUp(self):
self.aggregator = aggregator.MetricsAggregator("Foo")
def submit_metric(self, name, value,
dimensions=None,
value_meta=None,
exception=None):
if exception:
with self.assertRaises(exception):
self.aggregator.submit_metric(name,
value,
metrics_pkg.Gauge,
dimensions=dimensions,
delegated_tenant=None,
hostname=None,
device_name=None,
value_meta=value_meta)
else:
self.aggregator.submit_metric(name,
value,
metrics_pkg.Gauge,
dimensions=dimensions,
delegated_tenant=None,
hostname=None,
device_name=None,
value_meta=value_meta)
def testValidMetric(self):
dimensions = {'A': 'B', 'B': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
5,
dimensions=dimensions,
value_meta=value_meta)
def testValidMetricUnicodeDimensionValue(self):
dimensions = {six.unichr(2440): 'B', 'B': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
5,
dimensions=dimensions,
value_meta=value_meta)
def testValidMetricUnicodeDimensionKey(self):
dimensions = {'A': 'B', 'B': six.unichr(920), 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
5,
dimensions=dimensions,
value_meta=value_meta)
def testValidMetricUnicodeMetricName(self):
dimensions = {'A': 'B', 'B': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric(six.unichr(6021),
5,
dimensions=dimensions,
value_meta=value_meta)
def testInvalidMetricName(self):
dimensions = {'A': 'B', 'B': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("TooLarge" * 255,
5,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidMetricName)
def testInvalidMetricNameEmpty(self):
dimensions = {'A': 'B', 'B': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric('',
5,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidMetricName)
def testInvalidMetricNameNonStr(self):
dimensions = {'A': 'B', 'B': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric(133,
5,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidMetricName)
def testInvalidMetricRestrictedCharacters(self):
dimensions = {'A': 'B', 'B': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric('"Foo"',
5,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidMetricName)
def testInvalidDimensionEmptyKey(self):
dimensions = {'A': 'B', '': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
5,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidDimensionKey)
def testInvalidDimensionEmptyValue(self):
dimensions = {'A': 'B', 'B': 'C', 'D': ''}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
5,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidDimensionValue)
def testInvalidDimensionNonStrKey(self):
dimensions = {'A': 'B', 4: 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
5,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidDimensionKey)
def testInvalidDimensionNonStrValue(self):
dimensions = {'A': 13.3, 'B': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
5,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidDimensionValue)
def testInvalidDimensionKeyLength(self):
dimensions = {'A'*256: 'B', 'B': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
5,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidDimensionKey)
def testInvalidDimensionValueLength(self):
dimensions = {'A': 'B', 'B': 'C'*256, 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
5,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidDimensionValue)
def testValidDimensionKeyParenthesesCharacter(self):
dimensions = {'A': 'B', 'B': 'C', '(D)': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
5,
dimensions=dimensions,
value_meta=value_meta)
def testInvalidDimensionValueRestrictedCharacters(self):
dimensions = {'A': 'B;', 'B': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
5,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidDimensionValue)
def testInvalidDimensionKeyLeadingUnderscore(self):
dimensions = {'_A': 'B', 'B': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
5,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidDimensionKey)
def testInvalidValue(self):
dimensions = {'A': 'B', 'B': 'C', 'D': 'E'}
value_meta = {"This is a test": "test, test, test"}
self.submit_metric("Foo",
"value",
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidValue)
def testValidNameChars(self):
for c in valid_name_chars:
self.submit_metric('test{}counter'.format(c), 2,
dimensions={"test-key": "test-value"})
def testInvalidNameChars(self):
for c in invalid_name_chars:
self.submit_metric('test{}counter'.format(c), 2,
dimensions={"test-key": "test-value"},
exception=metric_validator.InvalidMetricName)
def testValidDimensionChars(self):
for c in valid_dimension_chars:
self.submit_metric('test-counter', 2,
dimensions={"test{}key".format(c): "test{}value".format(c)})
def testInvalidDimensionChars(self):
for c in invalid_dimension_chars:
self.submit_metric('test-counter', 2,
dimensions={'test{}key'.format(c): 'test-value'},
exception=metric_validator.InvalidDimensionKey)
self.submit_metric('test-counter', 2,
dimensions={'test-key': 'test{}value'.format(c)},
exception=metric_validator.InvalidDimensionValue)
def testTooManyValueMeta(self):
dimensions = {'A': 'B', 'B': 'C', 'D': 'E'}
value_meta = {}
for i in range(0, 17):
value_meta['key{}'.format(i)] = 'value{}'.format(i)
self.submit_metric("Foo",
2,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidValueMeta)
def testEmptyValueMetaKey(self):
dimensions = {'A': 'B', 'B': 'C', 'D': 'E'}
value_meta = {'': 'BBB'}
self.submit_metric("Foo",
2,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidValueMeta)
def testTooLongValueMetaKey(self):
dimensions = {'A': 'B', 'B': 'C', 'D': 'E'}
key = "K"
for i in range(0, metric_validator.VALUE_META_NAME_MAX_LENGTH):
key = "{}{}".format(key, "1")
value_meta = {key: 'BBB'}
print(key)
self.submit_metric("Foo",
2,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidValueMeta)
def testTooLargeValueMeta(self):
dimensions = {'A': 'B', 'B': 'C', 'D': 'E'}
value_meta_value = ""
num_value_meta = 10
for i in range(0, metric_validator.VALUE_META_VALUE_MAX_LENGTH//num_value_meta):
value_meta_value = '{}{}'.format(value_meta_value, '1')
value_meta = {}
for i in range(0, num_value_meta):
value_meta['key{}'.format(i)] = value_meta_value
self.submit_metric("Foo",
2,
dimensions=dimensions,
value_meta=value_meta,
exception=metric_validator.InvalidValueMeta)