# Copyright 2018, The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This function returns devices recognised by adb. _fetch_adb_devices() { while read dev; do echo $dev | awk '{print $1}'; done < <(adb devices | egrep -v "^List|^$"||true) } # This function returns all paths contain TEST_MAPPING. _fetch_test_mapping_files() { [[ -z $ANDROID_BUILD_TOP ]] && return 0 find -maxdepth 5 -type f -name TEST_MAPPING |sed 's/^.\///g'| xargs dirname 2>/dev/null } function _pip_install() { _deb_installer python3-venv python3-pip || return 1 _activate_venv || return 1 requirements=(venv pyinstrument snakeviz) for mod in "${requirements[@]}"; do if ! _has_py_module $mod; then echo "Installing $mod..." pip3 install $mod >/dev/null if [ "$?" -ne 0 ]; then echo "pip3 install $mod failure." return 1 fi fi done } function _has_py_module() { [[ -z "$1" ]] && { echo "requires a module name."; return 1; } cmd="python3 -c ' import importlib.util as ut print(0 if ut.find_spec(\"$1\") else 1) '" return $(eval "$cmd") } function _deb_installer() { [[ -z "$@" ]] && { echo "requires a package name."; return 1; } declare -a missing_pkgs for pkg in "$@"; do if ! $(dpkg -l $pkg | egrep -q '^ii'); then missing_pkgs+=($pkg) fi done if [ ${#missing_pkgs[@]} -gt 0 ]; then echo -n "$(tput setaf 3)${missing_pkgs[@]}$(tput sgr0) are required. " read -p "Do you want to procees? [N/y] " answer case "$answer" in [yY]) sudo apt install "${missing_pkgs[@]}" -y ;; *) echo "No action taken. Exiting."; return 1 ;; esac fi } function _activate_venv() { local VENV="$ANDROID_HOST_OUT/.atest_venv" [[ ! -d "$VENV" ]] && python3 -m venv "$VENV" source "$VENV/bin/activate" || { echo unable to activate venv. deactivate return 1 } } function _atest_profile_cli() { echo "_atest_profile_cli is deprecated. Use _atest_pyinstrument instead." return 1 } function _atest_pyinstrument() { local T="$ANDROID_BUILD_TOP" profile="$HOME/.atest/$(date +'%FT%H-%M-%S').pyisession" _pip_install || return 1 m atest && python3 $T/tools/asuite/atest/profiler.py pyinstrument $profile\ $ANDROID_SOONG_HOST_OUT/bin/atest-dev --no-metrics "$@" if [ "$?" -eq 0 ]; then pyinstrument -t --load $profile || deactivate fi deactivate } function _atest_profile_web() { echo _atest_profile_web is deprecated. Use _atest_cprofile_snakeviz instead. return 1 } function _atest_cprofile_snakeviz() { local T="$ANDROID_BUILD_TOP" profile="$HOME/.atest/$(date +'%F_%H-%M-%S').pstats" _pip_install || return 1 m atest && python3 $T/tools/asuite/atest/profiler.py cProfile $profile \ $ANDROID_SOONG_HOST_OUT/bin/atest-dev --no-metrics "$@" if [ "$?" -eq 0 ]; then echo "$(tput bold)Use Ctrl-C to stop.$(tput sgr0)" snakeviz $profile >/dev/null || deactivate fi deactivate } # The main tab completion function. _atest() { COMPREPLY=() local cmd=$(which $1) local cur="${COMP_WORDS[COMP_CWORD]}" local prev="${COMP_WORDS[COMP_CWORD-1]}" _get_comp_words_by_ref -n : cur prev || true if [[ "$cmd" == *prebuilts/asuite/atest/linux-x86/atest ]]; then # prebuilts/asuite/atest/linux-x86/atest is shell script wrapper around # atest-py3, which is what we should actually use. cmd=$ANDROID_BUILD_TOP/prebuilts/asuite/atest/linux-x86/atest-py3 fi case "$cur" in -*) COMPREPLY=($(compgen -W "$(unzip -p $cmd atest/atest_flag_list_for_completion.txt)" -- $cur)) ;; */*) ;; *) # Use grep instead of compgen -W because compgen -W is very slow. It takes # ~0.7 seconds for compgen to read the all_modules.txt file. # TODO(b/256228056) This fails if $cur has special characters in it COMPREPLY=($(ls | grep "^$cur"; grep "^$cur" $ANDROID_PRODUCT_OUT/all_modules.txt 2>/dev/null)) ;; esac case "$prev" in --iterations|--retry-any-failure|--rerun-until-failure) COMPREPLY=(10) ;; --list-modules|-L) # TODO: genetate the list automately when the API is available. COMPREPLY=($(compgen -W "cts vts" -- $cur)) ;; --serial|-s) local adb_devices="$(_fetch_adb_devices)" if [ -n "$adb_devices" ]; then COMPREPLY=($(compgen -W "$(_fetch_adb_devices)" -- $cur)) else # Don't complete files/dirs when there'is no devices. compopt -o nospace COMPREPLY=("") fi ;; --test-mapping|-p) local mapping_files="$(_fetch_test_mapping_files)" if [ -n "$mapping_files" ]; then COMPREPLY=($(compgen -W "$mapping_files" -- $cur)) else # Don't complete files/dirs when TEST_MAPPING wasn't found. compopt -o nospace COMPREPLY=("") fi ;; esac __ltrim_colon_completions "$cur" "$prev" || true return 0 } function _atest_main() { # Only use this in interactive mode. # Warning: below check must be "return", not "exit". "exit" won't break the # build in interactive shell(e.g VM), but will result in build breakage in # non-interactive shell(e.g docker container); therefore, using "return" # adapts both conditions. [[ ! $- =~ 'i' ]] && return 0 # Complete file/dir name first by using option "nosort". # BASH version <= 4.3 doesn't have nosort option. # Note that nosort has no effect for zsh. local _atest_comp_options="-o default -o nosort" local _atest_executables=(atest atest-dev atest-py3 _atest_pyinstrument _atest_cprofile_snakeviz) for exec in "${_atest_executables[*]}"; do complete -F _atest $_atest_comp_options $exec 2>/dev/null || \ complete -F _atest -o default $exec done function atest-src() { echo "atest-src is deprecated, use m atest && atest-dev instead" >&2 return 1 } # Use prebuilt python3 for atest-dev function atest-dev() { atest_dev="$ANDROID_SOONG_HOST_OUT/bin/atest-dev" if [ ! -f $atest_dev ]; then echo "Cannot find atest-dev. Run 'm atest' to generate one." return 1 fi PREBUILT_TOOLS_DIR="$ANDROID_BUILD_TOP/prebuilts/build-tools/path/linux-x86" PATH=$PREBUILT_TOOLS_DIR:$PATH $atest_dev "$@" } } _atest_main