| Index: pydir/crosstest_generator.py
|
| diff --git a/pydir/crosstest_generator.py b/pydir/crosstest_generator.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..3038f4ced26899801e3df2d95de39956877c85c6
|
| --- /dev/null
|
| +++ b/pydir/crosstest_generator.py
|
| @@ -0,0 +1,165 @@
|
| +#!/usr/bin/env python2
|
| +
|
| +import argparse
|
| +import ConfigParser
|
| +import os
|
| +import shutil
|
| +import sys
|
| +
|
| +from utils import shellcmd
|
| +from utils import FindBaseNaCl
|
| +
|
| +def Match(desc, includes, excludes, default_match):
|
| + """Determines whether desc is a match against includes and excludes.
|
| +
|
| + 'desc' is a set of attributes, and 'includes' and 'excludes' are lists of sets
|
| + of attributes.
|
| +
|
| + If 'desc' matches any element from 'excludes', the result is False.
|
| + Otherwise, if 'desc' matches any element from 'includes', the result is True.
|
| + Otherwise, the 'default_match' value is returned.
|
| + """
|
| + for exclude in excludes:
|
| + if exclude < desc:
|
| + return False
|
| + for include in includes:
|
| + if include < desc:
|
| + return True
|
| + return default_match
|
| +
|
| +def main():
|
| + """Framework for cross test generation and execution.
|
| +
|
| + Builds and executes cross tests from the space of all possible attribute
|
| + combinations. The space can be restricted by providing subsets of attributes
|
| + to specifically include or exclude.
|
| + """
|
| + # pypath is where to find other Subzero python scripts.
|
| + pypath = os.path.abspath(os.path.dirname(sys.argv[0]))
|
| + root = FindBaseNaCl()
|
| +
|
| + # The rest of the attribute sets.
|
| + targets = [ 'x8632' ]
|
| + sandboxing = [ 'native', 'sandbox' ]
|
| + opt_levels = [ 'Om1', 'O2' ]
|
| + arch_attrs = [ 'sse2', 'sse4.1' ]
|
| + # all_keys is only used in the help text.
|
| + all_keys = '; '.join([' '.join(targets), ' '.join(sandboxing),
|
| + ' '.join(opt_levels), ' '.join(arch_attrs)])
|
| +
|
| + argparser = argparse.ArgumentParser(
|
| + description=' ' + main.__doc__ +
|
| + 'The set of attributes is the set of tests plus the following:\n' +
|
| + all_keys, formatter_class=argparse.RawTextHelpFormatter)
|
| + argparser.add_argument('--config', default='crosstest.cfg', dest='config',
|
| + metavar='FILE', help='Test configuration file')
|
| + argparser.add_argument('--print-tests', default=False, action='store_true',
|
| + help='Print the set of test names and exit')
|
| + argparser.add_argument('--include', '-i', default=[], dest='include',
|
| + action='append', metavar='ATTR_LIST',
|
| + help='Attributes to include (comma-separated). ' +
|
| + 'Can be used multiple times.')
|
| + argparser.add_argument('--exclude', '-e', default=[], dest='exclude',
|
| + action='append', metavar='ATTR_LIST',
|
| + help='Attributes to include (comma-separated). ' +
|
| + 'Can be used multiple times.')
|
| + argparser.add_argument('--verbose', '-v', default=False, action='store_true',
|
| + help='Use verbose output')
|
| + argparser.add_argument('--defer', default=False, action='store_true',
|
| + help='Defer execution until all executables are built')
|
| + argparser.add_argument('--no-compile', '-n', default=False,
|
| + action='store_true',
|
| + help="Don't build; reuse binaries from the last run")
|
| + argparser.add_argument('--dir', dest='dir', metavar='DIRECTORY',
|
| + default=('{root}/toolchain_build/src/subzero/' +
|
| + 'crosstest/Output').format(root=root),
|
| + help='Output directory')
|
| + argparser.add_argument('--lit', default=False, action='store_true',
|
| + help='Generate files for lit testing')
|
| + args = argparser.parse_args()
|
| +
|
| + # Run from the crosstest directory to make it easy to grab inputs.
|
| + crosstest_dir = '{root}/toolchain_build/src/subzero/crosstest'.format(
|
| + root=root)
|
| + os.chdir(crosstest_dir)
|
| +
|
| + tests = ConfigParser.RawConfigParser()
|
| + tests.read('crosstest.cfg')
|
| +
|
| + if args.print_tests:
|
| + print 'Test name attributes: ' + ' '.join(sorted(tests.sections()))
|
| + sys.exit(0)
|
| +
|
| + # includes and excludes are both lists of sets.
|
| + includes = [ set(item.split(',')) for item in args.include ]
|
| + excludes = [ set(item.split(',')) for item in args.exclude ]
|
| + # If any --include args are provided, the default is to not match.
|
| + default_match = not args.include
|
| +
|
| + # Delete and recreate the output directory, unless --no-compile was specified.
|
| + if not args.no_compile:
|
| + if os.path.exists(args.dir):
|
| + if os.path.isdir(args.dir):
|
| + shutil.rmtree(args.dir)
|
| + else:
|
| + os.remove(args.dir)
|
| + if not os.path.exists(args.dir):
|
| + os.makedirs(args.dir)
|
| +
|
| + # If --defer is specified, collect the run commands into deferred_cmds for
|
| + # later execution.
|
| + deferred_cmds = []
|
| + for test in sorted(tests.sections()):
|
| + for target in targets:
|
| + for sb in sandboxing:
|
| + for opt in opt_levels:
|
| + for attr in arch_attrs:
|
| + desc = [ test, target, sb, opt, attr ]
|
| + if Match(set(desc), includes, excludes, default_match):
|
| + exe = '{test}_{target}_{sb}_{opt}_{attr}'.format(
|
| + test=test, target=target, sb=sb, opt=opt,
|
| + attr=attr)
|
| + extra = (tests.get(test, 'flags').split(' ')
|
| + if tests.has_option(test, 'flags') else [])
|
| + # Generate the compile command.
|
| + cmp_cmd = ['{path}/crosstest.py'.format(path=pypath),
|
| + '-{opt}'.format(opt=opt),
|
| + '--mattr={attr}'.format(attr=attr),
|
| + '--prefix=Subzero_',
|
| + '--target={target}'.format(target=target),
|
| + '--sandbox={sb}'.format(sb='1' if sb=='sandbox'
|
| + else '0'),
|
| + '--dir={dir}'.format(dir=args.dir),
|
| + '--output={exe}'.format(exe=exe),
|
| + '--driver={drv}'.format(drv=tests.get(test, 'driver')),
|
| + ] + extra + \
|
| + [ '--test=' + t
|
| + for t in tests.get(test, 'test').split(' ') ]
|
| + run_cmd_base = os.path.join(args.dir, exe)
|
| + # Generate the run command.
|
| + run_cmd = run_cmd_base
|
| + if sb == 'sandbox':
|
| + run_cmd = '{root}/run.py -q '.format(root=root) + run_cmd
|
| + if args.lit:
|
| + # Create a file to drive the lit test.
|
| + with open(run_cmd_base + '.xtest', 'w') as f:
|
| + f.write('# RUN: sh %s | FileCheck %s\n')
|
| + f.write('cd ' + crosstest_dir + ' && \\\n')
|
| + f.write(' '.join(cmp_cmd) + ' && \\\n')
|
| + f.write(run_cmd + '\n')
|
| + f.write('echo Recreate a failure using ' + __file__ +
|
| + ' --include=' + ','.join(desc) + '\n')
|
| + f.write('# CHECK: Failures=0\n')
|
| + else:
|
| + if not args.no_compile:
|
| + shellcmd(cmp_cmd,
|
| + echo=args.verbose)
|
| + if (args.defer):
|
| + deferred_cmds.append(run_cmd)
|
| + else:
|
| + shellcmd(run_cmd, echo=True)
|
| + for run_cmd in deferred_cmds:
|
| + shellcmd(run_cmd, echo=True)
|
| +
|
| +if __name__ == '__main__':
|
| + main()
|
|
|