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