• 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 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