| #! /bin/bash |
| |
| YELLOW="\033[1;33m" |
| NOCOLOR="\033[0m" |
| BLUE="\033[1;34m" |
| RED="\033[1;91m" |
| |
| function happy_hedgehog { |
| echo -e "\t${BLUE}" |
| echo -e "\t ___------__" |
| echo -e "\t |\__-- /\ _-" |
| echo -e "\t |/_ __ -" |
| echo -e "\t // \ / \ /__" |
| echo -e "\t | 0 | 0 |__ --_ Gotta go fast!" |
| echo -e "\t \\____-- __ \ ___-" |
| echo -e "\t ( @ __/ / /_" |
| echo -e "\t -_____--- --_" |
| echo -e "\t // \ \\ ___-" |
| echo -e "\t //|\__/ \\ \\" |
| echo -e "\t \_-\_____/ \-\\" |
| echo -e "\t // \\--\|" |
| echo -e "\t ${RED}____${BLUE}// ||${RED}_" |
| echo -e "\t${RED} /_____\ /___\\" |
| echo -e "${NOCOLOR}" |
| } |
| |
| function sad_hedgehog { |
| echo -e "\t${BLUE}" |
| echo -e "\t ___------__" |
| echo -e "\t |\__-- /\ _-" |
| echo -e "\t |/_ __ -" |
| echo -e "\t // \ / \ /__" |
| echo -e "\t | 0 | 0 |__ --_ Gotta go sllloowwww!" |
| echo -e "\t \\____-- __ \ ___-" |
| echo -e "\t ( @ __ / /_" |
| echo -e "\t -_____--- --_" |
| echo -e "\t // \ \\ ___-" |
| echo -e "\t //|\__/ \\ \\" |
| echo -e "\t \_-\_____/ \-\\" |
| echo -e "\t // \\--\|" |
| echo -e "\t ${RED} ____${BLUE}// ||${RED}_" |
| echo -e "\t${RED} /_____\ /___\\" |
| echo -e "{$NOCOLOR}" |
| } |
| |
| PYTHON_BIN="python3.10" |
| |
| function check_environment { |
| if [[ -z "${ANDROID_BUILD_TOP}" ]] || [[ -z "${ANDROID_HOST_OUT}" ]] ; then |
| echo -e "${RED}ANDROID_BUILD_TOP${NOCOLOR} or ${RED}ANDROID_HOST_OUT${NOCOLOR} is not set for host run" |
| echo -e "Navigate to android root and run:" |
| echo -e "${YELLOW}" |
| echo -e ". build/envsetup.sh" |
| echo -e "lunch <fish>" |
| echo -e "${NOCOLOR}" |
| echo |
| exit 1 |
| fi |
| if ! [ -x "$(command -v ${PYTHON_BIN})" ] ; then |
| echo -e "${RED}You must have ${PYTHON_BIN} installed${NOCOLOR}" |
| exit 1 |
| fi |
| ${PYTHON_BIN} -m virtualenv --version |
| if [[ $? -ne 0 ]] ; then |
| echo -e "${RED}virtualenv not installed for ${PYTHON_BIN}${NOCOLOR}" |
| echo -e "${RED}Please run '${PYTHON_BIN} -m pip install virtualenv' to install it${NOCOLOR}" |
| exit 1 |
| fi |
| } |
| |
| ASHMEM_OUT="/dev/shm/out" |
| ASHMEM_DIST="${ASHMEM_OUT}/dist" |
| ASHMEM_VENV="${ASHMEM_DIST}/bluetooth_venv" |
| ASHMEM_GOTTA_GO_FAST="/dev/shm/gottagofast" |
| ASHMEM_HOST_LOGS="${ASHMEM_GOTTA_GO_FAST}/logs" |
| ASHMEM_OUT_TARGET="${ASHMEM_GOTTA_GO_FAST}/target" |
| ASHMEM_SOONG="${ASHMEM_GOTTA_GO_FAST}/out/soong" |
| CERT_HOST_LOGS="/tmp/logs/HostOnlyCert" |
| CERT_DEVICE_LOGS="TODO: Add this" |
| CERT_TEST_VENV=${ANDROID_BUILD_TOP}/out/dist/bluetooth_venv |
| OUT_TARGET="${ANDROID_BUILD_TOP}/out/target" |
| TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/host_config.yaml" |
| TEST_FILTER="--presubmit" |
| TEST_RUNNER="blueberry/tests/gd/gd_test_runner.py" |
| CPP_BUILD_TARGET="bluetooth_stack_with_facade root-canal bluetooth_packets_python3" |
| RUST_BUILD_TARGET="bluetooth_with_facades root-canal bluetooth_packets_python3 bt_topshim_facade" |
| BUILD_TARGET=$CPP_BUILD_TARGET |
| |
| CLEAN_VENV=false |
| GOTTA_GO_FAST=false |
| NUM_REPETITIONS="1" |
| SKIP_SOONG_BUILD=false |
| USE_ASHMEM_VENV=true |
| VERBOSE_MODE=false |
| DEVICE_TEST=false |
| |
| ## Verify devices connected and valid |
| DUT_SERIAL="DUT Not Set" |
| DUT_ADB="DUT Not Set" |
| DUT_NAME="DUT Not Set" |
| |
| # Used for position arguments needed for later |
| POSITIONAL=() |
| function parse_options { |
| while [[ $# -gt 0 ]] |
| do |
| key="$1" |
| case $key in |
| # This will delete the existing venv before running the test |
| # If you updated external libraries such as ACTS, you need to add this flag |
| --clean) |
| CLEAN_VENV=true |
| shift # past argument |
| ;; |
| --help) |
| echo |
| echo -e "${YELLOW}Help menu${NOCOLOR}" |
| echo -e "===================================" |
| echo -e "${BLUE} --clean${NOCOLOR}" |
| echo -e " Clean the virtul environment; use if ACTS has been updated." |
| echo -e "${BLUE} --disable-ashmem-venv${NOCOLOR}" |
| echo -e " Places the virtual environment on disk rather than in ashmem which is default." |
| echo -e "${BLUE} --gotta-go-fast${NOCOLOR}" |
| echo -e " Makes use of ashmem as best as possible for targeted speed increases." |
| echo -e "${BLUE} --device${NOCOLOR}" |
| echo -e " Run the test on the 2 real devices." |
| echo -e "${BLUE} --sl4a${NOCOLOR}" |
| echo -e " Run GD Sl4A combination tests using the default gd_sl4a config." |
| echo -e " Please install the correct SL4A build to DUT manually before running tests." |
| echo -e "${BLUE} --sl4a_sl4a${NOCOLOR}" |
| echo -e " Run SL$A combination tests using the default sl4a_sl4a config." |
| echo -e " Please install the correct SL4A build to DUT and cert manually before running tests." |
| echo -e "${BLUE} --rust${NOCOLOR}" |
| echo -e " Run the test using the rust implementation on the 2 real devices." |
| echo -e "${BLUE} --rhost${NOCOLOR}" |
| echo -e " Run the test using the rust implementation on the host." |
| echo -e "${BLUE} --repeat=<N>${NOCOLOR}" |
| echo -e " Repeat the test sequence N (int) number of times." |
| echo -e "${BLUE} --skip-soong-build${NOCOLOR}" |
| echo -e " Skips building soong targets. Use when you are just modifying simple python files." |
| echo -e "${BLUE} --test_config=<configfile>${NOCOLOR}" |
| echo -e " Override default test configuration." |
| echo -e "${BLUE} --verbose${NOCOLOR}" |
| echo -e " Displays device logs and test logs to output." |
| echo |
| echo -e "Usage: $0 [--clean|--host|--repeat=<N>|--test_config=<config>] [TestGroupName[:IndividualTestName]]" |
| echo -e " ${YELLOW}e.g." |
| echo -e " $0 --host --clean SecurityTest" |
| echo -e " $0 --host --verbose SecurityTest:test_dut_initiated_display_only_display_only ${NOCOLOR}" |
| echo |
| shift |
| exit 0 |
| ;; |
| # This will cause the bluetooth_venv to NOT be created in ashmem |
| # Using ashmem increases --clean build times by 40% (~21 seconds on my machine) |
| --disable-ashmem-venv) |
| USE_ASHMEM_VENV=false |
| shift # past argument |
| ;; |
| --gotta-go-fast) |
| GOTTA_GO_FAST=true |
| shift # past argument |
| ;; |
| --device) |
| DEVICE_TEST=true |
| TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/devices_config.yaml" |
| shift # past argument |
| ;; |
| # Repeat running the specified test cases by N times in one single setup |
| --repeat=*) |
| NUM_REPETITIONS="${key#*=}" |
| shift # past argument |
| ;; |
| --skip-soong-build) |
| SKIP_SOONG_BUILD=true |
| shift |
| ;; |
| --test_config=*) |
| TEST_CONFIG="${key#*=}" |
| shift # past argument |
| ;; |
| --rust) |
| BUILD_TARGET=$RUST_BUILD_TARGET |
| export RUST_BACKTRACE=1 |
| TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/rust_devices_config.yaml" |
| DEVICE_TEST=true |
| shift # past argument |
| ;; |
| --rhost) |
| export RUST_BACKTRACE=1 |
| BUILD_TARGET=$RUST_BUILD_TARGET |
| TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/rust_host_config.yaml" |
| shift # past argument |
| ;; |
| --sl4a) |
| TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd_sl4a/gd_sl4a_device_config.yaml" |
| TEST_RUNNER="blueberry/tests/gd_sl4a/gd_sl4a_test_runner.py" |
| DEVICE_TEST=true |
| shift # past argument |
| ;; |
| --sl4a_sl4a) |
| TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/sl4a_sl4a/sl4a_sl4a_device_config.yaml" |
| TEST_RUNNER="blueberry/tests/sl4a_sl4a/sl4a_sl4a_test_runner.py" |
| DEVICE_TEST=true |
| shift # past argument |
| ;; |
| # This will log everything to both log file and stdout |
| --verbose) |
| VERBOSE_MODE=true |
| shift # past argument |
| ;; |
| --*) # unknown argument |
| echo "$0: unrecognized argument '$1'" |
| echo "Try '$0 --help' for more information" |
| exit 1 |
| shift |
| ;; |
| *) # unknown option |
| POSITIONAL+=("$1") # save it in an array for later |
| shift # past argument |
| ;; |
| esac |
| done |
| set -- "${POSITIONAL[@]}" # restore positional parameters |
| |
| # Set the test filter |
| if [[ -n "$1" ]] ; then |
| TEST_FILTER="--tests $1" |
| fi |
| |
| INSTALL_ARGS="--reuse-libraries" |
| if [ "$CLEAN_VENV" == true ] ; then |
| echo -e "${YELLOW}Cleaning up existing virtualenv${NOCOLOR}" |
| rm -rf $CERT_TEST_VENV/* |
| rm -rf $CERT_TEST_VENV |
| mkdir -p ${CERT_TEST_VENV} |
| INSTALL_ARGS="" |
| else |
| echo -e "${YELLOW}Try to reuse existing virtualenv at ${CERT_TEST_VENV}${NOCOLOR}" |
| fi |
| |
| } |
| |
| function select_devices { |
| if [ "$DEVICE_TEST" == true ] ; then |
| RR="$(cat ${TEST_CONFIG}|grep \'CERT\\\|DUT\')" |
| if [ "$RR" != "" ]; then |
| DUT_SERIAL="$(menu-adb DUT)" |
| DUT_ADB="adb -s ${DUT_SERIAL}" |
| DUT_NAME="$(adb devices -l | grep -v "List of device" | grep ${DUT_SERIAL} | awk '{ print $6 }' | cut -d ':' -f 2)" |
| CERT_SERIAL="$(menu-adb CERT)" |
| CERT_ADB="adb -s ${CERT_SERIAL}" |
| CERT_NAME="$(adb devices -l | grep -v "List of device" | grep ${CERT_SERIAL} | awk '{ print $6 }' | cut -d ':' -f 2)" |
| |
| if [ "${CERT_SERIAL}" == "${DUT_SERIAL}" ]; then |
| echo |
| echo -e "${RED}ERROR: CERT and DUT cannot be the same device, or you only have one device connected!${NOCOLOR}" |
| echo |
| exit 1 |
| fi |
| |
| ## Set android devices in config |
| sed -i "s/'DUT'/'${DUT_SERIAL}'/g" ${TEST_CONFIG} |
| sed -i "s/'CERT'/'${CERT_SERIAL}'/g" ${TEST_CONFIG} |
| fi |
| fi |
| } |
| |
| function soong_build { |
| if [ "$CLEAN_VENV" == true ] ; then |
| $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --build-mode --"modules-in-a-dir" --dir="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system" dist $BUILD_TARGET -j $(nproc) |
| if [[ $? -ne 0 ]] ; then |
| echo -e "${RED}Failed to build ${BUILD_TARGET}${NOCOLOR}" |
| exit 1 |
| fi |
| else |
| $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --build-mode --"all-modules" --dir="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system" dist $BUILD_TARGET -j $(nproc) |
| if [[ $? -ne 0 ]] ; then |
| echo -e "${RED}Failed to build ${BUILD_TARGET}${NOCOLOR}" |
| exit 1 |
| fi |
| fi |
| } |
| |
| function setup_venv { |
| # Make venv in memory, decreases --clean build times by 40% |
| # Caveat is you lose the venv if the computer reboots |
| if [ "${USE_ASHMEM_VENV}" == true ] ; then |
| echo -e "${BLUE}Using ashmem virtual environment.${NOCOLOR}" |
| if [[ ! -L ${CERT_TEST_VENV} ]] ; then |
| echo -e "${BLUE}" |
| echo -ne "Creating ashmem dist folder..." |
| mkdir -p "${ASHMEM_VENV}" |
| # Ensure the directory doesn't exist |
| rm -rf "${CERT_TEST_VENV}" |
| echo -e "Done" |
| echo -ne "Sym linking ${ASHMEM_VENV} to ${CERT_TEST_VENV}..." |
| ln -s "${ASHMEM_VENV}" "${CERT_TEST_VENV}" |
| echo -e "Done" |
| echo -e "${NOCOLOR}" |
| fi |
| else |
| echo -e "${RED}Not using ashmem virtual environment.${NOCOLOR}" |
| if [[ -L ${CERT_TEST_VENV} ]] ; then |
| echo -e "${RED}" |
| echo -en "Removing sym link from ${ASHMEM_VENV} to ${CERT_TEST_VENV}..." |
| rm -rf ""${ASHMEM_VENV} "${CERT_TEST_VENV}" |
| echo -e "Done" |
| echo -en "Cleaning up memory..." |
| rm -rf "${ASHMEM_VENV}" |
| echo -e "Done" |
| echo -e "${NOCOLOR}" |
| fi |
| fi |
| ${PYTHON_BIN} -m virtualenv --python `which "${PYTHON_BIN}"` "${CERT_TEST_VENV}" |
| if [[ $? -ne 0 ]] ; then |
| echo -e "${RED}Error setting up virtualenv${NOCOLOR}" |
| exit 1 |
| fi |
| |
| unzip -o -q "${ANDROID_BUILD_TOP}/out/dist/bluetooth_cert_tests.zip" -d "${CERT_TEST_VENV}/sources" |
| if [[ $? -ne 0 ]] ; then |
| echo -e "${RED}Error unzipping bluetooth_cert_tests.zip${NOCOLOR}" |
| exit 1 |
| fi |
| |
| venv_common |
| } |
| |
| function incremental_venv { |
| #LINT.IfChange |
| HOST_BIN="${ANDROID_BUILD_TOP}/out/host/linux-x86/bin" |
| HOST_LIB="${ANDROID_BUILD_TOP}/out/host/linux-x86/lib64" |
| DEST_DIR="${ANDROID_BUILD_TOP}/out/dist/bluetooth_venv/sources" |
| DEST_LIB_DIR="${DEST_DIR}/lib64" |
| cp {$HOST_BIN,$DEST_DIR}/bluetooth_stack_with_facade |
| cp {$HOST_BIN,$DEST_DIR}/bluetooth_with_facades |
| cp {$HOST_BIN,$DEST_DIR}/bt_topshim_facade |
| cp {$HOST_BIN,$DEST_DIR}/root-canal |
| |
| cp {$HOST_LIB,$DEST_DIR}/bluetooth_packets_python3.so |
| |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libbase.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libbluetooth_gd.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libc++.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libchrome.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libcrypto-host.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libevent-host.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libgrpc++_unsecure.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libgrpc++.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libgrpc_wrap.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/liblog.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libssl-host.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libz-host.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libprotobuf-cpp-full.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libunwindstack.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/liblzma.so |
| cp {$HOST_LIB,$DEST_LIB_DIR}/libbacktrace.so |
| |
| i="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/setup.py" |
| cp {${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system,$DEST_DIR}${i#${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system} |
| for i in `find ${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry -name "*.py" -type f`; do |
| cp {${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system,$DEST_DIR}${i#${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system} |
| done |
| #LINT.ThenChange(../../Android.mk) |
| |
| venv_common |
| } |
| |
| function venv_common { |
| $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/sources/setup.py" --quiet build --force "${INSTALL_ARGS}") |
| if [[ $? -ne 0 ]] ; then |
| echo -e "${RED}Error building GD Python libraries${NOCOLOR}" |
| echo -e "${YELLOW}NOTE:${NOCOLOR} To build external libraries the first time, please add --clean option." |
| exit 1 |
| fi |
| |
| $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/sources/setup.py" --quiet install --skip-build --force "${INSTALL_ARGS}") |
| if [[ $? -ne 0 ]] ; then |
| echo -e "${RED}Error installing GD Python libraries${NOCOLOR}" |
| exit 1 |
| fi |
| |
| "${CERT_TEST_VENV}/bin/python" -c " |
| import bluetooth_packets_python3 as bp3 |
| bp3.BaseStruct |
| " |
| if [[ $? -ne 0 ]] ; then |
| echo -e "${RED}Setup failed as bluetooth_packets_python3 cannot be imported${NOCOLOR}" |
| exit 1 |
| fi |
| |
| if [ "${VERBOSE_MODE}" == true ] ; then |
| TEMP_CONFIG=/tmp/temp_mobly_config.yaml |
| cat "${TEST_CONFIG}" | "${CERT_TEST_VENV}/bin/python" -c " |
| import sys |
| import yaml |
| config = yaml.load(sys.stdin) |
| config['verbose_mode'] = True |
| print(yaml.dump(config)) |
| " > "${TEMP_CONFIG}" |
| TEST_CONFIG="${TEMP_CONFIG}" |
| if [[ $? -ne 0 ]] ; then |
| echo -e "${RED}Setup failed as verbose mode is chosen but cannot be enabled${NOCOLOR}" |
| exit 1 |
| fi |
| fi |
| } |
| |
| function gotta_go_fast { |
| if [ "${GOTTA_GO_FAST}" == true ] ; then |
| # Call here to explicitly note the flag is in use |
| happy_hedgehog |
| if [[ ! -L "${CERT_HOST_LOGS}" ]] ; then |
| rm -rf "${CERT_HOST_LOGS}" |
| mkdir -p "${ASHMEM_HOST_LOGS}" |
| ln -s "${ASHMEM_HOST_LOGS}" "${CERT_HOST_LOGS}" |
| fi |
| |
| if [[ ! -L "${OUT_TARGET}" ]] ; then |
| rm -rf "${OUT_TARGET}" |
| mkdir -p "${ASHMEM_OUT_TARGET}" |
| ln -s "${ASHMEM_OUT_TARGET}" "${OUT_TARGET}" |
| fi |
| else |
| if [[ -L "${CERT_HOST_LOGS}" ]] ; then |
| # Call here so we don't spam anyone not using the flag |
| sad_hedgehog |
| rm -rf "${CERT_HOST_LOGS}" |
| rm -rf "${ASHMEM_HOST_LOGS}" |
| fi |
| |
| if [[ -L "${OUT_TARGET}" ]] ; then |
| rm -rf "${OUT_TARGET}" |
| rm -rf "${ASHMEM_OUT_TARGET}" |
| fi |
| fi |
| } |
| |
| function run_tests { |
| for n in $(seq "${NUM_REPETITIONS}"); do |
| $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/sources/${TEST_RUNNER}" \ |
| "-c ${TEST_CONFIG}" "${TEST_FILTER}") |
| done |
| |
| if [ "${CLEAN_VENV}" != true ] ; then |
| echo -e "${YELLOW}NOTE:${NOCOLOR} Completed tests using existing external libraries in virtualenv." |
| echo -e "${YELLOW}NOTE:${NOCOLOR} To update external libraries, please add --clean option." |
| fi |
| } |
| |
| function menu-adb() { |
| TMP=$(adb devices -l | grep -v "List of device" | awk '{ print $1 }') |
| # TODO(optedoblivion): If the device doesn't have a name (offline), it misnames them |
| NTMP=$(adb devices -l | grep -v "List of device" | awk '{ print $6 }' | cut -d ':' -f 2) |
| SERIALS=($TMP) |
| DEVICES=($NTMP) |
| LEN=${#SERIALS[@]} |
| result=0 |
| if [ $LEN -lt 1 ]; then |
| echo -e "${YELLOW}No devices connected!${NOCOLOR}" |
| return 1 |
| fi |
| |
| if [ "$LEN" == "" ]; then |
| LEN=0 |
| fi |
| |
| answer=0 |
| |
| DEVICE_NAME="$1 device" |
| |
| if [ $LEN -gt 1 ]; then |
| echo "+-------------------------------------------------+" 1>&2 |
| echo "| Choose a ${DEVICE_NAME}: " 1>&2 |
| echo "+-------------------------------------------------+" 1>&2 |
| echo "| |" 1>&2 |
| let fixed_len=$LEN-1 |
| for i in `seq 0 $fixed_len`; |
| do |
| serial=${SERIALS[i]} |
| device=${DEVICES[i]} |
| echo "| $i) $serial $device" 1>&2 |
| ## TODO[MSB]: Find character count, fill with space and ending box wall |
| done |
| echo "| |" 1>&2 |
| echo "+-------------------------------------------------+" 1>&2 |
| echo 1>&2 |
| echo -n "Index number: " 1>&2 |
| read answer |
| fi |
| |
| if [ $answer -ge $LEN ]; then |
| echo |
| echo "Please choose a correct index!" 1>&2 |
| echo |
| return 1 |
| fi |
| |
| SERIAL=${SERIALS[$answer]} |
| echo $SERIAL |
| } |
| |
| function main { |
| check_environment |
| parse_options $@ |
| select_devices |
| if [[ "${SKIP_SOONG_BUILD}" != true ]] ; then |
| soong_build |
| fi |
| if [ "$CLEAN_VENV" == true ] ; then |
| setup_venv |
| else |
| incremental_venv |
| fi |
| gotta_go_fast |
| run_tests |
| } |
| |
| main $@ |