diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-09-22 05:16:02 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-09-22 05:16:02 +0000 |
commit | b5cbf77c2e753e5519d962a06eb2e638b3669ddd (patch) | |
tree | fe08cd6e65a317de7dd2402dd9d6c0845b8c5f4a /clang | |
parent | f9539d0c3fbdf3b4d963b353982d41c1ee652b63 (diff) | |
download | bcm5719-llvm-b5cbf77c2e753e5519d962a06eb2e638b3669ddd.tar.gz bcm5719-llvm-b5cbf77c2e753e5519d962a06eb2e638b3669ddd.zip |
Remove old test runner, this has moved to LLVM/utils/lit and all known clients
have been updated.
- Please let me know of any problems.
llvm-svn: 82524
Diffstat (limited to 'clang')
-rw-r--r-- | clang/test/Makefile | 14 | ||||
-rw-r--r-- | clang/test/lit.cfg | 286 | ||||
-rw-r--r-- | clang/utils/test/ExampleTests/fail.c | 3 | ||||
-rw-r--r-- | clang/utils/test/ExampleTests/lit.cfg | 12 | ||||
-rw-r--r-- | clang/utils/test/ExampleTests/pass.c | 1 | ||||
-rw-r--r-- | clang/utils/test/ExampleTests/xfail.c | 2 | ||||
-rw-r--r-- | clang/utils/test/ExampleTests/xpass.c | 2 | ||||
-rwxr-xr-x | clang/utils/test/MultiTestRunner.py | 399 | ||||
-rw-r--r-- | clang/utils/test/ProgressBar.py | 227 | ||||
-rw-r--r-- | clang/utils/test/ShUtil.py | 390 | ||||
-rwxr-xr-x | clang/utils/test/TestRunner.py | 334 | ||||
-rw-r--r-- | clang/utils/test/TestingConfig.py | 27 | ||||
-rw-r--r-- | clang/utils/test/Util.py | 70 |
13 files changed, 135 insertions, 1632 deletions
diff --git a/clang/test/Makefile b/clang/test/Makefile index 9ed683435f4..6ed13d6b88e 100644 --- a/clang/test/Makefile +++ b/clang/test/Makefile @@ -8,8 +8,8 @@ else TESTDIRS ?= $(PROJ_SRC_DIR) endif -# LIT2 wants objdir paths, so it will pick up the lit.site.cfg. -LIT2_TESTDIRS := $(TESTDIRS:$(PROJ_SRC_DIR)%=$(PROJ_OBJ_DIR)%) +# 'lit' wants objdir paths, so it will pick up the lit.site.cfg. +TESTDIRS := $(TESTDIRS:$(PROJ_SRC_DIR)%=$(PROJ_OBJ_DIR)%) ifndef TESTARGS ifdef VERBOSE @@ -25,20 +25,10 @@ else VGARG= endif -ifndef LIT1 all:: lit.site.cfg @ echo '--- Running clang tests for $(TARGET_TRIPLE) ---' @ $(LLVM_SRC_ROOT)/utils/lit/lit.py \ - $(TESTARGS) $(LIT2_TESTDIRS) $(VGARG) -else -all:: - @ echo '--- Running clang tests for $(TARGET_TRIPLE) ---' - @ $(PROJ_SRC_DIR)/../utils/test/MultiTestRunner.py \ - --root $(PROJ_SRC_DIR) \ - --path $(ToolDir) \ - --path $(LLVM_SRC_ROOT)/test/Scripts \ $(TESTARGS) $(TESTDIRS) $(VGARG) -endif FORCE: diff --git a/clang/test/lit.cfg b/clang/test/lit.cfg index 0a99aa4ee9d..450b6149223 100644 --- a/clang/test/lit.cfg +++ b/clang/test/lit.cfg @@ -1,166 +1,146 @@ # -*- Python -*- -def config_new(): - import os +import os - # Configuration file for the 'lit' test runner. +# Configuration file for the 'lit' test runner. - # name: The name of this test suite. - config.name = 'Clang' +# name: The name of this test suite. +config.name = 'Clang' - # testFormat: The test format to use to interpret tests. - # - # For now we require '&&' between commands, until they get globally killed and - # the test runner updated. - config.test_format = lit.formats.ShTest(execute_external = True, - require_and_and = True) - - # suffixes: A list of file extensions to treat as test files. - config.suffixes = ['.c', '.cpp', '.m', '.mm'] - - # test_source_root: The root path where tests are located. - config.test_source_root = os.path.dirname(__file__) - - # test_exec_root: The root path where tests should be run. - clang_obj_root = getattr(config, 'clang_obj_root', None) - if clang_obj_root is not None: - config.test_exec_root = os.path.join(clang_obj_root, 'test') - - # Set llvm_{src,obj}_root for use by others. - config.llvm_src_root = getattr(config, 'llvm_src_root', None) - config.llvm_obj_root = getattr(config, 'llvm_obj_root', None) - - # Tweak the PATH to include the tools dir and the scripts dir. - if clang_obj_root is not None: - llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) - if not llvm_tools_dir: - lit.fatal('No LLVM tools dir set!') - path = os.path.pathsep.join((llvm_tools_dir, - os.path.join(config.llvm_src_root, - 'test', 'Scripts'), - config.environment['PATH'])) - config.environment['PATH'] = path - - ### - - # Check that the object root is known. - if config.test_exec_root is None: - # Otherwise, we haven't loaded the site specific configuration (the user is - # probably trying to run on a test file directly, and either the site - # configuration hasn't been created by the build system, or we are in an - # out-of-tree build situation). - - # Try to detect the situation where we are using an out-of-tree build by - # looking for 'llvm-config'. - # - # FIXME: I debated (i.e., wrote and threw away) adding logic to - # automagically generate the lit.site.cfg if we are in some kind of fresh - # build situation. This means knowing how to invoke the build system - # though, and I decided it was too much magic. - - llvm_config = lit.util.which('llvm-config', config.environment['PATH']) - if not llvm_config: - lit.fatal('No site specific configuration available!') - - # Get the source and object roots. - llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip() - llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip() - clang_src_root = os.path.join(llvm_src_root, "tools", "clang") - clang_obj_root = os.path.join(llvm_obj_root, "tools", "clang") - - # Validate that we got a tree which points to here, using the standard - # tools/clang layout. - this_src_root = os.path.dirname(config.test_source_root) - if os.path.realpath(clang_src_root) != os.path.realpath(this_src_root): - lit.fatal('No site specific configuration available!') - - # Check that the site specific configuration exists. - site_cfg = os.path.join(clang_obj_root, 'test', 'lit.site.cfg') - if not os.path.exists(site_cfg): - lit.fatal('No site specific configuration available!') - - # Okay, that worked. Notify the user of the automagic, and reconfigure. - lit.note('using out-of-tree build at %r' % clang_obj_root) - lit.load_config(config, site_cfg) - raise SystemExit - - ### - - # Discover the 'clang' and 'clangcc' to use. - - import os - - def inferClang(PATH): - # Determine which clang to use. - clang = os.getenv('CLANG') - - # If the user set clang in the environment, definitely use that and don't - # try to validate. - if clang: - return clang - - # Otherwise look in the path. - clang = lit.util.which('clang', PATH) - - if not clang: - lit.fatal("couldn't find 'clang' program, try setting " - "CLANG in your environment") +# testFormat: The test format to use to interpret tests. +# +# For now we require '&&' between commands, until they get globally killed and +# the test runner updated. +config.test_format = lit.formats.ShTest(execute_external = True, + require_and_and = True) +# suffixes: A list of file extensions to treat as test files. +config.suffixes = ['.c', '.cpp', '.m', '.mm'] + +# test_source_root: The root path where tests are located. +config.test_source_root = os.path.dirname(__file__) + +# test_exec_root: The root path where tests should be run. +clang_obj_root = getattr(config, 'clang_obj_root', None) +if clang_obj_root is not None: + config.test_exec_root = os.path.join(clang_obj_root, 'test') + +# Set llvm_{src,obj}_root for use by others. +config.llvm_src_root = getattr(config, 'llvm_src_root', None) +config.llvm_obj_root = getattr(config, 'llvm_obj_root', None) + +# Tweak the PATH to include the tools dir and the scripts dir. +if clang_obj_root is not None: + llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) + if not llvm_tools_dir: + lit.fatal('No LLVM tools dir set!') + path = os.path.pathsep.join((llvm_tools_dir, + os.path.join(config.llvm_src_root, + 'test', 'Scripts'), + config.environment['PATH'])) + config.environment['PATH'] = path + +### + +# Check that the object root is known. +if config.test_exec_root is None: + # Otherwise, we haven't loaded the site specific configuration (the user is + # probably trying to run on a test file directly, and either the site + # configuration hasn't been created by the build system, or we are in an + # out-of-tree build situation). + + # Try to detect the situation where we are using an out-of-tree build by + # looking for 'llvm-config'. + # + # FIXME: I debated (i.e., wrote and threw away) adding logic to + # automagically generate the lit.site.cfg if we are in some kind of fresh + # build situation. This means knowing how to invoke the build system + # though, and I decided it was too much magic. + + llvm_config = lit.util.which('llvm-config', config.environment['PATH']) + if not llvm_config: + lit.fatal('No site specific configuration available!') + + # Get the source and object roots. + llvm_src_root = lit.util.capture(['llvm-config', '--src-root']).strip() + llvm_obj_root = lit.util.capture(['llvm-config', '--obj-root']).strip() + clang_src_root = os.path.join(llvm_src_root, "tools", "clang") + clang_obj_root = os.path.join(llvm_obj_root, "tools", "clang") + + # Validate that we got a tree which points to here, using the standard + # tools/clang layout. + this_src_root = os.path.dirname(config.test_source_root) + if os.path.realpath(clang_src_root) != os.path.realpath(this_src_root): + lit.fatal('No site specific configuration available!') + + # Check that the site specific configuration exists. + site_cfg = os.path.join(clang_obj_root, 'test', 'lit.site.cfg') + if not os.path.exists(site_cfg): + lit.fatal('No site specific configuration available!') + + # Okay, that worked. Notify the user of the automagic, and reconfigure. + lit.note('using out-of-tree build at %r' % clang_obj_root) + lit.load_config(config, site_cfg) + raise SystemExit + +### + +# Discover the 'clang' and 'clangcc' to use. + +import os + +def inferClang(PATH): + # Determine which clang to use. + clang = os.getenv('CLANG') + + # If the user set clang in the environment, definitely use that and don't + # try to validate. + if clang: return clang - def inferClangCC(clang, PATH): - clangcc = os.getenv('CLANGCC') - - # If the user set clang in the environment, definitely use that and don't - # try to validate. - if clangcc: - return clangcc - - # Otherwise try adding -cc since we expect to be looking in a build - # directory. - if clang.endswith('.exe'): - clangccName = clang[:-4] + '-cc.exe' - else: - clangccName = clang + '-cc' - clangcc = lit.util.which(clangccName, PATH) - if not clangcc: - # Otherwise ask clang. - res = lit.util.capture([clang, '-print-prog-name=clang-cc']) - res = res.strip() - if res and os.path.exists(res): - clangcc = res - - if not clangcc: - lit.fatal("couldn't find 'clang-cc' program, try setting " - "CLANGCC in your environment") - - return clangcc + # Otherwise look in the path. + clang = lit.util.which('clang', PATH) - config.clang = inferClang(config.environment['PATH']) - if not lit.quiet: - lit.note('using clang: %r' % config.clang) - config.substitutions.append( (' clang ', ' ' + config.clang + ' ') ) + if not clang: + lit.fatal("couldn't find 'clang' program, try setting " + "CLANG in your environment") - config.clang_cc = inferClangCC(config.clang, config.environment['PATH']) - if not lit.quiet: - lit.note('using clang-cc: %r' % config.clang_cc) - config.substitutions.append( (' clang-cc ', ' ' + config.clang_cc + ' ') ) + return clang -if 'config' in globals(): - config_new() - raise SystemExit # End configuration. +def inferClangCC(clang, PATH): + clangcc = os.getenv('CLANGCC') -# Configuration file for the 'lit' test runner. - -# suffixes: A list of file extensions to treat as test files. -suffixes = ['.c', '.cpp', '.m', '.mm'] - -# environment: The base environment to use when running test commands. -# -# The 'PATH' and 'SYSTEMROOT' variables will be set automatically from the lit -# command line variables. -environment = {} + # If the user set clang in the environment, definitely use that and don't + # try to validate. + if clangcc: + return clangcc -# requireAndAnd: Require '&&' between commands, until they get globally killed -# and the test runner updated. -requireAndAnd = True + # Otherwise try adding -cc since we expect to be looking in a build + # directory. + if clang.endswith('.exe'): + clangccName = clang[:-4] + '-cc.exe' + else: + clangccName = clang + '-cc' + clangcc = lit.util.which(clangccName, PATH) + if not clangcc: + # Otherwise ask clang. + res = lit.util.capture([clang, '-print-prog-name=clang-cc']) + res = res.strip() + if res and os.path.exists(res): + clangcc = res + + if not clangcc: + lit.fatal("couldn't find 'clang-cc' program, try setting " + "CLANGCC in your environment") + + return clangcc + +config.clang = inferClang(config.environment['PATH']) +if not lit.quiet: + lit.note('using clang: %r' % config.clang) +config.substitutions.append( (' clang ', ' ' + config.clang + ' ') ) + +config.clang_cc = inferClangCC(config.clang, config.environment['PATH']) +if not lit.quiet: + lit.note('using clang-cc: %r' % config.clang_cc) +config.substitutions.append( (' clang-cc ', ' ' + config.clang_cc + ' ') ) diff --git a/clang/utils/test/ExampleTests/fail.c b/clang/utils/test/ExampleTests/fail.c deleted file mode 100644 index 749ba563913..00000000000 --- a/clang/utils/test/ExampleTests/fail.c +++ /dev/null @@ -1,3 +0,0 @@ -// RUN: echo 'I am some stdout' && -// RUN: echo 'I am some stderr' 1>&2 && -// RUN: false diff --git a/clang/utils/test/ExampleTests/lit.cfg b/clang/utils/test/ExampleTests/lit.cfg deleted file mode 100644 index 3bd18dc0f18..00000000000 --- a/clang/utils/test/ExampleTests/lit.cfg +++ /dev/null @@ -1,12 +0,0 @@ -# -*- Python -*- - -# Configuration file for the 'lit' test runner. - -# suffixes: A list of file extensions to treat as test files. -suffixes = ['.c', '.cpp', '.m', '.mm'] - -# environment: The base environment to use when running test commands. -# -# The 'PATH' and 'SYSTEMROOT' variables will be set automatically from the lit -# command line variables. -environment = {} diff --git a/clang/utils/test/ExampleTests/pass.c b/clang/utils/test/ExampleTests/pass.c deleted file mode 100644 index 5c1031cccc4..00000000000 --- a/clang/utils/test/ExampleTests/pass.c +++ /dev/null @@ -1 +0,0 @@ -// RUN: true diff --git a/clang/utils/test/ExampleTests/xfail.c b/clang/utils/test/ExampleTests/xfail.c deleted file mode 100644 index a6507099061..00000000000 --- a/clang/utils/test/ExampleTests/xfail.c +++ /dev/null @@ -1,2 +0,0 @@ -// RUN: false -// XFAIL diff --git a/clang/utils/test/ExampleTests/xpass.c b/clang/utils/test/ExampleTests/xpass.c deleted file mode 100644 index ad84990f7e2..00000000000 --- a/clang/utils/test/ExampleTests/xpass.c +++ /dev/null @@ -1,2 +0,0 @@ -// RUN: true -// XFAIL diff --git a/clang/utils/test/MultiTestRunner.py b/clang/utils/test/MultiTestRunner.py deleted file mode 100755 index 6e15f1cd8f3..00000000000 --- a/clang/utils/test/MultiTestRunner.py +++ /dev/null @@ -1,399 +0,0 @@ -#!/usr/bin/env python - -""" -MultiTestRunner - Harness for running multiple tests in the simple clang style. - -TODO --- - - Use configuration file for clang specific stuff - - Use a timeout / ulimit - - Detect signaled failures (abort) - - Better support for finding tests - - - Support "disabling" tests? The advantage of making this distinct from XFAIL - is it makes it more obvious that it is a temporary measure (and MTR can put - in a separate category). -""" - -import os, sys, re, random, time -import threading -from Queue import Queue - -import ProgressBar -import TestRunner -import Util - -from TestingConfig import TestingConfig -from TestRunner import TestStatus - -kConfigName = 'lit.cfg' - -def getTests(cfg, inputs): - for path in inputs: - if not os.path.exists(path): - Util.warning('Invalid test %r' % path) - continue - - if not os.path.isdir(path): - yield path - continue - - foundOne = False - for dirpath,dirnames,filenames in os.walk(path): - # FIXME: This doesn't belong here - if 'Output' in dirnames: - dirnames.remove('Output') - for f in filenames: - base,ext = os.path.splitext(f) - if ext in cfg.suffixes: - yield os.path.join(dirpath,f) - foundOne = True - if not foundOne: - Util.warning('No tests in input directory %r' % path) - -class TestingProgressDisplay: - def __init__(self, opts, numTests, progressBar=None): - self.opts = opts - self.numTests = numTests - self.digits = len(str(self.numTests)) - self.current = None - self.lock = threading.Lock() - self.progressBar = progressBar - self.progress = 0. - - def update(self, index, tr): - # Avoid locking overhead in quiet mode - if self.opts.quiet and not tr.failed(): - return - - # Output lock - self.lock.acquire() - try: - self.handleUpdate(index, tr) - finally: - self.lock.release() - - def finish(self): - if self.progressBar: - self.progressBar.clear() - elif self.opts.succinct: - sys.stdout.write('\n') - - def handleUpdate(self, index, tr): - if self.progressBar: - if tr.failed(): - self.progressBar.clear() - else: - # Force monotonicity - self.progress = max(self.progress, float(index)/self.numTests) - self.progressBar.update(self.progress, tr.path) - return - elif self.opts.succinct: - if not tr.failed(): - sys.stdout.write('.') - sys.stdout.flush() - return - else: - sys.stdout.write('\n') - - status = TestStatus.getName(tr.code).upper() - print '%s: %s (%*d of %*d)' % (status, tr.path, - self.digits, index+1, - self.digits, self.numTests) - - if tr.failed() and self.opts.showOutput: - print "%s TEST '%s' FAILED %s" % ('*'*20, tr.path, '*'*20) - print tr.output - print "*" * 20 - - sys.stdout.flush() - -class TestResult: - def __init__(self, path, code, output, elapsed): - self.path = path - self.code = code - self.output = output - self.elapsed = elapsed - - def failed(self): - return self.code in (TestStatus.Fail,TestStatus.XPass) - -class TestProvider: - def __init__(self, config, opts, tests, display): - self.config = config - self.opts = opts - self.tests = tests - self.index = 0 - self.lock = threading.Lock() - self.results = [None]*len(self.tests) - self.startTime = time.time() - self.progress = display - - def get(self): - self.lock.acquire() - try: - if self.opts.maxTime is not None: - if time.time() - self.startTime > self.opts.maxTime: - return None - if self.index >= len(self.tests): - return None - item = self.tests[self.index],self.index - self.index += 1 - return item - finally: - self.lock.release() - - def setResult(self, index, result): - self.results[index] = result - self.progress.update(index, result) - -class Tester(threading.Thread): - def __init__(self, provider): - threading.Thread.__init__(self) - self.provider = provider - - def run(self): - while 1: - item = self.provider.get() - if item is None: - break - self.runTest(item) - - def runTest(self, (path, index)): - base = TestRunner.getTestOutputBase('Output', path) - numTests = len(self.provider.tests) - digits = len(str(numTests)) - code = None - elapsed = None - try: - opts = self.provider.opts - startTime = time.time() - code, output = TestRunner.runOneTest(self.provider.config, - path, base) - elapsed = time.time() - startTime - except KeyboardInterrupt: - # This is a sad hack. Unfortunately subprocess goes - # bonkers with ctrl-c and we start forking merrily. - print '\nCtrl-C detected, goodbye.' - os.kill(0,9) - - self.provider.setResult(index, TestResult(path, code, output, elapsed)) - -def findConfigPath(root): - prev = None - while root != prev: - cfg = os.path.join(root, kConfigName) - if os.path.exists(cfg): - return cfg - - prev,root = root,os.path.dirname(root) - - raise ValueError,"Unable to find config file %r" % kConfigName - -def runTests(opts, provider): - # If only using one testing thread, don't use threads at all; this lets us - # profile, among other things. - if opts.numThreads == 1: - t = Tester(provider) - t.run() - return - - # Otherwise spin up the testing threads and wait for them to finish. - testers = [Tester(provider) for i in range(opts.numThreads)] - for t in testers: - t.start() - try: - for t in testers: - t.join() - except KeyboardInterrupt: - sys.exit(1) - -def main(): - global options - from optparse import OptionParser, OptionGroup - parser = OptionParser("usage: %prog [options] {file-or-path}") - - parser.add_option("", "--root", dest="root", - help="Path to root test directory", - action="store", default=None) - parser.add_option("", "--config", dest="config", - help="Testing configuration file [default='%s']" % kConfigName, - action="store", default=None) - - group = OptionGroup(parser, "Output Format") - # FIXME: I find these names very confusing, although I like the - # functionality. - group.add_option("-q", "--quiet", dest="quiet", - help="Suppress no error output", - action="store_true", default=False) - group.add_option("-s", "--succinct", dest="succinct", - help="Reduce amount of output", - action="store_true", default=False) - group.add_option("-v", "--verbose", dest="showOutput", - help="Show all test output", - action="store_true", default=False) - group.add_option("", "--no-progress-bar", dest="useProgressBar", - help="Do not use curses based progress bar", - action="store_false", default=True) - parser.add_option_group(group) - - group = OptionGroup(parser, "Test Execution") - group.add_option("-j", "--threads", dest="numThreads", - help="Number of testing threads", - type=int, action="store", - default=None) - group.add_option("", "--clang", dest="clang", - help="Program to use as \"clang\"", - action="store", default=None) - group.add_option("", "--clang-cc", dest="clangcc", - help="Program to use as \"clang-cc\"", - action="store", default=None) - group.add_option("", "--path", dest="path", - help="Additional paths to add to testing environment", - action="append", type=str, default=[]) - group.add_option("", "--no-sh", dest="useExternalShell", - help="Run tests using an external shell", - action="store_false", default=True) - group.add_option("", "--vg", dest="useValgrind", - help="Run tests under valgrind", - action="store_true", default=False) - group.add_option("", "--vg-arg", dest="valgrindArgs", - help="Specify an extra argument for valgrind", - type=str, action="append", default=[]) - group.add_option("", "--time-tests", dest="timeTests", - help="Track elapsed wall time for each test", - action="store_true", default=False) - parser.add_option_group(group) - - group = OptionGroup(parser, "Test Selection") - group.add_option("", "--max-tests", dest="maxTests", - help="Maximum number of tests to run", - action="store", type=int, default=None) - group.add_option("", "--max-time", dest="maxTime", - help="Maximum time to spend testing (in seconds)", - action="store", type=float, default=None) - group.add_option("", "--shuffle", dest="shuffle", - help="Run tests in random order", - action="store_true", default=False) - parser.add_option_group(group) - - (opts, args) = parser.parse_args() - - if not args: - parser.error('No inputs specified') - - if opts.numThreads is None: - opts.numThreads = Util.detectCPUs() - - inputs = args - - # Resolve root if not given, either infer it from the config file if given, - # otherwise from the inputs. - if not opts.root: - if opts.config: - opts.root = os.path.dirname(opts.config) - else: - opts.root = os.path.commonprefix([os.path.abspath(p) - for p in inputs]) - - # Find the config file, if not specified. - if not opts.config: - try: - opts.config = findConfigPath(opts.root) - except ValueError,e: - parser.error(e.args[0]) - - cfg = TestingConfig.frompath(opts.config) - - # Update the configuration based on the command line arguments. - for name in ('PATH','SYSTEMROOT'): - if name in cfg.environment: - parser.error("'%s' should not be set in configuration!" % name) - - cfg.root = opts.root - cfg.environment['PATH'] = os.pathsep.join(opts.path + - [os.environ.get('PATH','')]) - cfg.environment['SYSTEMROOT'] = os.environ.get('SYSTEMROOT','') - - if opts.clang is None: - opts.clang = TestRunner.inferClang(cfg) - if opts.clangcc is None: - opts.clangcc = TestRunner.inferClangCC(cfg, opts.clang) - - cfg.clang = opts.clang - cfg.clangcc = opts.clangcc - cfg.useValgrind = opts.useValgrind - cfg.valgrindArgs = opts.valgrindArgs - cfg.useExternalShell = opts.useExternalShell - - # FIXME: It could be worth loading these in parallel with testing. - allTests = list(getTests(cfg, args)) - allTests.sort() - - tests = allTests - if opts.shuffle: - random.shuffle(tests) - if opts.maxTests is not None: - tests = tests[:opts.maxTests] - - extra = '' - if len(tests) != len(allTests): - extra = ' of %d'%(len(allTests),) - header = '-- Testing: %d%s tests, %d threads --'%(len(tests),extra, - opts.numThreads) - - progressBar = None - if not opts.quiet: - if opts.useProgressBar: - try: - tc = ProgressBar.TerminalController() - progressBar = ProgressBar.ProgressBar(tc, header) - except ValueError: - pass - - if not progressBar: - print header - - # Don't create more threads than tests. - opts.numThreads = min(len(tests), opts.numThreads) - - startTime = time.time() - display = TestingProgressDisplay(opts, len(tests), progressBar) - provider = TestProvider(cfg, opts, tests, display) - runTests(opts, provider) - display.finish() - - if not opts.quiet: - print 'Testing Time: %.2fs'%(time.time() - startTime) - - # List test results organized by kind. - byCode = {} - for t in provider.results: - if t: - if t.code not in byCode: - byCode[t.code] = [] - byCode[t.code].append(t) - for title,code in (('Unexpected Passing Tests', TestStatus.XPass), - ('Failing Tests', TestStatus.Fail)): - elts = byCode.get(code) - if not elts: - continue - print '*'*20 - print '%s (%d):' % (title, len(elts)) - for tr in elts: - print '\t%s'%(tr.path,) - - numFailures = len(byCode.get(TestStatus.Fail,[])) - if numFailures: - print '\nFailures: %d' % (numFailures,) - sys.exit(1) - - if opts.timeTests: - print '\nTest Times:' - provider.results.sort(key=lambda t: t and t.elapsed) - for tr in provider.results: - if tr: - print '%.2fs: %s' % (tr.elapsed, tr.path) - -if __name__=='__main__': - main() diff --git a/clang/utils/test/ProgressBar.py b/clang/utils/test/ProgressBar.py deleted file mode 100644 index 13db7eccc91..00000000000 --- a/clang/utils/test/ProgressBar.py +++ /dev/null @@ -1,227 +0,0 @@ -#!/usr/bin/env python - -# Source: http://code.activestate.com/recipes/475116/, with -# modifications by Daniel Dunbar. - -import sys, re, time - -class TerminalController: - """ - A class that can be used to portably generate formatted output to - a terminal. - - `TerminalController` defines a set of instance variables whose - values are initialized to the control sequence necessary to - perform a given action. These can be simply included in normal - output to the terminal: - - >>> term = TerminalController() - >>> print 'This is '+term.GREEN+'green'+term.NORMAL - - Alternatively, the `render()` method can used, which replaces - '${action}' with the string required to perform 'action': - - >>> term = TerminalController() - >>> print term.render('This is ${GREEN}green${NORMAL}') - - If the terminal doesn't support a given action, then the value of - the corresponding instance variable will be set to ''. As a - result, the above code will still work on terminals that do not - support color, except that their output will not be colored. - Also, this means that you can test whether the terminal supports a - given action by simply testing the truth value of the - corresponding instance variable: - - >>> term = TerminalController() - >>> if term.CLEAR_SCREEN: - ... print 'This terminal supports clearning the screen.' - - Finally, if the width and height of the terminal are known, then - they will be stored in the `COLS` and `LINES` attributes. - """ - # Cursor movement: - BOL = '' #: Move the cursor to the beginning of the line - UP = '' #: Move the cursor up one line - DOWN = '' #: Move the cursor down one line - LEFT = '' #: Move the cursor left one char - RIGHT = '' #: Move the cursor right one char - - # Deletion: - CLEAR_SCREEN = '' #: Clear the screen and move to home position - CLEAR_EOL = '' #: Clear to the end of the line. - CLEAR_BOL = '' #: Clear to the beginning of the line. - CLEAR_EOS = '' #: Clear to the end of the screen - - # Output modes: - BOLD = '' #: Turn on bold mode - BLINK = '' #: Turn on blink mode - DIM = '' #: Turn on half-bright mode - REVERSE = '' #: Turn on reverse-video mode - NORMAL = '' #: Turn off all modes - - # Cursor display: - HIDE_CURSOR = '' #: Make the cursor invisible - SHOW_CURSOR = '' #: Make the cursor visible - - # Terminal size: - COLS = None #: Width of the terminal (None for unknown) - LINES = None #: Height of the terminal (None for unknown) - - # Foreground colors: - BLACK = BLUE = GREEN = CYAN = RED = MAGENTA = YELLOW = WHITE = '' - - # Background colors: - BG_BLACK = BG_BLUE = BG_GREEN = BG_CYAN = '' - BG_RED = BG_MAGENTA = BG_YELLOW = BG_WHITE = '' - - _STRING_CAPABILITIES = """ - BOL=cr UP=cuu1 DOWN=cud1 LEFT=cub1 RIGHT=cuf1 - CLEAR_SCREEN=clear CLEAR_EOL=el CLEAR_BOL=el1 CLEAR_EOS=ed BOLD=bold - BLINK=blink DIM=dim REVERSE=rev UNDERLINE=smul NORMAL=sgr0 - HIDE_CURSOR=cinvis SHOW_CURSOR=cnorm""".split() - _COLORS = """BLACK BLUE GREEN CYAN RED MAGENTA YELLOW WHITE""".split() - _ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split() - - def __init__(self, term_stream=sys.stdout): - """ - Create a `TerminalController` and initialize its attributes - with appropriate values for the current terminal. - `term_stream` is the stream that will be used for terminal - output; if this stream is not a tty, then the terminal is - assumed to be a dumb terminal (i.e., have no capabilities). - """ - # Curses isn't available on all platforms - try: import curses - except: return - - # If the stream isn't a tty, then assume it has no capabilities. - if not term_stream.isatty(): return - - # Check the terminal type. If we fail, then assume that the - # terminal has no capabilities. - try: curses.setupterm() - except: return - - # Look up numeric capabilities. - self.COLS = curses.tigetnum('cols') - self.LINES = curses.tigetnum('lines') - - # Look up string capabilities. - for capability in self._STRING_CAPABILITIES: - (attrib, cap_name) = capability.split('=') - setattr(self, attrib, self._tigetstr(cap_name) or '') - - # Colors - set_fg = self._tigetstr('setf') - if set_fg: - for i,color in zip(range(len(self._COLORS)), self._COLORS): - setattr(self, color, curses.tparm(set_fg, i) or '') - set_fg_ansi = self._tigetstr('setaf') - if set_fg_ansi: - for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS): - setattr(self, color, curses.tparm(set_fg_ansi, i) or '') - set_bg = self._tigetstr('setb') - if set_bg: - for i,color in zip(range(len(self._COLORS)), self._COLORS): - setattr(self, 'BG_'+color, curses.tparm(set_bg, i) or '') - set_bg_ansi = self._tigetstr('setab') - if set_bg_ansi: - for i,color in zip(range(len(self._ANSICOLORS)), self._ANSICOLORS): - setattr(self, 'BG_'+color, curses.tparm(set_bg_ansi, i) or '') - - def _tigetstr(self, cap_name): - # String capabilities can include "delays" of the form "$<2>". - # For any modern terminal, we should be able to just ignore - # these, so strip them out. - import curses - cap = curses.tigetstr(cap_name) or '' - return re.sub(r'\$<\d+>[/*]?', '', cap) - - def render(self, template): - """ - Replace each $-substitutions in the given template string with - the corresponding terminal control string (if it's defined) or - '' (if it's not). - """ - return re.sub(r'\$\$|\${\w+}', self._render_sub, template) - - def _render_sub(self, match): - s = match.group() - if s == '$$': return s - else: return getattr(self, s[2:-1]) - -####################################################################### -# Example use case: progress bar -####################################################################### - -class ProgressBar: - """ - A 3-line progress bar, which looks like:: - - Header - 20% [===========----------------------------------] - progress message - - The progress bar is colored, if the terminal supports color - output; and adjusts to the width of the terminal. - """ - BAR = '%s${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}%s\n' - HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n' - - def __init__(self, term, header, useETA=True): - self.term = term - if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL): - raise ValueError("Terminal isn't capable enough -- you " - "should use a simpler progress dispaly.") - self.width = self.term.COLS or 75 - self.bar = term.render(self.BAR) - self.header = self.term.render(self.HEADER % header.center(self.width)) - self.cleared = 1 #: true if we haven't drawn the bar yet. - self.useETA = useETA - if self.useETA: - self.startTime = time.time() - self.update(0, '') - - def update(self, percent, message): - if self.cleared: - sys.stdout.write(self.header) - self.cleared = 0 - prefix = '%3d%% ' % (percent*100,) - suffix = '' - if self.useETA: - elapsed = time.time() - self.startTime - if percent > .0001 and elapsed > 1: - total = elapsed / percent - eta = int(total - elapsed) - h = eta//3600. - m = (eta//60) % 60 - s = eta % 60 - suffix = ' ETA: %02d:%02d:%02d'%(h,m,s) - barWidth = self.width - len(prefix) - len(suffix) - 2 - n = int(barWidth*percent) - if len(message) < self.width: - message = message + ' '*(self.width - len(message)) - else: - message = '... ' + message[-(self.width-4):] - sys.stdout.write( - self.term.BOL + self.term.UP + self.term.CLEAR_EOL + - (self.bar % (prefix, '='*n, '-'*(barWidth-n), suffix)) + - self.term.CLEAR_EOL + message) - - def clear(self): - if not self.cleared: - sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL + - self.term.UP + self.term.CLEAR_EOL + - self.term.UP + self.term.CLEAR_EOL) - self.cleared = 1 - -def test(): - import time - tc = TerminalController() - p = ProgressBar(tc, 'Tests') - for i in range(101): - p.update(i/100., str(i)) - time.sleep(.3) - -if __name__=='__main__': - test() diff --git a/clang/utils/test/ShUtil.py b/clang/utils/test/ShUtil.py deleted file mode 100644 index dd4b584ac00..00000000000 --- a/clang/utils/test/ShUtil.py +++ /dev/null @@ -1,390 +0,0 @@ -import itertools - -import Util - -class ShLexer: - def __init__(self, data, win32Escapes = False): - self.data = data - self.pos = 0 - self.end = len(data) - self.win32Escapes = win32Escapes - - def eat(self): - c = self.data[self.pos] - self.pos += 1 - return c - - def look(self): - return self.data[self.pos] - - def maybe_eat(self, c): - """ - maybe_eat(c) - Consume the character c if it is the next character, - returning True if a character was consumed. """ - if self.data[self.pos] == c: - self.pos += 1 - return True - return False - - def lex_arg_fast(self, c): - # Get the leading whitespace free section. - chunk = self.data[self.pos - 1:].split(None, 1)[0] - - # If it has special characters, the fast path failed. - if ('|' in chunk or '&' in chunk or - '<' in chunk or '>' in chunk or - "'" in chunk or '"' in chunk or - '\\' in chunk): - return None - - self.pos = self.pos - 1 + len(chunk) - return chunk - - def lex_arg_slow(self, c): - if c in "'\"": - str = self.lex_arg_quoted(c) - else: - str = c - while self.pos != self.end: - c = self.look() - if c.isspace() or c in "|&": - break - elif c in '><': - # This is an annoying case; we treat '2>' as a single token so - # we don't have to track whitespace tokens. - - # If the parse string isn't an integer, do the usual thing. - if not str.isdigit(): - break - - # Otherwise, lex the operator and convert to a redirection - # token. - num = int(str) - tok = self.lex_one_token() - assert isinstance(tok, tuple) and len(tok) == 1 - return (tok[0], num) - elif c == '"': - self.eat() - str += self.lex_arg_quoted('"')
- elif not self.win32Escapes and c == '\\': - # Outside of a string, '\\' escapes everything. - self.eat() - if self.pos == self.end: - Util.warning("escape at end of quoted argument in: %r" % - self.data) - return str - str += self.eat() - else: - str += self.eat() - return str - - def lex_arg_quoted(self, delim): - str = '' - while self.pos != self.end: - c = self.eat() - if c == delim: - return str - elif c == '\\' and delim == '"': - # Inside a '"' quoted string, '\\' only escapes the quote - # character and backslash, otherwise it is preserved. - if self.pos == self.end: - Util.warning("escape at end of quoted argument in: %r" % - self.data) - return str - c = self.eat() - if c == '"': # - str += '"' - elif c == '\\': - str += '\\' - else: - str += '\\' + c - else: - str += c - Util.warning("missing quote character in %r" % self.data) - return str - - def lex_arg_checked(self, c): - pos = self.pos - res = self.lex_arg_fast(c) - end = self.pos - - self.pos = pos - reference = self.lex_arg_slow(c) - if res is not None: - if res != reference: - raise ValueError,"Fast path failure: %r != %r" % (res, reference) - if self.pos != end: - raise ValueError,"Fast path failure: %r != %r" % (self.pos, end) - return reference - - def lex_arg(self, c): - return self.lex_arg_fast(c) or self.lex_arg_slow(c) - - def lex_one_token(self): - """ - lex_one_token - Lex a single 'sh' token. """ - - c = self.eat() - if c in ';!': - return (c,) - if c == '|': - if self.maybe_eat('|'): - return ('||',) - return (c,) - if c == '&': - if self.maybe_eat('&'): - return ('&&',) - if self.maybe_eat('>'): - return ('&>',) - return (c,) - if c == '>': - if self.maybe_eat('&'): - return ('>&',) - if self.maybe_eat('>'): - return ('>>',) - return (c,) - if c == '<': - if self.maybe_eat('&'): - return ('<&',) - if self.maybe_eat('>'): - return ('<<',) - return (c,) - - return self.lex_arg(c) - - def lex(self): - while self.pos != self.end: - if self.look().isspace(): - self.eat() - else: - yield self.lex_one_token() - -### - -class Command: - def __init__(self, args, redirects): - self.args = list(args) - self.redirects = list(redirects) - - def __repr__(self): - return 'Command(%r, %r)' % (self.args, self.redirects) - - def __cmp__(self, other): - if not isinstance(other, Command): - return -1 - - return cmp((self.args, self.redirects), - (other.args, other.redirects)) - -class Pipeline: - def __init__(self, commands, negate): - self.commands = commands - self.negate = negate - - def __repr__(self): - return 'Pipeline(%r, %r)' % (self.commands, self.negate) - - def __cmp__(self, other): - if not isinstance(other, Pipeline): - return -1 - - return cmp((self.commands, self.negate), - (other.commands, other.negate)) - -class Seq: - def __init__(self, lhs, op, rhs): - assert op in (';', '&', '||', '&&') - self.op = op - self.lhs = lhs - self.rhs = rhs - - def __repr__(self): - return 'Seq(%r, %r, %r)' % (self.lhs, self.op, self.rhs) - - def __cmp__(self, other): - if not isinstance(other, Seq): - return -1 - - return cmp((self.lhs, self.op, self.rhs), - (other.lhs, other.op, other.rhs)) - -class ShParser: - def __init__(self, data, win32Escapes = False): - self.data = data - self.tokens = ShLexer(data, win32Escapes = win32Escapes).lex() - - def lex(self): - try: - return self.tokens.next() - except StopIteration: - return None - - def look(self): - next = self.lex() - if next is not None: - self.tokens = itertools.chain([next], self.tokens) - return next - - def parse_command(self): - tok = self.lex() - if not tok: - raise ValueError,"empty command!" - if isinstance(tok, tuple): - raise ValueError,"syntax error near unexpected token %r" % tok[0] - - args = [tok] - redirects = [] - while 1: - tok = self.look() - - # EOF? - if tok is None: - break - - # If this is an argument, just add it to the current command. - if isinstance(tok, str): - args.append(self.lex()) - continue - - # Otherwise see if it is a terminator. - assert isinstance(tok, tuple) - if tok[0] in ('|',';','&','||','&&'): - break - - # Otherwise it must be a redirection. - op = self.lex() - arg = self.lex() - if not arg: - raise ValueError,"syntax error near token %r" % op[0] - redirects.append((op, arg)) - - return Command(args, redirects) - - def parse_pipeline(self): - negate = False - if self.look() == ('!',): - self.lex() - negate = True - - commands = [self.parse_command()] - while self.look() == ('|',): - self.lex() - commands.append(self.parse_command()) - return Pipeline(commands, negate) - - def parse(self): - lhs = self.parse_pipeline() - - while self.look(): - operator = self.lex() - assert isinstance(operator, tuple) and len(operator) == 1 - - if not self.look(): - raise ValueError, "missing argument to operator %r" % operator[0] - - # FIXME: Operator precedence!! - lhs = Seq(lhs, operator[0], self.parse_pipeline()) - - return lhs - -### - -import unittest - -class TestShLexer(unittest.TestCase): - def lex(self, str, *args, **kwargs): - return list(ShLexer(str, *args, **kwargs).lex()) - - def test_basic(self): - self.assertEqual(self.lex('a|b>c&d<e'), - ['a', ('|',), 'b', ('>',), 'c', ('&',), 'd', - ('<',), 'e']) - - def test_redirection_tokens(self): - self.assertEqual(self.lex('a2>c'), - ['a2', ('>',), 'c']) - self.assertEqual(self.lex('a 2>c'), - ['a', ('>',2), 'c']) - - def test_quoting(self): - self.assertEqual(self.lex(""" 'a' """), - ['a']) - self.assertEqual(self.lex(""" "hello\\"world" """), - ['hello"world']) - self.assertEqual(self.lex(""" "hello\\'world" """), - ["hello\\'world"]) - self.assertEqual(self.lex(""" "hello\\\\world" """), - ["hello\\world"]) - self.assertEqual(self.lex(""" he"llo wo"rld """), - ["hello world"]) - self.assertEqual(self.lex(""" a\\ b a\\\\b """), - ["a b", "a\\b"]) - self.assertEqual(self.lex(""" "" "" """), - ["", ""]) - self.assertEqual(self.lex(""" a\\ b """, win32Escapes = True), - ['a\\', 'b']) - -class TestShParse(unittest.TestCase): - def parse(self, str): - return ShParser(str).parse() - - def test_basic(self): - self.assertEqual(self.parse('echo hello'), - Pipeline([Command(['echo', 'hello'], [])], False)) - self.assertEqual(self.parse('echo ""'), - Pipeline([Command(['echo', ''], [])], False)) - - def test_redirection(self): - self.assertEqual(self.parse('echo hello > c'), - Pipeline([Command(['echo', 'hello'], - [((('>'),), 'c')])], False)) - self.assertEqual(self.parse('echo hello > c >> d'), - Pipeline([Command(['echo', 'hello'], [(('>',), 'c'), - (('>>',), 'd')])], False)) - - def test_pipeline(self): - self.assertEqual(self.parse('a | b'), - Pipeline([Command(['a'], []), - Command(['b'], [])], - False)) - - self.assertEqual(self.parse('a | b | c'), - Pipeline([Command(['a'], []), - Command(['b'], []), - Command(['c'], [])], - False)) - - self.assertEqual(self.parse('! a'), - Pipeline([Command(['a'], [])], - True)) - - def test_list(self): - self.assertEqual(self.parse('a ; b'), - Seq(Pipeline([Command(['a'], [])], False), - ';', - Pipeline([Command(['b'], [])], False))) - - self.assertEqual(self.parse('a & b'), - Seq(Pipeline([Command(['a'], [])], False), - '&', - Pipeline([Command(['b'], [])], False))) - - self.assertEqual(self.parse('a && b'), - Seq(Pipeline([Command(['a'], [])], False), - '&&', - Pipeline([Command(['b'], [])], False))) - - self.assertEqual(self.parse('a || b'), - Seq(Pipeline([Command(['a'], [])], False), - '||', - Pipeline([Command(['b'], [])], False))) - - self.assertEqual(self.parse('a && b || c'), - Seq(Seq(Pipeline([Command(['a'], [])], False), - '&&', - Pipeline([Command(['b'], [])], False)), - '||', - Pipeline([Command(['c'], [])], False))) - -if __name__ == '__main__': - unittest.main() diff --git a/clang/utils/test/TestRunner.py b/clang/utils/test/TestRunner.py deleted file mode 100755 index 2fdede0c0d4..00000000000 --- a/clang/utils/test/TestRunner.py +++ /dev/null @@ -1,334 +0,0 @@ -import os -import platform -import re -import signal -import subprocess -import sys - -import ShUtil -import Util - -kSystemName = platform.system() - -class TestStatus: - Pass = 0 - XFail = 1 - Fail = 2 - XPass = 3 - Invalid = 4 - - kNames = ['Pass','XFail','Fail','XPass','Invalid'] - @staticmethod - def getName(code): - return TestStatus.kNames[code] - -def executeShCmd(cmd, cfg, cwd, results): - if isinstance(cmd, ShUtil.Seq): - if cmd.op == ';': - res = executeShCmd(cmd.lhs, cfg, cwd, results) - return executeShCmd(cmd.rhs, cfg, cwd, results) - - if cmd.op == '&': - raise NotImplementedError,"unsupported test command: '&'" - - if cmd.op == '||': - res = executeShCmd(cmd.lhs, cfg, cwd, results) - if res != 0: - res = executeShCmd(cmd.rhs, cfg, cwd, results) - return res - if cmd.op == '&&': - res = executeShCmd(cmd.lhs, cfg, cwd, results) - if res is None: - return res - - if res == 0: - res = executeShCmd(cmd.rhs, cfg, cwd, results) - return res - - raise ValueError,'Unknown shell command: %r' % cmd.op - - assert isinstance(cmd, ShUtil.Pipeline) - procs = [] - input = subprocess.PIPE - for j in cmd.commands: - # FIXME: This is broken, it doesn't account for the accumulative nature - # of redirects. - stdin = input - stdout = stderr = subprocess.PIPE - for r in j.redirects: - if r[0] == ('>',2): - stderr = open(r[1], 'w') - elif r[0] == ('>&',2) and r[1] == '1': - stderr = subprocess.STDOUT - elif r[0] == ('>',): - stdout = open(r[1], 'w') - elif r[0] == ('<',): - stdin = open(r[1], 'r') - else: - raise NotImplementedError,"Unsupported redirect: %r" % r - - procs.append(subprocess.Popen(j.args, cwd=cwd, - stdin = stdin, - stdout = stdout, - stderr = stderr, - env = cfg.environment)) - - # Immediately close stdin for any process taking stdin from us. - if stdin == subprocess.PIPE: - procs[-1].stdin.close() - procs[-1].stdin = None - - if stdout == subprocess.PIPE: - input = procs[-1].stdout - else: - input = subprocess.PIPE - - # FIXME: There is a potential for deadlock here, when we have a pipe and - # some process other than the last one ends up blocked on stderr. - procData = [None] * len(procs) - procData[-1] = procs[-1].communicate() - for i in range(len(procs) - 1): - if procs[i].stdout is not None: - out = procs[i].stdout.read() - else: - out = '' - if procs[i].stderr is not None: - err = procs[i].stderr.read() - else: - err = '' - procData[i] = (out,err) - - # FIXME: Fix tests to work with pipefail, and make exitCode max across - # procs. - for i,(out,err) in enumerate(procData): - exitCode = res = procs[i].wait() - results.append((cmd.commands[i], out, err, res)) - - if cmd.negate: - exitCode = not exitCode - - return exitCode - -def executeScriptInternal(cfg, commands, cwd): - cmd = ShUtil.ShParser(' &&\n'.join(commands), - kSystemName == 'Windows').parse() - - results = [] - try: - exitCode = executeShCmd(cmd, cfg, cwd, results) - except: - import traceback - - out = '' - err = 'Exception during script execution:\n%s\n' % traceback.format_exc() - return out, err, 127 - - out = err = '' - for i,(cmd, cmd_out,cmd_err,res) in enumerate(results): - out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args)) - out += 'Command %d Result: %r\n' % (i, res) - out += 'Command %d Output:\n%s\n\n' % (i, cmd_out) - out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err) - - return out, err, exitCode - -def executeScript(cfg, script, commands, cwd): - # Write script file - f = open(script,'w') - if kSystemName == 'Windows': - f.write('\nif %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands)) - else: - f.write(' &&\n'.join(commands)) - f.write('\n') - f.close() - - if kSystemName == 'Windows': - command = ['cmd','/c', script] - else: - command = ['/bin/sh', script] - if cfg.useValgrind: - # FIXME: Running valgrind on sh is overkill. We probably could just - # run on clang with no real loss. - valgrindArgs = ['valgrind', '-q', - '--tool=memcheck', '--trace-children=yes', - '--error-exitcode=123'] + cfg.valgrindArgs - command = valgrindArgs + command - - p = subprocess.Popen(command, cwd=cwd, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env=cfg.environment) - out,err = p.communicate() - exitCode = p.wait() - - return out, err, exitCode - -import StringIO -def runOneTest(cfg, testPath, tmpBase): - # Make paths absolute. - tmpBase = os.path.abspath(tmpBase) - testPath = os.path.abspath(testPath) - - # Create the output directory if it does not already exist. - - Util.mkdir_p(os.path.dirname(tmpBase)) - script = tmpBase + '.script' - if kSystemName == 'Windows': - script += '.bat' - - substitutions = [('%s', testPath), - ('%S', os.path.dirname(testPath)), - ('%t', tmpBase + '.tmp'), - (' clang ', ' ' + cfg.clang + ' '), - (' clang-cc ', ' ' + cfg.clangcc + ' ')] - - # Collect the test lines from the script. - scriptLines = [] - xfailLines = [] - for ln in open(testPath): - if 'RUN:' in ln: - # Isolate the command to run. - index = ln.index('RUN:') - ln = ln[index+4:] - - # Strip trailing newline. - scriptLines.append(ln) - elif 'XFAIL' in ln: - xfailLines.append(ln) - - # FIXME: Support something like END, in case we need to process large - # files. - - # Verify the script contains a run line. - if not scriptLines: - return (TestStatus.Fail, "Test has no run line!") - - # Apply substitutions to the script. - def processLine(ln): - # Apply substitutions - for a,b in substitutions: - ln = ln.replace(a,b) - - # Strip the trailing newline and any extra whitespace. - return ln.strip() - scriptLines = map(processLine, scriptLines) - - # Validate interior lines for '&&', a lovely historical artifact. - for i in range(len(scriptLines) - 1): - ln = scriptLines[i] - - if not ln.endswith('&&'): - return (TestStatus.Fail, - ("MISSING \'&&\': %s\n" + - "FOLLOWED BY : %s\n") % (ln, scriptLines[i + 1])) - - # Strip off '&&' - scriptLines[i] = ln[:-2] - - if not cfg.useExternalShell: - res = executeScriptInternal(cfg, scriptLines, os.path.dirname(testPath)) - - if res is not None: - out, err, exitCode = res - elif True: - return (TestStatus.Fail, - "Unable to execute internally:\n%s\n" - % '\n'.join(scriptLines)) - else: - out, err, exitCode = executeScript(cfg, script, scriptLines, - os.path.dirname(testPath)) - else: - out, err, exitCode = executeScript(cfg, script, scriptLines, - os.path.dirname(testPath)) - - # Detect Ctrl-C in subprocess. - if exitCode == -signal.SIGINT: - raise KeyboardInterrupt - - if xfailLines: - ok = exitCode != 0 - status = (TestStatus.XPass, TestStatus.XFail)[ok] - else: - ok = exitCode == 0 - status = (TestStatus.Fail, TestStatus.Pass)[ok] - - if ok: - return (status,'') - - output = StringIO.StringIO() - print >>output, "Script:" - print >>output, "--" - print >>output, '\n'.join(scriptLines) - print >>output, "--" - print >>output, "Exit Code: %r" % exitCode - print >>output, "Command Output (stdout):" - print >>output, "--" - output.write(out) - print >>output, "--" - print >>output, "Command Output (stderr):" - print >>output, "--" - output.write(err) - print >>output, "--" - return (status, output.getvalue()) - -def capture(args): - p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out,_ = p.communicate() - return out - -def inferClang(cfg): - # Determine which clang to use. - clang = os.getenv('CLANG') - - # If the user set clang in the environment, definitely use that and don't - # try to validate. - if clang: - return clang - - # Otherwise look in the path. - clang = Util.which('clang', cfg.environment['PATH']) - - if not clang: - print >>sys.stderr, "error: couldn't find 'clang' program, try setting CLANG in your environment" - sys.exit(1) - - return clang - -def inferClangCC(cfg, clang): - clangcc = os.getenv('CLANGCC') - - # If the user set clang in the environment, definitely use that and don't - # try to validate. - if clangcc: - return clangcc - - # Otherwise try adding -cc since we expect to be looking in a build - # directory. - if clang.endswith('.exe'): - clangccName = clang[:-4] + '-cc.exe' - else: - clangccName = clang + '-cc' - clangcc = Util.which(clangccName, cfg.environment['PATH']) - if not clangcc: - # Otherwise ask clang. - res = capture([clang, '-print-prog-name=clang-cc']) - res = res.strip() - if res and os.path.exists(res): - clangcc = res - - if not clangcc: - print >>sys.stderr, "error: couldn't find 'clang-cc' program, try setting CLANGCC in your environment" - sys.exit(1) - - return clangcc - -def getTestOutputBase(dir, testpath): - """getTestOutputBase(dir, testpath) - Get the full path for temporary files - corresponding to the given test path.""" - - # Form the output base out of the test parent directory name and the test - # name. FIXME: Find a better way to organize test results. - return os.path.join(dir, - os.path.basename(os.path.dirname(testpath)), - os.path.basename(testpath)) diff --git a/clang/utils/test/TestingConfig.py b/clang/utils/test/TestingConfig.py deleted file mode 100644 index b611d78e14d..00000000000 --- a/clang/utils/test/TestingConfig.py +++ /dev/null @@ -1,27 +0,0 @@ -class TestingConfig: - """" - TestingConfig - Information on a how to run a group of tests. - """ - - @staticmethod - def frompath(path): - data = {} - f = open(path) - exec f in {},data - - return TestingConfig(suffixes = data.get('suffixes', []), - environment = data.get('environment', {})) - - def __init__(self, suffixes, environment): - self.suffixes = set(suffixes) - self.environment = dict(environment) - - # Variables set internally. - self.root = None - self.useValgrind = None - self.useExternalShell = None - self.valgrindArgs = [] - - # FIXME: These need to move into a substitutions mechanism. - self.clang = None - self.clangcc = None diff --git a/clang/utils/test/Util.py b/clang/utils/test/Util.py deleted file mode 100644 index 66cbd0dfa52..00000000000 --- a/clang/utils/test/Util.py +++ /dev/null @@ -1,70 +0,0 @@ -import errno, os, sys - -def warning(msg): - print >>sys.stderr, '%s: warning: %s' % (sys.argv[0], msg) - -def detectCPUs(): - """ - Detects the number of CPUs on a system. Cribbed from pp. - """ - # Linux, Unix and MacOS: - if hasattr(os, "sysconf"): - if os.sysconf_names.has_key("SC_NPROCESSORS_ONLN"): - # Linux & Unix: - ncpus = os.sysconf("SC_NPROCESSORS_ONLN") - if isinstance(ncpus, int) and ncpus > 0: - return ncpus - else: # OSX: - return int(os.popen2("sysctl -n hw.ncpu")[1].read()) - # Windows: - if os.environ.has_key("NUMBER_OF_PROCESSORS"): - ncpus = int(os.environ["NUMBER_OF_PROCESSORS"]); - if ncpus > 0: - return ncpus - return 1 # Default - -def mkdir_p(path): - """mkdir_p(path) - Make the "path" directory, if it does not exist; this - will also make directories for any missing parent directories.""" - - if not path or os.path.exists(path): - return - - parent = os.path.dirname(path) - if parent != path: - mkdir_p(parent) - - try: - os.mkdir(path) - except OSError,e: - # Ignore EEXIST, which may occur during a race condition. - if e.errno != errno.EEXIST: - raise - -def which(command, paths = None): - """which(command, [paths]) - Look up the given command in the paths string (or - the PATH environment variable, if unspecified).""" - - if paths is None: - paths = os.environ.get('PATH','') - - # Check for absolute match first. - if os.path.exists(command): - return command - - # Would be nice if Python had a lib function for this. - if not paths: - paths = os.defpath - - # Get suffixes to search. - pathext = os.environ.get('PATHEXT', '').split(os.pathsep) - - # Search the paths... - for path in paths.split(os.pathsep): - for ext in pathext: - p = os.path.join(path, command + ext) - if os.path.exists(p): - return p - - return None - |