Home | History | Annotate | Download | only in system_tests
      1 #/usr/bin/env python3.4
      2 #
      3 # Copyright (C) 2016 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License"); you may not
      6 # use this file except in compliance with the License. You may obtain a copy of
      7 # the License at
      8 #
      9 # http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     14 # License for the specific language governing permissions and limitations under
     15 # the License.
     16 """
     17 Basic LE Stress tests.
     18 """
     19 
     20 import concurrent
     21 import pprint
     22 import time
     23 
     24 from queue import Empty
     25 from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
     26 from acts.test_utils.bt.bt_test_utils import BtTestUtilsError
     27 from acts.test_utils.bt.bt_test_utils import clear_bonded_devices
     28 from acts.test_utils.bt.bt_test_utils import generate_ble_advertise_objects
     29 from acts.test_utils.bt.bt_test_utils import generate_ble_scan_objects
     30 from acts.test_utils.bt.bt_test_utils import get_advanced_droid_list
     31 from acts.test_utils.bt.bt_test_utils import get_mac_address_of_generic_advertisement
     32 from acts.test_utils.bt.bt_test_utils import reset_bluetooth
     33 from acts.test_utils.bt.bt_test_utils import scan_result
     34 
     35 class BleStressTest(BluetoothBaseTest):
     36     default_timeout = 10
     37     PAIRING_TIMEOUT = 20
     38 
     39     def __init__(self, controllers):
     40         BluetoothBaseTest.__init__(self, controllers)
     41         self.droid_list = get_advanced_droid_list(self.android_devices)
     42         self.scn_ad = self.android_devices[0]
     43         self.adv_ad = self.android_devices[1]
     44 
     45     def teardown_test(self):
     46         super(BluetoothBaseTest, self).teardown_test()
     47         self.log_stats()
     48 
     49     def bleadvertise_verify_onsuccess_handler(self, event):
     50         test_result = True
     51         self.log.debug("Verifying onSuccess event")
     52         self.log.debug(pprint.pformat(event))
     53         return test_result
     54 
     55     def _verify_successful_bond(self, target_address):
     56         end_time = time.time() + self.PAIRING_TIMEOUT
     57         self.log.info("Verifying devices are bonded")
     58         while time.time() < end_time:
     59             bonded_devices = self.scn_ad.droid.bluetoothGetBondedDevices()
     60             if target_address in {d['address'] for d in bonded_devices}:
     61                 self.log.info("Successfully bonded to device")
     62                 return True
     63         return False
     64 
     65     @BluetoothBaseTest.bt_test_wrap
     66     def test_loop_scanning_1000(self):
     67         """Stress start/stop scan instances.
     68 
     69         This test will start and stop scan instances as fast as possible. This
     70         will guarantee that the scan instances are properly being cleaned up
     71         when the scan is stopped.
     72 
     73         Steps:
     74         1. Start a scan instance.
     75         2. Stop the scan instance.
     76         3. Repeat steps 1-2 1000 times.
     77 
     78         Expected Result:
     79         Neither starting or stopping scan instances causes any failures.
     80 
     81         Returns:
     82           Pass if True
     83           Fail if False
     84 
     85         TAGS: LE, Scanning, Stress
     86         Priority: 1
     87         """
     88         test_result = True
     89         for _ in range(1000):
     90             filter_list, scan_settings, scan_callback = generate_ble_scan_objects(
     91                 self.scn_ad.droid)
     92             self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
     93                                               scan_callback)
     94             self.scn_ad.droid.bleStopBleScan(scan_callback)
     95         return test_result
     96 
     97     @BluetoothBaseTest.bt_test_wrap
     98     def test_loop_scanning_100_verify_no_hci_timeout(self):
     99         """Stress start/stop scan instances variant.
    100 
    101         This test will start and stop scan instances with a one second timeout
    102         in between each iteration. This testcase was added because the specific
    103         timing combination caused hci timeouts.
    104 
    105         Steps:
    106         1. Start a scan instance.
    107         2. Stop the scan instance.
    108         3. Sleep for 1 second.
    109         4. Repeat steps 1-3 100 times.
    110 
    111         Expected Result:
    112         Neither starting or stopping scan instances causes any failures.
    113 
    114         Returns:
    115           Pass if True
    116           Fail if False
    117 
    118         TAGS: LE, Scanning, Stress
    119         Priority: 1
    120         """
    121         for _ in range(self.droid_list[1]['max_advertisements']):
    122             adv_callback, adv_data, adv_settings = generate_ble_advertise_objects(
    123                 self.adv_ad.droid)
    124             self.adv_ad.droid.bleStartBleAdvertising(adv_callback, adv_data,
    125                                                      adv_settings)
    126         for _ in range(100):
    127             filter_list, scan_settings, scan_callback = generate_ble_scan_objects(
    128                 self.scn_ad.droid)
    129             self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
    130                                               scan_callback)
    131             self.log.info(self.scn_ad.ed.pop_event(scan_result.format(
    132                 scan_callback)))
    133             self.scn_ad.droid.bleStopBleScan(scan_callback)
    134             time.sleep(1)
    135         return True
    136 
    137     @BluetoothBaseTest.bt_test_wrap
    138     def test_loop_advertising_100(self):
    139         """Stress start/stop advertising instances.
    140 
    141         This test will start and stop advertising instances as fast as possible.
    142 
    143         Steps:
    144         1. Start a advertising instance.
    145         2. Find that an onSuccess callback is triggered.
    146         3. Stop the advertising instance.
    147         4. Repeat steps 1-3 100 times.
    148 
    149         Expected Result:
    150         Neither starting or stopping advertising instances causes any failures.
    151 
    152         Returns:
    153           Pass if True
    154           Fail if False
    155 
    156         TAGS: LE, Advertising, Stress
    157         Priority: 1
    158         """
    159         test_result = True
    160         for _ in range(100):
    161             advertise_callback, advertise_data, advertise_settings = generate_ble_advertise_objects(
    162                 self.adv_ad.droid)
    163             self.adv_ad.droid.bleStartBleAdvertising(
    164                 advertise_callback, advertise_data, advertise_settings)
    165             expected_advertise_event_name = "".join(["BleAdvertise", str(
    166                 advertise_callback), "onSuccess"])
    167             worker = self.adv_ad.ed.handle_event(
    168                 self.bleadvertise_verify_onsuccess_handler,
    169                 expected_advertise_event_name, ([]), self.default_timeout)
    170             try:
    171                 self.log.debug(worker.result(self.default_timeout))
    172             except Empty as error:
    173                 self.log.debug(" ".join(["Test failed with Empty error:", str(
    174                     error)]))
    175                 test_result = False
    176             except concurrent.futures._base.TimeoutError as error:
    177                 self.log.debug(" ".join([
    178                     "Test failed, filtering callback onSuccess never occurred:",
    179                     str(error)
    180                 ]))
    181                 test_result = False
    182             self.adv_ad.droid.bleStopBleAdvertising(advertise_callback)
    183         return test_result
    184 
    185     @BluetoothBaseTest.bt_test_wrap
    186     def test_restart_advertise_callback_after_bt_toggle(self):
    187         """Test to reuse an advertise callback.
    188 
    189         This will verify if advertising objects can be reused after a bluetooth
    190         toggle.
    191 
    192         Steps:
    193         1. Start a advertising instance.
    194         2. Find that an onSuccess callback is triggered.
    195         3. Stop the advertising instance.
    196         4. Toggle bluetooth off and on.
    197         5. Start an advertising instance on the same objects used in step 1.
    198         6. Find that an onSuccess callback is triggered.
    199 
    200         Expected Result:
    201         Advertisement should start successfully.
    202 
    203         Returns:
    204           Pass if True
    205           Fail if False
    206 
    207         TAGS: LE, Advertising, Stress
    208         Priority: 1
    209         """
    210         test_result = True
    211         advertise_callback, advertise_data, advertise_settings = generate_ble_advertise_objects(
    212             self.adv_ad.droid)
    213         self.adv_ad.droid.bleStartBleAdvertising(
    214             advertise_callback, advertise_data, advertise_settings)
    215         expected_advertise_event_name = "".join(["BleAdvertise", str(
    216             advertise_callback), "onSuccess"])
    217         worker = self.adv_ad.ed.handle_event(
    218             self.bleadvertise_verify_onsuccess_handler,
    219             expected_advertise_event_name, ([]), self.default_timeout)
    220         try:
    221             self.log.debug(worker.result(self.default_timeout))
    222         except Empty as error:
    223             self.log.debug(" ".join(["Test failed with Empty error:", str(
    224                 error)]))
    225             test_result = False
    226         except concurrent.futures._base.TimeoutError as error:
    227             self.log.debug(" ".join(
    228                 ["Test failed, filtering callback onSuccess never occurred:",
    229                  str(error)]))
    230         test_result = reset_bluetooth([self.scn_ad])
    231         if not test_result:
    232             return test_result
    233         time.sleep(5)
    234         self.adv_ad.droid.bleStartBleAdvertising(
    235             advertise_callback, advertise_data, advertise_settings)
    236         worker = self.adv_ad.ed.handle_event(
    237             self.bleadvertise_verify_onsuccess_handler,
    238             expected_advertise_event_name, ([]), self.default_timeout)
    239         try:
    240             self.log.debug(worker.result(self.default_timeout))
    241         except Empty as error:
    242             self.log.debug(" ".join(["Test failed with Empty error:", str(
    243                 error)]))
    244             test_result = False
    245         except concurrent.futures._base.TimeoutError as error:
    246             self.log.debug(" ".join(
    247                 ["Test failed, filtering callback onSuccess never occurred:",
    248                  str(error)]))
    249         return test_result
    250 
    251     @BluetoothBaseTest.bt_test_wrap
    252     def test_restart_scan_callback_after_bt_toggle(self):
    253         """Test to reuse an scan callback.
    254 
    255         This will verify if scan objects can be reused after a bluetooth
    256         toggle.
    257 
    258         Steps:
    259         1. Start a scanning instance.
    260         3. Stop the scanning instance.
    261         4. Toggle bluetooth off and on.
    262         5. Start an scanning instance on the same objects used in step 1.
    263 
    264         Expected Result:
    265         Scanner should start successfully.
    266 
    267         Returns:
    268           Pass if True
    269           Fail if False
    270 
    271         TAGS: LE, Scanning, Stress
    272         Priority: 1
    273         """
    274         test_result = True
    275         filter_list, scan_settings, scan_callback = generate_ble_scan_objects(
    276             self.scn_ad.droid)
    277         self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
    278                                           scan_callback)
    279         reset_bluetooth([self.scn_ad])
    280         self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
    281                                           scan_callback)
    282         return test_result
    283 
    284     @BluetoothBaseTest.bt_test_wrap
    285     def test_le_pairing(self):
    286         """Test LE pairing transport stress
    287 
    288         This will test LE pairing between two android devices.
    289 
    290         Steps:
    291         1. Start an LE advertisement on secondary device.
    292         2. Find address from primary device.
    293         3. Discover and bond to LE address.
    294         4. Stop LE advertisement on secondary device.
    295         5. Repeat steps 1-4 100 times
    296 
    297         Expected Result:
    298         LE pairing should pass 100 times.
    299 
    300         Returns:
    301           Pass if True
    302           Fail if False
    303 
    304         TAGS: LE, Scanning, Stress, Pairing
    305         Priority: 1
    306         """
    307         iterations = 100
    308         for i in range(iterations):
    309             try:
    310                 target_address, adv_callback = get_mac_address_of_generic_advertisement(
    311                     self.scn_ad, self.adv_ad)
    312             except BtTestUtilsError as err:
    313                 self.log.error(err)
    314                 return False
    315             self.log.info("Begin interation {}/{}".format(i + 1, iterations))
    316             self.scn_ad.droid.bluetoothStartPairingHelper()
    317             self.adv_ad.droid.bluetoothStartPairingHelper()
    318             start_time = self.start_timer()
    319             self.scn_ad.droid.bluetoothDiscoverAndBond(target_address)
    320             if not self._verify_successful_bond(target_address):
    321                 self.log.error("Failed to bond devices.")
    322                 return False
    323             self.log.info("Total time (ms): {}".format(self.end_timer()))
    324             if not clear_bonded_devices(self.scn_ad):
    325                 self.log.error("Failed to unbond device from scanner.")
    326                 return False
    327             if not clear_bonded_devices(self.adv_ad):
    328                 self.log.error("Failed to unbond device from advertiser.")
    329                 return False
    330             self.adv_ad.droid.bleStopBleAdvertising(adv_callback)
    331             # Magic sleep to let unbonding finish
    332             time.sleep(2)
    333         return True
    334