1 #!/usr/bin/env python 2 # Copyright 2015 The Chromium Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 import os 7 import sys 8 import unittest 9 10 if __name__ == '__main__': 11 sys.path.append( 12 os.path.abspath(os.path.join(os.path.dirname(__file__), 13 '..', '..', '..'))) 14 15 from devil import devil_env 16 from devil.android import device_errors 17 from devil.android import device_utils 18 from devil.android.tools import device_monitor 19 20 with devil_env.SysPath(devil_env.PYMOCK_PATH): 21 import mock # pylint: disable=import-error 22 23 24 class DeviceMonitorTest(unittest.TestCase): 25 26 def setUp(self): 27 self.device = mock.Mock(spec=device_utils.DeviceUtils, 28 serial='device_cereal', build_id='abc123', build_product='clownfish', 29 GetIMEI=lambda: '123456789') 30 self.file_contents = { 31 '/proc/meminfo': """ 32 MemTotal: 1234567 kB 33 MemFree: 1000000 kB 34 MemUsed: 234567 kB 35 """, 36 '/sys/class/thermal/thermal_zone0/type': 'CPU-therm', 37 '/sys/class/thermal/thermal_zone0/temp': '30', 38 '/proc/uptime': '12345 99999', 39 } 40 self.device.ReadFile = mock.MagicMock( 41 side_effect=lambda file_name: self.file_contents[file_name]) 42 43 self.device.ListProcesses.return_value = ['p1', 'p2', 'p3', 'p4', 'p5'] 44 45 self.cmd_outputs = { 46 'grep': ['/sys/class/thermal/thermal_zone0/type'], 47 } 48 49 def mock_run_shell(cmd, **_kwargs): 50 args = cmd.split() if isinstance(cmd, basestring) else cmd 51 try: 52 return self.cmd_outputs[args[0]] 53 except KeyError: 54 raise device_errors.AdbShellCommandFailedError(cmd, None, None) 55 56 self.device.RunShellCommand = mock.MagicMock(side_effect=mock_run_shell) 57 58 self.battery = mock.Mock() 59 self.battery.GetBatteryInfo = mock.MagicMock( 60 return_value={'level': '80', 'temperature': '123'}) 61 62 self.expected_status = { 63 'device_cereal': { 64 'processes': 5, 65 'temp': { 66 'CPU-therm': 30.0 67 }, 68 'battery': { 69 'temperature': 123, 70 'level': 80 71 }, 72 'uptime': 12345.0, 73 'mem': { 74 'total': 1234567, 75 'free': 1000000 76 }, 77 'build': { 78 'build.id': 'abc123', 79 'product.device': 'clownfish', 80 }, 81 'imei': '123456789', 82 'state': 'available', 83 } 84 } 85 86 @mock.patch('devil.android.battery_utils.BatteryUtils') 87 @mock.patch('devil.android.device_utils.DeviceUtils.HealthyDevices') 88 def test_getStats(self, get_devices, get_battery): 89 get_devices.return_value = [self.device] 90 get_battery.return_value = self.battery 91 92 status = device_monitor.get_all_status(None) 93 self.assertEquals(self.expected_status, status['devices']) 94 95 @mock.patch('devil.android.battery_utils.BatteryUtils') 96 @mock.patch('devil.android.device_utils.DeviceUtils.HealthyDevices') 97 def test_getStatsNoBattery(self, get_devices, get_battery): 98 get_devices.return_value = [self.device] 99 get_battery.return_value = self.battery 100 broken_battery_info = mock.Mock() 101 broken_battery_info.GetBatteryInfo = mock.MagicMock( 102 return_value={'level': '-1', 'temperature': 'not_a_number'}) 103 get_battery.return_value = broken_battery_info 104 105 # Should be same status dict but without battery stats. 106 expected_status_no_battery = self.expected_status.copy() 107 expected_status_no_battery['device_cereal'].pop('battery') 108 109 status = device_monitor.get_all_status(None) 110 self.assertEquals(expected_status_no_battery, status['devices']) 111 112 @mock.patch('devil.android.battery_utils.BatteryUtils') 113 @mock.patch('devil.android.device_utils.DeviceUtils.HealthyDevices') 114 def test_getStatsNoPs(self, get_devices, get_battery): 115 get_devices.return_value = [self.device] 116 get_battery.return_value = self.battery 117 # Throw exception when listing processes. 118 self.device.ListProcesses.side_effect = device_errors.AdbCommandFailedError( 119 ['ps'], 'something failed', 1) 120 121 # Should be same status dict but without process stats. 122 expected_status_no_ps = self.expected_status.copy() 123 expected_status_no_ps['device_cereal'].pop('processes') 124 125 status = device_monitor.get_all_status(None) 126 self.assertEquals(expected_status_no_ps, status['devices']) 127 128 @mock.patch('devil.android.battery_utils.BatteryUtils') 129 @mock.patch('devil.android.device_utils.DeviceUtils.HealthyDevices') 130 def test_getStatsNoSensors(self, get_devices, get_battery): 131 get_devices.return_value = [self.device] 132 get_battery.return_value = self.battery 133 del self.cmd_outputs['grep'] # Throw exception on run shell grep command. 134 135 # Should be same status dict but without temp stats. 136 expected_status_no_temp = self.expected_status.copy() 137 expected_status_no_temp['device_cereal'].pop('temp') 138 139 status = device_monitor.get_all_status(None) 140 self.assertEquals(expected_status_no_temp, status['devices']) 141 142 @mock.patch('devil.android.battery_utils.BatteryUtils') 143 @mock.patch('devil.android.device_utils.DeviceUtils.HealthyDevices') 144 def test_getStatsWithBlacklist(self, get_devices, get_battery): 145 get_devices.return_value = [self.device] 146 get_battery.return_value = self.battery 147 blacklist = mock.Mock() 148 blacklist.Read = mock.MagicMock( 149 return_value={'bad_device': {'reason': 'offline'}}) 150 151 # Should be same status dict but with extra blacklisted device. 152 expected_status = self.expected_status.copy() 153 expected_status['bad_device'] = {'state': 'offline'} 154 155 status = device_monitor.get_all_status(blacklist) 156 self.assertEquals(expected_status, status['devices']) 157 158 @mock.patch('devil.android.battery_utils.BatteryUtils') 159 @mock.patch('devil.android.device_utils.DeviceUtils.HealthyDevices') 160 def test_brokenTempValue(self, get_devices, get_battery): 161 self.file_contents['/sys/class/thermal/thermal_zone0/temp'] = 'n0t a numb3r' 162 get_devices.return_value = [self.device] 163 get_battery.return_value = self.battery 164 165 expected_status_no_temp = self.expected_status.copy() 166 expected_status_no_temp['device_cereal'].pop('temp') 167 168 status = device_monitor.get_all_status(None) 169 self.assertEquals(self.expected_status, status['devices']) 170 171 172 if __name__ == '__main__': 173 sys.exit(unittest.main()) 174