# Copyright (c) 2013 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 logging
import multiprocessing
import re
import select
import time

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros.network import ping_runner
from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
from autotest_lib.server import site_attenuator
from autotest_lib.server.cros.network import hostap_config
from autotest_lib.server.cros.network import rvr_test_base

class Reporter(object):
    """Object that forwards stdout from Host.run to a pipe.

    The |stdout_tee| parameter for Host.run() requires an object that looks
    like a Python built-in file.  In particular, it needs 'flush', which a
    multiprocessing.Connection (the object returned by multiprocessing.Pipe)
    doesn't have.  This wrapper provides that functionaly in order to allow a
    pipe to be the target of a stdout_tee.

    """

    def __init__(self, write_pipe):
        """Initializes reporter.

        @param write_pipe: the place to send output.

        """
        self._write_pipe = write_pipe


    def flush(self):
        """Flushes the output - not used by the pipe."""
        pass


    def close(self):
        """Closes the pipe."""
        return self._write_pipe.close()


    def fileno(self):
        """Returns the file number of the pipe."""
        return self._write_pipe.fileno()


    def write(self, string):
        """Write to the pipe.

        @param string: the string to write to the pipe.

        """
        self._write_pipe.send(string)


    def writelines(self, sequence):
        """Write a number of lines to the pipe.

        @param sequence: the array of lines to be written.

        """
        for string in sequence:
            self._write_pipe.send(string)


class LaunchIwEvent(object):
    """Calls 'iw event' and searches for a list of events in its output.

    This class provides a framework for launching 'iw event' in its own
    process and searching its output for an ordered list of events expressed
    as regular expressions.

    Expected to be called as follows:
        launch_iw_event = LaunchIwEvent(self.context.client.command_iw,
                                        self.context.client.host,
                                        timeout_seconds=60.0)
        # Do things that cause nl80211 traffic

        # Now, wait for the results you want.
        if not launch_iw_event.wait_for_events(['RSSI went below threshold',
                                                'scan started',
                                                # ...
                                                'connected to']):
            raise error.TestFail('Did not find all expected events')

    """
    # A timeout from Host.run(timeout) kills the process and that takes a
    # few seconds.  Therefore, we need to add some margin to the select
    # timeout (which will kill the process if Host.run(timeout) fails for some
    # reason).
    TIMEOUT_MARGIN_SECONDS = 5

    def __init__(self, iw_command, dut, timeout_seconds):
        """Launches 'iw event' process with communication channel for output

        @param dut: Host object for the dut
        @param timeout_seconds: timeout for 'iw event' (since it never
        returns)

        """
        self._iw_command = iw_command
        self._dut = dut
        self._timeout_seconds = timeout_seconds
        self._pipe_reader, pipe_writer = multiprocessing.Pipe()
        self._iw_event = multiprocessing.Process(target=self.do_iw,
                                                 args=(pipe_writer,
                                                       self._timeout_seconds,))
        self._iw_event.start()


    def do_iw(self, connection, timeout_seconds):
        """Runs 'iw event'

        iw results are passed back, on the fly, through a supplied connection
        object.  The process terminates itself after a specified timeout.

        @param connection: a Connection object to which results are written.
        @param timeout_seconds: number of seconds before 'iw event' is killed.

        """
        reporter = Reporter(connection)
        # ignore_timeout just ignores the _exception_; the timeout is still
        # valid.
        self._dut.run('%s event' % self._iw_command,
                      timeout=timeout_seconds,
                      stdout_tee=reporter,
                      ignore_timeout=True)


    def wait_for_events(self, expected_events):
        """Waits for 'expected_events' (in order) from iw.

        @param expected_events: a list of strings that are regular expressions.
            This method searches for the each expression, in the order that they
            appear in |expected_events|, in the stream of output from iw. x

        @returns: True if all events were found.  False, otherwise.

        """
        if not expected_events:
            logging.error('No events')
            return False

        expected_event = expected_events.pop(0)
        done_time = (time.time() + self._timeout_seconds +
                     LaunchIwEvent.TIMEOUT_MARGIN_SECONDS)
        received_event_log = []
        while expected_event:
            timeout = done_time - time.time()
            if timeout <= 0:
                break
            (sread, swrite, sexec) = select.select(
                    [self._pipe_reader], [], [], timeout)
            if sread:
                received_event = sread[0].recv()
                received_event_log.append(received_event)
                if re.search(expected_event, received_event):
                    logging.info('Found expected event: "%s"',
                                 received_event.rstrip())
                    if expected_events:
                        expected_event = expected_events.pop(0)
                    else:
                        expected_event = None
                        logging.info('Found ALL expected events')
                        break
            else:  # Timeout.
                break

        if expected_event:
            logging.error('Never found expected event "%s". iw log:',
                          expected_event)
            for event in received_event_log:
                logging.error(event.rstrip())
            return False
        return True


