| # 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 contextlib |
| import logging |
| import time |
| |
| from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.server.cros import dark_resume_utils |
| from autotest_lib.server.cros.network import hostap_config |
| from autotest_lib.server.cros.network import wifi_cell_test_base |
| from autotest_lib.server.cros.network import wifi_client |
| |
| class network_WiFi_ReconnectInDarkResume(wifi_cell_test_base.WiFiCellTestBase): |
| """Test that known WiFi access points wake up the system.""" |
| |
| version = 1 |
| |
| def initialize(self, host): |
| """Set up for dark resume.""" |
| self._dr_utils = dark_resume_utils.DarkResumeUtils(host) |
| |
| |
| def check_connected_on_last_resume(self): |
| """Checks whether the DUT was connected on its last resume. |
| |
| Checks that the DUT was connected after waking from suspend by parsing |
| the last instance shill log message that reports shill's connection |
| status on resume. Fails the test if this log message reports that |
| the DUT woke up disconnected. |
| |
| """ |
| # As of build R43 6913.0.0, the shill log message from the function |
| # OnAfterResume is called as soon as shill resumes from suspend, and |
| # will report whether or not shill is connected. The log message will |
| # take one of the following two forms: |
| # |
| # [...] [INFO:wifi.cc($PID)] OnAfterResume: connected |
| # [...] [INFO:wifi.cc($PID)] OnAfterResume: not connected |
| # |
| # where $PID is an arbitrary PID number. By checking if the last |
| # instance of this message contains the substring "not connected", we |
| # can determine whether or not shill was connected on its last resume. |
| connection_status_msg_regex_str = 'INFO:wifi\.cc.*OnAfterResume' |
| not_connected_substr = 'not connected' |
| connected_substr = 'connected' |
| |
| cmd = ('grep -E %s /var/log/net.log | tail -1' % |
| connection_status_msg_regex_str) |
| cmdresult = self.context.client.host.run(cmd).stdout |
| if not cmdresult: |
| raise error.TestFail( |
| 'Could not find resume connection status log message.') |
| if not_connected_substr in cmdresult: |
| raise error.TestFail( |
| 'Client was not connected upon waking from suspend.') |
| if not connected_substr in cmdresult: |
| raise error.TestFail( |
| 'Resume log message did not contain connection status.') |
| logging.info('Client was connected upon waking from suspend.') |
| |
| |
| def run_once(self): |
| """Body of the test.""" |
| self.context.configure(hostap_config.HostapConfig(channel=1)) |
| assoc_params = xmlrpc_datatypes.AssociationParameters( |
| ssid=self.context.router.get_ssid()) |
| self.context.assert_connect_wifi(assoc_params) |
| |
| client = self.context.client |
| router = self.context.router |
| ap_ssid = router.get_ssid() |
| |
| # Enable the wake on SSID feature in shill, and set the scan period. |
| with contextlib.nested( |
| client.wake_on_wifi_features(wifi_client.WAKE_ON_WIFI_SSID), |
| client.net_detect_scan_period_seconds( |
| wifi_client.NET_DETECT_SCAN_WAIT_TIME_SECONDS)): |
| logging.info('Set up WoWLAN') |
| |
| with self._dr_utils.suspend(): |
| # Wait for suspend actions to finish. |
| time.sleep(wifi_client.SUSPEND_WAIT_TIME_SECONDS) |
| |
| # Bring the AP down so that DUT is disconnected. |
| router.deconfig_aps() |
| |
| # Wait for the DUT to wake on disconnect in dark resume, then |
| # suspend again. |
| time.sleep(wifi_client.DARK_RESUME_WAIT_TIME_SECONDS) |
| |
| # Bring the AP back up to wake up the DUT. |
| logging.info('Bringing AP back online.') |
| self.context.configure(hostap_config.HostapConfig( |
| ssid=ap_ssid, channel=1)) |
| |
| # Wait long enough for the NIC on the DUT to perform a net |
| # detect scan, discover the AP with the white-listed SSID, wake |
| # up in dark resume, connect, then suspend again. |
| time.sleep(wifi_client.NET_DETECT_SCAN_WAIT_TIME_SECONDS + |
| wifi_client.DARK_RESUME_WAIT_TIME_SECONDS) |
| |
| self.check_connected_on_last_resume() |
| |
| |
| def cleanup(self): |
| self._dr_utils.teardown() |
| # Make sure we clean up everything |
| super(network_WiFi_ReconnectInDarkResume, self).cleanup() |