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
5import logging
6
7from autotest_lib.client.bin import utils
8from autotest_lib.client.common_lib import error
9from autotest_lib.client.common_lib import utils
10from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
11from autotest_lib.client.cros import constants
12from autotest_lib.server import frontend
13from autotest_lib.server import site_utils
14from autotest_lib.server import test
15from autotest_lib.site_utils import lxc
16from autotest_lib.server.cros.network import wifi_test_context_manager
17
18class WiFiCellTestBase(test.test):
19    """An abstract base class for autotests in WiFi cells.
20
21    WiFiCell tests refer to participants in the test as client, router, and
22    server.  The client is just the DUT and the router is a nearby AP which we
23    configure in various ways to test the ability of the client to connect.
24    There is a third entity called a server which is distinct from the autotest
25    server.  In WiFiTests, the server is a host which the client can only talk
26    to over the WiFi network.
27
28    WiFiTests have a notion of the control network vs the WiFi network.  The
29    control network refers to the network between the machine running the
30    autotest server and the various machines involved in the test.  The WiFi
31    network is the subnet(s) formed by WiFi routers between the server and the
32    client.
33
34    """
35
36    def _install_pyshark(self):
37        """Installs pyshark and its dependencies for packet capture analysis.
38
39        Uses SSP to install the required pyshark python module and its
40        dependencies including the tshark binary.
41        """
42        logging.info('Installing Pyshark')
43        try:
44            lxc.install_packages(['tshark', 'python-dev', 'libxml2-dev',
45                                  'libxslt-dev', 'zlib1g-dev'],
46                                 ['pyshark'])
47        except error.ContainerError as e:
48            logging.info('Not installing pyshark: %s', e)
49        except error.CmdError as e:
50            raise error.TestError('Error installing pyshark: %s', e)
51
52
53    def initialize(self, host):
54        self._install_pyshark()
55        if utils.host_could_be_in_afe(host.hostname):
56            # There are some DUTs that have different types of wifi modules.
57            # In order to generate separate performance graphs, a variant
58            # name is needed.  Writing this key will generate results with
59            # the name of <board>-<variant>.
60            afe = frontend.AFE(debug=True)
61            variant_name = site_utils.get_label_from_afe(host.hostname,
62                                                         'variant:',
63                                                         afe)
64            if variant_name:
65                self.write_test_keyval({constants.VARIANT_KEY: variant_name})
66
67    @property
68    def context(self):
69        """@return the WiFi context for this test."""
70        return self._wifi_context
71
72
73    def parse_additional_arguments(self, commandline_args, additional_params):
74        """Parse additional arguments for use in test.
75
76        Subclasses should override this method do any other commandline parsing
77        and setting grabbing that they need to do.  For test clarity, do not
78        parse additional settings in the body of run_once.
79
80        @param commandline_args dict of argument key, value pairs.
81        @param additional_params object defined by test control file.
82
83        """
84        pass
85
86
87    def warmup(self, host, raw_cmdline_args, additional_params=None):
88        """
89        Use the additional_params argument to pass in custom test data from
90        control file to reuse test logic.  This object will be passed down via
91        parse_additional_arguments.
92
93        @param host host object representing the client DUT.
94        @param raw_cmdline_args raw input from autotest.
95        @param additional_params object passed in from control file.
96
97        """
98        cmdline_args = utils.args_to_dict(raw_cmdline_args)
99        logging.info('Running wifi test with commandline arguments: %r',
100                     cmdline_args)
101        self._wifi_context = wifi_test_context_manager.WiFiTestContextManager(
102                self.__class__.__name__,
103                host,
104                cmdline_args,
105                self.debugdir)
106
107        self._wifi_context.setup()
108        self.parse_additional_arguments(cmdline_args, additional_params)
109
110        msg = '======= WiFi autotest setup complete. Starting test... ======='
111        self._wifi_context.client.shill_debug_log(msg)
112
113
114    def cleanup(self):
115        msg = '======= WiFi autotest complete. Cleaning up... ======='
116        self._wifi_context.client.shill_debug_log(msg)
117        # If we fail during initialization, we might not have a context.
118        if hasattr(self, '_wifi_context'):
119            self._wifi_context.teardown()
120
121
122    def configure_and_connect_to_ap(self, configuration_parameters):
123        """
124        Configure the router as an AP with the given parameters and connect
125        the DUT to it.
126
127        @param configuration_parameters HostapConfig object.
128
129        @return name of the configured AP
130        """
131        self.context.configure(configuration_parameters)
132        ap_ssid = self.context.router.get_ssid()
133        assoc_params = xmlrpc_datatypes.AssociationParameters(ssid=ap_ssid)
134        self.context.assert_connect_wifi(assoc_params)
135        return ap_ssid
136