| # Copyright 2015 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import json |
| import logging |
| import time |
| import sys |
| |
| from autotest_lib.client.bin import utils |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes |
| from autotest_lib.server.cros import stress |
| from autotest_lib.server.cros.network import wifi_cell_test_base |
| from autotest_lib.server.cros.multimedia import remote_facade_factory |
| |
| _DELAY = 10 |
| _START_TIMEOUT_SECONDS = 20 |
| |
| |
| class network_WiFi_SuspendStress(wifi_cell_test_base.WiFiCellTestBase): |
| """ |
| 1. If the control file is control.integration, the test uses servo to |
| repeatedly close & open lid while running BrowserTests. |
| 2. Any other control file , the test suspend and resume with powerd_dbus |
| command and assert wifi connectivity to router. |
| """ |
| version = 1 |
| |
| |
| def parse_additional_arguments(self, commandline_args, additional_params): |
| """Hook into super class to take control files parameters. |
| |
| @param commandline_args dict of parsed parameters from the autotest. |
| @param additional_params list of tuple(HostapConfig, |
| AssociationParameters). |
| """ |
| self._configurations = additional_params |
| |
| |
| def logged_in(self): |
| """Checks if the host has a logged in user. |
| |
| @return True if a user is logged in on the device. |
| |
| """ |
| try: |
| out = self._host.run('cryptohome --action=status').stdout |
| except: |
| return False |
| try: |
| status = json.loads(out.strip()) |
| except ValueError: |
| logging.info('Cryptohome did not return a value.') |
| return False |
| |
| success = any((mount['mounted'] for mount in status['mounts'])) |
| if success: |
| # Chrome needs a few moments to get ready, otherwise an immediate |
| # suspend will power down the system. |
| time.sleep(5) |
| return success |
| |
| |
| def check_servo_lid_open_support(self): |
| """ Check if DUT supports servo lid_open/close. Ref:http://b/37436993""" |
| try: |
| self._host.servo.lid_close() |
| self._host.servo.lid_open() |
| except AssertionError: |
| raise error.TestNAError('Error setting lid_open status. ' |
| 'Skipping test run on this board. %s.' |
| % sys.exc_info()[1]) |
| |
| |
| def stress_wifi_suspend(self, try_servo=True): |
| """ Perform the suspend stress. |
| |
| @param try_servo:option to toogle use powerd vs servo_lid to suspend. |
| """ |
| # servo might be taking time to come up; wait a bit |
| if not self._host.servo and try_servo: |
| time.sleep(10) |
| |
| boot_id = self._host.get_boot_id() |
| if (not try_servo or |
| self._host.servo.get('lid_open') == 'not_applicable'): |
| self.context.client.do_suspend(_DELAY) |
| else: |
| self._host.servo.lid_close() |
| self._host.wait_down(timeout=_DELAY) |
| self._host.servo.lid_open() |
| self._host.wait_up(timeout=_DELAY) |
| |
| self._host.test_wait_for_resume(boot_id) |
| state_info = self.context.wait_for_connection( |
| self.context.router.get_ssid()) |
| self._timings.append(state_info.time) |
| |
| |
| def powerd_non_servo_wifi_suspend(self): |
| """ Perform the suspend stress with powerdbus.""" |
| self.stress_wifi_suspend(try_servo=False) |
| |
| |
| def run_once(self, suspends=5, integration=None): |
| self._host = self.context.client.host |
| |
| for router_conf, client_conf in self._configurations: |
| self.context.configure(configuration_parameters=router_conf) |
| assoc_params = xmlrpc_datatypes.AssociationParameters( |
| is_hidden=client_conf.is_hidden, |
| security_config=client_conf.security_config, |
| ssid=self.context.router.get_ssid()) |
| self.context.assert_connect_wifi(assoc_params) |
| self._timings = list() |
| |
| if integration: |
| if not self._host.servo: |
| raise error.TestNAError('Servo object returned None. ' |
| 'Check if servo is missing or bad') |
| |
| # If the DUT is up and cold_reset is set to on, that means the |
| # DUT does not support cold_reset. We can't run the test, |
| # because it may get in a bad state and we won't be able |
| # to recover. |
| if self._host.servo.get('cold_reset') == 'on': |
| raise error.TestNAError('This DUT does not support ' |
| 'cold reset, exiting') |
| self.factory = remote_facade_factory.RemoteFacadeFactory( |
| self._host, no_chrome=True) |
| logging.info('Running Wifi Suspend Stress Integration test.') |
| browser_facade = self.factory.create_browser_facade() |
| browser_facade.start_default_chrome() |
| utils.poll_for_condition(condition=self.logged_in, |
| timeout=_START_TIMEOUT_SECONDS, |
| sleep_interval=1, |
| desc='User not logged in.') |
| self.check_servo_lid_open_support() |
| stressor = stress.CountedStressor(self.stress_wifi_suspend) |
| else: |
| logging.info('Running Non integration Wifi Stress test.') |
| stressor = stress.CountedStressor( |
| self.powerd_non_servo_wifi_suspend) |
| |
| stressor.start(suspends) |
| stressor.wait() |
| |
| perf_dict = {'fastest': max(self._timings), |
| 'slowest': min(self._timings), |
| 'average': (float(sum(self._timings)) / |
| len(self._timings))} |
| for key in perf_dict: |
| self.output_perf_value(description=key, |
| value=perf_dict[key], |
| units='seconds', |
| higher_is_better=False, |
| graph=router_conf.perf_loggable_description) |
| |
| |
| def cleanup(self): |
| """Cold reboot the device so the WiFi card is back in a good state.""" |
| if self._host.servo and self._host.servo.get('cold_reset') == 'off': |
| self._host.servo.get_power_state_controller().reset() |