From 3d13cd1bdbfea745ed1c3d265023240b64b4e988 Mon Sep 17 00:00:00 2001 From: Eric Li Date: Wed, 31 Mar 2010 11:47:22 -0700 Subject: [PATCH] New autotest wrapper script and bash complete support. A new command line script was introduced in this CL named autotest, which is intend to replace both build_autotest.sh and run_remote_tests.sh in the future. This change list should be reviewed with http://codereview.chromium.org/1513006 http://codereview.chromium.org/1595001 all together. autotest --board x86-generic --build=all will build all client tests. autotest --board x86-generic --build=unioxbench,ltp will build enlisted client tests. autotest --board x86-generic -c client/tests/sleeptest/control -m 12.34.56.78 ... will invoke autoserv inside emerge-x86-generic cross-compiling env, and do a prebuild of the client test before it got pushed onto client host. you could also: 1. bash complete the directory/file name from autotest directory after -c or -s args. 2. supply any autoserv commandline args transparently. Note: replace build_autotest.sh/run_remotes_test.sh is only a future plan. When all the three CLs got pushed, no existing use cases should be broken. I need to change: 1. build_packages script from third_party/chromiumos-overlay/chromeos/scripts/build_packages. 2. add "enable_server_precompile: False " to third_party/autotest/files/global_config.ini to activate it. Review URL: http://codereview.chromium.org/1595001 --- autotest | 19 +++++ autotest.py | 183 ++++++++++++++++++++++++++++++++++++++++++++++++ bash_completion | 45 ++++++++++-- 3 files changed, 241 insertions(+), 6 deletions(-) create mode 100755 autotest create mode 100644 autotest.py diff --git a/autotest b/autotest new file mode 100755 index 0000000000..2838a33975 --- /dev/null +++ b/autotest @@ -0,0 +1,19 @@ +#!/bin/bash + +# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This script is a shell wrapper of autotest.py inside a chroot environment. +# Note you should/could not directly call autotest.py within the same directory. + +. "$(dirname $0)/common.sh" + +# Script must be run inside the chroot +assert_inside_chroot + +SSH_KEY=$(dirname $0)/mod_for_test_scripts/ssh_keys/testing_rsa +chmod 400 ${SSH_KEY} +export GCLIENT_ROOT +python $(dirname $0)/autotest.py $@ || die "autotest failed." + diff --git a/autotest.py b/autotest.py new file mode 100644 index 0000000000..ba1d0e2e78 --- /dev/null +++ b/autotest.py @@ -0,0 +1,183 @@ +# Copyright (c) 2010 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# A python wrapper to call autotest ebuild. +# +# DO NOT CALL THIS SCRIPT DIRECTLY, CALL src/scripts/autotest INSTEAD. + +import logging, optparse, os, subprocess, sys + + +def run(cmd): + return subprocess.call(cmd, stdout=sys.stdout, stderr=sys.stderr) + + +class MyOptionPaser(optparse.OptionParser): + """Override python's builtin OptionParser to accept any undefined args.""" + + help = False + + def _process_args(self, largs, rargs, values): + # see /usr/lib64/python2.6/optparse.py line 1414-1463 + while rargs: + arg = rargs[0] + # We handle bare "--" explicitly, and bare "-" is handled by the + # standard arg handler since the short arg case ensures that the + # len of the opt string is greater than 1. + if arg == "--": + del rargs[0] + return + elif arg[0:2] == "--": + # process a single long option (possibly with value(s)) + try: + self._process_long_opt(rargs, values) + except optparse.BadOptionError: + largs.append(arg) + elif arg[:1] == "-" and len(arg) > 1: + # process a cluster of short options (possibly with + # value(s) for the last one only) + try: + self._process_short_opts(rargs, values) + except optparse.BadOptionError: + largs.append(arg) + elif self.allow_interspersed_args: + largs.append(arg) + del rargs[0] + else: + return # stop now, leave this arg in rargs + + def print_help(self, file=None): + optparse.OptionParser.print_help(self, file) + MyOptionPaser.help = True + + +parser = MyOptionPaser() +parser.allow_interspersed_args = True + +DEFAULT_BOARD = os.environ.get('DEFAULT_BOARD', '') + +parser.add_option('--autox', dest='autox', action='store_true', + help='Build autox along with autotest.') +parser.add_option('--board', dest='board', action='store', + default=DEFAULT_BOARD, + help='The board for which you are building autotest.') +parser.add_option('--build', dest='build', action='store', + help='Only prebuild client tests, do not run.') +parser.add_option('--buildcheck', dest='buildcheck', action='store_true', + help='Fail if tests fail to build.') +parser.add_option('--jobs', dest='jobs', action='store', type=int, + default=-1, + help='How many packages to build in parallel at maximum.') +parser.add_option('--noprompt', dest='noprompt', action='store_true', + help='Prompt user when building all tests.') + + +AUTOSERV='../third_party/autotest/files/server/autoserv' +AUTOTEST_CLIENT='../third_party/autotest/files/client/bin/autotest_client' + +def parse_args_and_help(): + + def nop(_): + pass + + sys_exit = sys.exit + sys.exit = nop + options, args = parser.parse_args() + sys.exit = sys_exit + + if MyOptionPaser.help: + if options.build: + print + print 'Options inherited from autotest_client, which is used in build', + print 'only mode.' + run([AUTOTEST_CLIENT, '--help']) + else: + print + print 'Options inherited from autoserv:' + run([AUTOSERV, '--help']) + sys.exit(-1) + return options, args + + +def build_autotest(options): + environ = os.environ + if options.jobs != -1: + emerge_jobs = '--jobs=%d' % options.jobs + else: + emerge_jobs = '' + + # Decide on USE flags based on options + use_flag = environ.get('USE', '') + if not options.autox: + use_flag = use_flag + ' -autox' + if options.buildcheck: + use_flag = use_flag + ' buildcheck' + + board_blacklist_file = ('%s/src/overlays/overlay-%s/autotest-blacklist' % + (os.environ['GCLIENT_ROOT'], options.board)) + if os.path.exists(board_blacklist_file): + blacklist = [line.strip() + for line in open(board_blacklist_file).readlines()] + else: + blacklist = [] + + all_tests = 'compilebench,dbench,disktest,netperf2,ltp,unixbench' + site_tests = '../third_party/autotest/files/client/site_tests' + for site_test in os.listdir(site_tests): + test_path = os.path.join(site_tests, site_test) + if (os.path.exists(test_path) and os.path.isdir(test_path) + and site_test not in blacklist): + all_tests += ',' + site_test + + if 'all' == options.build.lower(): + if options.noprompt is not True: + print 'You want to pre-build all client tests and it may take a long', + print 'time to finish.' + print 'Are you sure you want to continue?(N/y)', + answer = sys.stdin.readline() + if 'y' != answer[0].lower(): + print 'Use --build to specify tests you like to pre-compile. ' + print 'E.g.: ./autotest --build=disktest,hardware_SAT' + sys.exit(0) + test_list = all_tests + else: + test_list = options.build + + environ['FEATURES'] = ('%s -buildpkg -collision-protect' % + environ.get('FEATURES', '')) + environ['TEST_LIST'] = test_list + environ['USE'] = use_flag + emerge_cmd = ['emerge-%s' % options.board, + 'chromeos-base/autotest'] + if emerge_jobs: + emerge_cmd.append(emerge_jobs) + status = run(emerge_cmd) + if status: + print 'build_autotest failed.' + sys.exit(status) + + +def run_autoserv(board, args): + environ = os.environ + environ['AUTOSERV_ARGS'] = ' '.join(args) + environ['FEATURES'] = ('%s -buildpkg -digest noauto' % + environ.get('FEATURES', '')) + ebuild_cmd = ['ebuild-%s' % board, + '../third_party/chromiumos-overlay/chromeos-base/' + 'autotest/autotest-0.0.1.ebuild', + 'clean', 'unpack', 'test'] + run(ebuild_cmd) + + +def main(): + options, args = parse_args_and_help() + if options.build: + build_autotest(options) + else: + run_autoserv(options.board, args) + + +if __name__ == '__main__': + main() + diff --git a/bash_completion b/bash_completion index 5b74b1f131..e114e5e4e1 100644 --- a/bash_completion +++ b/bash_completion @@ -73,17 +73,23 @@ _board_sysroots() fi } +_complete_board_sysroot_flag() +{ + COMPREPLY=() + local arg=$(_argeq --board) + if [[ ${arg} == --board=* ]]; then + COMPREPLY=( $(compgen -W "$(_board_sysroots)" -- ${arg#--board=}) ) + return 0 + fi + return 1 +} + # Completion for --board= argument for existing board sysroots # _board_sysroot() { _flag_complete && return 0 - - COMPREPLY=() - local arg=$(_argeq --board) - if [[ ${arg} == --board=* ]]; then - COMPREPLY=( $(compgen -W "$(_board_sysroots)" -- ${arg#--board=}) ) - fi + _complete_board_flag && return 0 } complete -o bashdefault -o default -F _board_sysroot \ @@ -119,6 +125,33 @@ _board_overlay() complete -o bashdefault -o default -F _board_overlay setup_board +# Completion for -c and -s argument for autotest script +_ls_autotest() { + local autotest_dir=../third_party/autotest/files + ls --color=never -dBFH ${autotest_dir}/$1* 2>/dev/null |\ + sed s/"..\/third_party\/autotest\/files\/"//g +} + +_autotest_complete() +{ + _flag_complete && return 0 + + local arg=$(_argeq -c) + if [[ ${arg} == -c=* ]]; then + COMPREPLY=($(compgen -W "$(_ls_autotest ${arg#-c=})")) + return 0 + fi + + arg=$(_argeq -s) + if [[ ${arg} == -s=* ]]; then + COMPREPLY=($(compgen -W "$(_ls_autotest ${arg#-s=})")) + return 0 + fi + + _complete_board_sysroot_flag && return 0 +} + +complete -o bashdefault -o default -o nospace -F _autotest_complete autotest ### Local Variables: ### mode: shell-script