class ModifiedRoamThreshold(object):
    """Context manager manages wpa_supplicant's roam_threshold"""

    def __init__(self, client, roam_threshold):
        """Saves parameters for __enter__.

        @param client: WiFiClient
        @param roam_threshold: integer: supplicant's new value for roam
               threshold.

        """
        self._client = client
        self._original_threshold = None
        self._roam_threshold = roam_threshold


    def __enter__(self):
        """Saves current roam threshold, sets a new one."""
        logging.info('- Setting supplicant\'s roam threshold')
        self._original_threshold = self._client.get_roam_threshold(
                self._client.wifi_if)

        if self._original_threshold is None:
            raise error.TestFail('Device (%s) or property not found.' %
                                 self._client.wifi_if)
        if not self._client.set_roam_threshold(self._client.wifi_if,
                                               self._roam_threshold):
            raise error.TestFail('Could not set roam threshold')

        logging.info('changed roam threshold from %r to %r',
                     self._original_threshold,
                     self._client.get_roam_threshold(self._client.wifi_if))


    def __exit__(self, type, value, traceback):
        """Reinstates the previous roam threshold.

        @param type: exception type - unused
        @param value: exception value - unused
        @param traceback: exception traceback - unused

        """
        logging.info('- Resetting supplicant\'s roam threshold to %d',
                     self._original_threshold)
        if not self._client.set_roam_threshold(self._client.wifi_if,
                                               self._original_threshold):
            raise error.TestFail('Could not reset roam threshold')


