1#!/usr/bin/env python3 2# 3# Copyright 2019 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the 'License'); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an 'AS IS' BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import os 18import statistics 19import unittest 20from unittest import mock 21from unittest.mock import patch 22 23from acts.controllers import power_metrics 24from acts.controllers.power_metrics import CURRENT 25from acts.controllers.power_metrics import END_TIMESTAMP 26from acts.controllers.power_metrics import HOUR 27from acts.controllers.power_metrics import MILLIAMP 28from acts.controllers.power_metrics import MINUTE 29from acts.controllers.power_metrics import Metric 30from acts.controllers.power_metrics import PowerMetrics 31from acts.controllers.power_metrics import START_TIMESTAMP 32from acts.controllers.power_metrics import TIME 33from acts.controllers.power_metrics import WATT 34 35FAKE_UNIT_TYPE = 'fake_unit' 36FAKE_UNIT = 'F' 37 38 39class MeasurementTest(unittest.TestCase): 40 """Unit tests for the Measurement class.""" 41 42 def test_init_with_valid_unit_type(self): 43 """Test that a Measurement is properly initialized given a valid unit 44 type. 45 """ 46 measurement = Metric(2, CURRENT, MILLIAMP) 47 self.assertEqual(measurement.value, 2) 48 self.assertEqual(measurement.unit, MILLIAMP) 49 50 def test_init_with_invalid_unit_type(self): 51 """Test that __init__ raises an error if given an invalid unit type.""" 52 with self.assertRaisesRegex(TypeError, 'valid unit type'): 53 measurement = Metric(2, FAKE_UNIT_TYPE, FAKE_UNIT) 54 55 def test_unit_conversion(self): 56 """Test that to_unit correctly converts value and unit.""" 57 ratio = 1000 58 current_amps = Metric.amps(15) 59 current_milliamps = current_amps.to_unit(MILLIAMP) 60 self.assertEqual(current_milliamps.value / current_amps.value, ratio) 61 62 def test_unit_conversion_with_wrong_type(self): 63 """Test that to_unit raises and error if incompatible unit type is 64 specified. 65 """ 66 current_amps = Metric.amps(3.4) 67 with self.assertRaisesRegex(TypeError, 'Incompatible units'): 68 power_watts = current_amps.to_unit(WATT) 69 70 def test_comparison_operators(self): 71 """Test that the comparison operators work as intended.""" 72 # time_a == time_b < time_c 73 time_a = Metric.seconds(120) 74 time_b = Metric(2, TIME, MINUTE) 75 time_c = Metric(0.1, TIME, HOUR) 76 77 self.assertEqual(time_a, time_b) 78 self.assertEqual(time_b, time_a) 79 self.assertLessEqual(time_a, time_b) 80 self.assertGreaterEqual(time_a, time_b) 81 82 self.assertNotEqual(time_a, time_c) 83 self.assertNotEqual(time_c, time_a) 84 self.assertLess(time_a, time_c) 85 self.assertLessEqual(time_a, time_c) 86 self.assertGreater(time_c, time_a) 87 self.assertGreaterEqual(time_c, time_a) 88 89 def test_arithmetic_operators(self): 90 """Test that the addition and subtraction operators work as intended""" 91 time_a = Metric(3, TIME, HOUR) 92 time_b = Metric(90, TIME, MINUTE) 93 94 sum_ = time_a + time_b 95 self.assertEqual(sum_.value, 4.5) 96 self.assertEqual(sum_.unit, HOUR) 97 98 sum_reversed = time_b + time_a 99 self.assertEqual(sum_reversed.value, 270) 100 self.assertEqual(sum_reversed.unit, MINUTE) 101 102 diff = time_a - time_b 103 self.assertEqual(diff.value, 1.5) 104 self.assertEqual(diff.unit, HOUR) 105 106 diff_reversed = time_b - time_a 107 self.assertEqual(diff_reversed.value, -90) 108 self.assertEqual(diff_reversed.unit, MINUTE) 109 110 111class PowerMetricsTest(unittest.TestCase): 112 """Unit tests for the PowerMetrics class.""" 113 114 SAMPLES = [0.13, 0.95, 0.32, 4.84, 2.48, 4.11, 4.85, 4.88, 4.22, 2.2] 115 RAW_DATA = list(zip(range(10), SAMPLES)) 116 VOLTAGE = 4.2 117 118 def setUp(self): 119 self.power_metrics = PowerMetrics(self.VOLTAGE) 120 121 def test_import_raw_data(self): 122 """Test that power metrics can be loaded from file. Simply ensure that 123 the number of samples is correct.""" 124 125 imported_data = power_metrics.import_raw_data( 126 os.path.join(os.path.dirname(__file__), 127 'data/sample_monsoon_data') 128 ) 129 130 count = 0 131 for _, __ in imported_data: 132 count = count + 1 133 self.assertEqual(count, 10) 134 135 @patch('acts.controllers.power_metrics.PowerMetrics') 136 def test_split_by_test_with_timestamps(self, mock_power_metric_type): 137 """Test that given test timestamps, a power metric is generated from 138 a subset of samples corresponding to the test.""" 139 timestamps = {'sample_test': {START_TIMESTAMP: 3500, 140 END_TIMESTAMP: 8500}} 141 142 mock_power_metric = mock.Mock() 143 mock_power_metric_type.side_effect = lambda v: mock_power_metric 144 metrics = power_metrics.generate_test_metrics(self.RAW_DATA, 145 timestamps=timestamps, 146 voltage=self.VOLTAGE) 147 148 self.assertEqual(mock_power_metric.update_metrics.call_count, 5) 149 150 def test_numeric_metrics(self): 151 """Test that the numeric metrics have correct values.""" 152 timestamps = {'sample_test': {START_TIMESTAMP: 0, 153 END_TIMESTAMP: 10000}} 154 metrics = power_metrics.generate_test_metrics(self.RAW_DATA, 155 timestamps=timestamps, 156 voltage=self.VOLTAGE) 157 metrics_as_dic = {m.name: m for m in metrics['sample_test']} 158 self.assertAlmostEqual(metrics_as_dic['avg_current'].value, 159 statistics.mean(self.SAMPLES) * 1000) 160 self.assertAlmostEqual(metrics_as_dic['max_current'].value, 161 max(self.SAMPLES) * 1000) 162 self.assertAlmostEqual(metrics_as_dic['min_current'].value, 163 min(self.SAMPLES) * 1000) 164 self.assertAlmostEqual( 165 metrics_as_dic['stdev_current'].value, 166 statistics.stdev(self.SAMPLES) * 1000) 167 self.assertAlmostEqual( 168 self.power_metrics.avg_power.value, 169 self.power_metrics.avg_current.value * self.VOLTAGE) 170 171 172if __name__ == '__main__': 173 unittest.main() 174