From 6089e491ed3c067074c27a62bd0a339117cf752f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 9 Nov 2011 16:15:53 +1100 Subject: [PATCH] autotest: improved error checking and child termination we now report pass/fail for each test --- Tools/autotest/arducopter.py | 5 +- Tools/autotest/autotest.py | 88 ++++++++++++++++++++++++++++-------- Tools/autotest/util.py | 29 ++++++++++-- 3 files changed, 95 insertions(+), 27 deletions(-) diff --git a/Tools/autotest/arducopter.py b/Tools/autotest/arducopter.py index d5c6467db4..9dc8e662d1 100644 --- a/Tools/autotest/arducopter.py +++ b/Tools/autotest/arducopter.py @@ -287,6 +287,7 @@ def fly_ArduCopter(): # start hil_quad.py hquad = pexpect.spawn(util.reltopdir('../HILTest/hil_quad.py') + ' --fgout=192.168.2.15:9123 --home=%s' % HOME_LOCATION, logfile=sys.stdout, timeout=10) + util.pexpect_autoclose(hquad) hquad.expect('Starting at') expect_list.extend([hquad, sil, mavproxy]) @@ -325,5 +326,5 @@ def fly_ArduCopter(): if failed: print("FAILED: %s" % e) - sys.exit(1) - + return False + return True diff --git a/Tools/autotest/autotest.py b/Tools/autotest/autotest.py index 04227437b0..b3133a5c23 100755 --- a/Tools/autotest/autotest.py +++ b/Tools/autotest/autotest.py @@ -3,7 +3,7 @@ # Andrew Tridgell, October 2011 import pexpect, os, util, sys, shutil, arducopter -import optparse, fnmatch +import optparse, fnmatch, time os.putenv('TMPDIR', util.reltopdir('tmp')) @@ -25,7 +25,7 @@ def get_default_params(atype): util.pexpect_close(mavproxy) util.pexpect_close(sil) print("Saved defaults for %s to %s" % (atype, dest)) - + return True def dump_logs(atype): '''dump DataFlash logs''' @@ -48,6 +48,7 @@ def dump_logs(atype): util.pexpect_close(sil) log.close() print("Saved log for %s to %s" % (atype, logfile)) + return True def test_prerequesites(): '''check we have the right directories and tools to run tests''' @@ -60,6 +61,8 @@ You need to install HILTest in %s You can get it from git://git.samba.org/tridge/UAV/HILTest.git ''' % util.reltopdir('../HILTest')) + return False + return True ############## main program ############# @@ -70,9 +73,14 @@ parser.add_option("--list", action='store_true', default=False, help='list the a opts, args = parser.parse_args() steps = [ + 'prerequesites', + 'build1280.ArduPlane', + 'build2560.ArduPlane', 'build.ArduPlane', 'defaults.ArduPlane', 'logs.ArduPlane', + 'build1280.ArduCopter', + 'build2560.ArduCopter', 'build.ArduCopter', 'defaults.ArduCopter', 'fly.ArduCopter', @@ -88,34 +96,74 @@ def skip_step(step): return True return False +def run_step(step): + '''run one step''' + if step == "prerequesites": + return test_prerequesites() + + if step == 'build.ArduPlane': + return util.build_SIL('ArduPlane') + + if step == 'build.ArduCopter': + return util.build_SIL('ArduCopter') + + if step == 'build1280.ArduCopter': + return util.build_AVR('ArduCopter', board='mega') + + if step == 'build2560.ArduCopter': + return util.build_AVR('ArduCopter', board='mega2560') + + if step == 'build1280.ArduPlane': + return util.build_AVR('ArduPlane', board='mega') + + if step == 'build2560.ArduPlane': + return util.build_AVR('ArduPlane', board='mega2560') + + if step == 'defaults.ArduPlane': + return get_default_params('ArduPlane') + + if step == 'defaults.ArduCopter': + return get_default_params('ArduCopter') + + if step == 'logs.ArduPlane': + return dump_logs('ArduPlane') + + if step == 'logs.ArduCopter': + return dump_logs('ArduCopter') + + if step == 'fly.ArduCopter': + return arducopter.fly_ArduCopter() + + raise RuntimeError("Unknown step %s" % step) + + def run_tests(steps): '''run a list of steps''' - test_prerequesites() + passed = True for step in steps: if skip_step(step): continue - if step == 'build.ArduPlane': - util.build_SIL('ArduPlane') - elif step == 'build.ArduCopter': - util.build_SIL('ArduCopter') - elif step == 'defaults.ArduPlane': - get_default_params('ArduPlane') - elif step == 'defaults.ArduCopter': - get_default_params('ArduCopter') - elif step == 'logs.ArduPlane': - dump_logs('ArduPlane') - elif step == 'logs.ArduCopter': - dump_logs('ArduCopter') - elif step == 'fly.ArduCopter': - arducopter.fly_ArduCopter() - else: - raise RuntimeError("Unknown step %s" % step) + + print(">>>> RUNNING STEP: %s at %s" % (step, time.asctime())) + try: + if not run_step(step): + print(">>>> FAILED STEP: %s at %s" % (step, time.asctime())) + passed = False + continue + except Exception, msg: + passed = False + print(">>>> FAILED STEP: %s at %s (%s)" % (step, time.asctime(), msg)) + continue + print(">>>> PASSED STEP: %s at %s" % (step, time.asctime())) + return passed try: - run_tests(steps) + if not run_tests(steps): + sys.exit(1) except KeyboardInterrupt: util.pexpect_close_all() + sys.exit(1) except Exception: # make sure we kill off any children util.pexpect_close_all() diff --git a/Tools/autotest/util.py b/Tools/autotest/util.py index 3570e5ade8..bbb56f11e7 100644 --- a/Tools/autotest/util.py +++ b/Tools/autotest/util.py @@ -47,13 +47,33 @@ def build_SIL(atype): run_cmd("make -f ../libraries/Desktop/Makefile.desktop clean hil", dir=reltopdir(atype), checkfail=True) + return True +def build_AVR(atype, board='mega2560'): + '''build AVR binaries''' + config = open(reltopdir('config.mk'), mode='w') + config.write(''' +BOARD=%s +PORT=/dev/null +''' % board) + config.close() + run_cmd("make clean", dir=reltopdir(atype), checkfail=True) + run_cmd("make", dir=reltopdir(atype), checkfail=True) + return True + + +# list of pexpect children to close on exit close_list = [] +def pexpect_autoclose(p): + '''mark for autoclosing''' + global close_list + close_list.append(p) + def pexpect_close(p): '''close a pexpect child''' global close_list - p.close() + p.close(force=True) close_list.remove(p) def pexpect_close_all(): @@ -61,13 +81,12 @@ def pexpect_close_all(): global close_list for p in close_list[:]: try: - p.close() + p.close(Force=True) except Exception: pass def start_SIL(atype, valgrind=True, wipe=False, CLI=False): '''launch a SIL instance''' - global close_list cmd="" if valgrind and os.path.exists('/usr/bin/valgrind'): cmd += 'valgrind -q --log-file=%s-valgrind.log ' % atype @@ -77,7 +96,7 @@ def start_SIL(atype, valgrind=True, wipe=False, CLI=False): if CLI: cmd += ' -s' ret = pexpect.spawn(cmd, logfile=sys.stdout, timeout=5) - close_list.append(ret) + pexpect_autoclose(ret) ret.expect('Waiting for connection') return ret @@ -95,7 +114,7 @@ def start_MAVProxy_SIL(atype, aircraft=None, setup=False, master='tcp:127.0.0.1: if options is not None: cmd += ' ' + options ret = pexpect.spawn(cmd, logfile=logfile, timeout=60) - close_list.append(ret) + pexpect_autoclose(ret) return ret