blob: bfc7caa57eba48d50adbc5b7d53654f8f1cc9463 [file] [log] [blame]
#/usr/bin/env python3.4
#
# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""
Basic LE Stress tests.
"""
import concurrent
import pprint
import time
from queue import Empty
from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
from acts.test_utils.bt.bt_test_utils import BtTestUtilsError
from acts.test_utils.bt.bt_test_utils import clear_bonded_devices
from acts.test_utils.bt.bt_test_utils import generate_ble_advertise_objects
from acts.test_utils.bt.bt_test_utils import generate_ble_scan_objects
from acts.test_utils.bt.bt_test_utils import get_advanced_droid_list
from acts.test_utils.bt.bt_test_utils import get_mac_address_of_generic_advertisement
from acts.test_utils.bt.bt_test_utils import reset_bluetooth
from acts.test_utils.bt.bt_test_utils import scan_result
class BleStressTest(BluetoothBaseTest):
default_timeout = 10
PAIRING_TIMEOUT = 20
def __init__(self, controllers):
BluetoothBaseTest.__init__(self, controllers)
self.droid_list = get_advanced_droid_list(self.android_devices)
self.scn_ad = self.android_devices[0]
self.adv_ad = self.android_devices[1]
def teardown_test(self):
super().teardown_test()
self.log_stats()
def bleadvertise_verify_onsuccess_handler(self, event):
test_result = True
self.log.debug("Verifying onSuccess event")
self.log.debug(pprint.pformat(event))
return test_result
@BluetoothBaseTest.bt_test_wrap
def test_loop_scanning_1000(self):
"""Stress start/stop scan instances.
This test will start and stop scan instances as fast as possible. This
will guarantee that the scan instances are properly being cleaned up
when the scan is stopped.
Steps:
1. Start a scan instance.
2. Stop the scan instance.
3. Repeat steps 1-2 1000 times.
Expected Result:
Neither starting or stopping scan instances causes any failures.
Returns:
Pass if True
Fail if False
TAGS: LE, Scanning, Stress
Priority: 1
"""
test_result = True
for _ in range(1000):
filter_list, scan_settings, scan_callback = generate_ble_scan_objects(
self.scn_ad.droid)
self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
scan_callback)
self.scn_ad.droid.bleStopBleScan(scan_callback)
return test_result
@BluetoothBaseTest.bt_test_wrap
def test_loop_scanning_100_verify_no_hci_timeout(self):
"""Stress start/stop scan instances variant.
This test will start and stop scan instances with a one second timeout
in between each iteration. This testcase was added because the specific
timing combination caused hci timeouts.
Steps:
1. Start a scan instance.
2. Stop the scan instance.
3. Sleep for 1 second.
4. Repeat steps 1-3 100 times.
Expected Result:
Neither starting or stopping scan instances causes any failures.
Returns:
Pass if True
Fail if False
TAGS: LE, Scanning, Stress
Priority: 1
"""
for _ in range(self.droid_list[1]['max_advertisements']):
adv_callback, adv_data, adv_settings = generate_ble_advertise_objects(
self.adv_ad.droid)
self.adv_ad.droid.bleStartBleAdvertising(adv_callback, adv_data,
adv_settings)
for _ in range(100):
filter_list, scan_settings, scan_callback = generate_ble_scan_objects(
self.scn_ad.droid)
self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
scan_callback)
self.log.info(self.scn_ad.ed.pop_event(scan_result.format(
scan_callback)))
self.scn_ad.droid.bleStopBleScan(scan_callback)
time.sleep(1)
return True
@BluetoothBaseTest.bt_test_wrap
def test_loop_advertising_100(self):
"""Stress start/stop advertising instances.
This test will start and stop advertising instances as fast as possible.
Steps:
1. Start a advertising instance.
2. Find that an onSuccess callback is triggered.
3. Stop the advertising instance.
4. Repeat steps 1-3 100 times.
Expected Result:
Neither starting or stopping advertising instances causes any failures.
Returns:
Pass if True
Fail if False
TAGS: LE, Advertising, Stress
Priority: 1
"""
test_result = True
for _ in range(100):
advertise_callback, advertise_data, advertise_settings = generate_ble_advertise_objects(
self.adv_ad.droid)
self.adv_ad.droid.bleStartBleAdvertising(
advertise_callback, advertise_data, advertise_settings)
expected_advertise_event_name = "".join(["BleAdvertise", str(
advertise_callback), "onSuccess"])
worker = self.adv_ad.ed.handle_event(
self.bleadvertise_verify_onsuccess_handler,
expected_advertise_event_name, ([]), self.default_timeout)
try:
self.log.debug(worker.result(self.default_timeout))
except Empty as error:
self.log.debug(" ".join(["Test failed with Empty error:", str(
error)]))
test_result = False
except concurrent.futures._base.TimeoutError as error:
self.log.debug(" ".join([
"Test failed, filtering callback onSuccess never occurred:",
str(error)
]))
test_result = False
self.adv_ad.droid.bleStopBleAdvertising(advertise_callback)
return test_result
@BluetoothBaseTest.bt_test_wrap
def test_restart_advertise_callback_after_bt_toggle(self):
"""Test to reuse an advertise callback.
This will verify if advertising objects can be reused after a bluetooth
toggle.
Steps:
1. Start a advertising instance.
2. Find that an onSuccess callback is triggered.
3. Stop the advertising instance.
4. Toggle bluetooth off and on.
5. Start an advertising instance on the same objects used in step 1.
6. Find that an onSuccess callback is triggered.
Expected Result:
Advertisement should start successfully.
Returns:
Pass if True
Fail if False
TAGS: LE, Advertising, Stress
Priority: 1
"""
test_result = True
advertise_callback, advertise_data, advertise_settings = generate_ble_advertise_objects(
self.adv_ad.droid)
self.adv_ad.droid.bleStartBleAdvertising(
advertise_callback, advertise_data, advertise_settings)
expected_advertise_event_name = "".join(["BleAdvertise", str(
advertise_callback), "onSuccess"])
worker = self.adv_ad.ed.handle_event(
self.bleadvertise_verify_onsuccess_handler,
expected_advertise_event_name, ([]), self.default_timeout)
try:
self.log.debug(worker.result(self.default_timeout))
except Empty as error:
self.log.debug(" ".join(["Test failed with Empty error:", str(
error)]))
test_result = False
except concurrent.futures._base.TimeoutError as error:
self.log.debug(" ".join(
["Test failed, filtering callback onSuccess never occurred:",
str(error)]))
test_result = reset_bluetooth([self.scn_ad])
if not test_result:
return test_result
time.sleep(5)
self.adv_ad.droid.bleStartBleAdvertising(
advertise_callback, advertise_data, advertise_settings)
worker = self.adv_ad.ed.handle_event(
self.bleadvertise_verify_onsuccess_handler,
expected_advertise_event_name, ([]), self.default_timeout)
try:
self.log.debug(worker.result(self.default_timeout))
except Empty as error:
self.log.debug(" ".join(["Test failed with Empty error:", str(
error)]))
test_result = False
except concurrent.futures._base.TimeoutError as error:
self.log.debug(" ".join(
["Test failed, filtering callback onSuccess never occurred:",
str(error)]))
return test_result
@BluetoothBaseTest.bt_test_wrap
def test_restart_scan_callback_after_bt_toggle(self):
"""Test to reuse an scan callback.
This will verify if scan objects can be reused after a bluetooth
toggle.
Steps:
1. Start a scanning instance.
3. Stop the scanning instance.
4. Toggle bluetooth off and on.
5. Start an scanning instance on the same objects used in step 1.
Expected Result:
Scanner should start successfully.
Returns:
Pass if True
Fail if False
TAGS: LE, Scanning, Stress
Priority: 1
"""
test_result = True
filter_list, scan_settings, scan_callback = generate_ble_scan_objects(
self.scn_ad.droid)
self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
scan_callback)
reset_bluetooth([self.scn_ad])
self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
scan_callback)
return test_result
def _verify_successful_bond(self, target_address):
end_time = time.time() + self.PAIRING_TIMEOUT
self.log.info("Verifying devices are bonded")
while time.time() < end_time:
bonded_devices = self.scn_ad.droid.bluetoothGetBondedDevices()
if target_address in {d['address'] for d in bonded_devices}:
self.log.info("Successfully bonded to device")
return True
return False
def _get_time_in_milliseconds(self):
return int(round(time.time() * 1000))
@BluetoothBaseTest.bt_test_wrap
def test_le_pairing(self):
"""Test LE pairing transport stress
This will test LE pairing between two android devices.
Steps:
1. Start an LE advertisement on secondary device.
2. Find address from primary device.
3. Discover and bond to LE address.
4. Stop LE advertisement on secondary device.
5. Repeat steps 1-4 100 times
Expected Result:
LE pairing should pass 100 times.
Returns:
Pass if True
Fail if False
TAGS: LE, Scanning, Stress, Pairing
Priority: 1
"""
iterations = 100
for i in range(iterations):
try:
target_address, adv_callback = get_mac_address_of_generic_advertisement(
self.scn_ad, self.adv_ad)
except BtTestUtilsError as err:
self.log.error(err)
return False
self.log.info("Begin interation {}/{}".format(i + 1, iterations))
self.scn_ad.droid.bluetoothStartPairingHelper()
self.adv_ad.droid.bluetoothStartPairingHelper()
start_time = self.start_timer()
self.scn_ad.droid.bluetoothDiscoverAndBond(target_address)
if not self._verify_successful_bond(target_address):
self.log.error("Failed to bond devices.")
return False
self.log.info("Total time (ms): {}".format(self.end_timer()))
if not clear_bonded_devices(self.scn_ad):
self.log.error("Failed to unbond device from scanner.")
return False
if not clear_bonded_devices(self.adv_ad):
self.log.error("Failed to unbond device from advertiser.")
return False
self.adv_ad.droid.bleStopBleAdvertising(adv_callback)
# Magic sleep to let unbonding finish
time.sleep(2)
return True