• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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