1*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2018, The Android Open Source Project 2*c2e18aaaSAndroid Build Coastguard Worker# 3*c2e18aaaSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*c2e18aaaSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*c2e18aaaSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*c2e18aaaSAndroid Build Coastguard Worker# 7*c2e18aaaSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*c2e18aaaSAndroid Build Coastguard Worker# 9*c2e18aaaSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*c2e18aaaSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*c2e18aaaSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*c2e18aaaSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*c2e18aaaSAndroid Build Coastguard Worker# limitations under the License. 14*c2e18aaaSAndroid Build Coastguard Worker 15*c2e18aaaSAndroid Build Coastguard Worker# This function returns devices recognised by adb. 16*c2e18aaaSAndroid Build Coastguard Worker_fetch_adb_devices() { 17*c2e18aaaSAndroid Build Coastguard Worker while read dev; do echo $dev | awk '{print $1}'; done < <(adb devices | egrep -v "^List|^$"||true) 18*c2e18aaaSAndroid Build Coastguard Worker} 19*c2e18aaaSAndroid Build Coastguard Worker 20*c2e18aaaSAndroid Build Coastguard Worker# This function returns all paths contain TEST_MAPPING. 21*c2e18aaaSAndroid Build Coastguard Worker_fetch_test_mapping_files() { 22*c2e18aaaSAndroid Build Coastguard Worker [[ -z $ANDROID_BUILD_TOP ]] && return 0 23*c2e18aaaSAndroid Build Coastguard Worker find -maxdepth 5 -type f -name TEST_MAPPING |sed 's/^.\///g'| xargs dirname 2>/dev/null 24*c2e18aaaSAndroid Build Coastguard Worker} 25*c2e18aaaSAndroid Build Coastguard Worker 26*c2e18aaaSAndroid Build Coastguard Workerfunction _pip_install() { 27*c2e18aaaSAndroid Build Coastguard Worker _deb_installer python3-venv python3-pip || return 1 28*c2e18aaaSAndroid Build Coastguard Worker _activate_venv || return 1 29*c2e18aaaSAndroid Build Coastguard Worker requirements=(venv pyinstrument snakeviz) 30*c2e18aaaSAndroid Build Coastguard Worker for mod in "${requirements[@]}"; do 31*c2e18aaaSAndroid Build Coastguard Worker if ! _has_py_module $mod; then 32*c2e18aaaSAndroid Build Coastguard Worker echo "Installing $mod..." 33*c2e18aaaSAndroid Build Coastguard Worker pip3 install $mod >/dev/null 34*c2e18aaaSAndroid Build Coastguard Worker if [ "$?" -ne 0 ]; then 35*c2e18aaaSAndroid Build Coastguard Worker echo "pip3 install $mod failure." 36*c2e18aaaSAndroid Build Coastguard Worker return 1 37*c2e18aaaSAndroid Build Coastguard Worker fi 38*c2e18aaaSAndroid Build Coastguard Worker fi 39*c2e18aaaSAndroid Build Coastguard Worker done 40*c2e18aaaSAndroid Build Coastguard Worker} 41*c2e18aaaSAndroid Build Coastguard Worker 42*c2e18aaaSAndroid Build Coastguard Workerfunction _has_py_module() { 43*c2e18aaaSAndroid Build Coastguard Worker [[ -z "$1" ]] && { echo "requires a module name."; return 1; } 44*c2e18aaaSAndroid Build Coastguard Worker 45*c2e18aaaSAndroid Build Coastguard Worker cmd="python3 -c ' 46*c2e18aaaSAndroid Build Coastguard Workerimport importlib.util as ut 47*c2e18aaaSAndroid Build Coastguard Workerprint(0 if ut.find_spec(\"$1\") else 1) 48*c2e18aaaSAndroid Build Coastguard Worker'" 49*c2e18aaaSAndroid Build Coastguard Worker return $(eval "$cmd") 50*c2e18aaaSAndroid Build Coastguard Worker} 51*c2e18aaaSAndroid Build Coastguard Worker 52*c2e18aaaSAndroid Build Coastguard Workerfunction _deb_installer() { 53*c2e18aaaSAndroid Build Coastguard Worker [[ -z "$@" ]] && { echo "requires a package name."; return 1; } 54*c2e18aaaSAndroid Build Coastguard Worker 55*c2e18aaaSAndroid Build Coastguard Worker declare -a missing_pkgs 56*c2e18aaaSAndroid Build Coastguard Worker for pkg in "$@"; do 57*c2e18aaaSAndroid Build Coastguard Worker if ! $(dpkg -l $pkg | egrep -q '^ii'); then 58*c2e18aaaSAndroid Build Coastguard Worker missing_pkgs+=($pkg) 59*c2e18aaaSAndroid Build Coastguard Worker fi 60*c2e18aaaSAndroid Build Coastguard Worker done 61*c2e18aaaSAndroid Build Coastguard Worker 62*c2e18aaaSAndroid Build Coastguard Worker if [ ${#missing_pkgs[@]} -gt 0 ]; then 63*c2e18aaaSAndroid Build Coastguard Worker echo -n "$(tput setaf 3)${missing_pkgs[@]}$(tput sgr0) are required. " 64*c2e18aaaSAndroid Build Coastguard Worker read -p "Do you want to procees? [N/y] " answer 65*c2e18aaaSAndroid Build Coastguard Worker case "$answer" in 66*c2e18aaaSAndroid Build Coastguard Worker [yY]) 67*c2e18aaaSAndroid Build Coastguard Worker sudo apt install "${missing_pkgs[@]}" -y 68*c2e18aaaSAndroid Build Coastguard Worker ;; 69*c2e18aaaSAndroid Build Coastguard Worker *) 70*c2e18aaaSAndroid Build Coastguard Worker echo "No action taken. Exiting."; return 1 71*c2e18aaaSAndroid Build Coastguard Worker ;; 72*c2e18aaaSAndroid Build Coastguard Worker esac 73*c2e18aaaSAndroid Build Coastguard Worker fi 74*c2e18aaaSAndroid Build Coastguard Worker} 75*c2e18aaaSAndroid Build Coastguard Worker 76*c2e18aaaSAndroid Build Coastguard Workerfunction _activate_venv() { 77*c2e18aaaSAndroid Build Coastguard Worker local VENV="$ANDROID_HOST_OUT/.atest_venv" 78*c2e18aaaSAndroid Build Coastguard Worker [[ ! -d "$VENV" ]] && python3 -m venv "$VENV" 79*c2e18aaaSAndroid Build Coastguard Worker source "$VENV/bin/activate" || { 80*c2e18aaaSAndroid Build Coastguard Worker echo unable to activate venv. 81*c2e18aaaSAndroid Build Coastguard Worker deactivate 82*c2e18aaaSAndroid Build Coastguard Worker return 1 83*c2e18aaaSAndroid Build Coastguard Worker } 84*c2e18aaaSAndroid Build Coastguard Worker} 85*c2e18aaaSAndroid Build Coastguard Worker 86*c2e18aaaSAndroid Build Coastguard Workerfunction _atest_profile_cli() { 87*c2e18aaaSAndroid Build Coastguard Worker echo "_atest_profile_cli is deprecated. Use _atest_pyinstrument instead." 88*c2e18aaaSAndroid Build Coastguard Worker return 1 89*c2e18aaaSAndroid Build Coastguard Worker} 90*c2e18aaaSAndroid Build Coastguard Worker 91*c2e18aaaSAndroid Build Coastguard Workerfunction _atest_pyinstrument() { 92*c2e18aaaSAndroid Build Coastguard Worker local T="$ANDROID_BUILD_TOP" 93*c2e18aaaSAndroid Build Coastguard Worker profile="$HOME/.atest/$(date +'%FT%H-%M-%S').pyisession" 94*c2e18aaaSAndroid Build Coastguard Worker 95*c2e18aaaSAndroid Build Coastguard Worker _pip_install || return 1 96*c2e18aaaSAndroid Build Coastguard Worker m atest && python3 $T/tools/asuite/atest/profiler.py pyinstrument $profile\ 97*c2e18aaaSAndroid Build Coastguard Worker $ANDROID_SOONG_HOST_OUT/bin/atest-dev --no-metrics "$@" 98*c2e18aaaSAndroid Build Coastguard Worker if [ "$?" -eq 0 ]; then 99*c2e18aaaSAndroid Build Coastguard Worker pyinstrument -t --load $profile || deactivate 100*c2e18aaaSAndroid Build Coastguard Worker fi 101*c2e18aaaSAndroid Build Coastguard Worker deactivate 102*c2e18aaaSAndroid Build Coastguard Worker} 103*c2e18aaaSAndroid Build Coastguard Worker 104*c2e18aaaSAndroid Build Coastguard Workerfunction _atest_profile_web() { 105*c2e18aaaSAndroid Build Coastguard Worker echo _atest_profile_web is deprecated. Use _atest_cprofile_snakeviz instead. 106*c2e18aaaSAndroid Build Coastguard Worker return 1 107*c2e18aaaSAndroid Build Coastguard Worker} 108*c2e18aaaSAndroid Build Coastguard Worker 109*c2e18aaaSAndroid Build Coastguard Workerfunction _atest_cprofile_snakeviz() { 110*c2e18aaaSAndroid Build Coastguard Worker local T="$ANDROID_BUILD_TOP" 111*c2e18aaaSAndroid Build Coastguard Worker profile="$HOME/.atest/$(date +'%F_%H-%M-%S').pstats" 112*c2e18aaaSAndroid Build Coastguard Worker 113*c2e18aaaSAndroid Build Coastguard Worker _pip_install || return 1 114*c2e18aaaSAndroid Build Coastguard Worker m atest && python3 $T/tools/asuite/atest/profiler.py cProfile $profile \ 115*c2e18aaaSAndroid Build Coastguard Worker $ANDROID_SOONG_HOST_OUT/bin/atest-dev --no-metrics "$@" 116*c2e18aaaSAndroid Build Coastguard Worker if [ "$?" -eq 0 ]; then 117*c2e18aaaSAndroid Build Coastguard Worker echo "$(tput bold)Use Ctrl-C to stop.$(tput sgr0)" 118*c2e18aaaSAndroid Build Coastguard Worker snakeviz $profile >/dev/null || deactivate 119*c2e18aaaSAndroid Build Coastguard Worker fi 120*c2e18aaaSAndroid Build Coastguard Worker deactivate 121*c2e18aaaSAndroid Build Coastguard Worker} 122*c2e18aaaSAndroid Build Coastguard Worker 123*c2e18aaaSAndroid Build Coastguard Worker# The main tab completion function. 124*c2e18aaaSAndroid Build Coastguard Worker_atest() { 125*c2e18aaaSAndroid Build Coastguard Worker COMPREPLY=() 126*c2e18aaaSAndroid Build Coastguard Worker local cmd=$(which $1) 127*c2e18aaaSAndroid Build Coastguard Worker local cur="${COMP_WORDS[COMP_CWORD]}" 128*c2e18aaaSAndroid Build Coastguard Worker local prev="${COMP_WORDS[COMP_CWORD-1]}" 129*c2e18aaaSAndroid Build Coastguard Worker _get_comp_words_by_ref -n : cur prev || true 130*c2e18aaaSAndroid Build Coastguard Worker 131*c2e18aaaSAndroid Build Coastguard Worker if [[ "$cmd" == *prebuilts/asuite/atest/linux-x86/atest ]]; then 132*c2e18aaaSAndroid Build Coastguard Worker # prebuilts/asuite/atest/linux-x86/atest is shell script wrapper around 133*c2e18aaaSAndroid Build Coastguard Worker # atest-py3, which is what we should actually use. 134*c2e18aaaSAndroid Build Coastguard Worker cmd=$ANDROID_BUILD_TOP/prebuilts/asuite/atest/linux-x86/atest-py3 135*c2e18aaaSAndroid Build Coastguard Worker fi 136*c2e18aaaSAndroid Build Coastguard Worker 137*c2e18aaaSAndroid Build Coastguard Worker case "$cur" in 138*c2e18aaaSAndroid Build Coastguard Worker -*) 139*c2e18aaaSAndroid Build Coastguard Worker COMPREPLY=($(compgen -W "$(unzip -p $cmd atest/atest_flag_list_for_completion.txt)" -- $cur)) 140*c2e18aaaSAndroid Build Coastguard Worker ;; 141*c2e18aaaSAndroid Build Coastguard Worker */*) 142*c2e18aaaSAndroid Build Coastguard Worker ;; 143*c2e18aaaSAndroid Build Coastguard Worker *) 144*c2e18aaaSAndroid Build Coastguard Worker # Use grep instead of compgen -W because compgen -W is very slow. It takes 145*c2e18aaaSAndroid Build Coastguard Worker # ~0.7 seconds for compgen to read the all_modules.txt file. 146*c2e18aaaSAndroid Build Coastguard Worker # TODO(b/256228056) This fails if $cur has special characters in it 147*c2e18aaaSAndroid Build Coastguard Worker COMPREPLY=($(ls | grep "^$cur"; grep "^$cur" $ANDROID_PRODUCT_OUT/all_modules.txt 2>/dev/null)) 148*c2e18aaaSAndroid Build Coastguard Worker ;; 149*c2e18aaaSAndroid Build Coastguard Worker esac 150*c2e18aaaSAndroid Build Coastguard Worker 151*c2e18aaaSAndroid Build Coastguard Worker case "$prev" in 152*c2e18aaaSAndroid Build Coastguard Worker --iterations|--retry-any-failure|--rerun-until-failure) 153*c2e18aaaSAndroid Build Coastguard Worker COMPREPLY=(10) ;; 154*c2e18aaaSAndroid Build Coastguard Worker --list-modules|-L) 155*c2e18aaaSAndroid Build Coastguard Worker # TODO: genetate the list automately when the API is available. 156*c2e18aaaSAndroid Build Coastguard Worker COMPREPLY=($(compgen -W "cts vts" -- $cur)) ;; 157*c2e18aaaSAndroid Build Coastguard Worker --serial|-s) 158*c2e18aaaSAndroid Build Coastguard Worker local adb_devices="$(_fetch_adb_devices)" 159*c2e18aaaSAndroid Build Coastguard Worker if [ -n "$adb_devices" ]; then 160*c2e18aaaSAndroid Build Coastguard Worker COMPREPLY=($(compgen -W "$(_fetch_adb_devices)" -- $cur)) 161*c2e18aaaSAndroid Build Coastguard Worker else 162*c2e18aaaSAndroid Build Coastguard Worker # Don't complete files/dirs when there'is no devices. 163*c2e18aaaSAndroid Build Coastguard Worker compopt -o nospace 164*c2e18aaaSAndroid Build Coastguard Worker COMPREPLY=("") 165*c2e18aaaSAndroid Build Coastguard Worker fi ;; 166*c2e18aaaSAndroid Build Coastguard Worker --test-mapping|-p) 167*c2e18aaaSAndroid Build Coastguard Worker local mapping_files="$(_fetch_test_mapping_files)" 168*c2e18aaaSAndroid Build Coastguard Worker if [ -n "$mapping_files" ]; then 169*c2e18aaaSAndroid Build Coastguard Worker COMPREPLY=($(compgen -W "$mapping_files" -- $cur)) 170*c2e18aaaSAndroid Build Coastguard Worker else 171*c2e18aaaSAndroid Build Coastguard Worker # Don't complete files/dirs when TEST_MAPPING wasn't found. 172*c2e18aaaSAndroid Build Coastguard Worker compopt -o nospace 173*c2e18aaaSAndroid Build Coastguard Worker COMPREPLY=("") 174*c2e18aaaSAndroid Build Coastguard Worker fi ;; 175*c2e18aaaSAndroid Build Coastguard Worker esac 176*c2e18aaaSAndroid Build Coastguard Worker __ltrim_colon_completions "$cur" "$prev" || true 177*c2e18aaaSAndroid Build Coastguard Worker return 0 178*c2e18aaaSAndroid Build Coastguard Worker} 179*c2e18aaaSAndroid Build Coastguard Worker 180*c2e18aaaSAndroid Build Coastguard Workerfunction _atest_main() { 181*c2e18aaaSAndroid Build Coastguard Worker # Only use this in interactive mode. 182*c2e18aaaSAndroid Build Coastguard Worker # Warning: below check must be "return", not "exit". "exit" won't break the 183*c2e18aaaSAndroid Build Coastguard Worker # build in interactive shell(e.g VM), but will result in build breakage in 184*c2e18aaaSAndroid Build Coastguard Worker # non-interactive shell(e.g docker container); therefore, using "return" 185*c2e18aaaSAndroid Build Coastguard Worker # adapts both conditions. 186*c2e18aaaSAndroid Build Coastguard Worker [[ ! $- =~ 'i' ]] && return 0 187*c2e18aaaSAndroid Build Coastguard Worker 188*c2e18aaaSAndroid Build Coastguard Worker # Complete file/dir name first by using option "nosort". 189*c2e18aaaSAndroid Build Coastguard Worker # BASH version <= 4.3 doesn't have nosort option. 190*c2e18aaaSAndroid Build Coastguard Worker # Note that nosort has no effect for zsh. 191*c2e18aaaSAndroid Build Coastguard Worker local _atest_comp_options="-o default -o nosort" 192*c2e18aaaSAndroid Build Coastguard Worker local _atest_executables=(atest 193*c2e18aaaSAndroid Build Coastguard Worker atest-dev 194*c2e18aaaSAndroid Build Coastguard Worker atest-py3 195*c2e18aaaSAndroid Build Coastguard Worker _atest_pyinstrument 196*c2e18aaaSAndroid Build Coastguard Worker _atest_cprofile_snakeviz) 197*c2e18aaaSAndroid Build Coastguard Worker for exec in "${_atest_executables[*]}"; do 198*c2e18aaaSAndroid Build Coastguard Worker complete -F _atest $_atest_comp_options $exec 2>/dev/null || \ 199*c2e18aaaSAndroid Build Coastguard Worker complete -F _atest -o default $exec 200*c2e18aaaSAndroid Build Coastguard Worker done 201*c2e18aaaSAndroid Build Coastguard Worker 202*c2e18aaaSAndroid Build Coastguard Worker function atest-src() { 203*c2e18aaaSAndroid Build Coastguard Worker echo "atest-src is deprecated, use m atest && atest-dev instead" >&2 204*c2e18aaaSAndroid Build Coastguard Worker return 1 205*c2e18aaaSAndroid Build Coastguard Worker } 206*c2e18aaaSAndroid Build Coastguard Worker 207*c2e18aaaSAndroid Build Coastguard Worker # Use prebuilt python3 for atest-dev 208*c2e18aaaSAndroid Build Coastguard Worker function atest-dev() { 209*c2e18aaaSAndroid Build Coastguard Worker atest_dev="$ANDROID_SOONG_HOST_OUT/bin/atest-dev" 210*c2e18aaaSAndroid Build Coastguard Worker if [ ! -f $atest_dev ]; then 211*c2e18aaaSAndroid Build Coastguard Worker echo "Cannot find atest-dev. Run 'm atest' to generate one." 212*c2e18aaaSAndroid Build Coastguard Worker return 1 213*c2e18aaaSAndroid Build Coastguard Worker fi 214*c2e18aaaSAndroid Build Coastguard Worker PREBUILT_TOOLS_DIR="$ANDROID_BUILD_TOP/prebuilts/build-tools/path/linux-x86" 215*c2e18aaaSAndroid Build Coastguard Worker PATH=$PREBUILT_TOOLS_DIR:$PATH $atest_dev "$@" 216*c2e18aaaSAndroid Build Coastguard Worker } 217*c2e18aaaSAndroid Build Coastguard Worker} 218*c2e18aaaSAndroid Build Coastguard Worker 219*c2e18aaaSAndroid Build Coastguard Worker_atest_main 220