1# Copyright 2015 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 json 6import logging 7import time 8import sys 9 10from autotest_lib.client.bin import utils 11from autotest_lib.client.common_lib import error 12from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes 13from autotest_lib.server.cros import stress 14from autotest_lib.server.cros.network import wifi_cell_test_base 15from autotest_lib.server.cros.multimedia import remote_facade_factory 16 17_DELAY = 10 18_START_TIMEOUT_SECONDS = 20 19 20 21class network_WiFi_SuspendStress(wifi_cell_test_base.WiFiCellTestBase): 22 """ 23 1. If the control file is control.integration, the test uses servo to 24 repeatedly close & open lid while running BrowserTests. 25 2. Any other control file , the test suspend and resume with powerd_dbus 26 command and assert wifi connectivity to router. 27 """ 28 version = 1 29 30 31 def parse_additional_arguments(self, commandline_args, additional_params): 32 """Hook into super class to take control files parameters. 33 34 @param commandline_args dict of parsed parameters from the autotest. 35 @param additional_params list of tuple(HostapConfig, 36 AssociationParameters). 37 """ 38 self._configurations = additional_params 39 40 41 def logged_in(self): 42 """Checks if the host has a logged in user. 43 44 @return True if a user is logged in on the device. 45 46 """ 47 try: 48 out = self._host.run('cryptohome --action=status').stdout 49 except: 50 return False 51 try: 52 status = json.loads(out.strip()) 53 except ValueError: 54 logging.info('Cryptohome did not return a value.') 55 return False 56 57 success = any((mount['mounted'] for mount in status['mounts'])) 58 if success: 59 # Chrome needs a few moments to get ready, otherwise an immediate 60 # suspend will power down the system. 61 time.sleep(5) 62 return success 63 64 65 def check_servo_lid_open_support(self): 66 """ Check if DUT supports servo lid_open/close. Ref:http://b/37436993""" 67 try: 68 self._host.servo.lid_close() 69 self._host.servo.lid_open() 70 except AssertionError: 71 raise error.TestNAError('Error setting lid_open status. ' 72 'Skipping test run on this board. %s.' 73 % sys.exc_info()[1]) 74 75 76 def stress_wifi_suspend(self, try_servo=True): 77 """ Perform the suspend stress. 78 79 @param try_servo:option to toogle use powerd vs servo_lid to suspend. 80 """ 81 # servo might be taking time to come up; wait a bit 82 if not self._host.servo and try_servo: 83 time.sleep(10) 84 85 boot_id = self._host.get_boot_id() 86 if (not try_servo or 87 self._host.servo.get('lid_open') == 'not_applicable'): 88 self.context.client.do_suspend(_DELAY) 89 else: 90 self._host.servo.lid_close() 91 self._host.wait_down(timeout=_DELAY) 92 self._host.servo.lid_open() 93 self._host.wait_up(timeout=_DELAY) 94 95 self._host.test_wait_for_resume(boot_id) 96 state_info = self.context.wait_for_connection( 97 self.context.router.get_ssid()) 98 self._timings.append(state_info.time) 99 100 101 def powerd_non_servo_wifi_suspend(self): 102 """ Perform the suspend stress with powerdbus.""" 103 self.stress_wifi_suspend(try_servo=False) 104 105 106 def run_once(self, suspends=5, integration=None): 107 self._host = self.context.client.host 108 109 for router_conf, client_conf in self._configurations: 110 self.context.configure(configuration_parameters=router_conf) 111 assoc_params = xmlrpc_datatypes.AssociationParameters( 112 is_hidden=client_conf.is_hidden, 113 security_config=client_conf.security_config, 114 ssid=self.context.router.get_ssid()) 115 self.context.assert_connect_wifi(assoc_params) 116 self._timings = list() 117 118 if integration: 119 if not self._host.servo: 120 raise error.TestNAError('Servo object returned None. ' 121 'Check if servo is missing or bad') 122 123 # If the DUT is up and cold_reset is set to on, that means the 124 # DUT does not support cold_reset. We can't run the test, 125 # because it may get in a bad state and we won't be able 126 # to recover. 127 if self._host.servo.get('cold_reset') == 'on': 128 raise error.TestNAError('This DUT does not support ' 129 'cold reset, exiting') 130 self.factory = remote_facade_factory.RemoteFacadeFactory( 131 self._host, no_chrome=True) 132 logging.info('Running Wifi Suspend Stress Integration test.') 133 browser_facade = self.factory.create_browser_facade() 134 browser_facade.start_default_chrome() 135 utils.poll_for_condition(condition=self.logged_in, 136 timeout=_START_TIMEOUT_SECONDS, 137 sleep_interval=1, 138 desc='User not logged in.') 139 self.check_servo_lid_open_support() 140 stressor = stress.CountedStressor(self.stress_wifi_suspend) 141 else: 142 logging.info('Running Non integration Wifi Stress test.') 143 stressor = stress.CountedStressor( 144 self.powerd_non_servo_wifi_suspend) 145 146 stressor.start(suspends) 147 stressor.wait() 148 149 perf_dict = {'fastest': max(self._timings), 150 'slowest': min(self._timings), 151 'average': (float(sum(self._timings)) / 152 len(self._timings))} 153 for key in perf_dict: 154 self.output_perf_value(description=key, 155 value=perf_dict[key], 156 units='seconds', 157 higher_is_better=False, 158 graph=router_conf.perf_loggable_description) 159 160 161 def cleanup(self): 162 """Cold reboot the device so the WiFi card is back in a good state.""" 163 if self._host.servo and self._host.servo.get('cold_reset') == 'off': 164 self._host.servo.get_power_state_controller().reset() 165