Deletes an old, unused metric library.
This library was the precursor to the current existing library.
Bug: None
Test: UT
Change-Id: Icffb46cde8156a831bc4c44104003425dda4990b
diff --git a/acts/framework/acts/libs/metrics/__init__.py b/acts/framework/acts/libs/metrics/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/acts/framework/acts/libs/metrics/__init__.py
+++ /dev/null
diff --git a/acts/framework/acts/libs/metrics/bindings.py b/acts/framework/acts/libs/metrics/bindings.py
deleted file mode 100644
index 8b11c03..0000000
--- a/acts/framework/acts/libs/metrics/bindings.py
+++ /dev/null
@@ -1,96 +0,0 @@
-import json
-
-from acts.libs.test_binding.binding import Binding
-
-
-def _metric_binding_base(metric, binding_name, bind_to_arg=True,
- arg_modifier=None, before=None,
- after=None):
- """The base decorator for creating a binding between a test and a metric.
-
- Args:
- metric: The metric to use.
- binding_name: The name of the metric binding. This will be the metric
- group displayed in the summary.
- bind_to_arg: If True, the metric will be bound to an argument of
- binding_name on the target.
- arg_modifier: The function to use as a argument modifier. Must be of
- format (inner, *arg, **kwarg) => (*newArg, **newKwargs).
- before: The function to call before the test. Must be of format
- (inner, instance, *arg, **kwarg) => void
- after: The function to call after the test. Must be of format
- (inner, result, *args, **kwargs) => void
-
- Returns:
- The method that will create the binding.
- """
-
- def _arg_modifier(inner, *args, **kwargs):
- if binding_name in kwargs:
- raise ValueError(
- 'Cannot have two bindings with name %s.' % binding_name)
-
- new_kwargs = dict(kwargs)
- if bind_to_arg:
- new_kwargs[binding_name] = metric
-
- if arg_modifier:
- return arg_modifier(*args, **new_kwargs)
- else:
- return args, new_kwargs
-
- def _inner(func):
- return Binding(inner=func, arg_modifier=_arg_modifier, before=_before,
- after=_after)
-
- def _before(inner, instance, *args, **kwargs):
- metric.setup(instance, inner, binding_name)
- if before:
- before(inner, instance, *args, **kwargs)
-
- def _after(inner, result, *args, **kwargs):
- if after:
- after(inner, result, *args, **kwargs)
-
- metric.finish()
-
- return _inner
-
-
-def metric_binding(metric, binding_name, bind_to_arg=True):
- """Decorator that will bind a metric to a kwarg.
-
- Args:
- metric: The metric to bind.
- binding_name: The name the metric should be recorded under.
- bind_to_arg: If true, the metric object will be passed in as a named
- argument with the same name as binding_name.
-
- Returns:
- The method that will create the binding.
- """
- return _metric_binding_base(metric, binding_name, bind_to_arg=bind_to_arg)
-
-
-def auto_passive_metric(metric, binding_name, bind_to_arg=True):
- """Decorator that will bind a metric to auto run with a test.
-
- Args:
- metric: The metric to bind.
- binding_name: The name the metric should be recorded under.
- bind_to_arg: If true, the metric object will be passed in as a named
- argument with the same name as binding_name.
-
- Returns:
- The method that will create the binding.
- """
-
- def _before(inner, *args, **kwargs):
- metric.start()
-
- def _after(inner, result, *args, **kwargs):
- metric.stop()
-
- return _metric_binding_base(metric, binding_name, bind_to_arg=bind_to_arg,
- before=_before,
- after=_after)
diff --git a/acts/framework/acts/libs/metrics/cpu_metric.py b/acts/framework/acts/libs/metrics/cpu_metric.py
deleted file mode 100644
index 1c31f7c..0000000
--- a/acts/framework/acts/libs/metrics/cpu_metric.py
+++ /dev/null
@@ -1,43 +0,0 @@
-import logging
-import re
-import time
-
-from acts.libs.metrics.metric import AsyncRecordableMetric
-
-CPU_INFO_REGEX = re.compile(
- '(?P<total>[^%]+)% TOTAL:'
- ' (?P<user>[^%]+)% user'
- ' \+ (?P<kernel>[^%]+)% kernel'
- ' \+ (?P<iowait>[^%]+)% iowait'
- ' \+ (?P<irq>[^%]+)% irq'
- ' \+ (?P<softirq>[^%]+)% softirq')
-
-
-class CpuMetric(AsyncRecordableMetric):
- """Metric for measuring the cpu usage of a phone over time."""
-
- def run_one_iteration(self):
- for android_device in self.test.android_devices:
- try:
- cpu_info = android_device.adb.shell('dumpsys cpuinfo')
- cpu_info_line = cpu_info.splitlines()[-1]
- current_time = time.time()
-
- match = CPU_INFO_REGEX.match(cpu_info_line)
- if match:
- record = {
- 'total': float(match.group('total')) / 100.0,
- 'user': float(match.group('user')) / 100.0,
- 'kernel': float(match.group('kernel')) / 100.0,
- 'io': float(match.group('iowait')) / 100.0,
- 'irq': float(match.group('irq')) / 100.0,
- 'softirg': float(match.group('softirq')) / 100.0,
- }
-
- self.record(record, current_time, android_device.serial)
- else:
- logging.error('Invalid format: %s', cpu_info_line)
- except Exception as e:
- serial = android_device.serial
- logging.exception(
- 'Could not record for android device %s', serial)
diff --git a/acts/framework/acts/libs/metrics/metric.py b/acts/framework/acts/libs/metrics/metric.py
deleted file mode 100644
index 5112999..0000000
--- a/acts/framework/acts/libs/metrics/metric.py
+++ /dev/null
@@ -1,185 +0,0 @@
-import json
-import os
-import threading
-
-
-class Metric(object):
- """An object that can measure a metric during a test."""
-
- def __init__(self):
- self.test = None
- self.testcase = None
- self.metric_dir = None
- self.binding_name = None
-
- def setup(self, test, testcase, binding_name):
- """Sets up the metric to work with a test.
-
- Args:
- test: An instance of the test class.
- testcase: The testcase function to be called.
- binding_name: The name this metric will be bound as in the output.
- """
- self.test = test
- self.testcase = testcase
- self.binding_name = binding_name
- self.metric_dir = os.path.join(self.test.log_path, 'undeclared_output',
- type(self.test).__name__,
- self.testcase.__name__,
- self.binding_name)
- os.makedirs(self.metric_dir)
-
- def finish(self):
- """Called when the metric is being cleaned up and has finished."""
- pass
-
-
-class PassiveMetric(Metric):
- """A metric that records information passively while a test runs."""
-
- def start(self):
- """Starts the metric."""
- pass
-
- def pause(self):
- """Pauses the metric."""
- pass
-
- def stop(self):
- """Stops the metric."""
- pass
-
-
-class JsonMetric(Metric):
- """A metric that will write out to a json file when finished.
-
- Warnings: This metric will store all values in memory and will not be
- released automatically until the process ends. For large amounts of data
- either make sure to clear the data manually when done, or stream to a file
- directly while the test is running.
- """
-
- def as_json(self):
- pass
-
- def finish(self):
- metric_file = os.path.join(self.metric_dir, 'raw.json')
- with open(metric_file, mode='w') as f:
- f.write(json.dumps(self.as_json(), indent=2))
-
-
-class RecordableMetric(Metric):
- """A metric that provides recording data as a stream.
-
- RecordableMetrics provide recording x,y value metrics as a stream. This
- is often used to record variable and constant data such as a metrics change
- over time.
-
- RecordableMetrics can record to multiple channels which represent multiple
- recordings of the same metric. For example you might record the same metric
- on multiple phones. Each pone would be given there own channel.
-
- Metrics will be recorded to a smetric file. Each value recorded will be
- recorded on it's own line as a json. To read back simply read each entry
- line by line.
-
- Attributes:
- default_channel: The default channel to write to if none is given.
- open_channels: A mapping of channel name to file handle. Channels will
- be kept open until the metric finishes to improve performance.
- This mapping keeps track of all open channels so they may be written
- to multiple times, and closed on finished.
- """
-
- def __init__(self, default_channel='std'):
- """
- Args:
- default_channel: The channel to record to by default if no channel
- is given.
- """
- self.default_channel = default_channel
- self.open_channels = {}
-
- def record(self, value, key, channel=None):
- """Records a single pair of values.
-
- Args:
- value: The variable part of the recording. This will be the metric
- data.
- key: The constant part of the recording. This will signify the
- conditions the measurement happened.
- channel: The channel to record to.
- """
- channel = channel or self.default_channel
-
- stream_file = self._get_channel_stream(channel)
-
- entry = {
- 'key': key,
- 'value': value,
- }
-
- stream_file.write(json.dumps(entry))
- stream_file.write('\n')
-
- def _get_channel_stream(self, channel):
- if channel not in self.open_channels:
- channel_file = os.path.join(self.metric_dir, channel + '.smetric')
-
- if os.path.exists(channel_file):
- raise ValueError(
- 'Trying to record to a smetric that already exists.')
-
- if not os.path.exists(os.path.dirname(channel_file)):
- os.makedirs(os.path.dirname(channel_file))
-
- stream_file = open(channel_file, mode='w')
- self.open_channels[channel] = stream_file
- else:
- stream_file = self.open_channels[channel]
- return stream_file
-
- def finish(self):
- for blob in self.open_channels.values():
- blob.close()
-
-
-class AsyncRecordableMetric(RecordableMetric, PassiveMetric):
- """A metric that runs in another thread and records at a certain rate."""
-
- def __init__(self, rate, default_channel="std"):
- """
- Args:
- rate: The rate to record at (in seconds).
- default_channel: The channel to record to by default.
- """
- super().__init__(default_channel)
- self.rate = rate
- self.timer = None
- self.has_stopped = False
- self.lock = threading.Lock()
-
- def start(self):
- if self.timer:
- return
-
- self.has_stopped = False
-
- self._iteration()
-
- def stop(self):
- with self.lock:
- if self.timer:
- self.timer.cancel()
- self.timer = None
-
- def _iteration(self):
- with self.lock:
- if not self.has_stopped:
- self.run_one_iteration()
- self.timer = threading.Timer(self.rate, self._iteration)
- self.timer.start()
-
- def run_one_iteration(self):
- """Called once every iteration to record."""
- pass
diff --git a/acts/framework/acts/libs/metrics/time_metric.py b/acts/framework/acts/libs/metrics/time_metric.py
deleted file mode 100644
index e89f962..0000000
--- a/acts/framework/acts/libs/metrics/time_metric.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import time
-from enum import IntEnum
-
-from acts.libs.metrics.metric import PassiveMetric, JsonMetric
-
-
-class TestTime(PassiveMetric, JsonMetric):
- """A metric which will measure the amount of time passed."""
-
- class Status(IntEnum):
- STATUS_STOPPED = 0
- STATUS_RUNNING = 1
- STATUS_PAUSED = 2
-
- def __init__(self):
- super().__init__()
- self.status = TestTime.Status.STATUS_STOPPED
- self.last_start_time = 0
- self.duration = 0
-
- def start(self):
- if self.status == TestTime.Status.STATUS_STOPPED:
- self.duration = 0
- if self.status != TestTime.Status.STATUS_RUNNING:
- self.last_start_time = time.time()
- self.status = TestTime.Status.STATUS_RUNNING
-
- def pause(self):
- if self.status == TestTime.Status.STATUS_RUNNING:
- self.status = TestTime.Status.STATUS_PAUSED
- self.duration = time.time() - self.last_start_time
-
- def stop(self):
- if self.status == TestTime.Status.STATUS_RUNNING:
- self.duration = time.time() - self.last_start_time
- self.status = TestTime.Status.STATUS_STOPPED
-
- def as_json(self):
- return {
- 'time': self.duration
- }
diff --git a/acts/framework/tests/libs/metrics/__init__.py b/acts/framework/tests/libs/metrics/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/acts/framework/tests/libs/metrics/__init__.py
+++ /dev/null
diff --git a/acts/framework/tests/libs/metrics/auto_passive_metric_binding_test.py b/acts/framework/tests/libs/metrics/auto_passive_metric_binding_test.py
deleted file mode 100644
index 55fba3c..0000000
--- a/acts/framework/tests/libs/metrics/auto_passive_metric_binding_test.py
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2017 - The Android Open Source Project
-#
-# 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
-
-from acts.libs.metrics.bindings import auto_passive_metric
-from acts.libs.metrics.metric import PassiveMetric
-from acts import signals
-
-
-class MockMetric(PassiveMetric):
- def __init__(self):
- self.started = False
- self.stopped = False
-
- def setup(self, test, testcase, binding_name):
- self.test = test
- self.testcase = testcase
- self.binding_name = binding_name
-
- def start(self):
- self.started = True
-
- def stop(self):
- self.stopped = True
-
- def finish(self):
- pass
-
-
-class AutoPassiveMetricBindingTest(unittest.TestCase):
-
- def test_binding(self):
-
- metric = MockMetric()
-
- class TestTest(object):
- @auto_passive_metric(metric, 'binding', bind_to_arg=False)
- def test(self):
- pass
-
- test = TestTest()
-
- try:
- test.test()
- except signals.TestPass:
- pass
-
- self.assertTrue(metric.started)
- self.assertTrue(metric.stopped)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/acts/framework/tests/libs/metrics/json_metric_test.py b/acts/framework/tests/libs/metrics/json_metric_test.py
deleted file mode 100644
index 05930b8..0000000
--- a/acts/framework/tests/libs/metrics/json_metric_test.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2017 - The Android Open Source Project
-#
-# 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 json
-import os
-import unittest
-
-import mock
-from mock import patch, Mock, MagicMock
-
-from acts.libs.metrics.metric import JsonMetric
-from acts.libs.test_binding.all_tests_decorator import for_all_tests
-
-
-class MockJsonMetric(JsonMetric):
- def __init__(self, mock_json, mock_metric_dir):
- super().__init__()
- self.json = mock_json
- self.metric_dir = mock_metric_dir
-
- def setup(self, test, testcase, binding_name):
- pass
-
- def as_json(self):
- return self.json
-
-
-class JsonMetricTest(unittest.TestCase):
- def test_write_json_on_finish(self):
- mock_open = mock.mock_open()
-
- mock_json = {
- 'v': 10
- }
- mock_path = '/metric/path'
- mock_metric = MockJsonMetric(mock_json, mock_path)
-
- with patch('builtins.open', mock_open):
- mock_metric.finish()
-
- mock_open.assert_called_with(os.path.join(mock_path, 'raw.json'),
- mode='w')
- mock_open().write.assert_called_with(json.dumps(mock_json, indent=2))
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/acts/framework/tests/libs/metrics/metric_binding_test.py b/acts/framework/tests/libs/metrics/metric_binding_test.py
deleted file mode 100644
index f5d5a59..0000000
--- a/acts/framework/tests/libs/metrics/metric_binding_test.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2017 - The Android Open Source Project
-#
-# 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
-
-from acts.libs.metrics.bindings import metric_binding
-from acts.libs.metrics.metric import Metric
-from acts import signals
-
-
-class MockMetric(Metric):
- def setup(self, test, testcase, binding_name):
- self.test = test
- self.testcase = testcase
- self.binding_name = binding_name
-
-
-class MetricBindingTest(unittest.TestCase):
-
- def test_binding(self):
-
- metric = MockMetric()
-
- class TestTest(object):
- @metric_binding(metric, 'binding', bind_to_arg=False)
- def test(self):
- pass
-
- test = TestTest()
-
- try:
- test.test()
- except signals.TestPass:
- pass
-
- self.assertEqual(metric.test.__class__.__name__, TestTest.__name__)
- self.assertEqual(metric.testcase.__name__, TestTest.test.__name__)
- self.assertEqual(metric.binding_name, 'binding')
-
- def test_arg_binding(self):
-
- metric = MockMetric()
-
- class TestTest(object):
- def __init__(self):
- self.grabbed_metric = None
-
- @metric_binding(metric, 'binding', bind_to_arg=True)
- def test(self, binding):
- self.grabbed_metric = binding
-
- test = TestTest()
-
- try:
- test.test()
- except signals.TestPass:
- pass
-
- self.assertEqual(test.grabbed_metric, metric)
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/acts/framework/tests/libs/metrics/recordable_metric_test.py b/acts/framework/tests/libs/metrics/recordable_metric_test.py
deleted file mode 100644
index 73819d5..0000000
--- a/acts/framework/tests/libs/metrics/recordable_metric_test.py
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2017 - The Android Open Source Project
-#
-# 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 json
-import os
-import unittest
-
-import mock
-from mock import patch, Mock, MagicMock
-
-from acts.libs.metrics.metric import RecordableMetric
-
-
-class MockRecordableMetric(RecordableMetric):
- def __init__(self, mock_metric_dir):
- super().__init__()
- self.metric_dir = mock_metric_dir
-
- def setup(self, test, testcase, binding_name):
- pass
-
-
-class RecordableMetricTest(unittest.TestCase):
- def get_mock_channel_stream(self, path, *args, **kwargs):
- if path not in self._mock_channel_stream_lookup:
- self._mock_channel_stream_lookup[path] = mock.MagicMock()
-
- return self._mock_channel_stream_lookup[path]
-
- def setUp(self):
- self._mock_channel_stream_lookup = {}
-
- @patch("os.path.exists")
- @patch("os.makedirs")
- @patch("builtins.open")
- def test_create_channel_stream(self, mock_open, mock_make_dirs,
- mock_exists):
- mock_path = '/metric/path'
- mock_metric = MockRecordableMetric(mock_path)
-
- mock_exists.return_value = False
- mock_open.side_effect = self.get_mock_channel_stream
-
- mock_metric.record(10, "test", "new")
- mock_open.assert_called_with(os.path.join(mock_path, "new.smetric"),
- mode='w')
-
- mock_metric.record(20, "test", "other")
- mock_open.assert_called_with(os.path.join(mock_path, "other.smetric"),
- mode='w')
-
- mock_metric.finish()
-
- @patch("os.path.exists")
- @patch("os.makedirs")
- @patch("builtins.open")
- def test_create_channel_error_on_existing_stream(self, mock_open,
- mock_make_dirs,
- mock_exists):
- mock_path = '/metric/path'
- mock_metric = MockRecordableMetric(mock_path)
-
- mock_exists.return_value = True
- mock_open.side_effect = self.get_mock_channel_stream
-
- with self.assertRaises(ValueError):
- mock_metric.record(10, "test", "new")
-
- @patch("os.path.exists")
- @patch("os.makedirs")
- @patch("builtins.open")
- def test_record_to_channel_stream(self, mock_open,
- mock_make_dirs,
- mock_exists):
- mock_path = '/metric/path'
- new_metric_path = os.path.join(mock_path, 'new.smetric')
- mock_metric = MockRecordableMetric(mock_path)
-
- mock_exists.return_value = False
- mock_open.side_effect = self.get_mock_channel_stream
-
- key = "test"
- value = 10
- mock_metric.record(value, key, "new")
-
- expected_json = json.dumps({
- "key": key,
- "value": value,
- })
- mock_stream = self.get_mock_channel_stream(new_metric_path)
- self.assertTrue(
- mock_stream.write.call_args_list[0] == mock.call(expected_json))
- self.assertTrue(
- mock_stream.write.call_args_list[1] == mock.call("\n"))
-
- @patch("os.path.exists")
- @patch("os.makedirs")
- @patch("builtins.open")
- def test_close_blobs_on_finished(self, mock_open,
- mock_make_dirs,
- mock_exists):
- mock_path = '/metric/path'
- new_metric_path = os.path.join(mock_path, 'new.smetric')
- mock_metric = MockRecordableMetric(mock_path)
-
- mock_exists.return_value = False
- mock_open.side_effect = self.get_mock_channel_stream
-
- mock_metric.record(10, "test", "new")
- mock_metric.finish()
-
- mock_stream = self.get_mock_channel_stream(new_metric_path)
- self.assertTrue(mock_stream.close.called)
-
-
-if __name__ == "__main__":
- unittest.main()