# Copyright (c) 2012 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 common
import fnmatch
import logging
import os
import re
import stat
import tempfile
import time
import traceback

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.client.common_lib.cros import site_eap_certs
from autotest_lib.client.cros import constants
from autotest_lib.server import autotest
from autotest_lib.server import hosts
from autotest_lib.server import site_attenuator
from autotest_lib.server import site_host_route
from autotest_lib.server import site_linux_bridge_router
from autotest_lib.server import site_linux_cros_router
from autotest_lib.server import site_linux_router
from autotest_lib.server import site_linux_server
from autotest_lib.server import site_linux_system
from autotest_lib.server import test
from autotest_lib.server.cros import remote_command
from autotest_lib.server.cros import wifi_test_utils
from autotest_lib.server.cros.network import wifi_client

class ScriptNotFound(Exception):
    """Raised when site_wlan scripts cannot be found."""
    def __init__(self, scriptname):
        super(ScriptNotFound, self).__init__(
            'Script %s not found in search path' % scriptname)


class WiFiTest(object):
    """
    Deprecated WiFi Test.

    Each test is specified as a dict.  There must be a "name" entry that
    gives the test name (a string) and a "steps" entry that has an ordered
    tuple of test steps, where each step is a tuple [func, {args}].

    Step funcs are one of:
      config                  configure the router/AP using the specified params
                              (ssid automatically supplied); params are give as
                              BSD ifconfig(8) parameters and translated to match
                              the target router/AP's cli syntax
      deconfig                de-configure/shut-off the router/AP
      connect                 connect client to AP using specified parameters
                              (ssid automatically supplied)
      disconnect              disconnect client from AP
      client_check_*          check the client's connection state to verify
                              a parameter was setup as expected; e.g.
                              client_check_dtimperiod checks the DTIM period
                              set on the AP was adopted by the client
      client_monitor_start    start monitoring for wireless system events as
                              needed (e.g, kick off a process that listens)
      client_monitor_stop     stop monitoring for wireless system events
      client_check_event_*    check the client's event log for an event;
                              should always be preceded by client_monitor_start
      sleep                   pause on the autotest server for a time
      client_ping             ping the server on the client machine
      vpn_client_load_tunnel  load 'tun' device for VPN client
      vpn_client_kill         Kill the running VPN client.  Do nothing
                              if not running.
      vpn_client_connect      launch a VPN client to connect with the
                              VPN server
      client_reboot           reboots the client and waits for it to come back.
                              The amount of time to wait can be specified by a
                              'timeout' parameter, in seconds.

    Steps that are done on the client or server machine are implemented in
    this class.  Steps that are done on the wifi router are implemented in
    a separate class that knows how to control the router.  We support
    a setup that uses a stumpy with an extra radio and a special software
    image set up to facillitate routing.  The driver stack on this machine
    is based on Linux/mac80211.  Additional router support can be added
    by adding a new class and auto-selecting it in __init__.

    The WiFiTest class could be generalized to handle clients other than
    ChromeOS; this would useful for systems that use Network Manager or
    wpa_supplicant directly.

    """

    _result_expect_failure = 1
    _result_expect_success = 2
    _result_dont_care = 3


    def __init__(self, name, steps, client_requirements, config):
        self.name = name
        self.steps = steps
        self.debug_dir = './debug'
        step_req_client, step_req_router = self.__get_step_requirements()
        self.client_requirements = (client_requirements + step_req_client)
        self.router_requirements = step_req_router
        self.perf_keyvals = {}

        self.cur_frequency   = None
        self.cur_phymode     = None
        self.cur_security    = None
        self.cur_attenuation = None
        self.vpn_kind        = None
        #
        # There is a case that leaves some profiles in profile storage but
        # not on the stack. This will cause the failure for 'profile_create'
        # in later test cases. We use a list to record the created profiles
        # and remove them all after the test case ends.
        #
        # Example:
        # 1. profile_create: top  (in profile storage)
        # 2. profile_push: top    (in profile storage and also on the stack)
        # 3. connect
        # 4. profile_pop: top     (still in profile storage)
        # 5. The test case ends with a failure.
        # 6. Another test case starts.
        # 7. profile_create: top  (failure)
        #
        self.created_profiles = []

        router = config['router']
        #
        # The server machine may be multi-homed or only on the wifi
        # network.  When only on the wifi net we suppress server_*
        # requests since we cannot initiate them from the control machine.
        #
        server = config['server']
        # NB: server may not be reachable on the control network

        self.router = hosts.SSHHost(router['addr'],
                                    port=int(router.get('port', 22)))

        defaults = config.get('defaults', {})
        self.deftimeout = defaults.get('timeout', 30)
        self.defpingcount = defaults.get('pingcount', 10)

        if not site_linux_router.isLinuxRouter(self.router):
            raise error.TestFail('Unsupported router')

        if site_linux_cros_router.isLinuxCrosRouter(self.router):
            self.wifi = site_linux_cros_router.LinuxCrosRouter(
                self.router, router, self.name)
        else:
            self.wifi = site_linux_bridge_router.LinuxBridgeRouter(
                self.router, router, self.name)

        attenuator = config.get('attenuator', dict())
        # NB: Attenuator must be reachable on the control network
        if attenuator.get('addr', None):
            attenuator_host = hosts.SSHHost(attenuator['addr'],
                                            port=int(attenuator.get('port',22)))
            self.attenuator = site_attenuator.Attenuator(attenuator_host)

        #
        # The client machine must be reachable from the control machine.
        # The address on the wifi network is retrieved each time it
        # associates to the router.
        #
        client = config['client']

        self.client_proxy = wifi_client.WiFiClient(
                hosts.create_host(client['addr']),
                self.debug_dir)
        self.client_at = autotest.Autotest(self.client)
        self.client_wifi_device_path = None   # client's flimflam wifi path
        self.client_signal_info = {}
        self.client_installed_scripts = {}
        self.client_logfile = client.get("logfile", "/var/log/messages")

        if not 'addr' in server:
            raise error.TestError('All current WiFi tests require a server '
                                  'reachable on the control network.')

        # The 'hosting_server' is a machine which hosts network
        # services, such as OpenVPN or StrongSwan.
        self.hosting_server = site_linux_server.LinuxServer(
                hosts.SSHHost(server['addr'], port=int(server.get('port', 22))),
                server)

        # potential bg thread for ping untilstop
        self.ping_thread = None

        # potential bg thread for client network monitoring
        self.client_netdump_thread = None
        self.client_stats_thread = None
        # TODO(wiley) Fix the actual FLIMFLAM_TEST_PATH rather than this hack.
        self.client_cmd_flimflam_lib = ('/usr/local' +
                                        constants.FLIMFLAM_TEST_PATH)

        self.host_route_args = {}

        # Synchronize time on all devices
        for system in (self.client_proxy, self.hosting_server, self.wifi):
            system.sync_host_times()

        # Find all repeated steps and create iterators for them
        self.iterated_steps = {}
        step_names = [step[0] for step in steps]
        for step_name in list(set(step_names)):
            if step_names.count(step_name) > 1:
                self.iterated_steps[step_name] = 0

        self.run_options = config['run_options']
        if (config['router']['addr'] == config['server']['addr'] and
            'server_capture_all' in self.run_options):
            # Do not perform capture on the server if it is the same host
            # as the router.  Instead, use the 'router_capture_all' option
            # so the router instance can mediate phy usage.
            self.run_options.remove('server_capture_all')
            if 'router_capture_all' not in self.run_options:
                self.run_options.append('router_capture_all')

        self.command_hooks = {}

        if 'server_capture_all' in self.run_options:
            self.__add_hook('config', self.hosting_server.start_capture_params)
        if 'router_capture_all' in self.run_options:
            self.__add_hook('config', self.wifi.start_capture_params)
        if 'client_capture_all' in self.run_options:
            self.__add_hook('config', self.client_start_capture)
        if 'client_stats_all' in self.run_options:
            self.__add_hook('config', self.client_start_statistics)

        self.ethernet_mac_address = None
        mac_string = wifi_test_utils.get_interface_mac(
                self.client, 'eth0', self.client_proxy.command_ip)
        if mac_string:
          pieces = mac_string.split(":")
          self.ethernet_mac_address = "".join(pieces)

        self.init_profile()


    @property
    def client(self):
        """ @return host object representing the DUT. """
        return self.client_proxy.host


    @property
    def server(self):
        """ @return host object representing the server. """
        return self.hosting_server.server


    @property
    def server_wifi_ip(self):
        """ @return string IPv4 address for the client to ping. """
        if self.wifi.force_local_server:
            # Server WiFi IP is created using a local server address.
            return self.wifi.local_server_address(0)
        return self.hosting_server.wifi_ip


    @property
    def client_wlanif(self):
        """@return string client WiFi device (e.g. mlan0)."""
        return self.client_proxy.wifi_if


    def init_profile(self):
       # NB: do last so code above doesn't need to cleanup on failure
       self.test_profile = {'name':'test'}
       # cleanup in case a previous failure left the profile around
       self.profile_cleanup()
       self.profile_create(self.test_profile)
       self.profile_push(self.test_profile)


    def cleanup(self, params):
        """ Cleanup state: disconnect client and destroy ap """
        if 'no_cleanup_disconnect' not in self.run_options:
            self.wifi.destroy({})

        self.wifi.cleanup({})
        self.profile_cleanup()
        self.client_stop_capture({})
        self.client_stop_statistics({})
        self.client_proxy.firewall_cleanup()
        self.host_route_cleanup({})
        self.wifi.stop_capture()
        self.hosting_server.stop_capture()


    def __get_step_requirements(self):
        # This finds out what additional requirements are implicit based on
        # the steps outlined in the test description.
        client_reqs = set()
        router_reqs = set()
        for step in self.steps:
            if len(step) < 2 or step[1].__class__ != dict:
                continue
            method = step[0]
            params = step[1]
            if method != 'config':
                continue
            if 'channel' in params and int(params['channel']) > 5000:
                client_reqs.add(site_linux_system.LinuxSystem.CAPABILITY_5GHZ)
                router_reqs.add(site_linux_system.LinuxSystem.CAPABILITY_5GHZ)
            if 'multi_interface' in params:
                router_reqs.add(
                        site_linux_system.LinuxSystem.CAPABILITY_MULTI_AP)
        logging.info("Step requirements: Client: %s, AP: %s" %
                     (repr(client_reqs), repr(router_reqs)))
        return list(client_reqs), list(router_reqs)


    def __add_hook(self, hook, fn):
        if hook not in self.command_hooks:
            self.command_hooks[hook] = []

        self.command_hooks[hook].append(fn)


    def __run_hooks(self, hook, params):
        if hook not in self.command_hooks:
            return

        for fn in self.command_hooks[hook]:
            if getattr(fn, 'im_class', None):
                hook_name = "%s.%s" % (fn.im_class.__name__, fn.__name__)
            else:
                hook_name = fn.__name__
            logging.info("%s: hook '%s' for method '%s' params %s", self.name,
                         hook_name, hook, params)
            fn(params)


    def run(self):
        """
        Run a WiFi test.  Each step is interpreted as a method either in this
        class or in one of the ancillary router or server classes and invoked
        with the supplied parameter dictionary.

        This routine bases its expectation of the method's result on the value
        (if any) of a prefix before the method name:

          - No prefix: The operation is expected to succeed.

          - '!': The operation is expected to fail; this is useful, for
            example, for testing parameter checking in flimflam.

          - '~': We don't care whether the operation succeeds or fails; this
            is especially useful during cleanup (e.g., deleting profiles).
        """
        for requirement in self.client_requirements:
            if not requirement in self.client_proxy.capabilities:
                raise error.TestNAError(
                    "%s: client is missing required capability: %s" %
                    (self.name, requirement))

        self.wifi.require_capabilities(self.router_requirements)

        for step_number, s in enumerate(self.steps):
            method = s[0]
            if method[0] == '!':
                expect_result = WiFiTest._result_expect_failure
                method = method[1:]
            elif method[0] == '~':
                expect_result = WiFiTest._result_dont_care
                method = method[1:]
            else:
                expect_result = WiFiTest._result_expect_success
            if len(s) > 1:
                params = s[1]
            else:
                params = {}
            if len(s) > 2:
                failure_string = s[2]
            else:
                failure_string = None

            # What should perf data be prefixed with?
            if 'perf_prefix' in params:
                self.prefix = '%s_%s' % (method, params.pop('perf_prefix'))
            elif method in self.iterated_steps:
                self.prefix = '%s_%02d' % (method, self.iterated_steps[method])
                self.iterated_steps[method] += 1
            else:
                self.prefix = method

            self.__run_hooks(method, params)

            expectation = (" (expect failure)"
                           if expect_result is WiFiTest._result_expect_failure
                           else "")

            logging.info("-------------------------------------------")
            logging.info("%s: step %d '%s'%s params %s",
                         self.name, step_number+1, method, expectation, params)

            self.error_message = ''
            func = getattr(self, method, None)
            if func is None:
                func = getattr(self.wifi, method, None)
            if func is None:
                func = getattr(self.hosting_server, method, None)
            if func is None and self.attenuator:  # Must be an Attenuator method
                func = getattr(self.attenuator, method, None)

            if func is not None:
                try:
                    func(params)
                    if expect_result is WiFiTest._result_expect_failure:
                        # TODO(wdg): This should be rewritten so that we don't
                        # swap the expectation value of a succeeding test,
                        # here.  It's non-intuitive.
                        expect_result = WiFiTest._result_expect_success
                        raise error.TestFail("Succeeded (but expected "
                                             "failure).")
                except Exception, e:
                    if expect_result is WiFiTest._result_dont_care:
                        logging.info("%s: Failed (but we don't care).",
                                     self.name)
                        continue
                    elif expect_result is WiFiTest._result_expect_failure:
                        if not failure_string:
                            logging.info("%s: Failed (but we expected that).",
                                         self.name)
                            continue

                        # If test did not explicitly specify an error message,
                        # perhaps we can scoop one out of the exception
                        if not self.error_message and hasattr(e, 'result_obj'):
                            self.error_message = (e.result_obj.stderr +
                                                  e.result_obj.stdout)
                        if re.search(failure_string, self.error_message):
                            logging.info("%s: Failed (but we expected that).",
                                         self.name)
                            continue

                        logging.error("Expected failure, but error string does "
                                      "not match what was expected. Got %s but "
                                      "expected %s.",
                                      self.error_message,
                                      failure_string)
                    logging.error("%s: Step '%s' failed: %s; abort test",
                        self.name, method, str(e))
                    logging.info("===========================================")
                    self.cleanup({})
                    traceback.print_exc()
                    raise e
            else:
                logging.error("%s: Step '%s' unknown; abort test",
                    self.name, method)
                logging.info("===========================================")
                self.cleanup({})
                break
        else:
            logging.info("===========================================")
            # If all steps ran successfully perform the normal cleanup steps
            self.cleanup({})


    def write_keyvals(self, job):
        job.write_perf_keyval(self.perf_keyvals)

    def write_perf(self, data):
        for key, value in data.iteritems():
            if value is not None:
                self.perf_keyvals['%s_%s' % (self.prefix, key)] = value


    def __get_local_file(self, pattern):
        """
        Pass a string pattern with a "%...d" in it, and get back a unique
        string with the number of times this pattern has been used.  This
        is useful for creating unique local file names to store data
        related to each test run.
        """
        if not getattr(self, 'local_file_counts', None):
            self.local_file_counts = {}
        file_count = self.local_file_counts.get(pattern, 0)
        self.local_file_counts[pattern] = file_count + 1
        return os.join(self.debug_dir, pattern % file_count)


    def install_script(self, script_name, *support_scripts):
        if script_name in self.client_installed_scripts:
            return self.client_installed_scripts[script_name]
        script_client_dir = self.client.get_tmp_dir()
        script_client_file = os.path.join(script_client_dir, script_name)
        for copy_file in [script_name] + list(support_scripts):
            # Look either relative to the current location of this file or
            # relative to ../client/common_lib/cros/site_wlan for the script.
            script_relative_paths = [['.'],
                                     ['..', 'client', 'common_lib',
                                      'cros', 'site_wlan']]
            for rel_path in script_relative_paths:
                src_file = os.path.join(
                    os.path.dirname(os.path.realpath(__file__)),
                    *(rel_path + [copy_file]))
                if os.path.exists(src_file):
                    break
            else:
                raise ScriptNotFound(copy_file)

            dest_file = os.path.join(script_client_dir,
                                     os.path.basename(src_file))
            self.client.send_file(src_file, dest_file, delete_dest=True)
        self.client_installed_scripts[script_name] = script_client_file
        return script_client_file

    def insert_file(self, host, filename, contents):
        """
        Send a byte string to a file on a remote host.

        @param host host object representing a remote machine.
        @param filename string path on remote machine to copy to.
        @param contents raw contents of the file to be created

        """
        # Write the contents to local disk first so we can use the easy
        # built in mechanism to do this.
        with tempfile.NamedTemporaryFile() as f:
            f.write(contents)
            f.flush()
            os.chmod(f.name, stat.S_IRUSR | stat.S_IWUSR |
                             stat.S_IRGRP | stat.S_IWGRP |
                             stat.S_IROTH | stat.S_IWOTH)
            host.send_file(f.name, filename, delete_dest=True)


    def install_files(self, params):
        """ Install files on the client or router with the provided
        contents"""

        systemname = params.get('system', None)
        if systemname == 'router':
            system = self.router
        elif systemname == 'client':
            system = self.client
        elif systemname == 'server':
            system = self.server
        else:
            raise error.TestFail('install_files: Must specify router, '
                                 'server or client')

        for name,contents in params.get('files', {}).iteritems():
            self.insert_file(system, name, contents)


    def __clean_tpm(self):
        self.client.run("initctl restart chapsd")
        cryptohome_cmd = "/usr/sbin/cryptohome"
        self.client.run(cryptohome_cmd + " --action=tpm_take_ownership",
                ignore_status = True)
        self.client.run(cryptohome_cmd + " --action=tpm_wait_ownership",
                ignore_status = True)


    def __load_tpm_token(self, token_auth):
        chaps_dir = "/tmp/chaps/"
        self.client.run("rm -rf " + chaps_dir)
        self.client.run("mkdir " + chaps_dir)
        self.client.run("chown %s:%s %s" % (
                "chaps",
                "chronos-access",
                chaps_dir))
        self.client.run("chaps_client --load --path=%s --auth=\"%s\"" % (
                chaps_dir,
                token_auth))

    def install_tpm_object(self, params):
        if not "data" in params:
            raise error.TestFail("Need a data parameter to install a TPM"
                                 "certificate")
        if not "id" in params:
            raise error.TestFail("Need an object id to install a TPM"
                                 "certificate")
        if not "object_type" in params:
            raise error.TestFail("Need to know whether the requested TPM "
                                 "object is a private key or a certificate.")
        if params["object_type"] == "cert":
            conv_cmd = "openssl x509 -in %s -inform PEM -out %s -outform DER"
            load_cmd = "p11_replay --import --path=%s --type=cert --id=%s"
        elif params["object_type"] == "key":
            conv_cmd = "openssl rsa -in %s -inform PEM -out %s -outform DER"
            load_cmd = "p11_replay --import --path=%s --type=privkey --id=%s"
        else:
            raise error.TestFail("Invalid object type, expected either cert "
                                 "or key.")
        data = params["data"]
        object_id = params["id"]
        pem_path = self.client.run("mktemp").stdout.strip()
        der_path = self.client.run("mktemp").stdout.strip()
        self.install_files({ "system":"client", "files":{ pem_path:data } } )
        # Convert those keys into DER format
        self.client.run(conv_cmd % (pem_path, der_path))
        # load that stuff into the TPM
        self.client.run(load_cmd % (der_path, object_id))


    def initialize_tpm(self, params):
        """ Remove past state from TPM, and install a new token so that we can
        later install objects to the TPM.  Call this function before calling
        install_tpm_object. """
        self.__clean_tpm()
        token_auth = site_eap_certs.auth_pin
        self.__load_tpm_token(token_auth)


    def install_nss_certificate(self, params):
        """ Install an PEM certifcate into the NSS database on the client. """
        if not 'data' in params:
            raise error.TestFail('Need a data parameter to install a NSS '
                                 'certificate')
        if not 'id' in params:
            raise error.TestFail('Need an object id to install an NSS '
                                 'certificate')

        data = params['data']
        object_id = params['id']
        pem_path = self.client.run('mktemp').stdout.strip()
        der_path = self.client.run('mktemp').stdout.strip()

        # Copy the PEM input certificate into a temporary file on the client.
        self.install_files({ 'system' : 'client',
                             'files' : { pem_path : data } } )

        # Convert the certificate into DER format
        self.client.run('openssl x509 -in %s -inform PEM -out %s -outform DER' %
                        (pem_path, der_path))
        # Load that stuff into the NSS database.
        self.client.run('nsscertutil -A -t P,, -i %s -n %s -d sql:%s' %
                        (der_path, object_id, site_eap_certs.nss_cert_db_path))
        # Make sure the NSS database remains accessible by the NSS user.
        self.client.run('chown -R %s: %s' %
                        (site_eap_certs.nss_cert_db_user,
                         site_eap_certs.nss_cert_db_path))
        # Cleanup.
        self.client.run('rm -f %s %s' % (pem_path, der_path))


    def initialize_nss(self, params):
        """ Initialize the NSS database on the client. """
        self.client.run('rm -rf %s' % site_eap_certs.nss_cert_db_path)
        self.client.run('mkdir -p %s' % site_eap_certs.nss_cert_db_path)
        self.client.run('echo "\n\n" | nsscertutil -N -d sql:%s' %
                        site_eap_certs.nss_cert_db_path)


    def connect(self, params):
        """ Connect client to AP/router """

        script_client_file = self.install_script('site_wlan_connect.py',
                                                 'site_wlan_dbus_setup.py',
                                                 'site_wlan_wait_state.py',
                                                 'constants.py')

        flags = []
        if params.get('debug', True):
            flags.append('--debug')
        if params.get('hidden', False):
            flags.append('--hidden')
        if 'mode' in params:
            flags.append('--mode=%s' % params['mode'])
        if params.get('nosave', False):
            flags.append('--nosave')

        result = self.client.run('python "%s" %s "%s" "%s" "%s" "%d" "%d"' %
            (script_client_file,
             ' '.join(flags),
             params.get('ssid', self.wifi.get_ssid()),
             params.get('security', ''),
             params.get('psk', ''),
             params.get('assoc_timeout', self.deftimeout),
             params.get('config_timeout', self.deftimeout))).stdout.rstrip()

        result_times = re.match('OK ([0-9\.]*) ([0-9\.]*) ([0-9\.]*) '
                                '([0-9\.]*) ([0-9]+) (\S+) (\w+) .*',
                                result)
        if not result_times:
            raise error.TestFail('Connect succeeded but result not parsed: ' +
                                 result)

        self.write_perf({'acquire_s'    : result_times.group(1),
                         'select_s'     : result_times.group(2),
                         'assoc_s'      : result_times.group(3),
                         'config_s'     : result_times.group(4),
                         'frequency'    : result_times.group(5)})
        for k in ('already_connected', 'clear_error', 'fast_fail',
                  'get_prop', 'in_progress', 'lost_dbus', 'multiple_attempts'):
            if re.search(k, result) is not None:
                self.write_perf({k:'true'})

        print "%s: %s" % (self.name, result)

        # stash connection state to emit for each test result
        self.cur_frequency = result_times.group(5)
        self.cur_phymode = result_times.group(6)
        self.cur_security = result_times.group(7)

        # fetch IP address of wireless device
        logging.info("%s: client WiFi-IP is %s",
                     self.name, self.client_proxy.wifi_ip)
        # TODO(sleffler) not right for non-mac80211 devices
        # TODO(sleffler) verify debugfs is mounted @ /sys/kernel/debug
        self.client_debugfs_path = "/sys/kernel/debug/ieee80211/%s/netdev:%s" \
            % ("phy0", self.client_wlanif)


    def disconnect(self, params):
        """ Disconnect previously connected client """
        script_client_file = self.install_script('site_wlan_disconnect.py',
                                                 'site_wlan_dbus_setup.py',
                                                 'constants.py')
        result = self.client.run('python "%s" "%s" "%d"' %
            (script_client_file,
            params.get('ssid', self.wifi.get_ssid()),
            params.get('wait_timeout', self.deftimeout))).stdout.rstrip()

        print "%s: %s" % (self.name, result)


    def profile(self, params):
        """ Display profile information -- for debugging. """

        print "\nSERVICES:"
        result = self.client.run('%s/list-services' %
                        (self.client_cmd_flimflam_lib),
                        ignore_status=True)
        print "%s: %s" % (self.name, result)

        print "\nENTRIES:"
        result = self.client.run('%s/profile list-entries' %
                        (self.client_cmd_flimflam_lib),
                        ignore_status=True)
        print "%s: %s" % (self.name, result)

    def client_check_profile_properties(self, params):
        """ Verify that profile/entries properties equal expected values. """

        args = ['--param %s:%s' % (var, val) for var, val in params.iteritems()]
        if self.ethernet_mac_address:
          args.append('--ethmac %s' % self.ethernet_mac_address)
        args.append('--command ClientCheckProfileProperties')

        script_client_file = self.install_script('site_wlan_profiles.py',
                                                 'site_wlan_dbus_setup.py',
                                                 'constants.py')

        result = self.client.run('python "%s" %s' %
             (script_client_file, ' '.join(args))).stdout.rstrip()

        print "%s: %s" % (self.name, result)

    def client_profile_delete_entry(self, params):
        """ Verify that profile/entries properties equal expected values. """

        args = ['--param %s:%s' % (var, val) for var, val in params.iteritems()]
        if self.ethernet_mac_address:
          args.append('--ethmac %s' % self.ethernet_mac_address)
        args.append('--command ClientProfileDeleteEntry')

        script_client_file = self.install_script('site_wlan_profiles.py',
                                                 'site_wlan_dbus_setup.py',
                                                 'constants.py')

        result = self.client.run('python "%s" %s' %
             (script_client_file, ' '.join(args))).stdout.rstrip()

        print "%s: %s" % (self.name, result)

    def __wait_service_start(self, params):
        """ Wait for service transitions on client. """

        script_client_file = self.install_script('site_wlan_wait_state.py',
                                                 'site_wlan_dbus_setup.py',
                                                 'constants.py')
        args = []

        # Whether to print out all state transitions of watched services to
        # stderr
        if params.get('debug', True):
            args.append('--debug')
        # Time limit on the execution of a single step
        if 'step_timeout' in params:
            args.append('--step_timeout %d' % int(params['step_timeout']))
        # Time limit to wait for a service to appear in the service list
        if 'service_timeout' in params:
            args.append('--svc_timeout %d' % int(params['service_timeout']))
        # Time limit on the execution of the entire series of steps
        args.append('--run_timeout=%d' % int(params.get('run_timeout', 10)))

        states = params.get('states', [])
        if not states:
            raise error.TestFail('No states given to wait for')

        for service, state in states:
            args.append('"%s=%s"' % (service or self.wifi.get_ssid(), state))

        self.wait_service_states = states
        return 'python "%s" %s' % (script_client_file, ' '.join(args))


    def __wait_service_complete(self, params, result):
        print "%s: %s" % (self.name, result)

        states = self.wait_service_states
        cstates = []
        counts = {}
        for service, state in states:
            cstate = state.strip('+-').replace(':', '_')
            cstates.append(cstate)
            if state in counts:
                counts[cstate] = 1
            else:
                counts[cstate] = 0

        for cstate, intr in zip(cstates, result.stdout.split(' ')):
            if intr.startswith('ERR_'):
                raise error.TestFail('Wait for step %s failed with error %s' %
                                     (cstate, intr))
            if counts[cstate]:
                index = '%s%d' % (cstate, counts[cstate] - 1)
                counts[cstate] += 1
            else:
                index = cstate

            self.write_perf({ index:float(intr) })
            print "  %s: %s" % (state, intr)

            max = 'max_' + cstate
            if max in params and float(intr) > float(params[max]):
                raise error.TestFail('Too long to reach %s state: %f > %f' %
                                     (cstate, float(intr), float(params[max])))


    def wait_service(self, params):
        result = self.client.run(self.__wait_service_start(params))
        self.__wait_service_complete(params, result)


    def wait_service_suspend_bg(self, params):
        params['after_command'] = self.__wait_service_start(params)
        self.client_suspend_bg(params)


    def wait_service_suspend_end(self, params):
        self.client_suspend_end(params)
        self.__wait_service_complete(params, self.client_suspend_thread.result)


    def client_powersave_on(self, params):
        """Enable power save operation.

        @param params ignored, but required by this framework.

        """
        self.client_proxy.powersave_switch(True)


    def client_powersave_off(self, params):
        """Disable power save operation.

        @param params ignored, but required by this framework.

        """
        self.client_proxy.powersave_switch(False)


    def __client_check(self, param, want):
        """ Verify negotiated station mode parameter """
        result = self.client.run("cat '%s/%s'" %
            (self.client_debugfs_path, param))
        got = result.stdout.rstrip()       # NB: chop \n
        if got != want:
            raise error.TestFail("client_check_%s: wanted %s got %s" %
                                 (param, want, got))


    def __client_check_iw_link(self, iw_link_key, desired_value):
        """Assert that the current wireless link property is |desired_value|.

        @param iw_link_key string one of IW_LINK_KEY_* defined in WiFiClient.
        @param desired_value string desired value of iw link property.

        """
        self.client_proxy.check_iw_link_value(iw_link_key, desired_value)


    def client_check_dtimperiod(self, params):
        """ Verify negotiated DTIM period """
        self.__client_check_iw_link("dtim period", params[0])


    def client_check_rifs(self, params):
        """ Verify negotiated RIFS setting """
        self.__client_check("rifs", params[0])


    def client_check_shortgi20(self, params):
        """ Verify negotiated Short GI setting """
        self.__client_check("sgi20", params[0])


    def client_check_shortgi40(self, params):
        """ Verify negotiated Short GI setting """
        self.__client_check("sgi40", params[0])


    def client_check_shortslot(self, params):
        """ Verify negotiated Short Slot setting """
        self.__client_check("short_slot", params[0])


    def client_check_protection(self, params):
        """ Verify negotiated CTS protection setting """
        self.__client_check("cts_prot", params[0])


    def client_monitor_start(self, params):
        """ Start monitoring system events """
        raise NotImplementedError("client_monitor_start")


    def client_monitor_stop(self, params):
        """ Stop monitoring system events """
        raise NotImplementedError("client_monitor_stop")


    def client_check_event_mic(self, params):
        """ Check for MIC error event """
        raise NotImplementedError("client_check_event_mic")


    def client_check_event_countermeasures(self, params):
        """ Check for WPA CounterMeasures event """
        raise NotImplementedError("client_check_event_countermeasures")


    def client_check_frequency(self, params):
        """ Verify current frequency """
        self.__client_check_iw_link("freq", params[0])


    def client_check_service_properties(self, params):
        """ Verify that service properties attained their expected values. """
        service = params.pop("service", None)
        if self.ethernet_mac_address and service == "ethernet":
          service = "ethernet_%s" % self.ethernet_mac_address
        states = [(service, "%s:%s" % (var, val))
                  for var, val in params.iteritems()]
        self.wait_service({ "run_timeout": 0, "states": states})

    def sleep(self, params):
        time.sleep(float(params['time']))


    def __unreachable(self, method):
        logging.info("%s: SKIP step %s; server is unreachable",
            self.name, method)


    def __get_pingstats(self, stats):
        stats['frequency'] = self.cur_frequency
        stats['phymode']   = self.cur_phymode
        stats['security']  = self.cur_security
        return stats


    def __print_pingstats(self, label, stats):
        logging.info("%s: %s%s/%s, %s%% loss, rtt %s/%s/%s",
            self.name, label, stats['xmit'], stats['recv'], stats['loss'],
             stats['min'], stats['avg'], stats['max'])


    def iw_event_scan(self, params):
        """ Obtain the event scan output and store it

        Params:
            duration: Indicates time in seconds.  If no duration
                      provided, iw even runs until iw_even_scan_stop
                      is called.
        """
        duration = params.get('duration', 0)
        cmd = '%s event -f' % self.client_proxy.command_iw
        self.iw_event_thread = remote_command.Command(self.client, cmd)

        if duration:
            time.sleep(float(duration))
            self.iw_event_thread_stop({})


    def iw_event_scan_stop(self, params):
        """ Stops the iw event thread """
        self.iw_event_thread.join()
        self.iw_event_thread_output = self.iw_event_thread.result.stdout
        logging.debug('Output of iw scan is %s' % self.iw_event_thread_output)


    def search_iw_events(self, params):
        """ Searches through the last run iw event scan for strings

        Params:
            match: A list of strings to match.

        Raises:
            error.TestFail if any strings in match are not found in
                iw event output.
        """
        match_list = params.get('match', [])
        if not hasattr(self, 'iw_event_thread_output'):
            return

        for match in match_list:
            if match not in self.iw_event_thread_output:
                raise error.TestFail("Expecting %s in iw event output but "
                               "it wasn't present.")


    def client_ping(self, params):
        """
        Ping the server from the client.

        @param params dict of parameters used to form ping arguments.

        """
        params = params.copy()
        if 'ping_ip' in params:
            ping_ip = params.pop('ping_ip')
        else:
            if 'dest' in params:
                ping_dest = params.pop('dest')
            else:
                if self.wifi.has_local_server():
                    ping_dest = 'router'
                else:
                    ping_dest = 'server'

            if ping_dest == 'server':
                ping_ip = self.server_wifi_ip
            elif ping_dest == 'router':
                ping_ip = self.wifi.get_wifi_ip(params.get('ap', 0))
            else:
                raise error.TestFail('Unknown ping destination "%s"' %
                                     ping_dest)

        count = int(params.pop('count', self.defpingcount))
        if params:
            raise error.TestFail('Unhandled ping parameters %r.' % params)

        ping_config = ping_runner.PingConfig(ping_ip, count=count,
                                             ignore_result=True)
        stats = self.client_proxy.ping(ping_config).old_style_output
        stats = self.__get_pingstats(stdout)
        self.write_perf(stats)
        self.__print_pingstats("client_ping ", stats)


    def set_attenuation(self, params):
        """ Record current attenuation value """
        self.cur_attenuation = self.attenuator.set_attenuation(params)

    def _parse_attenuation(self, params):
        """ Sanity check attenuation values and make simple corrections """
        # Attenuations are measured in units of dB
        fixed_atten = params.get('fixed_atten', None)
        start_atten = params.get('start_atten', fixed_atten)
        end_atten = params.get('end_atten', None)

        if ((fixed_atten is None) or (start_atten is None) or
            (end_atten is None)):
            err = ('Please specify all attenuation values for this test: '
                   'fixed_atten, start_atten, end_atten.')
            raise error.TestFail(err)

        fixed_atten = int(fixed_atten)
        start_atten = int(start_atten)
        end_atten = int(end_atten)

        if start_atten < fixed_atten:
            logging.warning('start_atten (%d) reset to fixed_atten (%d)',
                            start_atten, fixed_atten)
            start_atten = fixed_atten
        if end_atten < start_atten:
            logging.warning('end_atten (%d) reset to start_atten (%d)',
                            end_atten, start_atten)
            end_atten = start_atten
        return fixed_atten, start_atten, end_atten


    def client_start_capture(self, params):
        """Start capturing network traffic on the client.

        @param params dict of site_wifitest parameters.

        """
        self.client_proxy.start_capture()


    def client_stop_capture(self, params):
        """Stop capturing network traffic on the client.

        Stop capturing packets on the client, and copy the previous
        ongoing packet capture file to the autotest server.

        @param params dict of site_wifitest parameters.

        """
        self.client_proxy.stop_capture()


    def client_suspend(self, params):
        """ Suspend the system """

        script_client_file = self.install_script('site_system_suspend.py',
                                                 '../client/cros/rtc.py',
                                                 '../client/cros/'
                                                 'sys_power.py',
                                                 '../client/cros/'
                                                 'upstart.py')
        result = self.client.run('python "%s" %d' %
            (script_client_file, int(params.get("suspend_time", 5))))


    def client_suspend_bg(self, params):
        """ Suspend the system in the background """

        script_client_file = self.install_script('site_system_suspend.py',
                                                 '../client/cros/rtc.py',
                                                 '../client/cros/'
                                                 'sys_power.py',
                                                 '../client/cros/'
                                                 'upstart.py')
        cmd = ('python "%s" %d %s' %
               (script_client_file,
                int(params.get("suspend_time", 5)),
                params.get("after_command", '')))
        self.client_suspend_thread = remote_command.Command(self.client, cmd)


    def client_suspend_end(self, params):
        """ Join the backgrounded suspend thread """

        self.client_suspend_thread.join()
        if self.client_suspend_thread.result.exit_status:
            raise error.TestError('suspend failed')

    def restart_supplicant(self, params):
        """ Restart wpa_supplicant.  Cert params are unfortunately "sticky". """

        self.client.run("stop wpasupplicant; start wpasupplicant")


    def profile_create(self, params):
        """ Create a profile with the specified name """
        self.client.run('%s/profile create %s' %
                        (self.client_cmd_flimflam_lib, params['name']))
        self.created_profiles.append(params['name'])

    def profile_remove(self, params, ignore_status=False):
        """ Remove the specified profile """
        self.client.run('%s/profile remove %s' %
                        (self.client_cmd_flimflam_lib, params['name']),
                         ignore_status=ignore_status)

    def profile_push(self, params):
        """ Push the specified profile on the stack """
        self.client.run('%s/profile push %s' %
                        (self.client_cmd_flimflam_lib, params['name']))

    def profile_pop(self, params, ignore_status=False):
        """ Pop the specified profile from the stack or any profile
            if no name is specified.
        """
        if 'name' in params:
            self.client.run('%s/profile pop %s' %
                            (self.client_cmd_flimflam_lib, params['name']),
                            ignore_status=ignore_status)
        else:
            self.client.run('%s/profile pop' %
                            (self.client_cmd_flimflam_lib),
                            ignore_status=ignore_status)


    def profile_cleanup(self):
        """ Cleanup all profiles """
        # Pop and remove all profiles on the stack until 'default' is found.
        self.client.run('%s/profile clean' %
                        (self.client_cmd_flimflam_lib))
        # Some profiles may still in profile storage but not on the stack,
        # invoke 'profile_remove' for self.created_profiles to make sure that
        # all profiles are deleted.
        for profile_name in self.created_profiles:
            self.profile_remove({'name':profile_name}, ignore_status=True)

    def __get_wifi_device_path(self):
        if self.client_wifi_device_path:
            return self.client_wifi_device_path
        ret = []
        result = self.client.run('%s/list-devices' %
                                 self.client_cmd_flimflam_lib)
        device_path = None
        for line in result.stdout.splitlines():
            m = re.match('\[\s*(\S*)\s*\]', line)
            if m is not None:
                device_path = m.group(1)
                continue
            if re.search('Name = Wireless', line) is not None:
                self.client_wifi_device_path = device_path
                break

        return self.client_wifi_device_path

    def enable_wifi(self, params):
        wifi = self.__get_wifi_device_path()
        if wifi:
            self.client.run('%s/enable-device %s' %
                            (self.client_cmd_flimflam_lib, wifi))

    def disable_wifi(self, params):
        wifi = self.__get_wifi_device_path()
        if wifi:
            self.client.run('%s/disable-device %s' %
                            (self.client_cmd_flimflam_lib, wifi))


    def client_get_signal(self, params):
        result = self.client.run('%s dev %s link; '
                                 '%s dev %s station dump; '
                                 '%s dev %s survey dump' %
                                 ((self.client_proxy.command_iw,
                                   self.client_wlanif) * 3))
        current_frequency = None
        link_frequency = None
        signal_info = {}
        signal_values = ( 'frequency', 'signal', 'signal avg', 'noise' )
        for line in result.stdout.splitlines():
            m = re.match('\s*(\S.*):\s*(\S*)', line)
            if m is None:
                continue
            var, val = m.groups()
            if var == 'freq':
                link_frequency = val
            elif var == 'frequency':
                current_frequency = val
            if (var in signal_values and
                (current_frequency == None or
                 current_frequency == link_frequency)):
                signal_info[var] = val

        self.client_signal_info = signal_info
        logging.info('Signal Info: %s' % repr(signal_info))


    def scan(self, params):
        """Ask the DUT to scan for SSIDs on frequencies.

        |params| may contain 'freq' and 'ssid' keys, which should
        map to lists of frequencies and ssids respectively.  Asserts
        that we find all 'ssid' members listed.

        @param params dict of settings for scan.

        """
        frequencies = map(int, params.get('freq', []))
        ssids = params.get('ssid', [])
        self.client_proxy.scan(frequencies, ssids)


    def vpn_client_load_tunnel(self, params):
        """ Load the 'tun' device.

            Necessary when the VPN Server is configured with 'dev tun'.
        """
        result = self.client.run('modprobe tun') # When server using tunnel.

    def vpn_client_connect(self, params):
        """ Configure & launch the VPN client.

            Parameters:

              'kind'      : required
                  Indicates the kind of VPN which is to be used.
                  Valid values are:

                    l2tpipsec-cert
                    l2tpipsec-psk
                    openvpn

              'vpn-host-ip': optional
                  Specifies the IP of the VPN server.  If not provided,
                  defaults to 'self.server_wifi_ip'

              'files'      : required
                  A dict which contains a set of file names.

                     'ca-certificate'     : path to CA certificate file
                     'client-certificate' : path to client certificate file
                     'client-key'         : path to client key file

              'remote-cert-tls' : optional
                    If provided, this option can be 'server', 'client' or
                    'none'.
                    If not specified, the default is 'none'.
                    The value provided is passed directly to 'connect-vpn'.
        """
        self.vpn_client_kill({}) # Must be first.  Relies on self.vpn_kind.
        self.vpn_kind = params.get('kind', None)

        # Starting up the VPN client may cause the DUT's routing table (esp.
        # the default route) to change.  Set up a host route backwards so
        # we don't lose our control connection in that event.
        self.__add_host_route(self.client)

        if self.vpn_kind is None:
            raise error.TestFail('No VPN kind specified for this test.')
        elif self.vpn_kind == 'openvpn':
            # 'ca_certificate', 'client-certificate' and 'client-key'.
            vpn_host_ip            = params.get('vpn-host-ip',
                                                self.server_wifi_ip)
            cert_pathnames         = params.get('files', {})
            remote_cert_tls_option = ""
            remote_cert_tls        = params.get('remote-cert-tls', None)

            if remote_cert_tls is not None:
                remote_cert_tls_option = "--remote-cert-tls " + remote_cert_tls

            result = self.client.run('%s/connect-vpn '
                                     '--verbose '
                                     '%s '
                                     'openvpn vpn-name %s vpn-domain '
                                     '%s '   # ca certificate
                                     '%s '   # client certificate
                                     '%s' %  # client key
                                     (self.client_cmd_flimflam_lib,
                                      remote_cert_tls_option,
                                      vpn_host_ip,
                                      cert_pathnames['ca-certificate'],
                                      cert_pathnames['client-certificate'],
                                      cert_pathnames['client-key']))
        elif self.vpn_kind == 'l2tpipsec-psk':
            # vpn_host_ip is self.server.ip because that is the
            # adapter that ipsec listens on.
            vpn_host_ip = params.get('vpn-host-ip', self.server.ip)
            password    = params.get('password'  , None)
            chapuser    = params.get('chapuser'  , None)
            chapsecret  = params.get('chapsecret', None)
            result = self.client.run('%s/connect-vpn '
                                     '--verbose '
                                     'l2tpipsec-psk vpn-name %s vpn-domain '
                                     '%s '  # password
                                     '%s '  # chapuser
                                     '%s' % # chapsecret
                                     (self.client_cmd_flimflam_lib,
                                      vpn_host_ip,
                                      password, chapuser, chapsecret))
        elif self.vpn_kind == 'l2tpipsec-cert':
            # vpn_host_ip is self.server.ip because that is the
            # adapter that ipsec listens on.
            vpn_host_ip = params.get('vpn-host-ip', self.server.ip)
            chapuser    = params.get('chapuser'  , None)
            chapsecret  = params.get('chapsecret', None)
            ca_cert_id  = params.get('cacertid', None)

            result = self.client.run('%s/connect-vpn '
                                     '--verbose '
                                     'l2tpipsec-cert vpn-name %s vpn-domain '
                                     '%s '   # CACertNSS
                                     '0 '    # ClientCertSlot
                                     '%s '   # ClientCertID
                                     '%s '   # PIN
                                     '%s '   # chapuser
                                     '%s' %  # chapsecret
                                     (self.client_cmd_flimflam_lib,
                                      vpn_host_ip,
                                      ca_cert_id,
                                      site_eap_certs.cert_1_tpm_key_id,
                                      site_eap_certs.auth_pin,
                                      chapuser,
                                      chapsecret))
        else:
            raise error.TestFail('(internal error): No launch case '
                                 'for VPN kind (%s)' % self.vpn_kind)

    def vpn_client_kill(self, params):
        """ Kill the VPN client if it's running. """
        if self.vpn_kind is not None:
            if self.vpn_kind == 'openvpn':
                self.client.run("pkill openvpn")
            elif self.vpn_kind in ('l2tpipsec-psk', 'l2tpipsec-cert'):
                self.client.run("/usr/sbin/ipsec stop")
            else:
                raise error.TestFail('(internal error): No kill case '
                                     'for VPN kind (%s)' % self.vpn_kind)
            self.vpn_kind = None

        self.__del_host_route(self.client)


    def __add_host_route(self, host):
        # What is the local address we use to get to the test host?
        local_ip = site_host_route.LocalHostRoute(host.ip).route_info["src"]

        # How does the test host currently get to this local address?
        host_route = site_host_route.RemoteHostRoute(host, local_ip).route_info

        # Flatten the returned dict into a single string
        route_args = " ".join(" ".join(x) for x in host_route.iteritems())

        self.host_route_args[host.ip] = "%s %s" % (local_ip, route_args)
        host.run("ip route add %s" % self.host_route_args[host.ip])

    def __del_host_route(self, host):
        if host.ip in self.host_route_args:
            host.run("ip route del %s" % self.host_route_args.pop(host.ip))

    def host_route_cleanup(self, params):
        for host in (self.client, self.server, self.router):
            self.__del_host_route(host)

    def log_time_diff(self, params):
        log_file = self.client_logfile

        time_diff = self.install_script('site_log_time_diff.py')
        result = self.client.run("python '%s' --from='%s' --to='%s'" %
                                      (time_diff, params['from'], params['to']))

        if '-' in result.stdout:
            logging.info("Unable to find timespan")
            return

        if "perf" in params:
            self.write_perf({params['perf']:float(result.stdout)})

    def client_deauth(self, params):
        self.wifi.deauth({'client': self.client_proxy.wifi_mac})

    def client_reboot(self, params):
        self.client_installed_scripts = {}

        if 'timeout' not in params:
            logging.info("Using default reboot timeout")
            self.client.reboot()
        else:
            reboot_timeout = float(params['timeout'])
            logging.info("Reboot timeout is %f seconds", reboot_timeout)
            self.client.reboot(timeout=reboot_timeout)

        self.profile_cleanup()
        self.profile_create(self.test_profile)
        self.profile_push(self.test_profile)

    def __store_pkcs11_resource(self, pkcs11_lib, user_pin, slot_id,
                                label, der_file_path, resource_type):
        self.client.run('pkcs11-tool '
                        '--module=%s '
                        '--pin %s '
                        '--id %s '
                        '--label %s '
                        '--write-object %s '
                        '--type %s' %
                        (pkcs11_lib,
                         user_pin,
                         slot_id,
                         label,
                         der_file_path,
                         resource_type))

    def client_start_statistics(self, params):
        """ Start capturing network statistics on the client """
        self.client_stop_statistics({})
        script = 'site_wlan_statistics.py'
        script_client_file = self.install_script(script)

        cmd = ('python %s --count=%s --period=%s' %
               (script_client_file,
                params.get('count', '-1'),
                params.get('period', '1')))
        logging.info(cmd)
        self.client_stats_thread = remote_command.Command(self.client, cmd)

    def client_stop_statistics(self, params):
        self.client.run('pkill -f site_wlan_statistics.py',
                        ignore_status=True)
        if self.client_stats_thread is not None:
            self.client_stats_thread.join()
            stats = self.client_stats_thread.result.stdout
            logging.info(stats)
            file(self.__get_local_file(
                    'client_interface_statistics_%02d.txt'), 'w').write(stats)
            self.client_stats_thread = None

    def client_configure_service(self, params):
        guid = params.pop('GUID', '')
        args = ''
        for var, val in params.iteritems():
            args += ' %s %s' % (var, val)
        self.client.run('%s/configure-service %s %s' %
                        (self.client_cmd_flimflam_lib, guid, args))

    def client_roam(self, params):
        instance = params.get('instance', 0)
        wifi_mac = self.wifi.get_hostapd_mac(instance)
        # The "wpa_cli" command can only be run as the "wpa" user.  That
        # user does not have a valid shell, so without specifying one, the
        # "su" command will fail.
        self.client.run('su wpa -s /bin/bash -c "%s roam %s"' %
                        (self.client_proxy.command_wpa_cli, wifi_mac))


