# Copyright 2015 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 contextlib
import logging
import time

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros.network import tcpdump_analyzer
from autotest_lib.server.cros.network import hostap_config
from autotest_lib.server.cros.network import lucid_sleep_test_base
from autotest_lib.server.cros.network import wifi_client

class network_WiFi_DarkResumeActiveScans(
        lucid_sleep_test_base.LucidSleepTestBase):
    """
    Test that no active scans are launched when the system wakes on dark resumes
    triggered by RTC timers and wake on pattern.
    """

    version = 1

    def stop_capture_and_check_for_probe_requests(self, mac):
        """
        Stop packet capture and check that no probe requests launched by the DUT
        with MAC address |mac| are found in the packet capture.  Fails test if
        any probe request frames are found.

        @param mac: MAC address of the DUT.
        """
        logging.info('Stopping packet capture')
        results = self.context.capture_host.stop_capture()
        if len(results) != 1:
            raise error.TestError('Expected to generate one packet '
                                  'capture but got %d captures instead.' %
                                  len(results))

        logging.info('Analyzing packet capture...')
        probe_req_pcap_filter = '%s and wlan.sa==%s' % (
                tcpdump_analyzer.WLAN_PROBE_REQ_ACCEPTOR, mac)
        # Get all the frames in chronological order.
        frames = tcpdump_analyzer.get_frames(results[0].local_pcap_path,
                probe_req_pcap_filter, reject_bad_fcs=False)
        if len(frames) > 0:
            raise error.TestFail('Packet capture contained probe requests!')

        logging.info('Packet capture contained no probe requests')


    def run_once(self):
        """Body of the test."""
        ap_config = hostap_config.HostapConfig(channel=1)
        self.configure_and_connect_to_ap(ap_config)
        self.context.assert_ping_from_dut()

        client = self.context.client
        router = self.context.router
        dut_mac = client.wifi_mac
        dut_ip = client.wifi_ip
        prev_num_dark_resumes = 0

        logging.info('DUT WiFi MAC = %s, IPv4 = %s', dut_mac, dut_ip)
        logging.info('Router WiFi IPv4 = %s', router.wifi_ip)

        # Trigger a wake on packet dark resume, and make sure that no probe
        # requests were launched during this dark resume.
        with client.wake_on_wifi_features(wifi_client.WAKE_ON_WIFI_PACKET):
            logging.info('Set up WoWLAN')

            # Wake on packets from the router.
            client.add_wake_packet_source(self.context.router.wifi_ip)

            with self.dr_utils.suspend():
                time.sleep(wifi_client.SUSPEND_WAIT_TIME_SECONDS)

                # Start capture after suspend concludes in case probe requests
                # are launched on the way to suspend.
                self.context.capture_host.start_capture(
                        ap_config.frequency,
                        width_type=ap_config.packet_capture_mode)

                # Send the DUT a packet from the router to wake it up.
                router.send_magic_packet(dut_ip, dut_mac)

                # Wait for the DUT to wake up in dark resume and suspend again.
                time.sleep(wifi_client.RECEIVE_PACKET_WAIT_TIME_SECONDS +
                           wifi_client.DARK_RESUME_WAIT_TIME_SECONDS)

                # Check for packet capture before waking the DUT with
                # |count_dark_resumes| because probe requests might be launched
                # during the wake.
                self.stop_capture_and_check_for_probe_requests(mac=dut_mac)

                prev_num_dark_resumes = self.dr_utils.count_dark_resumes()
                if prev_num_dark_resumes < 1:
                    raise error.TestFail('Client failed to wake on packet.')
                logging.info('Client woke up on packet successfully.')

        # Trigger a wake to scan RTC timer dark resume, and make sure that no
        # probe requests were launched during this dark resume.
        with contextlib.nested(
                client.wake_on_wifi_features(
                        wifi_client.WAKE_ON_WIFI_DARKCONNECT),
                client.wake_to_scan_period_seconds(
                        wifi_client.WAKE_TO_SCAN_PERIOD_SECONDS),
                client.force_wake_to_scan_timer(True)):

            # Bring the AP down so the DUT suspends disconnected.
            router.deconfig_aps()
            time.sleep(wifi_client.DISCONNECT_WAIT_TIME_SECONDS)

            with self.dr_utils.suspend():
                time.sleep(wifi_client.SUSPEND_WAIT_TIME_SECONDS)

                # Start capture after suspend concludes in case probe requests
                # are launched on the way to suspend.
                self.context.capture_host.start_capture(
                        ap_config.frequency,
                        width_type=ap_config.packet_capture_mode)

                # Wait for the DUT to wake to scan and suspend again.
                time.sleep(wifi_client.WAKE_TO_SCAN_PERIOD_SECONDS +
                           wifi_client.DARK_RESUME_WAIT_TIME_SECONDS)

                # Check for packet capture before waking the DUT with
                # |count_dark_resumes| because probe requests might be launched
                # during the wake.
                self.stop_capture_and_check_for_probe_requests(mac=dut_mac)

                if (self.dr_utils.count_dark_resumes() -
                    prev_num_dark_resumes) < 1:
                    raise error.TestFail('Client failed to wake up to scan.')
                logging.info('Client woke up to scan successfully.')
