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 logging
6import time
7
8from autotest_lib.client.common_lib import error
9from autotest_lib.server.cros.network import hostap_config
10from autotest_lib.server.cros.network import lucid_sleep_test_base
11from autotest_lib.server.cros.network import wifi_client
12
13class network_WiFi_FastReconnectInDarkResume(
14        lucid_sleep_test_base.LucidSleepTestBase):
15    """
16    Test that we can reconnect quickly (within the span of one dark resume)
17    if we are disconnected during suspend but the AP is still up.
18    """
19
20    version = 1
21
22    def run_once(self):
23        """Body of the test"""
24        self.configure_and_connect_to_ap(hostap_config.HostapConfig(channel=1))
25        client = self.context.client
26        client_mac = client.wifi_mac
27        router = self.context.router
28
29        # Enable the dark connect feature in shill.
30        with client.wake_on_wifi_features(wifi_client.WAKE_ON_WIFI_DARKCONNECT):
31            logging.info('Set up WoWLAN')
32            prev_dark_resume_count = self.dr_utils.count_dark_resumes()
33
34            with self.dr_utils.suspend():
35                # Wait for suspend actions to finish.
36                time.sleep(wifi_client.SUSPEND_WAIT_TIME_SECONDS)
37
38                logging.info('Deauthenticating the DUT')
39                # A deauth packet should instantaneously disconnect the DUT
40                # from the AP without bringing the AP down.
41                router.deauth_client(client_mac)
42
43                # Wait for the DUT to receive the disconnect, wake in
44                # dark resume, reconnect, then suspend again.
45                time.sleep(wifi_client.DISCONNECT_WAIT_TIME_SECONDS +
46                           wifi_client.DARK_RESUME_WAIT_TIME_SECONDS)
47
48            client.check_connected_on_last_resume()
49            dark_resume_count = (self.dr_utils.count_dark_resumes() -
50                                 prev_dark_resume_count)
51            if dark_resume_count != 1:
52                # If there was more than 1 dark resume, the DUT might not have
53                # reconnected on the dark resume triggered by the disconnect.
54                raise error.TestFail('Expected exactly one dark resume')
55