Home | History | Annotate | Download | only in tools
      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