1#! /bin/bash 2 3YELLOW="\033[1;33m" 4NOCOLOR="\033[0m" 5BLUE="\033[1;34m" 6RED="\033[1;91m" 7 8function happy_hedgehog { 9 echo -e "\t${BLUE}" 10 echo -e "\t ___------__" 11 echo -e "\t |\__-- /\ _-" 12 echo -e "\t |/_ __ -" 13 echo -e "\t // \ / \ /__" 14 echo -e "\t | 0 | 0 |__ --_ Gotta go fast!" 15 echo -e "\t \\____-- __ \ ___-" 16 echo -e "\t ( @ __/ / /_" 17 echo -e "\t -_____--- --_" 18 echo -e "\t // \ \\ ___-" 19 echo -e "\t //|\__/ \\ \\" 20 echo -e "\t \_-\_____/ \-\\" 21 echo -e "\t // \\--\|" 22 echo -e "\t ${RED}____${BLUE}// ||${RED}_" 23 echo -e "\t${RED} /_____\ /___\\" 24 echo -e "${NOCOLOR}" 25} 26 27function sad_hedgehog { 28 echo -e "\t${BLUE}" 29 echo -e "\t ___------__" 30 echo -e "\t |\__-- /\ _-" 31 echo -e "\t |/_ __ -" 32 echo -e "\t // \ / \ /__" 33 echo -e "\t | 0 | 0 |__ --_ Gotta go sllloowwww!" 34 echo -e "\t \\____-- __ \ ___-" 35 echo -e "\t ( @ __ / /_" 36 echo -e "\t -_____--- --_" 37 echo -e "\t // \ \\ ___-" 38 echo -e "\t //|\__/ \\ \\" 39 echo -e "\t \_-\_____/ \-\\" 40 echo -e "\t // \\--\|" 41 echo -e "\t ${RED} ____${BLUE}// ||${RED}_" 42 echo -e "\t${RED} /_____\ /___\\" 43 echo -e "{$NOCOLOR}" 44} 45 46PYTHON_BIN="python3.11" 47 48function check_environment { 49 if [[ -z "${ANDROID_BUILD_TOP}" ]] || [[ -z "${ANDROID_HOST_OUT}" ]] ; then 50 echo -e "${RED}ANDROID_BUILD_TOP${NOCOLOR} or ${RED}ANDROID_HOST_OUT${NOCOLOR} is not set for host run" 51 echo -e "Navigate to android root and run:" 52 echo -e "${YELLOW}" 53 echo -e ". build/envsetup.sh" 54 echo -e "lunch <fish>" 55 echo -e "${NOCOLOR}" 56 echo 57 exit 1 58 fi 59 if ! [ -x "$(command -v ${PYTHON_BIN})" ] ; then 60 echo -e "${RED}You must have ${PYTHON_BIN} installed${NOCOLOR}" 61 exit 1 62 fi 63 ${PYTHON_BIN} -m venv -h > /dev/null 64 if [[ $? -ne 0 ]] ; then 65 echo -e "${RED}venv not available for ${PYTHON_BIN}${NOCOLOR}" 66 exit 1 67 fi 68} 69 70ASHMEM_OUT="/dev/shm/out" 71ASHMEM_DIST="${ASHMEM_OUT}/dist" 72ASHMEM_VENV="${ASHMEM_DIST}/bluetooth_venv" 73ASHMEM_GOTTA_GO_FAST="/dev/shm/gottagofast" 74ASHMEM_HOST_LOGS="${ASHMEM_GOTTA_GO_FAST}/logs" 75ASHMEM_OUT_TARGET="${ASHMEM_GOTTA_GO_FAST}/target" 76ASHMEM_SOONG="${ASHMEM_GOTTA_GO_FAST}/out/soong" 77CERT_HOST_LOGS="/tmp/logs/HostOnlyCert" 78CERT_DEVICE_LOGS="TODO: Add this" 79CERT_TEST_VENV=${ANDROID_BUILD_TOP}/out/dist/bluetooth_venv 80OUT_TARGET="${ANDROID_BUILD_TOP}/out/target" 81TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/host_config.yaml" 82TEST_FILTER="--presubmit" 83TEST_RUNNER="blueberry/tests/gd/gd_test_runner.py" 84CPP_BUILD_TARGET="bluetooth_stack_with_facade root-canal gd_hci_packets_python3_gen gd_smp_packets_python3_gen" 85RUST_BUILD_TARGET="bluetooth_with_facades root-canal bt_topshim_facade gd_hci_packets_python3_gen gd_smp_packets_python3_gen" 86BUILD_TARGET=$CPP_BUILD_TARGET 87 88CLEAN_VENV=false 89GOTTA_GO_FAST=false 90NUM_REPETITIONS="1" 91SKIP_SOONG_BUILD=false 92USE_ASHMEM_VENV=true 93VERBOSE_MODE=false 94DEVICE_TEST=false 95 96## Verify devices connected and valid 97DUT_SERIAL="DUT Not Set" 98DUT_ADB="DUT Not Set" 99DUT_NAME="DUT Not Set" 100 101# Used for position arguments needed for later 102POSITIONAL=() 103function parse_options { 104 while [[ $# -gt 0 ]] 105 do 106 key="$1" 107 case $key in 108 # This will delete the existing venv before running the test 109 # If you updated external libraries such as ACTS, you need to add this flag 110 --clean) 111 CLEAN_VENV=true 112 shift # past argument 113 ;; 114 --help) 115 echo 116 echo -e "${YELLOW}Help menu${NOCOLOR}" 117 echo -e "===================================" 118 echo -e "${BLUE} --clean${NOCOLOR}" 119 echo -e " Clean the virtul environment; use if ACTS has been updated." 120 echo -e "${BLUE} --disable-ashmem-venv${NOCOLOR}" 121 echo -e " Places the virtual environment on disk rather than in ashmem which is default." 122 echo -e "${BLUE} --gotta-go-fast${NOCOLOR}" 123 echo -e " Makes use of ashmem as best as possible for targeted speed increases." 124 echo -e "${BLUE} --device${NOCOLOR}" 125 echo -e " Run the test on the 2 real devices." 126 echo -e "${BLUE} --topshim${NOCOLOR}" 127 echo -e " Run Topshim combination tests using the default topshim config." 128 echo -e "${BLUE} --rust${NOCOLOR}" 129 echo -e " Run the test using the rust implementation on the 2 real devices." 130 echo -e "${BLUE} --rhost${NOCOLOR}" 131 echo -e " Run the test using the rust implementation on the host." 132 echo -e "${BLUE} --repeat=<N>${NOCOLOR}" 133 echo -e " Repeat the test sequence N (int) number of times." 134 echo -e "${BLUE} --skip-soong-build${NOCOLOR}" 135 echo -e " Skips building soong targets. Use when you are just modifying simple python files." 136 echo -e "${BLUE} --test_config=<configfile>${NOCOLOR}" 137 echo -e " Override default test configuration." 138 echo -e "${BLUE} --verbose${NOCOLOR}" 139 echo -e " Displays device logs and test logs to output." 140 echo 141 echo -e "Usage: $0 [--clean|--repeat=<N>|--test_config=<config>] [TestGroupName[.IndividualTestName]]" 142 echo -e " ${YELLOW}e.g." 143 echo -e " $0 --clean SecurityTest" 144 echo -e " $0 --verbose SecurityTest:test_dut_initiated_display_only_display_only ${NOCOLOR}" 145 echo 146 shift 147 exit 0 148 ;; 149 # This will cause the bluetooth_venv to NOT be created in ashmem 150 # Using ashmem increases --clean build times by 40% (~21 seconds on my machine) 151 --disable-ashmem-venv) 152 USE_ASHMEM_VENV=false 153 shift # past argument 154 ;; 155 --gotta-go-fast) 156 GOTTA_GO_FAST=true 157 shift # past argument 158 ;; 159 --device) 160 DEVICE_TEST=true 161 TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/devices_config.yaml" 162 shift # past argument 163 ;; 164 # Repeat running the specified test cases by N times in one single setup 165 --repeat=*) 166 NUM_REPETITIONS="${key#*=}" 167 shift # past argument 168 ;; 169 --skip-soong-build) 170 SKIP_SOONG_BUILD=true 171 shift 172 ;; 173 --test_config=*) 174 TEST_CONFIG="${key#*=}" 175 shift # past argument 176 ;; 177 --rust) 178 BUILD_TARGET=$RUST_BUILD_TARGET 179 export RUST_BACKTRACE=1 180 TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/rust_devices_config.yaml" 181 DEVICE_TEST=true 182 shift # past argument 183 ;; 184 --rhost) 185 export RUST_BACKTRACE=1 186 BUILD_TARGET=$RUST_BUILD_TARGET 187 TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/gd/rust_host_config.yaml" 188 shift # past argument 189 ;; 190 --topshim) 191 TEST_CONFIG="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry/tests/topshim/topshim_host_config.yaml" 192 TEST_RUNNER="blueberry/tests/topshim/topshim_test_runner.py" 193 shift 194 ;; 195 # This will log everything to both log file and stdout 196 --verbose) 197 VERBOSE_MODE=true 198 shift # past argument 199 ;; 200 --*) # unknown argument 201 echo "$0: unrecognized argument '$1'" 202 echo "Try '$0 --help' for more information" 203 exit 1 204 shift 205 ;; 206 *) # unknown option 207 POSITIONAL+=("$1") # save it in an array for later 208 shift # past argument 209 ;; 210 esac 211 done 212 set -- "${POSITIONAL[@]}" # restore positional parameters 213 214 # Set the test filter 215 if [[ -n "$1" ]] ; then 216 TEST_FILTER="--tests $1" 217 fi 218 219 INSTALL_ARGS="--reuse-libraries" 220 if [ "$CLEAN_VENV" == true ] ; then 221 echo -e "${YELLOW}Cleaning up existing virtualenv${NOCOLOR}" 222 rm -rf $CERT_TEST_VENV/* 223 rm -rf $CERT_TEST_VENV 224 mkdir -p ${CERT_TEST_VENV} 225 INSTALL_ARGS="" 226 else 227 echo -e "${YELLOW}Try to reuse existing virtualenv at ${CERT_TEST_VENV}${NOCOLOR}" 228 fi 229 230} 231 232function select_devices { 233 if [ "$DEVICE_TEST" == true ] ; then 234 RR="$(cat ${TEST_CONFIG}|grep \'CERT\\\|DUT\')" 235 if [ "$RR" != "" ]; then 236 DUT_SERIAL="$(menu-adb DUT)" 237 DUT_ADB="adb -s ${DUT_SERIAL}" 238 DUT_NAME="$(adb devices -l | grep -v "List of device" | grep ${DUT_SERIAL} | awk '{ print $6 }' | cut -d ':' -f 2)" 239 CERT_SERIAL="$(menu-adb CERT)" 240 CERT_ADB="adb -s ${CERT_SERIAL}" 241 CERT_NAME="$(adb devices -l | grep -v "List of device" | grep ${CERT_SERIAL} | awk '{ print $6 }' | cut -d ':' -f 2)" 242 243 if [ "${CERT_SERIAL}" == "${DUT_SERIAL}" ]; then 244 echo 245 echo -e "${RED}ERROR: CERT and DUT cannot be the same device, or you only have one device connected!${NOCOLOR}" 246 echo 247 exit 1 248 fi 249 250 ## Set android devices in config 251 sed -i "s/'DUT'/'${DUT_SERIAL}'/g" ${TEST_CONFIG} 252 sed -i "s/'CERT'/'${CERT_SERIAL}'/g" ${TEST_CONFIG} 253 fi 254 fi 255} 256 257function soong_build { 258 if [ "$CLEAN_VENV" == true ] ; then 259 $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) 260 if [[ $? -ne 0 ]] ; then 261 echo -e "${RED}Failed to build ${BUILD_TARGET}${NOCOLOR}" 262 exit 1 263 fi 264 else 265 $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) 266 if [[ $? -ne 0 ]] ; then 267 echo -e "${RED}Failed to build ${BUILD_TARGET}${NOCOLOR}" 268 exit 1 269 fi 270 fi 271} 272 273function setup_venv { 274 # Make venv in memory, decreases --clean build times by 40% 275 # Caveat is you lose the venv if the computer reboots 276 if [ "${USE_ASHMEM_VENV}" == true ] ; then 277 echo -e "${BLUE}Using ashmem virtual environment.${NOCOLOR}" 278 if [[ ! -L ${CERT_TEST_VENV} ]] ; then 279 echo -e "${BLUE}" 280 echo -ne "Creating ashmem dist folder..." 281 mkdir -p "${ASHMEM_VENV}" 282 # Ensure the directory doesn't exist 283 rm -rf "${CERT_TEST_VENV}" 284 echo -e "Done" 285 echo -ne "Sym linking ${ASHMEM_VENV} to ${CERT_TEST_VENV}..." 286 ln -s "${ASHMEM_VENV}" "${CERT_TEST_VENV}" 287 echo -e "Done" 288 echo -e "${NOCOLOR}" 289 fi 290 else 291 echo -e "${RED}Not using ashmem virtual environment.${NOCOLOR}" 292 if [[ -L ${CERT_TEST_VENV} ]] ; then 293 echo -e "${RED}" 294 echo -en "Removing sym link from ${ASHMEM_VENV} to ${CERT_TEST_VENV}..." 295 rm -rf ""${ASHMEM_VENV} "${CERT_TEST_VENV}" 296 echo -e "Done" 297 echo -en "Cleaning up memory..." 298 rm -rf "${ASHMEM_VENV}" 299 echo -e "Done" 300 echo -e "${NOCOLOR}" 301 fi 302 fi 303 ${PYTHON_BIN} -m venv --clear "${CERT_TEST_VENV}" 304 if [[ $? -ne 0 ]] ; then 305 echo -e "${RED}Error setting up virtualenv${NOCOLOR}" 306 exit 1 307 fi 308 309 unzip -o -q "${ANDROID_BUILD_TOP}/out/dist/bluetooth_cert_tests.zip" -d "${CERT_TEST_VENV}/sources" 310 if [[ $? -ne 0 ]] ; then 311 echo -e "${RED}Error unzipping bluetooth_cert_tests.zip${NOCOLOR}" 312 exit 1 313 fi 314 315 venv_common 316} 317 318function incremental_venv { 319#LINT.IfChange 320 HOST_BIN="${ANDROID_BUILD_TOP}/out/host/linux-x86/bin" 321 HOST_LIB="${ANDROID_BUILD_TOP}/out/host/linux-x86/lib64" 322 DEST_DIR="${ANDROID_BUILD_TOP}/out/dist/bluetooth_venv/sources" 323 DEST_LIB_DIR="${DEST_DIR}/lib64" 324 cp {$HOST_BIN,$DEST_DIR}/bluetooth_stack_with_facade 325 cp {$HOST_BIN,$DEST_DIR}/bluetooth_with_facades 326 cp {$HOST_BIN,$DEST_DIR}/bt_topshim_facade 327 cp {$HOST_BIN,$DEST_DIR}/root-canal 328 329 cp {$HOST_LIB,$DEST_LIB_DIR}/libbase.so 330 cp {$HOST_LIB,$DEST_LIB_DIR}/libbluetooth_gd.so 331 cp {$HOST_LIB,$DEST_LIB_DIR}/libc++.so 332 cp {$HOST_LIB,$DEST_LIB_DIR}/libchrome.so 333 cp {$HOST_LIB,$DEST_LIB_DIR}/libcrypto-host.so 334 cp {$HOST_LIB,$DEST_LIB_DIR}/libevent-host.so 335 cp {$HOST_LIB,$DEST_LIB_DIR}/libgrpc++.so 336 cp {$HOST_LIB,$DEST_LIB_DIR}/libgrpc_wrap.so 337 cp {$HOST_LIB,$DEST_LIB_DIR}/liblog.so 338 cp {$HOST_LIB,$DEST_LIB_DIR}/libssl-host.so 339 cp {$HOST_LIB,$DEST_LIB_DIR}/libz-host.so 340 cp {$HOST_LIB,$DEST_LIB_DIR}/libprotobuf-cpp-full.so 341 cp {$HOST_LIB,$DEST_LIB_DIR}/libunwindstack.so 342 cp {$HOST_LIB,$DEST_LIB_DIR}/liblzma.so 343 344 i="${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/setup.py" 345 cp {${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system,$DEST_DIR}${i#${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system} 346 for i in `find ${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system/blueberry -name "*.py" -type f`; do 347 cp {${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system,$DEST_DIR}${i#${ANDROID_BUILD_TOP}/packages/modules/Bluetooth/system} 348 done 349#LINT.ThenChange(../../Android.mk) 350 351 venv_common 352} 353 354function venv_common { 355 $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/sources/setup.py" --quiet build --force "${INSTALL_ARGS}") 356 if [[ $? -ne 0 ]] ; then 357 echo -e "${RED}Error building GD Python libraries${NOCOLOR}" 358 echo -e "${YELLOW}NOTE:${NOCOLOR} To build external libraries the first time, please add --clean option." 359 exit 1 360 fi 361 362 $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/sources/setup.py" --quiet install --skip-build --force "${INSTALL_ARGS}") 363 if [[ $? -ne 0 ]] ; then 364 echo -e "${RED}Error installing GD Python libraries${NOCOLOR}" 365 exit 1 366 fi 367 368if [ "${VERBOSE_MODE}" == true ] ; then 369 TEMP_CONFIG=/tmp/temp_mobly_config.yaml 370 cat "${TEST_CONFIG}" | "${CERT_TEST_VENV}/bin/python" -c " 371import sys 372import yaml 373config = yaml.load(sys.stdin) 374config['verbose_mode'] = True 375print(yaml.dump(config)) 376 " > "${TEMP_CONFIG}" 377 TEST_CONFIG="${TEMP_CONFIG}" 378 if [[ $? -ne 0 ]] ; then 379 echo -e "${RED}Setup failed as verbose mode is chosen but cannot be enabled${NOCOLOR}" 380 exit 1 381 fi 382fi 383} 384 385function gotta_go_fast { 386 if [ "${GOTTA_GO_FAST}" == true ] ; then 387 # Call here to explicitly note the flag is in use 388 happy_hedgehog 389 if [[ ! -L "${CERT_HOST_LOGS}" ]] ; then 390 rm -rf "${CERT_HOST_LOGS}" 391 mkdir -p "${ASHMEM_HOST_LOGS}" 392 ln -s "${ASHMEM_HOST_LOGS}" "${CERT_HOST_LOGS}" 393 fi 394 395 if [[ ! -L "${OUT_TARGET}" ]] ; then 396 rm -rf "${OUT_TARGET}" 397 mkdir -p "${ASHMEM_OUT_TARGET}" 398 ln -s "${ASHMEM_OUT_TARGET}" "${OUT_TARGET}" 399 fi 400 else 401 if [[ -L "${CERT_HOST_LOGS}" ]] ; then 402 # Call here so we don't spam anyone not using the flag 403 sad_hedgehog 404 rm -rf "${CERT_HOST_LOGS}" 405 rm -rf "${ASHMEM_HOST_LOGS}" 406 fi 407 408 if [[ -L "${OUT_TARGET}" ]] ; then 409 rm -rf "${OUT_TARGET}" 410 rm -rf "${ASHMEM_OUT_TARGET}" 411 fi 412 fi 413} 414 415function run_tests { 416 for n in $(seq "${NUM_REPETITIONS}"); do 417 $(echo "${CERT_TEST_VENV}/bin/python" "${CERT_TEST_VENV}/sources/${TEST_RUNNER}" \ 418 "-c ${TEST_CONFIG}" "${TEST_FILTER}") 419 done 420 421 if [ "${CLEAN_VENV}" != true ] ; then 422 echo -e "${YELLOW}NOTE:${NOCOLOR} Completed tests using existing external libraries in virtualenv." 423 echo -e "${YELLOW}NOTE:${NOCOLOR} To update external libraries, please add --clean option." 424 fi 425} 426 427function menu-adb() { 428 TMP=$(adb devices -l | grep -v "List of device" | awk '{ print $1 }') 429 # TODO(optedoblivion): If the device doesn't have a name (offline), it misnames them 430 NTMP=$(adb devices -l | grep -v "List of device" | awk '{ print $6 }' | cut -d ':' -f 2) 431 SERIALS=($TMP) 432 DEVICES=($NTMP) 433 LEN=${#SERIALS[@]} 434 result=0 435 if [ $LEN -lt 1 ]; then 436 echo -e "${YELLOW}No devices connected!${NOCOLOR}" 437 return 1 438 fi 439 440 if [ "$LEN" == "" ]; then 441 LEN=0 442 fi 443 444 answer=0 445 446 DEVICE_NAME="$1 device" 447 448 if [ $LEN -gt 1 ]; then 449 echo "+-------------------------------------------------+" 1>&2 450 echo "| Choose a ${DEVICE_NAME}: " 1>&2 451 echo "+-------------------------------------------------+" 1>&2 452 echo "| |" 1>&2 453 let fixed_len=$LEN-1 454 for i in `seq 0 $fixed_len`; 455 do 456 serial=${SERIALS[i]} 457 device=${DEVICES[i]} 458 echo "| $i) $serial $device" 1>&2 459 ## TODO[MSB]: Find character count, fill with space and ending box wall 460 done 461 echo "| |" 1>&2 462 echo "+-------------------------------------------------+" 1>&2 463 echo 1>&2 464 echo -n "Index number: " 1>&2 465 read answer 466 fi 467 468 if [ $answer -ge $LEN ]; then 469 echo 470 echo "Please choose a correct index!" 1>&2 471 echo 472 return 1 473 fi 474 475 SERIAL=${SERIALS[$answer]} 476 echo $SERIAL 477} 478 479function main { 480 check_environment 481 parse_options $@ 482 select_devices 483 if [[ "${SKIP_SOONG_BUILD}" != true ]] ; then 484 soong_build 485 fi 486 if [ "$CLEAN_VENV" == true ] ; then 487 setup_venv 488 else 489 incremental_venv 490 fi 491 gotta_go_fast 492 run_tests 493} 494 495main $@ 496