diff options
Diffstat (limited to 'runtest.py')
-rw-r--r-- | runtest.py | 264 |
1 files changed, 145 insertions, 119 deletions
@@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2001, 2002, 2003, 2004 The SCons Foundation +# __COPYRIGHT__ # # runtest.py - wrapper script for running SCons tests # @@ -96,20 +96,21 @@ import string import sys import time +if not hasattr(os, 'WEXITSTATUS'): + os.WEXITSTATUS = lambda x: x + all = 0 baseline = 0 debug = '' execute_tests = 1 format = None list_only = None -tests = [] printcommand = 1 package = None print_passed_summary = None scons = None scons_exec = None outputfile = None -qmtest = None testlistfile = None version = '' print_times = None @@ -119,13 +120,6 @@ spe = None cwd = os.getcwd() -if sys.platform == 'win32' or os.name == 'java': - lib_dir = os.path.join(sys.exec_prefix, "Lib") -else: - # The hard-coded "python" here is the directory name, - # not an executable, so it's all right. - lib_dir = os.path.join(sys.exec_prefix, "lib", "python" + sys.version[0:3]) - helpstr = """\ Usage: runtest.py [OPTIONS] [TEST ...] Options: @@ -137,6 +131,7 @@ Options: -h, --help Print this message and exit. -l, --list List available tests and exit. -n, --no-exec No execute, just print command lines. + --noqmtest Execute tests directly, not using QMTest. -o FILE, --output FILE Print test results to FILE. -P Python Use the specified Python interpreter. -p PACKAGE, --package PACKAGE @@ -167,7 +162,7 @@ Options: opts, args = getopt.getopt(sys.argv[1:], "ab:df:hlno:P:p:qv:Xx:t", ['all', 'aegis', 'baseline=', 'debug', 'file=', 'help', - 'list', 'no-exec', 'output=', + 'list', 'no-exec', 'noqmtest', 'output=', 'package=', 'passed', 'python=', 'qmtest', 'quiet', 'spe=', 'version=', 'exec=', 'time', @@ -179,7 +174,11 @@ for o, a in opts: elif o in ['-b', '--baseline']: baseline = a elif o in ['-d', '--debug']: - debug = os.path.join(lib_dir, "pdb.py") + for dir in sys.path: + pdb = os.path.join(dir, 'pdb.py') + if os.path.exists(pdb): + debug = pdb + break elif o in ['-f', '--file']: if not os.path.isabs(a): a = os.path.join(cwd, a) @@ -191,6 +190,8 @@ for o, a in opts: list_only = 1 elif o in ['-n', '--no-exec']: execute_tests = None + elif o in ['--noqmtest']: + qmtest = None elif o in ['-o', '--output']: if a != '-' and not os.path.isabs(a): a = os.path.join(cwd, a) @@ -202,7 +203,7 @@ for o, a in opts: elif o in ['-P', '--python']: python = a elif o in ['--qmtest']: - qmtest = 1 + qmtest = 'qmtest.py' elif o in ['-q', '--quiet']: printcommand = 0 elif o in ['--sp']: @@ -222,6 +223,17 @@ for o, a in opts: elif o in ['--aegis', '--xml']: format = o +if not args and not all and not testlistfile: + sys.stderr.write("""\ +runtest.py: No tests were specified. + List one or more tests on the command line, use the + -f option to specify a file containing a list of tests, + or use the -a option to find and run all tests. + +""") + sys.exit(1) + + def whereis(file): for dir in string.split(os.environ['PATH'], os.pathsep): f = os.path.join(dir, file) @@ -234,6 +246,16 @@ def whereis(file): return f return None +try: + qmtest +except NameError: + q = 'qmtest.py' + qmtest = whereis(q) + if qmtest: + qmtest = q + else: + sys.stderr.write('Warning: %s not found on $PATH, assuming --noqmtest option.\n' % q) + aegis = whereis('aegis') if format == '--aegis' and aegis: @@ -277,9 +299,9 @@ except AttributeError: return status >> 8 else: def spawn_it(command_args): + command = command_args[0] command_args = map(escape, command_args) - command_args = map(lambda s: string.replace(s, '\\','\\\\'), command_args) - return os.spawnv(os.P_WAIT, command_args[0], command_args) + return os.spawnv(os.P_WAIT, command, command_args) class Base: def __init__(self, path, spe=None): @@ -352,86 +374,8 @@ format_class = { '--aegis' : Aegis, '--xml' : XML, } -Test = format_class[format] - -if qmtest: - pass -elif args: - if spe: - for a in args: - if os.path.isabs(a): - for g in glob.glob(a): - tests.append(Test(g)) - else: - for dir in spe: - x = os.path.join(dir, a) - globs = glob.glob(x) - if globs: - for g in globs: - tests.append(Test(g)) - break - else: - for a in args: - for g in glob.glob(a): - tests.append(Test(g)) -elif all: - # Find all of the SCons functional tests in the local directory - # tree. This is anything under the 'src' subdirectory that ends - # with 'Tests.py', or any Python script (*.py) under the 'test' - # subdirectory. - # - # Note that there are some tests under 'src' that *begin* with - # 'test_', but they're packaging and installation tests, not - # functional tests, so we don't execute them by default. (They can - # still be executed by hand, though, and are routinely executed - # by the Aegis packaging build to make sure that we're building - # things correctly.) - tdict = {} - - def find_Tests_py(arg, dirname, names, tdict=tdict): - for n in filter(lambda n: n[-8:] == "Tests.py", names): - t = os.path.join(dirname, n) - if not tdict.has_key(t): - tdict[t] = Test(t) - os.path.walk('src', find_Tests_py, 0) - - def find_py(arg, dirname, names, tdict=tdict): - for n in filter(lambda n: n[-3:] == ".py", names): - t = os.path.join(dirname, n) - if not tdict.has_key(t): - tdict[t] = Test(t) - os.path.walk('test', find_py, 0) - - if format == '--aegis' and aegis: - cmd = "aegis -list -unf pf 2>/dev/null" - for line in os.popen(cmd, "r").readlines(): - a = string.split(line) - if a[0] == "test" and not tdict.has_key(a[-1]): - tdict[a[-1]] = Test(a[-1], spe) - cmd = "aegis -list -unf cf 2>/dev/null" - for line in os.popen(cmd, "r").readlines(): - a = string.split(line) - if a[0] == "test": - if a[1] == "remove": - del tdict[a[-1]] - elif not tdict.has_key(a[-1]): - tdict[a[-1]] = Test(a[-1], spe) - - keys = tdict.keys() - keys.sort() - tests = map(tdict.get, keys) -elif testlistfile: - tests = open(testlistfile, 'r').readlines() - tests = filter(lambda x: x[0] != '#', tests) - tests = map(lambda x: x[:-1], tests) - tests = map(Test, tests) -else: - sys.stderr.write("""\ -runtest.py: No tests were specified on the command line. - List one or more tests, or use the -a option - to find and run all tests. -""") +Test = format_class[format] if package: @@ -476,6 +420,8 @@ if package: scons_lib_dir = os.path.join(test_dir, dir[package], 'lib', l) pythonpath_dir = scons_lib_dir + scons_runtest_dir = os.path.join(cwd, 'build') + else: sd = None ld = None @@ -529,6 +475,8 @@ else: else: base = baseline + scons_runtest_dir = base + scons_script_dir = sd or os.path.join(base, 'src', 'script') scons_lib_dir = ld or os.path.join(base, 'src', 'engine') @@ -548,6 +496,7 @@ elif scons_lib_dir: if scons_exec: os.environ['SCONS_EXEC'] = '1' +os.environ['SCONS_RUNTEST_DIR'] = scons_runtest_dir os.environ['SCONS_SCRIPT_DIR'] = scons_script_dir os.environ['SCONS_CWD'] = cwd @@ -573,43 +522,123 @@ if old_pythonpath: os.pathsep + \ old_pythonpath +tests = [] + +if args: + if spe: + for a in args: + if os.path.isabs(a): + tests.extend(glob.glob(a)) + else: + for dir in spe: + x = os.path.join(dir, a) + globs = glob.glob(x) + if globs: + tests.extend(globs) + break + else: + for a in args: + tests.extend(glob.glob(a)) +elif testlistfile: + tests = open(testlistfile, 'r').readlines() + tests = filter(lambda x: x[0] != '#', tests) + tests = map(lambda x: x[:-1], tests) +elif all and not qmtest: + # Find all of the SCons functional tests in the local directory + # tree. This is anything under the 'src' subdirectory that ends + # with 'Tests.py', or any Python script (*.py) under the 'test' + # subdirectory. + # + # Note that there are some tests under 'src' that *begin* with + # 'test_', but they're packaging and installation tests, not + # functional tests, so we don't execute them by default. (They can + # still be executed by hand, though, and are routinely executed + # by the Aegis packaging build to make sure that we're building + # things correctly.) + tdict = {} + + def find_Tests_py(tdict, dirname, names): + for n in filter(lambda n: n[-8:] == "Tests.py", names): + t = os.path.join(dirname, n) + if not tdict.has_key(t): + tdict[t] = 1 + os.path.walk('src', find_Tests_py, tdict) + + def find_py(tdict, dirname, names): + for n in filter(lambda n: n[-3:] == ".py", names): + t = os.path.join(dirname, n) + if not tdict.has_key(t): + tdict[t] = 1 + os.path.walk('test', find_py, tdict) + + if format == '--aegis' and aegis: + cmd = "aegis -list -unf pf 2>/dev/null" + for line in os.popen(cmd, "r").readlines(): + a = string.split(line) + if a[0] == "test" and not tdict.has_key(a[-1]): + tdict[a[-1]] = Test(a[-1], spe) + cmd = "aegis -list -unf cf 2>/dev/null" + for line in os.popen(cmd, "r").readlines(): + a = string.split(line) + if a[0] == "test": + if a[1] == "remove": + del tdict[a[-1]] + elif not tdict.has_key(a[-1]): + tdict[a[-1]] = Test(a[-1], spe) + + tests = tdict.keys() + tests.sort() + if qmtest: if baseline: - result_stream = 'AegisBaselineStream' + aegis_result_stream = 'scons_tdb.AegisBaselineStream' qmr_file = 'baseline.qmr' else: - result_stream = 'AegisChangeStream' + aegis_result_stream = 'scons_tdb.AegisChangeStream' qmr_file = 'results.qmr' - #qmtest = r'D:\Applications\python23\scripts\qmtest.py' - qmtest = 'qmtest.py' - qmtest_args = [ - qmtest, + + if print_times: + aegis_result_stream = aegis_result_stream + "(print_time='1')" + + qmtest_args = [ qmtest, ] + + if format == '--aegis': + dir = os.path.join(cwd, 'build') + if not os.path.isdir(dir): + dir = cwd + qmtest_args.extend(['-D', dir]) + + qmtest_args.extend([ 'run', '--output %s' % qmr_file, '--format none', - '--result-stream=scons_tdb.%s' % result_stream, - ] + '--result-stream="%s"' % aegis_result_stream, + ]) if python: - qmtest_args.append('--context python=%s' % python) - - if print_times: - qmtest_args.append('--context print_time=1') + qmtest_args.append('--context python="%s"' % python) if outputfile: - #rs = '--result-stream=scons_tdb.AegisBatchStream(results_file=\\"%s\\")' % outputfile - rs = '\'--result-stream=scons_tdb.AegisBatchStream(results_file="%s")\'' % outputfile + if format == '--xml': + rsclass = 'scons_tdb.SConsXMLResultStream' + else: + rsclass = 'scons_tdb.AegisBatchStream' + qof = "r'" + outputfile + "'" + rs = '--result-stream="%s(filename=%s)"' % (rsclass, qof) qmtest_args.append(rs) - os.environ['SCONS'] = os.path.join(cwd, 'src', 'script', 'scons.py') + if format == '--aegis': + tests = map(lambda x: string.replace(x, cwd+os.sep, ''), tests) + else: + os.environ['SCONS'] = os.path.join(cwd, 'src', 'script', 'scons.py') - cmd = string.join(qmtest_args + args, ' ') + cmd = string.join(qmtest_args + tests, ' ') if printcommand: sys.stdout.write(cmd + '\n') sys.stdout.flush() status = 0 if execute_tests: - status = os.system(cmd) + status = os.WEXITSTATUS(os.system(cmd)) sys.exit(status) #try: @@ -617,6 +646,8 @@ if qmtest: #except OSError: # pass +tests = map(Test, tests) + class Unbuffered: def __init__(self, file): self.file = file @@ -644,20 +675,15 @@ if not python: # but time.time() does a better job on Linux systems, so let that be # the non-Windows default. -if print_times: - print_time_func = lambda fmt, time: sys.stdout.write(fmt % time) -else: - print_time_func = lambda fmt, time: None - if sys.platform == 'win32': time_func = time.clock else: time_func = time.time -if sys.platform == 'win32': - time_func = time.clock +if print_times: + print_time_func = lambda fmt, time: sys.stdout.write(fmt % time) else: - time_func = time.time + print_time_func = lambda fmt, time: None total_start_time = time_func() for t in tests: |