Home | History | Annotate | Download | only in platform_PowerStatusStress
      1 # Copyright (c) 2014 The Chromium OS 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 
      5 import logging, re, time
      6 from autotest_lib.server import autotest, test
      7 from autotest_lib.client.common_lib import error
      8 
      9 _CHARGING = 'CHARGING'
     10 _DISCHARGING = 'DISCHARGING'
     11 _WAIT_SECS_AFTER_SWITCH = 5
     12 _LONG_TIMEOUT = 120
     13 _CLIENT_LOGIN = 'desktopui_SimpleLogin'
     14 _WAKE_PRESS_IN_SEC = 0.2
     15 _SUSPEND_TIME = 10
     16 
     17 class platform_PowerStatusStress(test.test):
     18     """Uses RPM and servo to test the power_supply_info output. """
     19     version = 1
     20 
     21 
     22     def action_login(self):
     23         """Login i.e. runs running client test
     24 
     25         @exception TestFail failed to login within timeout.
     26 
     27         """
     28         self.autotest_client.run_test(_CLIENT_LOGIN,
     29                                       exit_without_logout=True)
     30 
     31 
     32     def wait_to_suspend(self, suspend_timeout = _LONG_TIMEOUT):
     33         """Wait for DUT to suspend.
     34 
     35         @param suspend_timeout: Time in seconds to wait to disconnect
     36 
     37         @exception TestFail if fail to suspend/disconnect in time
     38 
     39         """
     40         if not self.host.ping_wait_down(timeout=suspend_timeout):
     41             raise error.TestFail("Unable to suspend in %s sec" %
     42                                  suspend_timeout)
     43 
     44 
     45     def wait_to_come_up(self, resume_timeout = _LONG_TIMEOUT):
     46         """Wait for DUT to resume.
     47 
     48         @param resume_timeout: Time in seconds to wait to come up
     49 
     50         @exception TestFail if fail to come_up in time
     51 
     52         """
     53         if not self.host.wait_up(timeout=resume_timeout):
     54             raise error.TestFail("Unable to resume in %s sec" %
     55                                  resume_timeout)
     56 
     57 
     58     def do_suspend_resume(self):
     59         """ Suspends the DUT through powerd_dbus_suspend
     60         """
     61         #Suspend
     62         logging.debug('Suspending...')
     63         if self.has_lid:
     64             self.host.servo.lid_close()
     65             self.wait_to_suspend()
     66             time.sleep(_SUSPEND_TIME)
     67         else:
     68             self.host.suspend(suspend_time=_SUSPEND_TIME)
     69 
     70         #Resume
     71         logging.debug('Resuming...')
     72         if self.has_lid:
     73             self.host.servo.lid_open()
     74         else:
     75             self.host.servo.power_key(_WAKE_PRESS_IN_SEC)
     76         self.wait_to_come_up()
     77 
     78 
     79     def cleanup(self):
     80         """ Finish as powered on and lid open"""
     81         self.host.power_on()
     82         self.host.servo.lid_open()
     83 
     84 
     85     def switch_power_and_verify(self, powered_on, expected):
     86         """ Main action on switching the power state, and verifying status
     87 
     88         @param powered_on: a boolean ON if True, OFF else
     89         @param expected: touple of cmd and values to verify
     90 
     91         @exception TestFail  if line_power or battery state do not match
     92         """
     93         bat_state = _CHARGING if powered_on else _DISCHARGING,
     94         logging.info('Switching status to %s ', bat_state)
     95         if powered_on:
     96             self.host.power_on()
     97         else:
     98             self.host.power_off()
     99         time.sleep(_WAIT_SECS_AFTER_SWITCH)
    100 
    101         # Get power_supply_info output
    102         psi_output = self.host.run('power_supply_info').stdout.strip()
    103         psi_output = psi_output.replace('\n', '')
    104 
    105         exp_psi_online, exp_psi_enum_type, exp_psi_bat_state = expected
    106 
    107         is_psi_online = re.match(r'.+online:\s+%s.+' % exp_psi_online,
    108                                  psi_output) is not None
    109         is_psi_enum_type = re.match(r'.+enum type:\s+%s.+' % exp_psi_enum_type,
    110                                     psi_output) is not None
    111         is_psi_bat_state = re.match(r'.+state:\s+%s.+' % exp_psi_bat_state,
    112                                     psi_output) is not None
    113 
    114         if not all([is_psi_online, is_psi_enum_type, is_psi_bat_state]):
    115             raise error.TestFail('Bad %s state!' % bat_state)
    116 
    117 
    118     def run_once(self, host, loop_count):
    119         self.host = host
    120         dut_type = host.get_board_type()
    121         if dut_type != 'CHROMEBOOK':
    122             raise error.TestNAError(
    123                     'This test is not supported on %s' %  dut_type)
    124         self.autotest_client = autotest.Autotest(self.host)
    125 
    126         # Start as powered on
    127         if self.host.has_power():
    128             self.host.power_on()
    129         else:
    130             raise error.TestFail('No RPM is setup to device')
    131 
    132         # Check if DUT has lid.
    133         self.has_lid = True
    134         if self.host.servo.get('lid_open') == 'not_applicable':
    135             self.has_lid = False
    136         else:
    137             # Check if lid_open control is good.
    138             self.host.servo.lid_open()
    139             if self.host.servo.get('lid_open') != 'yes':
    140                 raise error.TestError('BAD lid_open control. Reset servo!')
    141 
    142         # Login to device
    143         self.action_login()
    144 
    145         pdu_connected = True
    146         for i in xrange(loop_count):
    147             logging.info('--- Iteration %d', (i + 1))
    148 
    149             # Suspend/resume
    150             self.do_suspend_resume()
    151 
    152             # Discharging state
    153             expected = ('no', 'Disconnected', 'Discharging')
    154             self.switch_power_and_verify(False, expected)
    155 
    156             # Suspend/resume
    157             self.do_suspend_resume()
    158 
    159             # Charging state - it could be any of the three below
    160             expected = ('yes', 'AC', '(Charging|Fully charged|Discharging)')
    161             self.switch_power_and_verify(True, expected)
    162