def __byfile(a, b):
    if a['file'] < b['file']:
        return -1
    elif a['file'] > b['file']:
        return 1
    else:
        return 0


def read_tests(dir, *args):
    """
    Collect WiFi test tuples from files.  File names are used to
    sort the test objects so the convention is to name them NNN<test>
    where NNN is a decimal number used to sort and <test> is an
    identifying name for the test; e.g. 000Check11b
    """
    tests = []
    for file in os.listdir(dir):
        if any(fnmatch.fnmatch(file, pat) for pat in args):
            fd = open(os.path.join(dir, file))
            try:
                test = eval(fd.read())
            except Exception, e:
                logging.error("%s: %s", os.path.join(dir, file), str(e))
                raise e
            test['file'] = file
            tests.append(test)
    # use filenames to sort
    return sorted(tests, cmp=__byfile)


def run_test_dir(test_name, job, args, machine):
    # convert autoserv args to something usable
    opts = dict([[k, v] for (k, e, v) in [x.partition('=') for x in args]])

    if utils.host_is_in_lab_zone(machine):
        # If we are in the lab use the names for the server, AKA rspro,
        # and the router as defined in:
        # go/chromeos-lab-hostname-convention
        server_addr = wifi_test_utils.get_server_addr_in_lab(machine)
        router_addr = wifi_test_utils.get_router_addr_in_lab(machine)
    else:
        server_addr = opts.get('server_addr', None)
        router_addr = opts.get('router_addr', None)

    config = {'client': {'addr': machine},
              'router': {'addr': router_addr},
              'server': {'addr': server_addr},
              'run_options': opts.get('run_options', '').split(',')}

    logging.info('Client %r, Server %r, AP %r' %
                 (machine, server_addr, router_addr))

    if not all([server_addr, router_addr]):
        raise error.TestFail('User must specify server_addr and router_addr')

    test_pat = opts.get('test_pat', '[0-9]*')
    test_dir = os.path.join(job.serverdir, "site_tests", test_name)

    for t in read_tests(test_dir, test_pat):
       job.run_test(test_name, testcase=t, config=config, tag=t['file'])


class test(test.test):
  """
  Base class for network_WiFi* classes that are created in the control
  directory for each test suite
  """
  version = 1
  testtype = WiFiTest

  def expect_failure(self, name, reason):
    if reason is None:
      reason = "no reason given"
    logging.info("%s: ignore failure (%s)", name, reason)


  # The testcase config, setup, etc are done out side the individual
  # test loop, in the control file.
  def run_once(self, testcase, config):
    name = testcase['name']
    try:
      if 'skip_test' in testcase and 'no_skip' not in config['run_options']:
        logging.info("%s: SKIP: %s", name, testcase['skip_test'])
        raise error.TestNAError(testcase['skip_test'])
      else:
        wt = self.testtype(name, testcase['steps'],
                           testcase.get('requires', []), config)
        wt.run()
        wt.write_keyvals(self)
    except error.TestFail:
      if 'expect_failure' in testcase:
        self.expect_failure(name, testcase['expect_failure'])
      else:
        raise
    except Exception, e:
      if 'expect_failure' in testcase:
        self.expect_failure(name, testcase['expect_failure'])
      else:
        raise
