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