blob: 64c13276b558bc9300489d7574790d1a4469b0bd [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.
from autotest_lib.client.bin import site_utils, test
from autotest_lib.client.common_lib import error
import dbus
import dbus.types
import gobject
import time
from autotest_lib.client.cros import backchannel, network, flimflam_test_path
from autotest_lib.client.cros.cellular import cell_tools
from autotest_lib.client.cros.cellular import mm
from autotest_lib.client.cros.cellular.pseudomodem import mm1
from autotest_lib.client.cros.cellular.pseudomodem import modem_cdma
from autotest_lib.client.cros.cellular.pseudomodem import pseudomodem
import flimflam
I_ACTIVATION_TEST = 'Interface.CDMAActivationTest'
ACTIVATION_STATE_TIMEOUT = 10
MODEM_STATE_TIMEOUT = 10
class ActivationTest(object):
"""
Super class that implements setup code that is common to the individual
tests.
"""
def __init__(self, pmm_context, test):
self.pmm_context = pmm_context
self.test = test
self.test_modem = self._setup_test_modem()
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.
"""
if not self.test_modem:
raise test.TestFail('Uninitialized test modem')
self.pmm_context.SetModem(self.test_modem)
self._run_test()
def _get_modem_properties_interface(self):
if not self.modem_properties_interface:
self.modem_properties_interface = \
self.test.modem().PropertiesInterface()
return self.modem_properties_interface
def _set_modem_activation_state(self, state):
interface = self._get_modem_properties_interface()
interface.Set(
mm1.I_MODEM_CDMA, 'ActivationState', dbus.types.UInt32(state))
def _get_modem_activation_state(self):
interface = self._get_modem_properties_interface()
return interface.Get(mm1.I_MODEM_CDMA, 'ActivationState')
def _setup_test_modem(self):
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 _setup_test_modem(self):
return modem_cdma.ModemCdma()
def _run_test(self):
network.ResetAllModems(self.test.flim)
# The modem state should be REGISTERED.
self.test.check_modem_state(mm1.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.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.MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING)
self.test.check_service_activation_state('activating')
# Service activation state should change to 'partially-activated'.
self._set_modem_activation_state(
mm1.MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED)
self.test.check_service_activation_state('partially-activated')
# Service activation state should change to 'activated'.
self._set_modem_activation_state(
mm1.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 _setup_test_modem(self):
return modem_cdma.ModemCdma(
modem_cdma.ModemCdma.CdmaNetwork(activated=False))
def _run_test(self):
network.ResetAllModems(self.test.flim)
# The modem state should be REGISTERED.
self.test.check_modem_state(mm1.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.find_cellular_service()
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 _setup_test_modem(self):
class TestModem(modem_cdma.ModemCdma):
"""
TestModem to test that shill retries OTASP activation until it
succeeds.
"""
def __init__(self):
self.activate_count = 0
modem_cdma.ModemCdma.__init__(self,
modem_cdma.ModemCdma.CdmaNetwork(activated=False))
def _InitializeProperties(self):
props = modem_cdma.ModemCdma._InitializeProperties(self)
# For the purposes of this test, introduce a property that
# stores how many times "Activate" has been called on this
# modem.
props[I_ACTIVATION_TEST] = {
'ActivateCount' : dbus.types.UInt32(self.activate_count)
}
return props
def _IncrementActivateCount(self):
self.activate_count += 1
self.Set(I_ACTIVATION_TEST,
'ActivateCount',
self.activate_count)
def Activate(self, carrier, return_cb, raise_cb):
"""
Activation will only succeed on the NUM_ACTIVATE_RETRIESth try.
"""
self._IncrementActivateCount()
if self.activate_count == \
ActivationFailureRetryTest.NUM_ACTIVATE_RETRIES:
modem_cdma.ModemCdma.Activate(
self, carrier, return_cb, raise_cb)
else:
def _raise_activation_error():
raise_cb(mm1.MMCdmaActivationError(
mm1.MMCdmaActivationError.START_FAILED))
gobject.idle_add(_raise_activation_error)
return TestModem()
def _run_test(self):
network.ResetAllModems(self.test.flim)
# The modem state should be REGISTERED.
self.test.check_modem_state(mm1.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 remain
# 'not-activated'.
service = self.test.find_cellular_service()
service.CompleteCellularActivation()
modem_props = self._get_modem_properties_interface()
while modem_props.Get(I_ACTIVATION_TEST, 'ActivateCount') < \
self.NUM_ACTIVATE_RETRIES:
self.test.check_service_activation_state('not-activated')
# Activation should succeed after the latest retry.
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 network_CDMAActivate(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 modem(self):
"""
Returns a D-Bus proxy for the current modem object exposed by the
modem manager.
@return A dbus.service.Object instance.
"""
manager, modem_path = mm.PickOneModem('')
return manager.GetModem(modem_path)
def modem_state(self):
"""
Gets the current modem state from the current modem manager.
@return The modem state, as a uint32 value.
"""
modem = self.modem()
props = modem.GetAll(mm1.I_MODEM)
return props['State']
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 error.TestFail, if the modem doesn't transition to
|expected_state| within |timeout|.
"""
site_utils.poll_for_condition(
lambda: self.modem_state() == expected_state,
exception=error.TestFail('Timed out waiting for modem state ' +
str(expected_state)),
timeout=timeout);
def find_cellular_service(self):
"""
Searches for a cellular service and returns it.
@return A dbus.service.Object instance.
@raises error.TestFail, if no cellular service is found.
"""
service = self.flim.FindCellularService()
if not service:
raise error.TestFail('Could not find cellular service.')
return service
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.
"""
service = self.find_cellular_service()
state = self.flim.WaitForServiceState(
service=service,
expected_states=[expected_state],
timeout=ACTIVATION_STATE_TIMEOUT,
property_name='Cellular.ActivationState')[0]
if state != expected_state:
raise error.TestFail(
'Service activation state should be \'%s\', but it is '
'\'%s\'.' % (expected_state, state))
def run_once(self):
with backchannel.Backchannel():
with pseudomodem.TestModemManagerContext(True, 'CDMA') as tmmc:
self.flim = flimflam.FlimFlam()
self.device_manager = flimflam.DeviceManager(self.flim)
self.flim.SetDebugTags(
'dbus+service+device+modem+cellular+portal+network+'
'manager+dhcp')
tests = [
ActivationStateTest(tmmc.GetPseudoModemManager(), self),
ActivationSuccessTest(tmmc.GetPseudoModemManager(), self),
ActivationFailureRetryTest(
tmmc.GetPseudoModemManager(), self)
]
with cell_tools.OtherDeviceShutdownContext('cellular'):
for test in tests:
test.run()