# 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.

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
from autotest_lib.client.common_lib.cros.network import xmlrpc_security_types
from autotest_lib.server.cros.network import hostap_config
from autotest_lib.server.cros.network import wifi_cell_test_base


class ProfileRemovingContext(object):
    """Creates and pushes a profile that is guaranteed to be removed."""

    @property
    def profile_name(self):
        """@return string: name of profile created and pushed."""
        return self._profile_name


    def __init__(self, wifi_client, profile_name='always_removed'):
        self._wifi_client = wifi_client
        self._profile_name = profile_name


    def __enter__(self):
        if not all([self._wifi_client.shill.create_profile(self.profile_name),
                    self._wifi_client.shill.push_profile(self.profile_name)]):
            raise error.TestFail('Failed to create/push profile %s' %
                                 self.profile_name)
        return self


    def __exit__(self, exc_type, exc_value, traceback):
        # Ignore pop errors in case the test popped it on its own
        self._wifi_client.shill.pop_profile(self.profile_name)
        if not self._wifi_client.shill.remove_profile(self.profile_name):
            raise error.TestFail('Failed to remove profile %s.' %
                                 self.profile_name)


class network_WiFi_ProfileBasic(wifi_cell_test_base.WiFiCellTestBase):
    """Tests that credentials are stored in profiles."""

    version = 1

    CHANNEL_NUMBER = 1
    STATE_TRANSITION_TIMEOUT_SECONDS = 20


    def _assert_state_transition(self, ssid, states):
        """Raise an error if a WiFi service doesn't transition to |states|.

        @param ssid: string ssid of service.
        @param states: list of string states to wait for.

        """
        result = self.context.client.wait_for_service_states(
                ssid, states,
                timeout_seconds=self.STATE_TRANSITION_TIMEOUT_SECONDS)

        success, state, duration_seconds = result
        if not success:
            raise error.TestFail('Timed out waiting for states: %r in %f '
                                 'seconds.  Ended in %s' %
                                 (states, duration_seconds, state))


    def run_once(self):
        """Body of the test."""
        self.context.client.shill.clean_profiles()
        wep_config = xmlrpc_security_types.WEPConfig(
                wep_keys=['abcde', 'fghij', 'klmno', 'pqrst'])
        ap_config0 = hostap_config.HostapConfig(
                channel=self.CHANNEL_NUMBER, security_config=wep_config)
        ap_config1 = hostap_config.HostapConfig(
                channel=self.CHANNEL_NUMBER, security_config=wep_config)
        with ProfileRemovingContext(self.context.client,
                                    profile_name='bottom') as bottom:
            self.context.configure(ap_config0)
            client_config0 = xmlrpc_datatypes.AssociationParameters(
                    security_config=ap_config0.security_config,
                    ssid=self.context.router.get_ssid())
            self.context.assert_connect_wifi(client_config0)
            self.context.assert_ping_from_dut(ap_num=0)
            # Check that popping a profile causes a loss of credentials and a
            # disconnect.
            if not self.context.client.shill.pop_profile(bottom.profile_name):
                raise error.TestFail('Failed to pop profile %s.' %
                                      bottom.profile_name)

            self._assert_state_transition(client_config0.ssid, ['idle'])
            # Check that pushing a profile causes credentials to reappear.
            if not self.context.client.shill.push_profile(bottom.profile_name):
                raise error.TestFail('Failed to push profile %s.' %
                                      bottom.profile_name)

            self._assert_state_transition(client_config0.ssid,
                                          self.context.client.CONNECTED_STATES)

            # Explicitly disconnect from the AP.
            self.context.client.shill.disconnect(client_config0.ssid)
            self._assert_state_transition(client_config0.ssid, ['idle'])

            with ProfileRemovingContext(self.context.client,
                                        profile_name='top') as top:
                # Changes to the profile stack should clear the "explicitly
                # disconnected" flag on all services.  This should cause shill
                # to re-connect to the AP.
                self._assert_state_transition(client_config0.ssid,
                                              self.context.client.CONNECTED_STATES)

                self.context.configure(ap_config1, multi_interface=True)
                client_config1 = xmlrpc_datatypes.AssociationParameters(
                        security_config=ap_config1.security_config,
                        ssid=self.context.router.get_ssid(instance=1))
                self.context.assert_connect_wifi(client_config1)
                self.context.assert_ping_from_dut(ap_num=1)
                # Check that deleting an entry also causes a disconnect and
                # autoconect to a previously remembered service.
                if not self.context.client.shill.delete_entries_for_ssid(
                        client_config1.ssid):
                    raise error.TestFail('Failed to delete profile entry for '
                                         '%s' % client_config1.ssid)

                self._assert_state_transition(client_config1.ssid, ['idle'])
                self._assert_state_transition(client_config0.ssid,
                                              self.context.client.CONNECTED_STATES)
                # Verify that the same sort of thing happens when we pop
                # a profile on top of another one.
                self.context.assert_connect_wifi(client_config1)
                self.context.assert_ping_from_dut(ap_num=1)
                if not self.context.client.shill.pop_profile(top.profile_name):
                    raise error.TestFail('Failed to pop profile %s.' %
                                          top.profile_name)
                self._assert_state_transition(client_config1.ssid, ['idle'])
                self._assert_state_transition(client_config0.ssid,
                                              self.context.client.CONNECTED_STATES)

                # Re-push the top profile.
                if not self.context.client.shill.push_profile(top.profile_name):
                    raise error.TestFail('Failed to push profile %s.' %
                                          top.profile_name)

                # Explicitly disconnect from the AP.
                self.context.client.shill.disconnect(client_config0.ssid)
                self._assert_state_transition(client_config0.ssid, ['idle'])

                # Verify that popping a profile -- even one which does not
                # affect the service profile -- returns explicitly disconnected
                # services back into the pool of connectable services.
                if not self.context.client.shill.pop_profile(top.profile_name):
                    raise error.TestFail('Failed to pop profile %s.' %
                                          top.profile_name)

                # A change to the profile stack should have caused us to
                # reconnect to the service, since the "explicitly disconnected"
                # flag will be removed.
                self._assert_state_transition(client_config0.ssid,
                                              self.context.client.CONNECTED_STATES)
