# 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('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, _, __) = 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 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 self.context.client.roam_threshold(
                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('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