class network_WiFi_RoamOnLowPower(rvr_test_base.RvRTestBase):
    """Tests roaming to an AP when the old one's signal is too weak.

    This test uses a dual-radio Stumpy as the AP and configures the radios to
    broadcast two BSS's with different frequencies on the same SSID.  The DUT
    connects to the first radio, the test attenuates that radio, and the DUT
    is supposed to roam to the second radio.

    This test requires a particular configuration of test equipment:

                                   +--------- StumpyCell/AP ----------+
                                   | chromeX.grover.hostY.router.cros |
                                   |                                  |
                                   |       [Radio 0]  [Radio 1]       |
                                   +--------A-----B----C-----D--------+
        +------ BeagleBone ------+          |     |    |     |
        | chromeX.grover.hostY.  |          |     X    |     X
        | attenuator.cros      [Port0]-[attenuator]    |
        |                      [Port1]----- | ----[attenuator]
        |                      [Port2]-X    |          |
        |                      [Port3]-X    +-----+    |
        |                        |                |    |
        +------------------------+                |    |
                                   +--------------E----F--------------+
                                   |             [Radio 0]            |
                                   |                                  |
                                   |    chromeX.grover.hostY.cros     |
                                   +-------------- DUT ---------------+

    Where antennas A, C, and E are the primary antennas for AP/radio0,
    AP/radio1, and DUT/radio0, respectively; and antennas B, D, and F are the
    auxilliary antennas for AP/radio0, AP/radio1, and DUT/radio0,
    respectively.  The BeagleBone controls 2 attenuators that are connected
    to the primary antennas of AP/radio0 and 1 which are fed into the primary
    and auxilliary antenna ports of DUT/radio 0.  Ports 2 and 3 of the
    BeagleBone as well as the auxillary antennae of AP/radio0 and 1 are
    terminated.

    This arrangement ensures that the attenuator port numbers are assigned to
    the primary radio, first, and the secondary radio, second.  If this happens,
    the ports will be numbered in the order in which the AP's channels are
    configured (port 0 is first, port 1 is second, etc.).

    This test is a de facto test that the ports are configured in that
    arrangement since swapping Port0 and Port1 would cause us to attenuate the
    secondary radio, providing no impetus for the DUT to switch radios and
    causing the test to fail to connect at radio 1's frequency.

    """

    version = 1

    FREQUENCY_0 = 2412
    FREQUENCY_1 = 2462
    PORT_0 = 0  # Port created first (on FREQUENCY_0)
    PORT_1 = 1  # Port created second (on FREQUENCY_1)

    # Supplicant's signal to noise threshold for roaming.  When noise is
    # measurable and S/N is less than the threshold, supplicant will attempt
    # to roam.  We're setting the roam threshold (and setting it so high --
    # it's usually 18) because some of the DUTs we're using have a hard time
    # measuring signals below -55 dBm.  A threshold of 40 roams when the
    # signal is about -50 dBm (since the noise tends to be around -89).
    ABSOLUTE_ROAM_THRESHOLD_DB = 40


    def run_once(self):
        """Test body."""
        self.context.client.clear_supplicant_blacklist()

        with ModifiedRoamThreshold(self.context.client,
                                   self.ABSOLUTE_ROAM_THRESHOLD_DB):
            logging.info('- Configure first AP & connect')
            self.context.configure(hostap_config.HostapConfig(
                    frequency=self.FREQUENCY_0,
                    mode=hostap_config.HostapConfig.MODE_11G))
            router_ssid = self.context.router.get_ssid()
            self.context.assert_connect_wifi(xmlrpc_datatypes.
                                             AssociationParameters(
                    ssid=router_ssid))
            self.context.assert_ping_from_dut()

            # Setup background scan configuration to set a signal level, below
            # which, supplicant will scan (3dB below the current level).  We
            # must reconnect for these parameters to take effect.
            logging.info('- Set background scan level')
            bgscan_config = xmlrpc_datatypes.BgscanConfiguration(
                    method='simple',
                    signal=self.context.client.wifi_signal_level - 3)
            self.context.client.shill.disconnect(router_ssid)
            self.context.assert_connect_wifi(
                    xmlrpc_datatypes.AssociationParameters(
                    ssid=router_ssid, bgscan_config=bgscan_config))

            logging.info('- Configure second AP')
            self.context.configure(hostap_config.HostapConfig(
                    ssid=router_ssid,
                    frequency=self.FREQUENCY_1,
                    mode=hostap_config.HostapConfig.MODE_11G),
                                   multi_interface=True)

            launch_iw_event = LaunchIwEvent(self.context.client.command_iw,
                                            self.context.client.host,
                                            timeout_seconds=60.0)

            logging.info('- Drop the power on the first AP')

            self.set_signal_to_force_roam(port=self.PORT_0,
                                          frequency=self.FREQUENCY_0)

            # Verify that the low signal event is generated, that supplicant
            # scans as a result (or, at least, that supplicant scans after the
            # threshold is passed), and that it connects to something.
            logging.info('- Wait for RSSI threshold drop, scan, and connect')
            if not launch_iw_event.wait_for_events(['RSSI went below threshold',
                                                    'scan started',
                                                    'connected to']):
                raise error.TestFail('Did not find all expected events')

            logging.info('- Wait for a connection on the second AP')
            # Instead of explicitly connecting, just wait to see if the DUT
            # connects to the second AP by itself
            self.context.wait_for_connection(ssid=router_ssid,
                                             freq=self.FREQUENCY_1, ap_num=1)

            # Clean up.
            self.context.router.deconfig()


    def set_signal_to_force_roam(self, port, frequency):
        """Adjust the AP attenuation to force the DUT to roam.

        wpa_supplicant (v2.0-devel) decides when to roam based on a number of
        factors even when we're only interested in the scenario when the roam
        is instigated by an RSSI drop.  The gates for roaming differ between
        systems that have drivers that measure noise and those that don't.  If
        the driver reports noise, the S/N of both the current BSS and the
        target BSS is capped at 30 and then the following conditions must be
        met:

            1) The S/N of the current AP must be below supplicant's roam
               threshold.
            2) The S/N of the roam target must be more than 3dB larger than
               that of the current BSS.

        If the driver does not report noise, the following condition must be
        met:

            3) The roam target's signal must be above the current BSS's signal
               by a signal-dependent value (that value doesn't currently go
               higher than 5).

        This would all be enough complication.  Unfortunately, the DUT's signal
        measurement hardware has typically not been optimized for accurate
        measurement throughout the signal range.  Based on some testing
        (crbug:295752), it was discovered that the DUT's measurements of signal
        levels somewhere below -50dBm show values greater than the actual signal
        and with quite a bit of variance.  Since wpa_supplicant uses this same
        mechanism to read its levels, this code must iterate to find values that
        will reliably trigger supplicant to roam to the second AP.

        It was also shown that some MIMO DUTs send different signal levels to
        their two radios (testing has shown this to be somewhere around 5dB to
        7dB).

        @param port: the beaglebone port that is desired to be attenuated.
        @param frequency: noise needs to be read for a frequency.

        """
        # wpa_supplicant calls an S/N of 30 dB "quite good signal" and caps the
        # S/N at this level for the purposes of roaming calculations.  We'll do
        # the same (since we're trying to instigate behavior in supplicant).
        GREAT_SNR = 30

        # The difference between the S/Ns of APs from 2), above.
        MIN_AP_SIGNAL_DIFF_FOR_ROAM_DB = 3

        # The maximum delta for a system that doesn't measure noise, from 3),
        # above.
        MIN_NOISELESS_SIGNAL_DIFF_FOR_ROAM_DB = 5

        # Adds a clear margin to attenuator levels to make sure that we
        # attenuate enough to do the job in light of signal and noise levels
        # that bounce around.  This value was reached empirically and further
        # tweaking may be necessary if this test gets flaky.
        SIGNAL_TO_NOISE_MARGIN_DB = 3

        # The measured difference between the radios on one of our APs.
        # TODO(wdg): dynamically measure the difference between the AP's radios
        # (crbug:307678).
        TEST_HW_SIGNAL_DELTA_DB = 7

        # wpa_supplicant's roaming algorithm differs between systems that can
        # measure noise and those that can't.  This code tracks those
        # differences.
        actual_signal_dbm = self.context.client.wifi_signal_level
        actual_noise_dbm = self.context.client.wifi_noise_level(frequency)
        logging.info('Radio 0 signal: %r, noise: %r', actual_signal_dbm,
                     actual_noise_dbm)
        if actual_noise_dbm is not None:
            system_measures_noise = True
            actual_snr_db = actual_signal_dbm - actual_noise_dbm
            radio1_snr_db = actual_snr_db - TEST_HW_SIGNAL_DELTA_DB

            # Supplicant will cap any S/N measurement used for roaming at
            # GREAT_SNR so we'll do the same.
            if radio1_snr_db > GREAT_SNR:
                radio1_snr_db = GREAT_SNR

            # In order to roam, the S/N of radio 0 must be both less than 3db
            # below radio1 and less than the roam threshold.
            logging.info('Radio 1 S/N = %d', radio1_snr_db)
            delta_snr_threshold_db = (radio1_snr_db -
                                      MIN_AP_SIGNAL_DIFF_FOR_ROAM_DB)
            if (delta_snr_threshold_db < self.ABSOLUTE_ROAM_THRESHOLD_DB):
                target_snr_db = delta_snr_threshold_db
                logging.info('Target S/N = %d (delta algorithm)',
                             target_snr_db)
            else:
                target_snr_db = self.ABSOLUTE_ROAM_THRESHOLD_DB
                logging.info('Target S/N = %d (threshold algorithm)',
                             target_snr_db)

            # Add some margin.
            target_snr_db -= SIGNAL_TO_NOISE_MARGIN_DB
            attenuation_db = actual_snr_db - target_snr_db
            logging.info('Noise: target S/N=%d attenuation=%r',
                         target_snr_db, attenuation_db)
        else:
            system_measures_noise = False
            # On a system that doesn't measure noise, supplicant needs the
            # signal from radio 0 to be less than that of radio 1 minus a fixed
            # delta value.  While we're here, subtract additional margin from
            # the target value.
            target_signal_dbm = (actual_signal_dbm - TEST_HW_SIGNAL_DELTA_DB -
                                 MIN_NOISELESS_SIGNAL_DIFF_FOR_ROAM_DB -
                                 SIGNAL_TO_NOISE_MARGIN_DB)
            attenuation_db = actual_signal_dbm - target_signal_dbm
            logging.info('No noise: target_signal=%r, attenuation=%r',
                         target_signal_dbm, attenuation_db)

        # Attenuate, measure S/N, repeat (due to flaky measurments) until S/N is
        # where we want it.
        keep_tweaking_snr = True
        while keep_tweaking_snr:
            # Keep attenuation values below the attenuator's maximum.
            if attenuation_db > (site_attenuator.Attenuator.
                                 MAX_VARIABLE_ATTENUATION):
                attenuation_db = (site_attenuator.Attenuator.
                                  MAX_VARIABLE_ATTENUATION)
            logging.info('Applying attenuation=%r', attenuation_db)
            self.context.attenuator.set_variable_attenuation_on_port(
                    port, attenuation_db)
            if attenuation_db >= (site_attenuator.Attenuator.
                                    MAX_VARIABLE_ATTENUATION):
                logging.warning('. NOTICE: Attenuation is at maximum value')
                keep_tweaking_snr = False
            elif system_measures_noise:
                actual_snr_db = self.get_signal_to_noise(frequency)
                if actual_snr_db > target_snr_db:
                    logging.info('. S/N (%d) > target value (%d)',
                                 actual_snr_db, target_snr_db)
                    attenuation_db += actual_snr_db - target_snr_db
                else:
                    logging.info('. GOOD S/N=%r', actual_snr_db)
                    keep_tweaking_snr = False
            else:
                actual_signal_dbm = self.context.client.wifi_signal_level
                logging.info('. signal=%r', actual_signal_dbm)
                if actual_signal_dbm > target_signal_dbm:
                    logging.info('. Signal > target value (%d)',
                                 target_signal_dbm)
                    attenuation_db += actual_signal_dbm - target_signal_dbm
                else:
                    keep_tweaking_snr = False

        logging.info('Done')


    def get_signal_to_noise(self, frequency):
        """Gets both the signal and the noise on the current connection.

        @param frequency: noise needs to be read for a frequency.
        @returns: signal and noise in dBm

        """
        ping_ip = self.context.get_wifi_addr(ap_num=0)
        ping_config = ping_runner.PingConfig(target_ip=ping_ip, count=1,
                                             ignore_status=True,
                                             ignore_result=True)
        self.context.client.ping(ping_config)  # Just to provide traffic.
        signal_dbm = self.context.client.wifi_signal_level
        noise_dbm = self.context.client.wifi_noise_level(frequency)
        print '. signal: %r, noise: %r' % (signal_dbm, noise_dbm)
        if noise_dbm is None:
            return None
        return signal_dbm - noise_dbm
