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 logging 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.LTEActivationTest' 18TEST_MODEMS_MODULE_PATH = os.path.join(os.path.dirname(__file__), 'files', 19 'modems.py') 20 21LONG_TIMEOUT = 20 22SHORT_TIMEOUT = 10 23 24class ActivationTest(object): 25 """ 26 Super class that implements setup code that is common to the individual 27 tests. 28 29 """ 30 def __init__(self, test): 31 self.test = test 32 33 34 def Cleanup(self): 35 """ 36 Makes the modem look like it has been activated to satisfy the test 37 end condition. 38 39 """ 40 # Set the MDN to a non-zero value, so that shill removes the ICCID from 41 # activating_iccid_store.profile. This way, individual test runs won't 42 # interfere with each other. 43 modem = self.test.pseudomm.wait_for_modem(timeout_seconds=LONG_TIMEOUT) 44 modem.iface_properties.Set(mm1_constants.I_MODEM, 45 'OwnNumbers', 46 ['1111111111']) 47 # Put the modem in the unknown subscription state so that the mdn value is 48 # used to remove the iccid entry 49 self.test.pseudomm.iface_testing.SetSubscriptionState( 50 mm1_constants.MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN) 51 time.sleep(5) 52 self.test.CheckServiceActivationState('activated') 53 54 55 def Run(self): 56 """ 57 Configures the pseudomodem to run with the test modem, runs the test 58 and cleans up. 59 60 """ 61 self.RunTest() 62 self.Cleanup() 63 64 65 def RunTest(self): 66 """ 67 Runs the body of the test. Should be implemented by the subclass. 68 69 """ 70 raise NotImplementedError() 71 72 73class ActivationResetTest(ActivationTest): 74 """ 75 This test verifies that the modem resets after online payment. 76 77 """ 78 def RunTest(self): 79 # Service should appear as 'not-activated'. 80 self.test.CheckServiceActivationState('not-activated') 81 self.test.CheckResetCalled(False) 82 83 # Call 'CompleteActivation' on the device. The service will become 84 # 'activating' and the modem should reset immediately. 85 # Not checking for the intermediate 'activating' state because it makes 86 # the test too fragile 87 service = self.test.FindCellularService() 88 service.CompleteCellularActivation() 89 time.sleep(SHORT_TIMEOUT) 90 self.test.CheckResetCalled(True) 91 92 93class ActivationDueToMdnTest(ActivationTest): 94 """ 95 This test verifies that a valid MDN should cause the service to get marked 96 as 'activated' when the modem is in unknown subscription state. 97 98 """ 99 def RunTest(self): 100 # Service should appear as 'not-activated'. 101 self.test.CheckServiceActivationState('not-activated') 102 103 # Update the MDN. The service should get marked as activated. 104 modem = self.test.pseudomm.get_modem() 105 modem.iface_properties.Set(mm1_constants.I_MODEM, 106 'OwnNumbers', 107 ['1111111111']) 108 # Put the modem in the unknown subscription state so that the mdn value is 109 # used to determine the service activation status. 110 self.test.pseudomm.iface_testing.SetSubscriptionState( 111 mm1_constants.MM_MODEM_3GPP_SUBSCRIPTION_STATE_UNKNOWN) 112 time.sleep(SHORT_TIMEOUT) 113 self.test.CheckServiceActivationState('activated') 114 115 116class cellular_ActivateLTE(test.test): 117 """ 118 After an online payment to activate a network, shill keeps track of service 119 activation by monitoring changes to network registration and MDN updates 120 combined with a modem reset. The test checks that the 121 Cellular.ActivationState property of the service has the correct value 122 associated with it by simulating possible scenarios using the pseudo modem 123 manager. 124 125 """ 126 version = 1 127 128 def GetModemState(self): 129 """Returns the current ModemManager modem state.""" 130 modem = self.pseudomm.get_modem() 131 props = modem.properties(mm1_constants.I_MODEM) 132 return props['State'] 133 134 135 def SetResetCalled(self, value): 136 """ 137 Sets the value of the "ResetCalled" property of the current 138 modem. 139 140 @param value: Value to set in the property. 141 142 """ 143 modem = self.pseudomm.get_modem() 144 if modem is None: 145 return 146 modem.iface_properties.Set( 147 I_ACTIVATION_TEST, 148 'ResetCalled', 149 dbus.types.Boolean(value)) 150 151 152 def GetResetCalled(self, modem): 153 """ 154 Returns the current value of the "ResetCalled" property of the current 155 modem. 156 157 @param modem: Modem proxy to send the query to. 158 159 """ 160 return modem.properties(I_ACTIVATION_TEST)['ResetCalled'] 161 162 163 def _CheckResetCalledHelper(self, expected_value): 164 modem = self.pseudomm.get_modem() 165 if modem is None: 166 return False 167 try: 168 return self.GetResetCalled(modem) == expected_value 169 except dbus.exceptions.DBusException as e: 170 name = e.get_dbus_name() 171 if (name == mm1_constants.DBUS_UNKNOWN_METHOD or 172 name == mm1_constants.DBUS_UNKNOWN_OBJECT): 173 return False 174 raise e 175 176 177 def CheckResetCalled(self, expected_value): 178 """ 179 Checks that the ResetCalled property on the modem matches the expect 180 value. 181 182 @param expected_value: The expected value of ResetCalled. 183 184 """ 185 utils.poll_for_condition( 186 lambda: self._CheckResetCalledHelper(expected_value), 187 exception=error.TestFail("\"ResetCalled\" did not match: " + 188 str(expected_value)), 189 timeout=LONG_TIMEOUT) 190 191 192 def CheckServiceActivationState(self, expected_state): 193 """ 194 Asserts that the service activation state matches |expected_state| 195 within SHORT_TIMEOUT. 196 197 @param expected_state: The expected service activation state. 198 199 """ 200 logging.info('Checking for service activation state: %s', 201 expected_state) 202 service = self.FindCellularService() 203 success, state, duration = self.test_env.shill.wait_for_property_in( 204 service, 205 'Cellular.ActivationState', 206 [expected_state], 207 SHORT_TIMEOUT) 208 if not success and state != expected_state: 209 raise error.TestError( 210 'Service activation state should be \'%s\', but it is \'%s\'.' 211 % (expected_state, state)) 212 213 214 def FindCellularService(self, check_not_none=True): 215 """ 216 Returns the current cellular service. 217 218 @param check_not_none: If True, an error will be raised if no service 219 was found. 220 221 """ 222 if check_not_none: 223 utils.poll_for_condition( 224 lambda: (self.test_env.shill.find_cellular_service_object() 225 is not None), 226 exception=error.TestError( 227 'Could not find cellular service within timeout.'), 228 timeout=LONG_TIMEOUT); 229 230 service = self.test_env.shill.find_cellular_service_object() 231 232 # Check once more, to make sure it's valid. 233 if check_not_none and not service: 234 raise error.TestError('Could not find cellular service.') 235 return service 236 237 238 def run_once(self): 239 tests = [ 240 ActivationResetTest(self), 241 ActivationDueToMdnTest(self), 242 ] 243 244 for test in tests: 245 logging.info("Running sub-test %s", test.__class__.__name__) 246 self.test_env = test_environment.CellularPseudoMMTestEnvironment( 247 pseudomm_args = ({'family' : '3GPP', 248 'test-module' : TEST_MODEMS_MODULE_PATH, 249 'test-modem-class' : 'TestModem', 250 'test-sim-class' : 'TestSIM'},)) 251 with self.test_env: 252 self.pseudomm = pm_proxy.PseudoMMProxy.get_proxy() 253 test.Run() 254