Home | History | Annotate | Download | only in network_WiFi_MissingBeacons
      1 # Copyright (c) 2013 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 
      5 import logging
      6 
      7 from autotest_lib.client.common_lib import error
      8 from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
      9 from autotest_lib.server.cros.network import hostap_config
     10 from autotest_lib.server.cros.network import wifi_cell_test_base
     11 
     12 
     13 class network_WiFi_MissingBeacons(wifi_cell_test_base.WiFiCellTestBase):
     14     """Test how a DUT behaves when an AP disappears suddenly.
     15 
     16     Connects a DUT to an AP, then kills the AP in such a way that no de-auth
     17     message is sent.  Asserts that the DUT marks itself as disconnected from
     18     the AP within MAX_DISCONNECT_TIME_SECONDS.
     19 
     20     """
     21 
     22     version = 1
     23 
     24     MAX_DISCONNECT_TIME_SECONDS = 20
     25 
     26 
     27     def _assert_disconnect(self, ssid):
     28         """Assert that we disconnect from |ssid| MAX_DISCONNECT_TIME_SECONDS.
     29 
     30         @param ssid: string ssid of network we expect to be disconnected from.
     31 
     32         """
     33         # Leave some margin of seconds to check how long it actually
     34         # takes to disconnect should we fail to disconnect in time.
     35         timeout_seconds = self.MAX_DISCONNECT_TIME_SECONDS + 10
     36         logging.info('Waiting %.2f seconds for client to notice the missing '
     37                      'AP.', timeout_seconds)
     38         result = self.context.client.wait_for_service_states(
     39                 ssid, ['idle'], timeout_seconds=timeout_seconds)
     40         success, state, duration_seconds = result
     41         if not success or duration_seconds > self.MAX_DISCONNECT_TIME_SECONDS:
     42             raise error.TestFail('Timed out waiting disconnect in %f '
     43                                  'seconds.  Ended in %s' %
     44                                  (duration_seconds, state))
     45         else:
     46             logging.info('Client detected the AP absence in %.2f seconds',
     47                          duration_seconds)
     48         # It seems redundant to disconnect a service that is already
     49         # disconnected, but it prevents shill from attempting to re-connect
     50         # and foiling future connection attempts.
     51         self.context.client.shill.disconnect(ssid)
     52 
     53 
     54     def run_once(self):
     55         """Body of the test."""
     56         ap_config = hostap_config.HostapConfig(channel=1)
     57         self.context.configure(ap_config)
     58         ssid = self.context.router.get_ssid()
     59         client_config = xmlrpc_datatypes.AssociationParameters(ssid=ssid)
     60         self.context.assert_connect_wifi(client_config)
     61         self.context.assert_ping_from_dut()
     62         # Take down the AP interface, which looks like the AP "disappeared"
     63         # from the DUT's point of view.  This is also much faster than actually
     64         # tearing down the AP, which allows us to watch for the client reporting
     65         # itself as disconnected.
     66         self.context.router.set_ap_interface_down()
     67         self._assert_disconnect(ssid)
     68         self.context.router.deconfig_aps()
     69         logging.info('Repeating test with a client scan just before AP death.')
     70         self.context.configure(ap_config)
     71         ssid = self.context.router.get_ssid()
     72         client_config = xmlrpc_datatypes.AssociationParameters(ssid=ssid)
     73         self.context.assert_connect_wifi(client_config)
     74         self.context.assert_ping_from_dut()
     75         self.context.client.scan(frequencies=[], ssids=[])
     76         self.context.router.set_ap_interface_down()
     77         self._assert_disconnect(ssid)
     78         self.context.router.deconfig_aps()
     79