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