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 5import logging, re, time 6from autotest_lib.server import autotest, test 7from 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 17class 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