blob: ed2356690a1dc2a20eae3da161e22f7cce9efaf8 [file] [log] [blame]
Thieu Le98327a42014-08-21 18:11:41 -07001# Copyright (c) 2014 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 contextlib
6import dbus
7import logging
8import sys
9import traceback
10
11import common
12from autotest_lib.client.common_lib import error
13from autotest_lib.client.cros import backchannel
14from autotest_lib.client.cros.cellular import cell_tools
15from autotest_lib.client.cros.cellular import mm
16from autotest_lib.client.cros.cellular.pseudomodem import pseudomodem_context
17from autotest_lib.client.cros.cellular.wardmodem import wardmodem
18from autotest_lib.client.cros.networking import cellular_proxy
Thieu Le5fe5f512014-09-03 12:52:10 -070019from autotest_lib.client.cros.networking import shill_proxy
Thieu Le98327a42014-08-21 18:11:41 -070020
21# Import 'flimflam_test_path' first in order to import flimflam.
22# pylint: disable=W0611
23from autotest_lib.client.cros import flimflam_test_path
24import flimflam
25
26class CellularTestEnvironment(object):
27 """Setup and verify cellular test environment.
28
29 This context manager configures the following:
30 - Sets up backchannel.
31 - Shuts down other devices except cellular.
32 - Shill and MM logging is enabled appropriately for cellular.
33 - Initializes members that tests should use to access test environment
34 (eg. |shill|, |flimflam|, |modem_manager|, |modem|).
35
36 Then it verifies the following is valid:
37 - The backchannel is using an Ethernet device.
38 - The SIM is inserted and valid.
39 - There is one and only one modem in the device.
40 - The modem is registered to the network.
41 - There is a cellular service in shill and it's not connected.
42
43 Don't use this base class directly, use the appropriate subclass.
44
45 Setup for over-the-air tests:
46 with CellularOTATestEnvironment() as test_env:
47 # Test body
48
49 Setup for pseudomodem tests:
50 with CellularPseudoMMTestEnvironment(
51 pseudomm_args=({'family': '3GPP'})) as test_env:
52 # Test body
53
54 Setup for wardmodem tests:
55 with CellularWardModemTestEnvironment(
56 wardmodem_modem='e362') as test_env:
57 # Test body
58
59 """
60
61 def __init__(self, use_backchannel=True, shutdown_other_devices=True):
62 """
63 @param use_backchannel: Set up the backchannel that can be used to
64 communicate with the DUT.
65 @param shutdown_other_devices: If True, shutdown all devices except
66 cellular.
67
68 """
69 # Tests should use this main loop instead of creating their own.
70 self.mainloop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
71 self.bus = dbus.SystemBus(mainloop=self.mainloop)
72
73 self.shill = None
74 self.flim = None # Only use this for legacy tests.
75 self.modem_manager = None
76 self.modem = None
77
78 self._context_managers = []
79 if use_backchannel:
80 self._context_managers.append(backchannel.Backchannel())
81 if shutdown_other_devices:
82 self._context_managers.append(
83 cell_tools.OtherDeviceShutdownContext('cellular'))
84
85
86 def __enter__(self):
87 try:
88 self._nested = contextlib.nested(*self._context_managers)
89 self._nested.__enter__()
90
91 self._initialize_components()
92 self._setup_logging()
93
94 self._verify_backchannel()
95 self._verify_sim()
96 self._wait_for_modem_registration()
97 self._verify_cellular_service()
98
99 return self
Thieu Le5fe5f512014-09-03 12:52:10 -0700100 except (error.TestError, dbus.DBusException,
101 shill_proxy.ShillProxyError) as e:
Thieu Le98327a42014-08-21 18:11:41 -0700102 except_type, except_value, except_traceback = sys.exc_info()
103 lines = traceback.format_exception(except_type, except_value,
104 except_traceback)
105 logging.error('Error during test initialization:\n' +
106 ''.join(lines))
107 self.__exit__(*sys.exc_info())
108 raise error.TestError('INIT_ERROR: %s' % str(e))
Thieu Le5fe5f512014-09-03 12:52:10 -0700109 except:
110 self.__exit__(*sys.exc_info())
111 raise
Thieu Le98327a42014-08-21 18:11:41 -0700112
113
114 def __exit__(self, exception, value, traceback):
115 return self._nested.__exit__(exception, value, traceback)
116
117
118 def _reset_modem(self):
119 modem_device = self.shill.find_cellular_device_object()
120 if not modem_device:
121 raise error.TestError('Cannot find cellular device in shill. '
122 'Is the modem plugged in?')
123 try:
124 # Cromo modems do not support being reset.
125 self.shill.reset_modem(modem_device, expect_service=False)
126 except dbus.DBusException as e:
127 if (e.get_dbus_name() !=
128 cellular_proxy.CellularProxy.ERROR_NOT_SUPPORTED):
129 raise
130
131
132 def _initialize_components(self):
133 """Get access to various test environment components. """
134 # CellularProxy.get_proxy() checks to see if shill is running and
135 # responding to DBus requests. It returns None if that's not the case.
136 self.shill = cellular_proxy.CellularProxy.get_proxy(self.bus)
137 if self.shill is None:
138 raise error.TestError('Cannot connect to shill, is shill running?')
139
140 # Keep this around to support older tests that haven't migrated to
141 # cellular_proxy.
142 self.flim = flimflam.FlimFlam()
143
144 # PickOneModem() makes sure there's a modem manager and that there is
145 # one and only one modem.
146 self._reset_modem()
147 self.modem_manager, modem_path = mm.PickOneModem('')
148 self.modem = self.modem_manager.GetModem(modem_path)
149 if self.modem is None:
150 raise error.TestError('Cannot get modem object at %s.' % modem_path)
151
152
153 def _setup_logging(self):
154 self.shill.set_logging_for_cellular_test()
155 self.modem_manager.SetDebugLogging()
156
157
158 def _verify_backchannel(self):
159 """Verify backchannel is on an ethernet device.
160
161 @raise error.TestError if backchannel is not on an ethernet device.
162
163 """
Thieu Le8bded2b2014-09-03 15:38:46 -0700164 if not backchannel.is_backchannel_using_ethernet():
165 raise error.TestError('An ethernet connection is required between '
166 'the test server and the device under test.')
Thieu Le98327a42014-08-21 18:11:41 -0700167
168
169 def _verify_sim(self):
170 """Verify SIM is valid.
171
172 @raise error.TestError if SIM does not exist or is invalid.
173
174 """
175 # TODO: Implement this (crbug.com/403155).
176 pass
177
178
179 def _wait_for_modem_registration(self):
180 """Wait for the modem to register with the network.
181
182 The modem should be enabled and registered with the network.
183
184 @raise error.TestError if modem is not registered.
185
186 """
187 # TODO: Implement this (crbug.com/403160).
188 pass
189
190
191 def _verify_cellular_service(self):
192 """Make sure a cellular service exists.
193
194 The cellular service should not be connected to the network.
195
196 @raise error.TestError if cellular service does not exist or if
197 there are multiple cellular services.
198
199 """
200 service = self.shill.wait_for_cellular_service_object()
201
202 try:
203 service.Disconnect()
204 except dbus.DBusException as e:
205 if (e.get_dbus_name() !=
206 cellular_proxy.CellularProxy.ERROR_NOT_CONNECTED):
207 raise
208 success, _, _ = self.shill.wait_for_property_in(
209 service,
210 cellular_proxy.CellularProxy.SERVICE_PROPERTY_STATE,
211 ('idle',),
212 cellular_proxy.CellularProxy.SERVICE_DISCONNECT_TIMEOUT)
213 if not success:
214 raise error.TestError(
215 'Cellular service needs to start in the idle state. '
216 'Modem disconnect may have failed.')
217
218
219class CellularOTATestEnvironment(CellularTestEnvironment):
220 """Setup and verify cellular over-the-air (OTA) test environment. """
221 def __init__(self, **kwargs):
222 super(CellularOTATestEnvironment, self).__init__(**kwargs)
223
224
225class CellularPseudoMMTestEnvironment(CellularTestEnvironment):
226 """Setup and verify cellular pseudomodem test environment. """
227 def __init__(self, pseudomm_args=None, **kwargs):
228 """
229 @param pseudomm_args: Tuple of arguments passed to the pseudomodem, see
230 pseudomodem_context.py for description of each argument in the
231 tuple: (flags_map, block_output, bus)
232
233 """
234 super(CellularPseudoMMTestEnvironment, self).__init__(**kwargs)
235 self._context_managers.append(
Thieu Le6724f282014-09-04 15:36:41 -0700236 pseudomodem_context.PseudoModemManagerContext(
237 True, bus=self.bus, *pseudomm_args))
Thieu Le98327a42014-08-21 18:11:41 -0700238
239
240class CellularWardModemTestEnvironment(CellularTestEnvironment):
241 """Setup and verify cellular ward modem test environment. """
242 def __init__(self, wardmodem_modem=None, **kwargs):
243 """
244 @param wardmodem_modem: Customized ward modem to use instead of the
245 default implementation, see wardmodem.py.
246
247 """
248 super(CellularWardModemTestEnvironment, self).__init__(**kwargs)
249 self._context_managers.append(
250 wardmodem.WardModemContext(args=['--modem', wardmodem_modem]))