1# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import dbus 6import dbus.types 7import os 8import time 9 10from autotest_lib.client.bin import test 11from autotest_lib.client.bin import utils 12from autotest_lib.client.common_lib import error 13from autotest_lib.client.cros.cellular import mm1_constants 14from autotest_lib.client.cros.cellular import test_environment 15from autotest_lib.client.cros.networking import pm_proxy 16 17I_ACTIVATION_TEST = 'Interface.CDMAActivationTest' 18ACTIVATION_STATE_TIMEOUT = 10 19MODEM_STATE_TIMEOUT = 10 20TEST_MODEMS_MODULE_PATH = os.path.join(os.path.dirname(__file__), 'files', 21 'modems.py') 22 23class ActivationTest(object): 24 """ 25 Super class that implements setup code that is common to the individual 26 tests. 27 28 """ 29 def __init__(self, test): 30 self.test = test 31 self.modem_properties_interface = None 32 33 34 def run(self): 35 """ 36 Restarts the pseudomodem with the modem object to be used for this 37 test and runs the test. 38 39 """ 40 self.pseudomm = pm_proxy.PseudoMMProxy.get_proxy() 41 self._run_test() 42 43 44 def _set_modem_activation_state(self, state): 45 self.pseudomm.get_modem().iface_properties.Set( 46 mm1_constants.I_MODEM_CDMA, 47 'ActivationState', 48 dbus.types.UInt32(state)) 49 50 51 def _get_modem_activation_state(self): 52 modem = self.pseudomm.get_modem() 53 return modem.properties(mm1_constants.I_MODEM_CDMA)['ActivationState'] 54 55 56 def pseudomodem_flags(self): 57 """ 58 Subclasses must override this method to setup the flags map passed to 59 pseudomodem to suite their needs. 60 61 """ 62 raise NotImplementedError() 63 64 65 def _run_test(self): 66 raise NotImplementedError() 67 68class ActivationStateTest(ActivationTest): 69 """ 70 This test verifies that the service "ActivationState" property matches the 71 cdma activation state exposed by ModemManager. 72 73 """ 74 def pseudomodem_flags(self): 75 return {'family' : 'CDMA'} 76 77 78 def _run_test(self): 79 self.test.reset_modem() 80 81 # The modem state should be REGISTERED. 82 self.test.check_modem_state(mm1_constants.MM_MODEM_STATE_REGISTERED) 83 84 # Service should appear as 'activated'. 85 self.test.check_service_activation_state('activated') 86 87 # Service activation state should change to 'not-activated'. 88 self._set_modem_activation_state( 89 mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_NOT_ACTIVATED) 90 self.test.check_service_activation_state('not-activated') 91 92 # Service activation state should change to 'activating'. 93 self._set_modem_activation_state( 94 mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATING) 95 self.test.check_service_activation_state('activating') 96 97 # Service activation state should change to 'partially-activated'. 98 st = mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_PARTIALLY_ACTIVATED 99 self._set_modem_activation_state(st) 100 self.test.check_service_activation_state('partially-activated') 101 102 # Service activation state should change to 'activated'. 103 self._set_modem_activation_state( 104 mm1_constants.MM_MODEM_CDMA_ACTIVATION_STATE_ACTIVATED) 105 self.test.check_service_activation_state('activated') 106 107 108class ActivationSuccessTest(ActivationTest): 109 """ 110 This test verifies that the service finally bacomes "activated" when the 111 service is told to initiate OTASP activation. 112 113 """ 114 def pseudomodem_flags(self): 115 return {'test-module' : TEST_MODEMS_MODULE_PATH, 116 'test-modem-class' : 'UnactivatedCdmaModem'} 117 118 119 def _run_test(self): 120 self.test.reset_modem() 121 122 # The modem state should be REGISTERED. 123 self.test.check_modem_state(mm1_constants.MM_MODEM_STATE_REGISTERED) 124 125 # Service should appear as 'not-activated'. 126 self.test.check_service_activation_state('not-activated') 127 128 # Call 'CompleteActivation' on the service. The service should become 129 # 'activating'. 130 service = self.test.test_env.shill.find_cellular_service_object() 131 service.CompleteCellularActivation() 132 self.test.check_service_activation_state('activating') 133 134 # The modem should reset in 5 seconds. Wait 5 more seconds to make sure 135 # a new service gets created. 136 time.sleep(10) 137 self.test.check_service_activation_state('activated') 138 139 140class ActivationFailureRetryTest(ActivationTest): 141 """ 142 This test verifies that if "ActivateAutomatic" fails, a retry will be 143 scheduled. 144 145 """ 146 NUM_ACTIVATE_RETRIES = 5 147 def pseudomodem_flags(self): 148 return {'test-module' : TEST_MODEMS_MODULE_PATH, 149 'test-modem-class' : 'ActivationRetryModem', 150 'test-modem-arg' : [self.NUM_ACTIVATE_RETRIES]} 151 152 153 def _run_test(self): 154 self.test.reset_modem() 155 156 # The modem state should be REGISTERED. 157 self.test.check_modem_state(mm1_constants.MM_MODEM_STATE_REGISTERED) 158 159 # Service should appear as 'not-activated'. 160 self.test.check_service_activation_state('not-activated') 161 162 # Call 'CompleteActivation' on the service. 163 service = self.test.test_env.shill.find_cellular_service_object() 164 service.CompleteCellularActivation() 165 166 # Wait for shill to retry the failed activations, except the last retry 167 # will succeed. 168 # NOTE: Don't check for transitory service activation states while this 169 # is happening because shill will reset the modem once the activation 170 # succeeds which will cause the existing service to get deleted. 171 modem = self.pseudomm.get_modem() 172 utils.poll_for_condition( 173 lambda: (modem.properties(I_ACTIVATION_TEST)['ActivateCount'] == 174 self.NUM_ACTIVATE_RETRIES), 175 exception=error.TestFail( 176 'Shill did not retry failed activation'), 177 timeout=10) 178 179 # The modem should reset in 5 seconds. Wait 5 more seconds to make sure 180 # a new service gets created. 181 time.sleep(10) 182 self.test.check_service_activation_state('activated') 183 184 185class cellular_ActivateCDMA(test.test): 186 """ 187 Tests various scenarios that may arise during the post-payment CDMA 188 activation process when shill accesses the modem via ModemManager. 189 190 """ 191 version = 1 192 193 def check_modem_state(self, expected_state, timeout=MODEM_STATE_TIMEOUT): 194 """ 195 Polls until the modem has the expected state within |timeout| seconds. 196 197 @param expected_state: The modem state the modem is expected to be in. 198 @param timeout: The timeout interval for polling. 199 200 @raises pm_proxy.ModemManager1ProxyError if the modem doesn't 201 transition to |expected_state| within |timeout|. 202 203 """ 204 modem = pm_proxy.PseudoMMProxy.get_proxy().get_modem() 205 modem.wait_for_states([expected_state], timeout_seconds=timeout) 206 207 208 def check_service_activation_state(self, expected_state): 209 """ 210 Waits until the current cellular service has the expected activation 211 state within ACTIVATION_STATE_TIMEOUT seconds. 212 213 @param expected_state: The activation state the service is expected to 214 be in. 215 @raises error.TestFail, if no cellular service is found or the service 216 activation state doesn't match |expected_state| within timeout. 217 218 """ 219 success, state, _ = self.test_env.shill.wait_for_property_in( 220 self.test_env.shill.find_cellular_service_object(), 221 'Cellular.ActivationState', 222 [expected_state], 223 ACTIVATION_STATE_TIMEOUT) 224 if not success: 225 raise error.TestFail( 226 'Service activation state should be \'%s\', but it is ' 227 '\'%s\'.' % (expected_state, state)) 228 229 230 def reset_modem(self): 231 """ 232 Resets the one and only modem in the DUT. 233 234 """ 235 modem = self.test_env.shill.find_cellular_device_object() 236 self.test_env.shill.reset_modem(modem) 237 238 239 def run_once(self): 240 tests = [ 241 ActivationStateTest(self), 242 ActivationSuccessTest(self), 243 ActivationFailureRetryTest(self) 244 ] 245 246 for test in tests: 247 self.test_env = test_environment.CellularPseudoMMTestEnvironment( 248 pseudomm_args=(test.pseudomodem_flags(),)) 249 with self.test_env: 250 test.run() 251