| # 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 dbus |
| import dbus.types |
| import os |
| import time |
| |
| from autotest_lib.client.bin import test |
| from autotest_lib.client.bin import utils |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.cros.cellular import mm1_constants |
| from autotest_lib.client.cros.cellular import test_environment |
| from autotest_lib.client.cros.networking import pm_proxy |
| |
| I_ACTIVATION_TEST = 'Interface.CDMAActivationTest' |
| ACTIVATION_STATE_TIMEOUT = 10 |
| MODEM_STATE_TIMEOUT = 10 |
| TEST_MODEMS_MODULE_PATH = os.path.join(os.path.dirname(__file__), 'files', |
| 'modems.py') |
| |
| class ActivationTest(object): |
| """ |
| Super class that implements setup code that is common to the individual |
| tests. |
| |
| """ |
| def __init__(self, test): |
| self.test = test |
| self.modem_properties_interface = None |
| |
| |
| def run(self): |
| """ |
| Restarts the pseudomodem with the modem object to be used for this |
| test and runs the test. |
| |
| """ |
| self.pseudomm = pm_proxy.PseudoMMProxy.get_proxy() |
| self._run_test() |
| |
| |
| def _set_modem_activation_state(self, state): |
| self.pseudomm.get_modem().iface_properties.Set( |
| mm1_constants.I_MODEM_CDMA, |
| 'ActivationState', |
| dbus.types.UInt32(state)) |
| |
| |
| def _get_modem_activation_state(self): |
| modem = self.pseudomm.get_modem() |
| return modem.properties(mm1_constants.I_MODEM_CDMA)['ActivationState'] |
| |
| |
| def pseudomodem_flags(self): |
| """ |
| Subclasses must override this method to setup the flags map passed to |
| pseudomodem to suite their needs. |
| |
| """ |
| raise NotImplementedError() |
| |
| |
| def _run_test(self): |
| raise NotImplementedError() |
| |
| class ActivationStateTest(ActivationTest): |
| """ |
| This test verifies that the service "ActivationState" property matches the |
| cdma activation state exposed by ModemManager. |
| |
| """ |
| def pseudomodem_flags(self): |
| return {'family' : 'CDMA'} |
| |
| |
| def _run_test(self): |
| self.test.reset_modem() |
| |
| # The modem state should be REGISTERED. |
| self.test.check_modem_state(mm1_constants.MM_MODEM_STATE_REGISTERED) |
| |
| # Service should appear as 'activated'. |
| self.test.check_service_activation_state('activated') |
| |
| # Service activation state should change to 'not-activated'. |
| self._set_modem_activation_state( |
| mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED) |
| self.test.check_service_activation_state('not-activated') |
| |
| # Service activation state should change to 'activating'. |
| self._set_modem_activation_state( |
| mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING) |
| self.test.check_service_activation_state('activating') |
| |
| # Service activation state should change to 'partially-activated'. |
| st = mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED |
| self._set_modem_activation_state(st) |
| self.test.check_service_activation_state('partially-activated') |
| |
| # Service activation state should change to 'activated'. |
| self._set_modem_activation_state( |
| mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED) |
| self.test.check_service_activation_state('activated') |
| |
| |
| class ActivationSuccessTest(ActivationTest): |
| """ |
| This test verifies that the service finally bacomes "activated" when the |
| service is told to initiate OTASP activation. |
| |
| """ |
| def pseudomodem_flags(self): |
| return {'test-module' : TEST_MODEMS_MODULE_PATH, |
| 'test-modem-class' : 'UnactivatedCdmaModem'} |
| |
| |
| def _run_test(self): |
| self.test.reset_modem() |
| |
| # The modem state should be REGISTERED. |
| self.test.check_modem_state(mm1_constants.MM_MODEM_STATE_REGISTERED) |
| |
| # Service should appear as 'not-activated'. |
| self.test.check_service_activation_state('not-activated') |
| |
| # Call 'CompleteActivation' on the service. The service should become |
| # 'activating'. |
| service = self.test.test_env.shill.find_cellular_service_object() |
| service.CompleteCellularActivation() |
| self.test.check_service_activation_state('activating') |
| |
| # The modem should reset in 5 seconds. Wait 5 more seconds to make sure |
| # a new service gets created. |
| time.sleep(10) |
| self.test.check_service_activation_state('activated') |
| |
| |
| class ActivationFailureRetryTest(ActivationTest): |
| """ |
| This test verifies that if "ActivateAutomatic" fails, a retry will be |
| scheduled. |
| |
| """ |
| NUM_ACTIVATE_RETRIES = 5 |
| def pseudomodem_flags(self): |
| return {'test-module' : TEST_MODEMS_MODULE_PATH, |
| 'test-modem-class' : 'ActivationRetryModem', |
| 'test-modem-arg' : [self.NUM_ACTIVATE_RETRIES]} |
| |
| |
| def _run_test(self): |
| self.test.reset_modem() |
| |
| # The modem state should be REGISTERED. |
| self.test.check_modem_state(mm1_constants.MM_MODEM_STATE_REGISTERED) |
| |
| # Service should appear as 'not-activated'. |
| self.test.check_service_activation_state('not-activated') |
| |
| # Call 'CompleteActivation' on the service. |
| service = self.test.test_env.shill.find_cellular_service_object() |
| service.CompleteCellularActivation() |
| |
| # Wait for shill to retry the failed activations, except the last retry |
| # will succeed. |
| # NOTE: Don't check for transitory service activation states while this |
| # is happening because shill will reset the modem once the activation |
| # succeeds which will cause the existing service to get deleted. |
| modem = self.pseudomm.get_modem() |
| utils.poll_for_condition( |
| lambda: (modem.properties(I_ACTIVATION_TEST)['ActivateCount'] == |
| self.NUM_ACTIVATE_RETRIES), |
| exception=error.TestFail( |
| 'Shill did not retry failed activation'), |
| timeout=10) |
| |
| # The modem should reset in 5 seconds. Wait 5 more seconds to make sure |
| # a new service gets created. |
| time.sleep(10) |
| self.test.check_service_activation_state('activated') |
| |
| |
| class cellular_ActivateCDMA(test.test): |
| """ |
| Tests various scenarios that may arise during the post-payment CDMA |
| activation process when shill accesses the modem via ModemManager. |
| |
| """ |
| version = 1 |
| |
| def check_modem_state(self, expected_state, timeout=MODEM_STATE_TIMEOUT): |
| """ |
| Polls until the modem has the expected state within |timeout| seconds. |
| |
| @param expected_state: The modem state the modem is expected to be in. |
| @param timeout: The timeout interval for polling. |
| |
| @raises pm_proxy.ModemManager1ProxyError if the modem doesn't |
| transition to |expected_state| within |timeout|. |
| |
| """ |
| modem = pm_proxy.PseudoMMProxy.get_proxy().get_modem() |
| modem.wait_for_states([expected_state], timeout_seconds=timeout) |
| |
| |
| def check_service_activation_state(self, expected_state): |
| """ |
| Waits until the current cellular service has the expected activation |
| state within ACTIVATION_STATE_TIMEOUT seconds. |
| |
| @param expected_state: The activation state the service is expected to |
| be in. |
| @raises error.TestFail, if no cellular service is found or the service |
| activation state doesn't match |expected_state| within timeout. |
| |
| """ |
| success, state, _ = self.test_env.shill.wait_for_property_in( |
| self.test_env.shill.find_cellular_service_object(), |
| 'Cellular.ActivationState', |
| [expected_state], |
| ACTIVATION_STATE_TIMEOUT) |
| if not success: |
| raise error.TestFail( |
| 'Service activation state should be \'%s\', but it is ' |
| '\'%s\'.' % (expected_state, state)) |
| |
| |
| def reset_modem(self): |
| """ |
| Resets the one and only modem in the DUT. |
| |
| """ |
| modem = self.test_env.shill.find_cellular_device_object() |
| self.test_env.shill.reset_modem(modem) |
| |
| |
| def run_once(self): |
| tests = [ |
| ActivationStateTest(self), |
| ActivationSuccessTest(self), |
| ActivationFailureRetryTest(self) |
| ] |
| |
| for test in tests: |
| self.test_env = test_environment.CellularPseudoMMTestEnvironment( |
| pseudomm_args=(test.pseudomodem_flags(),)) |
| with self.test_env: |
| test.run() |