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.core.platform.power_monitor import cros_power_monitor 8 9 10class CrosPowerMonitorMonitorTest(unittest.TestCase): 11 initial_power = ('''Device: Line Power 12 path: /sys/class/power_supply/AC 13 online: no 14 type: Mains 15 enum type: Disconnected 16 model name: 17 voltage (V): 0 18 current (A): 0 19Device: Battery 20 path: /sys/class/power_supply/BAT0 21 vendor: SANYO 22 model name: AP13J3K 23 serial number: 0061 24 state: Discharging 25 voltage (V): 11.816 26 energy (Wh): 31.8262 27 energy rate (W): 12.7849 28 current (A): 1.082 29 charge (Ah): 2.829 30 full charge (Ah): 4.03 31 full charge design (Ah): 4.03 32 percentage: 70.1985 33 display percentage: 73.9874 34 technology: Li-ion''') 35 final_power = ('''Device: Line Power 36 path: /sys/class/power_supply/AC 37 online: yes 38 type: Mains 39 enum type: Disconnected 40 model name: 41 voltage (V): 0 42 current (A): 0 43Device: Battery 44 path: /sys/class/power_supply/BAT0 45 vendor: SANYO 46 model name: AP13J3K 47 serial number: 0061 48 state: Discharging 49 voltage (V): 12.238 50 energy (Wh): 31.8262 51 energy rate (W): 12.7993 52 current (A): 1.082 53 charge (Ah): 2.827 54 full charge (Ah): 4.03 55 full charge design (Ah): 4.03 56 percentage: 70.1985 57 display percentage: 73.9874 58 technology: Li-ion''') 59 expected_parsing_power = { 60 'Line Power': { 61 'path': '/sys/class/power_supply/AC', 62 'online': 'no', 63 'type': 'Mains', 64 'enum type': 'Disconnected', 65 'voltage': '0', 66 'current': '0' 67 }, 68 'Battery': { 69 'path': '/sys/class/power_supply/BAT0', 70 'vendor': 'SANYO', 71 'model name': 'AP13J3K', 72 'serial number': '0061', 73 'state': 'Discharging', 74 'voltage': '11.816', 75 'energy': '31.8262', 76 'energy rate': '12.7849', 77 'current': '1.082', 78 'charge': '2.829', 79 'full charge': '4.03', 80 'full charge design': '4.03', 81 'percentage': '70.1985', 82 'display percentage': '73.9874', 83 'technology': 'Li-ion' 84 } 85 } 86 expected_power = { 87 'energy_consumption_mwh': 2558.42, 88 'power_samples_mw': [12784.9, 12799.3], 89 'component_utilization': { 90 'battery': { 91 'charge_full': 4.03, 92 'charge_full_design': 4.03, 93 'charge_now': 2.827, 94 'current_now': 1.082, 95 'energy': 31.8262, 96 'energy_rate': 12.7993, 97 'voltage_now': 12.238 98 } 99 } 100 } 101 expected_cpu = { 102 'whole_package': { 103 'frequency_percent': { 104 1700000000: 3.29254111574526, 105 1600000000: 0.0, 106 1500000000: 0.0, 107 1400000000: 0.15926805099535601, 108 1300000000: 0.47124116307273645, 109 1200000000: 0.818756100807525, 110 1100000000: 1.099381692400982, 111 1000000000: 2.5942528544384302, 112 900000000: 5.68661122326737, 113 800000000: 3.850545467654628, 114 700000000: 2.409691872245393, 115 600000000: 1.4693702487650486, 116 500000000: 2.4623575553879373, 117 400000000: 2.672038150383057, 118 300000000: 3.415770495015825, 119 200000000: 69.59817400982045 120 }, 121 'cstate_residency_percent': { 122 'C0': 83.67623835616438535, 123 'C1': 0.2698609589041096, 124 'C2': 0.2780191780821918, 125 'C3': 15.77588150684931505 126 } 127 }, 128 'cpu0': { 129 'frequency_percent': { 130 1700000000: 4.113700564971752, 131 1600000000: 0.0, 132 1500000000: 0.0, 133 1400000000: 0.1765536723163842, 134 1300000000: 0.4943502824858757, 135 1200000000: 0.7944915254237288, 136 1100000000: 1.2226341807909604, 137 1000000000: 3.0632062146892656, 138 900000000: 5.680614406779661, 139 800000000: 3.6679025423728815, 140 700000000: 2.379060734463277, 141 600000000: 1.4124293785310735, 142 500000000: 2.599752824858757, 143 400000000: 3.0102401129943503, 144 300000000: 3.650247175141243, 145 200000000: 67.73481638418079 146 }, 147 'cstate_residency_percent': { 148 'C0': 76.76226164383562, 149 'C1': 0.3189164383561644, 150 'C2': 0.4544301369863014, 151 'C3': 22.4643917808219178 152 } 153 }, 154 'cpu1': { 155 'frequency_percent': { 156 1700000000: 2.4713816665187682, 157 1600000000: 0.0, 158 1500000000: 0.0, 159 1400000000: 0.1419824296743278, 160 1300000000: 0.44813204365959713, 161 1200000000: 0.8430206761913214, 162 1100000000: 0.9761292040110037, 163 1000000000: 2.1252994941875945, 164 900000000: 5.69260803975508, 165 800000000: 4.033188392936374, 166 700000000: 2.4403230100275093, 167 600000000: 1.526311118999024, 168 500000000: 2.3249622859171177, 169 400000000: 2.3338361877717633, 170 300000000: 3.1812938148904073, 171 200000000: 71.46153163546012 172 }, 173 'cstate_residency_percent': { 174 'C0': 90.5902150684931507, 175 'C1': 0.2208054794520548, 176 'C2': 0.1016082191780822, 177 'C3': 9.0873712328767123 178 } 179 } 180 } 181 def testParsePowerSupplyInfo(self): 182 result = cros_power_monitor.CrosPowerMonitor.ParsePowerSupplyInfo( 183 self.initial_power) 184 self.assertDictEqual(result, self.expected_parsing_power) 185 186 def testParsePower(self): 187 results = cros_power_monitor.CrosPowerMonitor.ParsePower( 188 self.initial_power, self.final_power, 0.2) 189 for value in results['component_utilization']['battery']: 190 self.assertAlmostEqual( 191 results['component_utilization']['battery'][value], 192 self.expected_power['component_utilization']['battery'][value]) 193 self.assertAlmostEqual(results['energy_consumption_mwh'], 194 self.expected_power['energy_consumption_mwh']) 195 self.assertAlmostEqual(results['power_samples_mw'][0], 196 self.expected_power['power_samples_mw'][0]) 197 self.assertAlmostEqual(results['power_samples_mw'][1], 198 self.expected_power['power_samples_mw'][1]) 199 200 def testSplitSample(self): 201 sample = self.initial_power + '\n1408739546\n' 202 power, time = cros_power_monitor.CrosPowerMonitor.SplitSample(sample) 203 self.assertEqual(power, self.initial_power) 204 self.assertEqual(time, 1408739546) 205 206 def testCombineResults(self): 207 result = cros_power_monitor.CrosPowerMonitor.CombineResults( 208 self.expected_cpu, self.expected_power) 209 comp_util = result['component_utilization'] 210 # Test power values. 211 self.assertEqual(result['energy_consumption_mwh'], 212 self.expected_power['energy_consumption_mwh']) 213 self.assertEqual(result['power_samples_mw'], 214 self.expected_power['power_samples_mw']) 215 self.assertEqual(comp_util['battery'], 216 self.expected_power['component_utilization']['battery']) 217 # Test frequency values. 218 self.assertDictEqual( 219 comp_util['whole_package']['frequency_percent'], 220 self.expected_cpu['whole_package']['frequency_percent']) 221 self.assertDictEqual( 222 comp_util['cpu0']['frequency_percent'], 223 self.expected_cpu['cpu0']['frequency_percent']) 224 self.assertDictEqual( 225 comp_util['cpu1']['frequency_percent'], 226 self.expected_cpu['cpu1']['frequency_percent']) 227 # Test c-state residency values. 228 self.assertDictEqual( 229 comp_util['whole_package']['cstate_residency_percent'], 230 self.expected_cpu['whole_package']['cstate_residency_percent']) 231 self.assertDictEqual( 232 comp_util['cpu0']['cstate_residency_percent'], 233 self.expected_cpu['cpu0']['cstate_residency_percent']) 234 self.assertDictEqual( 235 comp_util['cpu1']['cstate_residency_percent'], 236 self.expected_cpu['cpu1']['cstate_residency_percent']) 237 238 def testCanMonitorPower(self): 239 # TODO(tmandel): Add a test here where the device cannot monitor power. 240 initial_status = cros_power_monitor.CrosPowerMonitor.ParsePowerSupplyInfo( 241 self.initial_power) 242 final_status = cros_power_monitor.CrosPowerMonitor.ParsePowerSupplyInfo( 243 self.final_power) 244 self.assertTrue(cros_power_monitor.CrosPowerMonitor.IsOnBatteryPower( 245 initial_status, 'peppy')) 246 self.assertTrue(cros_power_monitor.CrosPowerMonitor.IsOnBatteryPower( 247 final_status, 'butterfly')) 248