1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import unittest 6 7from telemetry.internal.platform.power_monitor import cros_power_monitor 8 9 10class CrosPowerMonitorMonitorTest(unittest.TestCase): 11 initial_power = ('''line_power_connected 0 12battery_present 1 13battery_percent 70.20 14battery_charge 2.83 15battery_charge_full 4.03 16battery_charge_full_design 4.03 17battery_current 1.08 18battery_energy 31.83 19battery_energy_rate 12.78 20battery_voltage 11.82 21battery_discharging 1''') 22 final_power = ('''line_power_connected 0 23battery_present 1 24battery_percent 70.20 25battery_charge 2.83 26battery_charge_full 4.03 27battery_charge_full_design 4.03 28battery_current 1.08 29battery_energy 31.83 30battery_energy_rate 12.80 31battery_voltage 12.24 32battery_discharging 1''') 33 incomplete_final_power = ('''line_power_connected 0 34battery_present 1 35battery_percent 70.20 36battery_charge 2.83 37battery_charge_full 4.03 38battery_charge_full_design 4.03 39battery_energy_rate 12.80 40battery_discharging 1''') 41 expected_power = { 42 'energy_consumption_mwh': 2558.0, 43 'power_samples_mw': [12780.0, 12800.0], 44 'component_utilization': { 45 'battery': { 46 'charge_full': 4.03, 47 'charge_full_design': 4.03, 48 'charge_now': 2.83, 49 'current_now': 1.08, 50 'energy': 31.83, 51 'energy_rate': 12.80, 52 'voltage_now': 12.24 53 } 54 } 55 } 56 expected_incomplete_power = { 57 'energy_consumption_mwh': 2558.0, 58 'power_samples_mw': [12780.0, 12800.0], 59 'component_utilization': { 60 'battery': { 61 'charge_full': 4.03, 62 'charge_full_design': 4.03, 63 'charge_now': 2.83, 64 'energy_rate': 12.80, 65 } 66 } 67 } 68 expected_cpu = { 69 'whole_package': { 70 'frequency_percent': { 71 1700000000: 3.29254111574526, 72 1600000000: 0.0, 73 1500000000: 0.0, 74 1400000000: 0.15926805099535601, 75 1300000000: 0.47124116307273645, 76 1200000000: 0.818756100807525, 77 1100000000: 1.099381692400982, 78 1000000000: 2.5942528544384302, 79 900000000: 5.68661122326737, 80 800000000: 3.850545467654628, 81 700000000: 2.409691872245393, 82 600000000: 1.4693702487650486, 83 500000000: 2.4623575553879373, 84 400000000: 2.672038150383057, 85 300000000: 3.415770495015825, 86 200000000: 69.59817400982045 87 }, 88 'cstate_residency_percent': { 89 'C0': 83.67623835616438535, 90 'C1': 0.2698609589041096, 91 'C2': 0.2780191780821918, 92 'C3': 15.77588150684931505 93 } 94 }, 95 'cpu0': { 96 'frequency_percent': { 97 1700000000: 4.113700564971752, 98 1600000000: 0.0, 99 1500000000: 0.0, 100 1400000000: 0.1765536723163842, 101 1300000000: 0.4943502824858757, 102 1200000000: 0.7944915254237288, 103 1100000000: 1.2226341807909604, 104 1000000000: 3.0632062146892656, 105 900000000: 5.680614406779661, 106 800000000: 3.6679025423728815, 107 700000000: 2.379060734463277, 108 600000000: 1.4124293785310735, 109 500000000: 2.599752824858757, 110 400000000: 3.0102401129943503, 111 300000000: 3.650247175141243, 112 200000000: 67.73481638418079 113 }, 114 'cstate_residency_percent': { 115 'C0': 76.76226164383562, 116 'C1': 0.3189164383561644, 117 'C2': 0.4544301369863014, 118 'C3': 22.4643917808219178 119 } 120 }, 121 'cpu1': { 122 'frequency_percent': { 123 1700000000: 2.4713816665187682, 124 1600000000: 0.0, 125 1500000000: 0.0, 126 1400000000: 0.1419824296743278, 127 1300000000: 0.44813204365959713, 128 1200000000: 0.8430206761913214, 129 1100000000: 0.9761292040110037, 130 1000000000: 2.1252994941875945, 131 900000000: 5.69260803975508, 132 800000000: 4.033188392936374, 133 700000000: 2.4403230100275093, 134 600000000: 1.526311118999024, 135 500000000: 2.3249622859171177, 136 400000000: 2.3338361877717633, 137 300000000: 3.1812938148904073, 138 200000000: 71.46153163546012 139 }, 140 'cstate_residency_percent': { 141 'C0': 90.5902150684931507, 142 'C1': 0.2208054794520548, 143 'C2': 0.1016082191780822, 144 'C3': 9.0873712328767123 145 } 146 } 147 } 148 149 def _assertPowerEqual(self, results, expected): 150 battery = results['component_utilization']['battery'] 151 expected_battery = expected['component_utilization']['battery'] 152 self.assertItemsEqual(battery.keys(), expected_battery.keys()) 153 for value in battery: 154 self.assertAlmostEqual(battery[value], expected_battery[value]) 155 156 self.assertAlmostEqual(results['energy_consumption_mwh'], 157 expected['energy_consumption_mwh']) 158 self.assertAlmostEqual(results['power_samples_mw'][0], 159 expected['power_samples_mw'][0]) 160 self.assertAlmostEqual(results['power_samples_mw'][1], 161 expected['power_samples_mw'][1]) 162 163 def testParsePower(self): 164 results = cros_power_monitor.CrosPowerMonitor.ParsePower( 165 self.initial_power, self.final_power, 0.2) 166 self._assertPowerEqual(results, self.expected_power) 167 168 def testParseIncompletePowerState(self): 169 """Test the case where dump_power_status only outputs partial fields. 170 171 CrosPowerMonitor hard-coded expected fields from dump_power_status, 172 this test ensures it parses successfully when expected fields does not 173 exist. It's mainly for backward compatibility. 174 """ 175 results = cros_power_monitor.CrosPowerMonitor.ParsePower( 176 self.initial_power, self.incomplete_final_power, 0.2) 177 self._assertPowerEqual(results, self.expected_incomplete_power) 178 179 180 def testSplitSample(self): 181 sample = self.initial_power + '\n1408739546\n' 182 power, time = cros_power_monitor.CrosPowerMonitor.SplitSample(sample) 183 self.assertEqual(power, self.initial_power) 184 self.assertEqual(time, 1408739546) 185 186 def testCombineResults(self): 187 result = cros_power_monitor.CrosPowerMonitor.CombineResults( 188 self.expected_cpu, self.expected_power) 189 comp_util = result['component_utilization'] 190 # Test power values. 191 self.assertEqual(result['energy_consumption_mwh'], 192 self.expected_power['energy_consumption_mwh']) 193 self.assertEqual(result['power_samples_mw'], 194 self.expected_power['power_samples_mw']) 195 self.assertEqual(comp_util['battery'], 196 self.expected_power['component_utilization']['battery']) 197 # Test frequency values. 198 self.assertDictEqual( 199 comp_util['whole_package']['frequency_percent'], 200 self.expected_cpu['whole_package']['frequency_percent']) 201 self.assertDictEqual( 202 comp_util['cpu0']['frequency_percent'], 203 self.expected_cpu['cpu0']['frequency_percent']) 204 self.assertDictEqual( 205 comp_util['cpu1']['frequency_percent'], 206 self.expected_cpu['cpu1']['frequency_percent']) 207 # Test c-state residency values. 208 self.assertDictEqual( 209 comp_util['whole_package']['cstate_residency_percent'], 210 self.expected_cpu['whole_package']['cstate_residency_percent']) 211 self.assertDictEqual( 212 comp_util['cpu0']['cstate_residency_percent'], 213 self.expected_cpu['cpu0']['cstate_residency_percent']) 214 self.assertDictEqual( 215 comp_util['cpu1']['cstate_residency_percent'], 216 self.expected_cpu['cpu1']['cstate_residency_percent']) 217 218 def testCanMonitorPower(self): 219 # TODO(tmandel): Add a test here where the device cannot monitor power. 220 initial_status = cros_power_monitor.CrosPowerMonitor.ParsePowerStatus( 221 self.initial_power) 222 final_status = cros_power_monitor.CrosPowerMonitor.ParsePowerStatus( 223 self.final_power) 224 self.assertTrue(cros_power_monitor.CrosPowerMonitor.IsOnBatteryPower( 225 initial_status, 'peppy')) 226 self.assertTrue(cros_power_monitor.CrosPowerMonitor.IsOnBatteryPower( 227 final_status, 'butterfly')) 228