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