blob: ba5b98ae8e28efc4e9aabb521190d6569cfdaf17 [file] [log] [blame]
# 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()