• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2019 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
5"""A Batch of of Bluetooth LE health tests"""
6
7import time
8
9from autotest_lib.server.cros.bluetooth.bluetooth_adapter_controller_role_tests\
10        import bluetooth_AdapterControllerRoleTests
11from autotest_lib.server.cros.bluetooth.bluetooth_adapter_quick_tests import (
12        BluetoothAdapterQuickTests)
13from autotest_lib.server.cros.bluetooth.bluetooth_adapter_pairing_tests import (
14        BluetoothAdapterPairingTests)
15from autotest_lib.server.cros.bluetooth.bluetooth_adapter_hidreports_tests \
16        import BluetoothAdapterHIDReportTests
17
18
19# TODO(b/161174805) - veyron_fievel and veyron_mickey experiencing an
20# unexpected re-connect to peer, causing peer tests to fail. LE Role tests are
21# being hit especially hard, so temporarily disabling these tests on veyron
22LAB_VEYRON_MODELS = ['veyron_mickey', 'veyron_fievel']
23
24class bluetooth_AdapterLEHealth(BluetoothAdapterQuickTests,
25        BluetoothAdapterPairingTests,
26        BluetoothAdapterHIDReportTests,
27        bluetooth_AdapterControllerRoleTests):
28    """A Batch of Bluetooth LE health tests. This test is written as a batch
29       of tests in order to reduce test time, since auto-test ramp up time is
30       costly. The batch is using BluetoothAdapterQuickTests wrapper methods to
31       start and end a test and a batch of tests.
32
33       This class can be called to run the entire test batch or to run a
34       specific test only
35    """
36
37    test_wrapper = BluetoothAdapterQuickTests.quick_test_test_decorator
38    batch_wrapper = BluetoothAdapterQuickTests.quick_test_batch_decorator
39
40    @test_wrapper('Discovery Test', devices={"BLE_MOUSE":1})
41    def le_discovery_test(self):
42        """Performs discovery test with mouse peripheral"""
43        device = self.devices['BLE_MOUSE'][0]
44
45        self.test_discover_device(device.address)
46
47        # Removed due to b:149093897 - the raspi peer can't instantly update
48        # the advertised name, causing this test to fail
49        # self.test_device_name(device.address, device.name)
50
51
52    @test_wrapper('Connect Disconnect Loop', devices={'BLE_MOUSE':1})
53    def le_connect_disconnect_loop(self):
54        """Run connect/disconnect loop initiated by DUT.
55           The test also checks that there are no undesired
56           reconnections.
57           TODO(ysahvit) - add connection creation attempts
58                           initiated by HID device
59        """
60
61        device = self.devices['BLE_MOUSE'][0]
62        self.connect_disconnect_loop(device=device, loops=3)
63
64    @test_wrapper('Mouse Reports', devices={'BLE_MOUSE':1})
65    def le_mouse_reports(self):
66        """Run all bluetooth mouse reports tests"""
67
68        device = self.devices['BLE_MOUSE'][0]
69        # Let the adapter pair, and connect to the target device.
70        self.test_discover_device(device.address)
71        time.sleep(self.TEST_SLEEP_SECS)
72        self.test_pairing(device.address, device.pin, trusted=True)
73
74        # With raspberry pi peer, it takes a moment before the device is
75        # registered as an input device. Without delay, the input recorder
76        # doesn't find the device
77        time.sleep(1)
78        self.run_mouse_tests(device=device)
79
80
81    @test_wrapper('Keyboard Reports', devices={'BLE_KEYBOARD':1})
82    def le_keyboard_reports(self):
83        """Run all bluetooth keyboard reports tests"""
84
85        device = self.devices['BLE_KEYBOARD'][0]
86        # Let the adapter pair, and connect to the target device.
87        self.test_discover_device(device.address)
88        time.sleep(self.TEST_SLEEP_SECS)
89        self.test_pairing(device.address, device.pin, trusted=True)
90
91        # With raspberry pi peer, it takes a moment before the device is
92        # registered as an input device. Without delay, the input recorder
93        # doesn't find the device
94        time.sleep(1)
95        self.run_keyboard_tests(device=device)
96
97
98    @test_wrapper('Battery Reporting', devices={'BLE_MOUSE': 1})
99    def battery_reporting(self):
100        """Run battery reporting tests"""
101
102        device = self.devices['BLE_MOUSE'][0]
103        # Let the adapter pair, and connect to the target device.
104        self.assert_on_fail(self.test_discover_device(device.address))
105        self.assert_on_fail(
106                self.test_pairing(device.address, device.pin, trusted=True))
107
108        self.run_battery_reporting_tests(device=device)
109
110    @test_wrapper('Auto Reconnect', devices={'BLE_MOUSE':1})
111    def le_auto_reconnect(self):
112        """LE reconnection loop by reseting HID and check reconnection"""
113
114        device = self.devices['BLE_MOUSE'][0]
115        self.auto_reconnect_loop(
116                device=device,
117                loops=3,
118                check_connected_method=self.test_mouse_left_click)
119
120    # TODO(b/165690676) - Test is disabled for AVL while it stabilizes in flaky
121    #                     suite. Remove flags once it's in stable suite.
122    @test_wrapper('Power toggle and Connect Loop', devices={'BLE_MOUSE': 1})
123    def le_power_toggle_connect_loop(self):
124        """Run autoconnect loop and cycle adapter power between runs.
125           The test makes sure the peer can reconnect after an adapter power
126           cycle.
127        """
128        device = self.devices['BLE_MOUSE'][0]
129        self.auto_reconnect_loop(
130                device=device,
131                loops=3,
132                check_connected_method=self.test_mouse_left_click,
133                restart_adapter=True)
134
135
136    @test_wrapper('GATT Client', devices={'BLE_KEYBOARD':1})
137    def le_gatt_client_attribute_browse_test(self):
138        """Browse the whole tree-structured GATT attributes"""
139
140        device = self.devices['BLE_KEYBOARD'][0]
141        self.test_discover_device(device.address)
142        time.sleep(self.TEST_SLEEP_SECS)
143        self.test_pairing(device.address, device.pin, trusted=True)
144        self.test_service_resolved(device.address)
145        self.test_gatt_browse(device.address)
146
147
148    # TODO (b/165949047) Flaky behavior on MVL/4.4 kernel causes flakiness when
149    # connection is initiated by slave. Skip the test until 2021 uprev
150    @test_wrapper('LE secondary Test',
151                  devices={'BLE_KEYBOARD': 1},
152                  skip_models=LAB_VEYRON_MODELS + ['bob'])
153    def le_role_secondary(self):
154        """Tests connection as secondary"""
155
156        self.verify_controller_capability(
157                        required_roles=['peripheral'],
158                        test_type=self.flag)
159
160        kbd = self.devices['BLE_KEYBOARD'][0]
161        kbd_test_func = lambda device: self.test_keyboard_input_from_trace(
162                device, 'simple_text')
163        self.controller_secondary_role_test(kbd, kbd_test_func)
164
165
166    @test_wrapper('LE primary Before secondary Test',
167                  devices={'BLE_KEYBOARD':1, 'BLE_MOUSE':1},
168                  skip_models=LAB_VEYRON_MODELS)
169    def le_role_primary_before_secondary(self):
170        """Tests connection as primary and then as secondary"""
171
172        self.verify_controller_capability(
173                        required_roles=['central-peripheral'],
174                        test_type=self.flag)
175
176        kbd = self.devices['BLE_KEYBOARD'][0]
177        mouse = self.devices['BLE_MOUSE'][0]
178
179        kbd_test_func = lambda device: self.test_keyboard_input_from_trace(
180                device, 'simple_text')
181        mouse_test_func = self.test_mouse_left_click
182
183        hid_test_device = (mouse, mouse_test_func, 'pre')
184        self.controller_secondary_role_test(
185                kbd, kbd_test_func, secondary_info=hid_test_device)
186
187
188    @test_wrapper('LE secondary Before primary Test', devices={'BLE_KEYBOARD':1,
189                                                          'BLE_MOUSE':1},
190                  skip_models=LAB_VEYRON_MODELS)
191    def le_role_secondary_before_primary(self):
192        """Tests connection as secondary and then as primary"""
193
194        self.verify_controller_capability(
195                        required_roles=['central-peripheral'],
196                        test_type=self.flag)
197
198        kbd = self.devices['BLE_KEYBOARD'][0]
199        mouse = self.devices['BLE_MOUSE'][0]
200
201        kbd_test_func = lambda device: self.test_keyboard_input_from_trace(
202                device, 'simple_text')
203        mouse_test_func = self.test_mouse_left_click
204
205        hid_test_device = (mouse, mouse_test_func, 'mid')
206        self.controller_secondary_role_test(
207                kbd, kbd_test_func, secondary_info=hid_test_device)
208
209
210    @test_wrapper('LE Sender Role Test', devices={'BLE_KEYBOARD':1},
211                  skip_models=LAB_VEYRON_MODELS)
212    def le_role_sender(self):
213        """Tests basic Nearby Sender role"""
214
215        self.verify_controller_capability(
216                        required_roles=['central'],
217                        test_type=self.flag)
218
219        kbd = self.devices['BLE_KEYBOARD'][0]
220        kbd_test_func = lambda device: self.test_keyboard_input_from_trace(
221                device, 'simple_text')
222
223        self.nearby_sender_role_test(kbd, kbd_test_func)
224
225
226    @test_wrapper('LE Sender Role Test During HID',
227                  devices={'BLE_KEYBOARD':1, 'BLE_MOUSE':1},
228                  skip_models=LAB_VEYRON_MODELS)
229    def le_role_sender_during_hid(self):
230        """Tests Nearby Sender role while already connected to HID device"""
231
232        self.verify_controller_capability(
233                        required_roles=['central-peripheral'],
234                        test_type=self.flag)
235
236        kbd = self.devices['BLE_KEYBOARD'][0]
237        mouse = self.devices['BLE_MOUSE'][0]
238
239        kbd_test_func = lambda device: self.test_keyboard_input_from_trace(
240                device, 'simple_text')
241        mouse_test_func = self.test_mouse_left_click
242
243        hid_test_device = (mouse, mouse_test_func, 'pre')
244        self.nearby_sender_role_test(
245                kbd, kbd_test_func, secondary_info=hid_test_device)
246
247
248    @test_wrapper('LE HID Test During Sender Role',
249                  devices={'BLE_KEYBOARD':1, 'BLE_MOUSE':1},
250                  skip_models=LAB_VEYRON_MODELS)
251    def le_role_hid_during_sender(self):
252        """Tests HID device while already in Nearby Sender role"""
253
254        self.verify_controller_capability(
255                        required_roles=['central'],
256                        test_type=self.flag)
257
258        kbd = self.devices['BLE_KEYBOARD'][0]
259        mouse = self.devices['BLE_MOUSE'][0]
260
261        kbd_test_func = lambda device: self.test_keyboard_input_from_trace(
262                device, 'simple_text')
263        mouse_test_func = self.test_mouse_left_click
264
265        hid_test_device = (mouse, mouse_test_func, 'mid')
266        self.nearby_sender_role_test(
267                kbd, kbd_test_func, secondary_info=hid_test_device)
268
269
270    # TODO (b/165949047) Flaky behavior on MVL/4.4 kernel causes flakiness when
271    # connection is initiated by slave. Skip the test until 2021 uprev
272    @test_wrapper('LE Receiver Role Test',
273                  devices={'BLE_KEYBOARD': 1},
274                  skip_models=LAB_VEYRON_MODELS + ['bob'])
275    def le_role_receiver(self):
276        """Tests basic Nearby Receiver role"""
277
278        self.verify_controller_capability(
279                        required_roles=['peripheral'],
280                        test_type=self.flag)
281
282        kbd = self.devices['BLE_KEYBOARD'][0]
283        kbd_test_func = lambda device: self.test_keyboard_input_from_trace(
284                device, 'simple_text')
285
286        self.nearby_receiver_role_test(kbd, kbd_test_func)
287
288
289    @test_wrapper('LE Receiver Role Test During HID',
290                  devices={'BLE_KEYBOARD':1, 'BLE_MOUSE':1},
291                  skip_models=LAB_VEYRON_MODELS)
292    def le_role_receiver_during_hid(self):
293        """Tests Nearby Receiver role while already connected to HID device"""
294
295        self.verify_controller_capability(
296                        required_roles=['central-peripheral'],
297                        test_type=self.flag)
298
299        kbd = self.devices['BLE_KEYBOARD'][0]
300        mouse = self.devices['BLE_MOUSE'][0]
301
302        kbd_test_func = lambda device: self.test_keyboard_input_from_trace(
303                device, 'simple_text')
304        mouse_test_func = self.test_mouse_left_click
305
306        hid_test_device = (mouse, mouse_test_func, 'pre')
307        self.nearby_receiver_role_test(
308                kbd, kbd_test_func, secondary_info=hid_test_device)
309
310
311    @test_wrapper('LE HID Test During Receiver Adv',
312                  devices={
313                          'BLE_KEYBOARD': 1,
314                          'BLE_MOUSE': 1
315                  },
316                  skip_models=LAB_VEYRON_MODELS)
317    def le_role_hid_during_receiver_adv(self):
318        """Tests HID device while already in Nearby Receiver role adv state"""
319
320        self.verify_controller_capability(
321                        required_roles=['central-peripheral'],
322                        test_type=self.flag)
323
324        kbd = self.devices['BLE_KEYBOARD'][0]
325        mouse = self.devices['BLE_MOUSE'][0]
326
327        kbd_test_func = lambda device: self.test_keyboard_input_from_trace(
328                device, 'simple_text')
329        mouse_test_func = self.test_mouse_left_click
330
331        hid_test_device = (mouse, mouse_test_func, 'mid')
332        self.nearby_receiver_role_test(
333                kbd, kbd_test_func, secondary_info=hid_test_device)
334
335
336    @test_wrapper('LE HID Test During Receiver Role',
337                  devices={'BLE_KEYBOARD':1, 'BLE_MOUSE':1},
338                  skip_models=LAB_VEYRON_MODELS)
339    def le_role_hid_during_receiver_connection(self):
340        """Tests HID device while already in Nearby Receiver role connection"""
341
342        self.verify_controller_capability(
343                        required_roles=['central-peripheral'],
344                        test_type=self.flag)
345
346        kbd = self.devices['BLE_KEYBOARD'][0]
347        mouse = self.devices['BLE_MOUSE'][0]
348
349        kbd_test_func = lambda device: self.test_keyboard_input_from_trace(
350                device, 'simple_text')
351        mouse_test_func = self.test_mouse_left_click
352
353        hid_test_device = (mouse, mouse_test_func, 'end')
354        self.nearby_receiver_role_test(
355                kbd, kbd_test_func, secondary_info=hid_test_device)
356
357
358    @batch_wrapper('LE Health')
359    def le_health_batch_run(self, num_iterations=1, test_name=None):
360        """Run the LE health test batch or a specific given test.
361           The wrapper of this method is implemented in batch_decorator.
362           Using the decorator a test batch method can implement the only its
363           core tests invocations and let the decorator handle the wrapper,
364           which is taking care for whether to run a specific test or the
365           batch as a whole, and running the batch in iterations
366
367           @param num_iterations: how many interations to run
368           @param test_name: specifc test to run otherwise None to run the
369                             whole batch
370        """
371        self.le_connect_disconnect_loop()
372        self.le_power_toggle_connect_loop()
373        self.le_mouse_reports()
374        self.le_keyboard_reports()
375        self.le_auto_reconnect()
376        self.le_discovery_test()
377
378        # Controller role tests
379        self.le_role_hid_during_receiver_adv()
380        self.le_role_hid_during_sender()
381        self.le_role_primary_before_secondary()
382        self.le_role_receiver()
383        self.le_role_receiver_during_hid()
384        self.le_role_secondary()
385        self.le_role_sender()
386        self.le_role_sender_during_hid()
387
388
389    def run_once(self,
390                 host,
391                 num_iterations=1,
392                 args_dict=None,
393                 test_name=None,
394                 flag='Quick Health'):
395        """Run the batch of Bluetooth LE health tests
396
397        @param host: the DUT, usually a chromebook
398        @param num_iterations: the number of rounds to execute the test
399        @test_name: the test to run, or None for all tests
400        """
401
402        # Initialize and run the test batch or the requested specific test
403        self.quick_test_init(host,
404                             use_btpeer=True,
405                             flag=flag,
406                             args_dict=args_dict)
407        self.le_health_batch_run(num_iterations, test_name)
408        self.quick_test_cleanup()
409