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# Get testable module names from module_info.json. 16# Will return null if module_info.json doesn't exist. 17_fetch_testable_modules() { 18 [ -z $ANDROID_PRODUCT_OUT ] && { exit 0; } 19 $PYTHON - << END 20import hashlib 21import os 22import pickle 23import sys 24 25atest_dir = os.path.join(os.environ['ANDROID_BUILD_TOP'], 'tools/tradefederation/core/atest') 26sys.path.append(atest_dir) 27import module_info 28 29module_info_json = os.path.join(os.environ["ANDROID_PRODUCT_OUT"] ,"module-info.json") 30 31# TODO: This method should be implemented while making module-info.json. 32def get_serialised_filename(mod_info): 33 """Determine the serialised filename used for reading testable modules. 34 35 mod_info: the path of module-info.json. 36 37 Returns: a path string hashed with md5 of module-info.json. 38 /dev/shm/atest_e89e37a2e8e45be71567520b8579ffb8 (Linux) 39 /tmp/atest_e89e37a2e8e45be71567520b8579ffb8 (MacOSX) 40 """ 41 serial_filename = "/tmp/atest_" if sys.platform == "darwin" else "/dev/shm/atest_" 42 with open(mod_info, 'r') as mod_info_obj: 43 serial_filename += hashlib.md5(mod_info_obj.read().encode('utf-8')).hexdigest() 44 return serial_filename 45 46# TODO: This method should be implemented while making module-info.json. 47def create_serialised_file(serial_file): 48 modules = module_info.ModuleInfo().get_testable_modules() 49 with open(serial_file, 'wb') as serial_file_obj: 50 pickle.dump(modules, serial_file_obj, protocol=2) 51 52if os.path.isfile(module_info_json): 53 latest_serial_file = get_serialised_filename(module_info_json) 54 # When module-info.json changes, recreate a serialisation file. 55 if not os.path.exists(latest_serial_file): 56 create_serialised_file(latest_serial_file) 57 else: 58 with open(latest_serial_file, 'rb') as serial_file_obj: 59 print("\n".join(pickle.load(serial_file_obj))) 60else: 61 print("") 62END 63} 64 65# This function invoke get_args() and return each item 66# of the list for tab completion candidates. 67_fetch_atest_args() { 68 [ -z $ANDROID_BUILD_TOP ] && { exit 0; } 69 $PYTHON - << END 70import os 71import sys 72 73atest_dir = os.path.join(os.environ['ANDROID_BUILD_TOP'], 'tools/tradefederation/core/atest') 74sys.path.append(atest_dir) 75 76import atest_arg_parser 77 78parser = atest_arg_parser.AtestArgParser() 79parser.add_atest_args() 80print("\n".join(parser.get_args())) 81END 82} 83 84# This function returns devices recognised by adb. 85_fetch_adb_devices() { 86 while read dev; do echo $dev | awk '{print $1}'; done < <(adb devices | egrep -v "^List|^$"||true) 87} 88 89# This function returns all paths contain TEST_MAPPING. 90_fetch_test_mapping_files() { 91 find -maxdepth 5 -type f -name TEST_MAPPING |sed 's/^.\///g'| xargs dirname 2>/dev/null 92} 93 94# The main tab completion function. 95_atest() { 96 # Not support completion on Darwin since the bash version of it 97 # is too old to fully support useful built-in commands/functions 98 # such as compopt, _get_comp_words_by_ref and __ltrim_colon_completions. 99 [[ "$(uname -s)" == "Darwin" ]] && return 0 100 101 local cur prev 102 COMPREPLY=() 103 cur="${COMP_WORDS[COMP_CWORD]}" 104 prev="${COMP_WORDS[COMP_CWORD-1]}" 105 _get_comp_words_by_ref -n : cur prev || true 106 107 case "$cur" in 108 -*) 109 COMPREPLY=($(compgen -W "$(_fetch_atest_args)" -- $cur)) 110 ;; 111 */*) 112 ;; 113 *) 114 local candidate_args=$(ls; _fetch_testable_modules) 115 COMPREPLY=($(compgen -W "$candidate_args" -- $cur)) 116 ;; 117 esac 118 119 case "$prev" in 120 --generate-baseline|--generate-new-metrics) 121 COMPREPLY=(5) ;; 122 --list-modules|-L) 123 # TODO: genetate the list automately when the API is availble. 124 COMPREPLY=($(compgen -W "cts vts" -- $cur)) ;; 125 --serial|-s) 126 local adb_devices="$(_fetch_adb_devices)" 127 if [ -n "$adb_devices" ]; then 128 COMPREPLY=($(compgen -W "$(_fetch_adb_devices)" -- $cur)) 129 else 130 # Don't complete files/dirs when there'is no devices. 131 compopt -o nospace 132 COMPREPLY=("") 133 fi ;; 134 --test-mapping|-p) 135 local mapping_files="$(_fetch_test_mapping_files)" 136 if [ -n "$mapping_files" ]; then 137 COMPREPLY=($(compgen -W "$mapping_files" -- $cur)) 138 else 139 # Don't complete files/dirs when TEST_MAPPING wasn't found. 140 compopt -o nospace 141 COMPREPLY=("") 142 fi ;; 143 esac 144 __ltrim_colon_completions "$cur" "$prev" || true 145 return 0 146} 147 148function _atest_main() { 149 # Only use this in interactive mode. 150 [[ ! $- =~ 'i' ]] && return 0 151 152 # Use Py2 as the default interpreter. This script is aiming for being 153 # compatible with both Py2 and Py3. 154 PYTHON= 155 if [ -x "$(which python2)" ]; then 156 PYTHON=$(which python2) 157 elif [ -x "$(which python3)" ]; then 158 PYTHON=$(which python3) 159 else 160 PYTHON="/usr/bin/env python" 161 fi 162 163 # Complete file/dir name first by using option "nosort". 164 # BASH version <= 4.3 doesn't have nosort option. 165 # Note that nosort has no effect for zsh. 166 local _atest_comp_options="-o default -o nosort" 167 local _atest_executables=(atest atest-dev atest-src) 168 for exec in "${_atest_executables[*]}"; do 169 complete -F _atest $_atest_comp_options $exec 2>/dev/null || \ 170 complete -F _atest -o default $exec 171 done 172 173 # Install atest-src for the convenience of debugging. 174 local atest_src="$(gettop)/tools/tradefederation/core/atest/atest.py" 175 [[ -f "$atest_src" ]] && alias atest-src="$atest_src" 176} 177 178_atest_main 179