Loading android/pandora/test/Android.bp +13 −1 Original line number Diff line number Diff line Loading @@ -28,10 +28,22 @@ python_test_host { "libavatar", "bumble_services_experimental-python", ], required: ["PandoraServer"], required: ["PandoraServer", "aapt"], test_suites: ["general-tests"], test_options: { unit_test: false, }, data: ["config.yml"], } sh_binary_host { name: "avatar.sh", src: "avatar.sh", required: [ "avatar", "pandora-python-gen-src", "pandora_experimental-python-gen-src", "tradefed", "tradefed-test-framework", ] } android/pandora/test/AndroidTest.xml +9 −5 Original line number Diff line number Diff line Loading @@ -15,24 +15,28 @@ ~ limitations under the License. --> <configuration description="Avatar tests."> <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"> <option name="force-root" value="true"/> </target_preparer> <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> <option name="test-file-name" value="PandoraServer.apk" /> <option name="install-arg" value="-r" /> <option name="install-arg" value="-g" /> </target_preparer> <target_preparer class="com.android.tradefed.targetprep.RunHostCommandTargetPreparer"> <option name="host-setup-command" value="adb -s $SERIAL forward tcp:7300 tcp:6211" /> <option name="host-setup-command" value="adb -s $SERIAL forward tcp:6211 tcp:6211" /> <option name="host-background-command" value="adb -s $SERIAL shell nc -L -p 6211 nc 192.168.97.1 7300" /> <option name="host-teardown-command" value="adb -s $SERIAL forward --remove tcp:7300" /> <option name="host-teardown-command" value="adb -s $SERIAL forward --remove tcp:6211" /> </target_preparer> <target_preparer class="com.android.tradefed.targetprep.PythonVirtualenvPreparer"> <option name="dep-module" value="grpcio" /> <option name="dep-module" value="cryptography" /> <option name="dep-module" value="grpcio==1.51.1" /> <option name="dep-module" value="cryptography==35" /> <option name="dep-module" value="appdirs==1.4.4" /> </target_preparer> <test class="com.android.tradefed.testtype.mobly.MoblyBinaryHostTest"> <option name="mobly-par-file-name" value="avatar" /> <option name="mobly-config-file-name" value="config.yml" /> <option name="mobly-test-timeout" value="1800000" /> <option name="test-bed" value="android.bumble" /> </test> </configuration> android/pandora/test/asha_test.py +15 −51 Original line number Diff line number Diff line Loading @@ -14,11 +14,9 @@ import asyncio import logging from typing import List, Optional, Tuple import time from avatar import PandoraDevices from avatar import parameterized from avatar import PandoraDevices, parameterized from avatar.aio import asynchronous from avatar.bumble_server.security import PairingDelegate from avatar.pandora_client import BumblePandoraClient, PandoraClient Loading @@ -26,20 +24,10 @@ from bumble.gatt import GATT_ASHA_SERVICE from mobly import base_test, test_runner from mobly.asserts import assert_equal # type: ignore from mobly.asserts import assert_in # type: ignore from pandora.host_pb2 import ( RANDOM, PUBLIC, AdvertiseResponse, Connection, DataTypes, OwnAddressType, ScanningResponse, ) from pandora.security_pb2 import ( LE_LEVEL3, LESecurityLevel ) from pandora._utils import Stream from pandora.host_pb2 import PUBLIC, RANDOM, AdvertiseResponse, Connection, DataTypes, OwnAddressType, ScanningResponse from pandora.security_pb2 import LE_LEVEL3, LESecurityLevel from typing import List, Optional, Tuple ASHA_UUID = GATT_ASHA_SERVICE.to_hex_str() HISYCNID: List[int] = [0x01, 0x02, 0x03, 0x04, 0x5, 0x6, 0x7, 0x8] Loading @@ -54,7 +42,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] def setup_class(self) -> None: self.devices = PandoraDevices(self) dut, ref = self.devices dut, ref, *_ = self.devices assert isinstance(ref, BumblePandoraClient) self.dut, self.ref = dut, ref Loading Loading @@ -91,13 +79,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] :return: ScanningResponse for ASHA """ scan_result = self.dut.host.Scan(own_address_type=dut_address_type) ref = next( ( x for x in scan_result if ASHA_UUID in x.data.incomplete_service_class_uuids16 ) ) ref = next((x for x in scan_result if ASHA_UUID in x.data.incomplete_service_class_uuids16)) scan_result.cancel() assert ref Loading @@ -111,9 +93,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] :return: a Tuple (DUT to REF connection, REF to DUT connection) """ # DUT connects to Ref dut_ref = self.dut.host.ConnectLE( own_address_type=dut_address_type, **ref.address_asdict() ).connection dut_ref = self.dut.host.ConnectLE(own_address_type=dut_address_type, **ref.address_asdict()).connection ref_dut = (next(advertisement)).connection assert dut_ref assert ref_dut Loading Loading @@ -207,9 +187,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] assert dut_ref # DUT starts pairing with the Ref. secure = self.dut.security.Secure( connection=dut_ref, le=LE_LEVEL3 ) secure = self.dut.security.Secure(connection=dut_ref, le=LE_LEVEL3) assert_equal(secure.WhichOneof("result"), "success") Loading @@ -235,9 +213,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] dut_ref, ref_dut = self.dut_connect_to_ref(advertisement, ref, dut_address_type) secure = self.dut.security.Secure( connection=dut_ref, le=LESecurityLevel.LE_LEVEL3 ) secure = self.dut.security.Secure(connection=dut_ref, le=LESecurityLevel.LE_LEVEL3) assert_equal(secure.WhichOneof("result"), "success") self.dut.host.Disconnect(dut_ref) Loading @@ -250,20 +226,14 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] self.dut.security_storage.DeleteBond(random=self.ref.random_address) # DUT connect to REF again dut_ref = ( self.dut.host.ConnectLE( own_address_type=dut_address_type, **ref.address_asdict() ) ).connection dut_ref = (self.dut.host.ConnectLE(own_address_type=dut_address_type, **ref.address_asdict())).connection # TODO very likely there is a bug in android here logging.debug("result should come out") advertisement.cancel() assert dut_ref secure = self.dut.security.Secure( connection=dut_ref, le=LESecurityLevel.LE_LEVEL3 ) secure = self.dut.security.Secure(connection=dut_ref, le=LESecurityLevel.LE_LEVEL3) assert_equal(secure.WhichOneof("result"), "success") Loading @@ -271,9 +241,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] (RANDOM, RANDOM), (RANDOM, PUBLIC), ) # type: ignore[misc] def test_connection( self, dut_address_type: OwnAddressType, ref_address_type: OwnAddressType ) -> None: def test_connection(self, dut_address_type: OwnAddressType, ref_address_type: OwnAddressType) -> None: """ DUT discovers Ref. DUT initiates connection to Ref. Loading Loading @@ -372,17 +340,13 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = self.dut_scan_for_asha(dut_address_type=dut_address_type) # manually connect and not cancel advertisement dut_ref = self.dut.host.ConnectLE( own_address_type=dut_address_type, **ref.address_asdict() ).connection dut_ref = self.dut.host.ConnectLE(own_address_type=dut_address_type, **ref.address_asdict()).connection ref_dut = next(advertisement).connection assert dut_ref assert ref_dut # pairing secure = self.dut.security.Secure( connection=dut_ref, le=LE_LEVEL3 ) secure = self.dut.security.Secure(connection=dut_ref, le=LE_LEVEL3) assert_equal(secure.WhichOneof("result"), "success") self.ref.host.Disconnect(connection=ref_dut) Loading android/pandora/test/avatar.sh 0 → 100755 +79 −0 Original line number Diff line number Diff line #!/usr/bin/env bash _BT_ROOT="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth" _TEST_ROOT="${_BT_ROOT}/android/pandora/test" _TEST_FILES=("${_TEST_ROOT}/main.py" "${_TEST_ROOT}/"*_test.py) _USAGE="avatar [OPTIONS] <COMMAND> ... OPTIONS: -h, --help Show this message and exit. COMMANDS: help Show this message and exit. format [FILES..] Format python test files. Files in 'p/m/B/android/pandora/test/*.py' are included by default. lint [FILES..] Lint python test files. Files in 'p/m/B/android/pandora/test/*.py' are included by default. run [OPTIONS..] Run avatar tests through tradefed. OPTIONS: (subset, see 'avatar run --help-all') --include-filter=<ClassA[#test_a]> Add a test filter in form of 'ClassA[#test_a]'. --test-bed Set mobly test bed (default is 'android.bumble'). --mobly-std-log Print mobly logs to standard outputs. --mobly-options=<'--opt-a --opt-b'> Pass additional options to mobly, like '--verbose' or '--list'. ... All other tradefed options, like '--log-level VERBOSE'. See 'avatar run --help-all' " _PANDORA_PYTHON_PATHS=( "${_BT_ROOT}/pandora/server/" "${ANDROID_BUILD_TOP}/external/pandora/avatar/" "${ANDROID_BUILD_TOP}/external/python/bumble/" "${ANDROID_BUILD_TOP}/external/python/mobly/" "${ANDROID_BUILD_TOP}/external/python/pyee/" "${ANDROID_BUILD_TOP}/out/soong/.intermediates/external/pandora/bt-test-interfaces/python/pandora-python-gen-src/gen/" "${ANDROID_BUILD_TOP}/out/soong/.intermediates/packages/modules/Bluetooth/pandora/interfaces/python/pandora_experimental-python-gen-src/gen/" ) case "$1" in 'format') shift pip install \ 'black==22.10.0' \ 'isort==5.12.0' black -S -l 119 "$@" "${_TEST_FILES[@]}" isort --profile black -l 119 --ds --lbt 1 --ca "$@" "${_TEST_FILES[@]}" ;; 'lint') shift pip install \ 'grpcio==1.51.1' \ 'protobuf==4.21.0' \ 'pyright==1.1.296' \ 'mypy==1.0' \ 'types-protobuf==4.21.0.3' export PYTHONPATH="$(IFS=:; echo "${_PANDORA_PYTHON_PATHS[*]}"):${PYTHONPATH}" pyright \ -p "${_TEST_ROOT}" \ "$@" "${_TEST_FILES[@]}" mypy \ --pretty --show-column-numbers --strict --no-warn-unused-ignores --ignore-missing-imports \ "$@" "${_TEST_FILES[@]}" ;; 'run') shift tradefed.sh \ run commandAndExit template/local_min --template:map test=avatar --log-level INFO \ "$@" ;; 'help'|'--help'|'-h') shift echo "${_USAGE}" exit 0 ;; '') echo "no command provided (try help)" echo "${_USAGE}" exit 1 ;; *) echo "$1: invalid command (try help)" echo "${_USAGE}" exit 1 ;; esac android/pandora/test/config.yml +15 −2 Original line number Diff line number Diff line --- TestBeds: - Name: ExampleTest - Name: android.bumble Controllers: AndroidDevice: '*' BumbleDevice: - transport: 'tcp-client:127.0.0.1:6211' classic_enabled: true - Name: bumble.bumble Controllers: BumbleDevice: - transport: 'tcp-client:127.0.0.1:7300' classic_enabled: true class_of_device: 2360324 keystore: 'JsonKeyStore' io_capability: display_output_only - transport: 'tcp-client:127.0.0.1:7300' classic_enabled: true class_of_device: 2360324 keystore: 'JsonKeyStore' AndroidDevice: '*' Loading
android/pandora/test/Android.bp +13 −1 Original line number Diff line number Diff line Loading @@ -28,10 +28,22 @@ python_test_host { "libavatar", "bumble_services_experimental-python", ], required: ["PandoraServer"], required: ["PandoraServer", "aapt"], test_suites: ["general-tests"], test_options: { unit_test: false, }, data: ["config.yml"], } sh_binary_host { name: "avatar.sh", src: "avatar.sh", required: [ "avatar", "pandora-python-gen-src", "pandora_experimental-python-gen-src", "tradefed", "tradefed-test-framework", ] }
android/pandora/test/AndroidTest.xml +9 −5 Original line number Diff line number Diff line Loading @@ -15,24 +15,28 @@ ~ limitations under the License. --> <configuration description="Avatar tests."> <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"> <option name="force-root" value="true"/> </target_preparer> <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> <option name="test-file-name" value="PandoraServer.apk" /> <option name="install-arg" value="-r" /> <option name="install-arg" value="-g" /> </target_preparer> <target_preparer class="com.android.tradefed.targetprep.RunHostCommandTargetPreparer"> <option name="host-setup-command" value="adb -s $SERIAL forward tcp:7300 tcp:6211" /> <option name="host-setup-command" value="adb -s $SERIAL forward tcp:6211 tcp:6211" /> <option name="host-background-command" value="adb -s $SERIAL shell nc -L -p 6211 nc 192.168.97.1 7300" /> <option name="host-teardown-command" value="adb -s $SERIAL forward --remove tcp:7300" /> <option name="host-teardown-command" value="adb -s $SERIAL forward --remove tcp:6211" /> </target_preparer> <target_preparer class="com.android.tradefed.targetprep.PythonVirtualenvPreparer"> <option name="dep-module" value="grpcio" /> <option name="dep-module" value="cryptography" /> <option name="dep-module" value="grpcio==1.51.1" /> <option name="dep-module" value="cryptography==35" /> <option name="dep-module" value="appdirs==1.4.4" /> </target_preparer> <test class="com.android.tradefed.testtype.mobly.MoblyBinaryHostTest"> <option name="mobly-par-file-name" value="avatar" /> <option name="mobly-config-file-name" value="config.yml" /> <option name="mobly-test-timeout" value="1800000" /> <option name="test-bed" value="android.bumble" /> </test> </configuration>
android/pandora/test/asha_test.py +15 −51 Original line number Diff line number Diff line Loading @@ -14,11 +14,9 @@ import asyncio import logging from typing import List, Optional, Tuple import time from avatar import PandoraDevices from avatar import parameterized from avatar import PandoraDevices, parameterized from avatar.aio import asynchronous from avatar.bumble_server.security import PairingDelegate from avatar.pandora_client import BumblePandoraClient, PandoraClient Loading @@ -26,20 +24,10 @@ from bumble.gatt import GATT_ASHA_SERVICE from mobly import base_test, test_runner from mobly.asserts import assert_equal # type: ignore from mobly.asserts import assert_in # type: ignore from pandora.host_pb2 import ( RANDOM, PUBLIC, AdvertiseResponse, Connection, DataTypes, OwnAddressType, ScanningResponse, ) from pandora.security_pb2 import ( LE_LEVEL3, LESecurityLevel ) from pandora._utils import Stream from pandora.host_pb2 import PUBLIC, RANDOM, AdvertiseResponse, Connection, DataTypes, OwnAddressType, ScanningResponse from pandora.security_pb2 import LE_LEVEL3, LESecurityLevel from typing import List, Optional, Tuple ASHA_UUID = GATT_ASHA_SERVICE.to_hex_str() HISYCNID: List[int] = [0x01, 0x02, 0x03, 0x04, 0x5, 0x6, 0x7, 0x8] Loading @@ -54,7 +42,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] def setup_class(self) -> None: self.devices = PandoraDevices(self) dut, ref = self.devices dut, ref, *_ = self.devices assert isinstance(ref, BumblePandoraClient) self.dut, self.ref = dut, ref Loading Loading @@ -91,13 +79,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] :return: ScanningResponse for ASHA """ scan_result = self.dut.host.Scan(own_address_type=dut_address_type) ref = next( ( x for x in scan_result if ASHA_UUID in x.data.incomplete_service_class_uuids16 ) ) ref = next((x for x in scan_result if ASHA_UUID in x.data.incomplete_service_class_uuids16)) scan_result.cancel() assert ref Loading @@ -111,9 +93,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] :return: a Tuple (DUT to REF connection, REF to DUT connection) """ # DUT connects to Ref dut_ref = self.dut.host.ConnectLE( own_address_type=dut_address_type, **ref.address_asdict() ).connection dut_ref = self.dut.host.ConnectLE(own_address_type=dut_address_type, **ref.address_asdict()).connection ref_dut = (next(advertisement)).connection assert dut_ref assert ref_dut Loading Loading @@ -207,9 +187,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] assert dut_ref # DUT starts pairing with the Ref. secure = self.dut.security.Secure( connection=dut_ref, le=LE_LEVEL3 ) secure = self.dut.security.Secure(connection=dut_ref, le=LE_LEVEL3) assert_equal(secure.WhichOneof("result"), "success") Loading @@ -235,9 +213,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] dut_ref, ref_dut = self.dut_connect_to_ref(advertisement, ref, dut_address_type) secure = self.dut.security.Secure( connection=dut_ref, le=LESecurityLevel.LE_LEVEL3 ) secure = self.dut.security.Secure(connection=dut_ref, le=LESecurityLevel.LE_LEVEL3) assert_equal(secure.WhichOneof("result"), "success") self.dut.host.Disconnect(dut_ref) Loading @@ -250,20 +226,14 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] self.dut.security_storage.DeleteBond(random=self.ref.random_address) # DUT connect to REF again dut_ref = ( self.dut.host.ConnectLE( own_address_type=dut_address_type, **ref.address_asdict() ) ).connection dut_ref = (self.dut.host.ConnectLE(own_address_type=dut_address_type, **ref.address_asdict())).connection # TODO very likely there is a bug in android here logging.debug("result should come out") advertisement.cancel() assert dut_ref secure = self.dut.security.Secure( connection=dut_ref, le=LESecurityLevel.LE_LEVEL3 ) secure = self.dut.security.Secure(connection=dut_ref, le=LESecurityLevel.LE_LEVEL3) assert_equal(secure.WhichOneof("result"), "success") Loading @@ -271,9 +241,7 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] (RANDOM, RANDOM), (RANDOM, PUBLIC), ) # type: ignore[misc] def test_connection( self, dut_address_type: OwnAddressType, ref_address_type: OwnAddressType ) -> None: def test_connection(self, dut_address_type: OwnAddressType, ref_address_type: OwnAddressType) -> None: """ DUT discovers Ref. DUT initiates connection to Ref. Loading Loading @@ -372,17 +340,13 @@ class ASHATest(base_test.BaseTestClass): # type: ignore[misc] ref = self.dut_scan_for_asha(dut_address_type=dut_address_type) # manually connect and not cancel advertisement dut_ref = self.dut.host.ConnectLE( own_address_type=dut_address_type, **ref.address_asdict() ).connection dut_ref = self.dut.host.ConnectLE(own_address_type=dut_address_type, **ref.address_asdict()).connection ref_dut = next(advertisement).connection assert dut_ref assert ref_dut # pairing secure = self.dut.security.Secure( connection=dut_ref, le=LE_LEVEL3 ) secure = self.dut.security.Secure(connection=dut_ref, le=LE_LEVEL3) assert_equal(secure.WhichOneof("result"), "success") self.ref.host.Disconnect(connection=ref_dut) Loading
android/pandora/test/avatar.sh 0 → 100755 +79 −0 Original line number Diff line number Diff line #!/usr/bin/env bash _BT_ROOT="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth" _TEST_ROOT="${_BT_ROOT}/android/pandora/test" _TEST_FILES=("${_TEST_ROOT}/main.py" "${_TEST_ROOT}/"*_test.py) _USAGE="avatar [OPTIONS] <COMMAND> ... OPTIONS: -h, --help Show this message and exit. COMMANDS: help Show this message and exit. format [FILES..] Format python test files. Files in 'p/m/B/android/pandora/test/*.py' are included by default. lint [FILES..] Lint python test files. Files in 'p/m/B/android/pandora/test/*.py' are included by default. run [OPTIONS..] Run avatar tests through tradefed. OPTIONS: (subset, see 'avatar run --help-all') --include-filter=<ClassA[#test_a]> Add a test filter in form of 'ClassA[#test_a]'. --test-bed Set mobly test bed (default is 'android.bumble'). --mobly-std-log Print mobly logs to standard outputs. --mobly-options=<'--opt-a --opt-b'> Pass additional options to mobly, like '--verbose' or '--list'. ... All other tradefed options, like '--log-level VERBOSE'. See 'avatar run --help-all' " _PANDORA_PYTHON_PATHS=( "${_BT_ROOT}/pandora/server/" "${ANDROID_BUILD_TOP}/external/pandora/avatar/" "${ANDROID_BUILD_TOP}/external/python/bumble/" "${ANDROID_BUILD_TOP}/external/python/mobly/" "${ANDROID_BUILD_TOP}/external/python/pyee/" "${ANDROID_BUILD_TOP}/out/soong/.intermediates/external/pandora/bt-test-interfaces/python/pandora-python-gen-src/gen/" "${ANDROID_BUILD_TOP}/out/soong/.intermediates/packages/modules/Bluetooth/pandora/interfaces/python/pandora_experimental-python-gen-src/gen/" ) case "$1" in 'format') shift pip install \ 'black==22.10.0' \ 'isort==5.12.0' black -S -l 119 "$@" "${_TEST_FILES[@]}" isort --profile black -l 119 --ds --lbt 1 --ca "$@" "${_TEST_FILES[@]}" ;; 'lint') shift pip install \ 'grpcio==1.51.1' \ 'protobuf==4.21.0' \ 'pyright==1.1.296' \ 'mypy==1.0' \ 'types-protobuf==4.21.0.3' export PYTHONPATH="$(IFS=:; echo "${_PANDORA_PYTHON_PATHS[*]}"):${PYTHONPATH}" pyright \ -p "${_TEST_ROOT}" \ "$@" "${_TEST_FILES[@]}" mypy \ --pretty --show-column-numbers --strict --no-warn-unused-ignores --ignore-missing-imports \ "$@" "${_TEST_FILES[@]}" ;; 'run') shift tradefed.sh \ run commandAndExit template/local_min --template:map test=avatar --log-level INFO \ "$@" ;; 'help'|'--help'|'-h') shift echo "${_USAGE}" exit 0 ;; '') echo "no command provided (try help)" echo "${_USAGE}" exit 1 ;; *) echo "$1: invalid command (try help)" echo "${_USAGE}" exit 1 ;; esac
android/pandora/test/config.yml +15 −2 Original line number Diff line number Diff line --- TestBeds: - Name: ExampleTest - Name: android.bumble Controllers: AndroidDevice: '*' BumbleDevice: - transport: 'tcp-client:127.0.0.1:6211' classic_enabled: true - Name: bumble.bumble Controllers: BumbleDevice: - transport: 'tcp-client:127.0.0.1:7300' classic_enabled: true class_of_device: 2360324 keystore: 'JsonKeyStore' io_capability: display_output_only - transport: 'tcp-client:127.0.0.1:7300' classic_enabled: true class_of_device: 2360324 keystore: 'JsonKeyStore' AndroidDevice: '*'