OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python2 |
| 2 |
| 3 import argparse |
| 4 import ConfigParser |
| 5 import os |
| 6 import shutil |
| 7 import sys |
| 8 |
| 9 from utils import shellcmd |
| 10 from utils import FindBaseNaCl |
| 11 |
| 12 def Match(desc, includes, excludes, default_match): |
| 13 """Determines whether desc is a match against includes and excludes. |
| 14 |
| 15 'desc' is a set of attributes, and 'includes' and 'excludes' are lists of sets |
| 16 of attributes. |
| 17 |
| 18 If 'desc' matches any element from 'excludes', the result is False. |
| 19 Otherwise, if 'desc' matches any element from 'includes', the result is True. |
| 20 Otherwise, the 'default_match' value is returned. |
| 21 """ |
| 22 for exclude in excludes: |
| 23 if exclude < desc: |
| 24 return False |
| 25 for include in includes: |
| 26 if include < desc: |
| 27 return True |
| 28 return default_match |
| 29 |
| 30 def main(): |
| 31 """Framework for cross test generation and execution. |
| 32 |
| 33 Builds and executes cross tests from the space of all possible attribute |
| 34 combinations. The space can be restricted by providing subsets of attributes |
| 35 to specifically include or exclude. |
| 36 """ |
| 37 # pypath is where to find other Subzero python scripts. |
| 38 pypath = os.path.abspath(os.path.dirname(sys.argv[0])) |
| 39 root = FindBaseNaCl() |
| 40 |
| 41 # The rest of the attribute sets. |
| 42 targets = [ 'x8632' ] |
| 43 sandboxing = [ 'native', 'sandbox' ] |
| 44 opt_levels = [ 'Om1', 'O2' ] |
| 45 arch_attrs = [ 'sse2', 'sse4.1' ] |
| 46 # all_keys is only used in the help text. |
| 47 all_keys = '; '.join([' '.join(targets), ' '.join(sandboxing), |
| 48 ' '.join(opt_levels), ' '.join(arch_attrs)]) |
| 49 |
| 50 argparser = argparse.ArgumentParser( |
| 51 description=' ' + main.__doc__ + |
| 52 'The set of attributes is the set of tests plus the following:\n' + |
| 53 all_keys, formatter_class=argparse.RawTextHelpFormatter) |
| 54 argparser.add_argument('--config', default='crosstest.cfg', dest='config', |
| 55 metavar='FILE', help='Test configuration file') |
| 56 argparser.add_argument('--print-tests', default=False, action='store_true', |
| 57 help='Print the set of test names and exit') |
| 58 argparser.add_argument('--include', '-i', default=[], dest='include', |
| 59 action='append', metavar='ATTR_LIST', |
| 60 help='Attributes to include (comma-separated). ' + |
| 61 'Can be used multiple times.') |
| 62 argparser.add_argument('--exclude', '-e', default=[], dest='exclude', |
| 63 action='append', metavar='ATTR_LIST', |
| 64 help='Attributes to include (comma-separated). ' + |
| 65 'Can be used multiple times.') |
| 66 argparser.add_argument('--verbose', '-v', default=False, action='store_true', |
| 67 help='Use verbose output') |
| 68 argparser.add_argument('--defer', default=False, action='store_true', |
| 69 help='Defer execution until all executables are built') |
| 70 argparser.add_argument('--no-compile', '-n', default=False, |
| 71 action='store_true', |
| 72 help="Don't build; reuse binaries from the last run") |
| 73 argparser.add_argument('--dir', dest='dir', metavar='DIRECTORY', |
| 74 default=('{root}/toolchain_build/src/subzero/' + |
| 75 'crosstest/Output').format(root=root), |
| 76 help='Output directory') |
| 77 argparser.add_argument('--lit', default=False, action='store_true', |
| 78 help='Generate files for lit testing') |
| 79 args = argparser.parse_args() |
| 80 |
| 81 # Run from the crosstest directory to make it easy to grab inputs. |
| 82 crosstest_dir = '{root}/toolchain_build/src/subzero/crosstest'.format( |
| 83 root=root) |
| 84 os.chdir(crosstest_dir) |
| 85 |
| 86 tests = ConfigParser.RawConfigParser() |
| 87 tests.read('crosstest.cfg') |
| 88 |
| 89 if args.print_tests: |
| 90 print 'Test name attributes: ' + ' '.join(sorted(tests.sections())) |
| 91 sys.exit(0) |
| 92 |
| 93 # includes and excludes are both lists of sets. |
| 94 includes = [ set(item.split(',')) for item in args.include ] |
| 95 excludes = [ set(item.split(',')) for item in args.exclude ] |
| 96 # If any --include args are provided, the default is to not match. |
| 97 default_match = not args.include |
| 98 |
| 99 # Delete and recreate the output directory, unless --no-compile was specified. |
| 100 if not args.no_compile: |
| 101 if os.path.exists(args.dir): |
| 102 if os.path.isdir(args.dir): |
| 103 shutil.rmtree(args.dir) |
| 104 else: |
| 105 os.remove(args.dir) |
| 106 if not os.path.exists(args.dir): |
| 107 os.makedirs(args.dir) |
| 108 |
| 109 # If --defer is specified, collect the run commands into deferred_cmds for |
| 110 # later execution. |
| 111 deferred_cmds = [] |
| 112 for test in sorted(tests.sections()): |
| 113 for target in targets: |
| 114 for sb in sandboxing: |
| 115 for opt in opt_levels: |
| 116 for attr in arch_attrs: |
| 117 desc = [ test, target, sb, opt, attr ] |
| 118 if Match(set(desc), includes, excludes, default_match): |
| 119 exe = '{test}_{target}_{sb}_{opt}_{attr}'.format( |
| 120 test=test, target=target, sb=sb, opt=opt, |
| 121 attr=attr) |
| 122 extra = (tests.get(test, 'flags').split(' ') |
| 123 if tests.has_option(test, 'flags') else []) |
| 124 # Generate the compile command. |
| 125 cmp_cmd = ['{path}/crosstest.py'.format(path=pypath), |
| 126 '-{opt}'.format(opt=opt), |
| 127 '--mattr={attr}'.format(attr=attr), |
| 128 '--prefix=Subzero_', |
| 129 '--target={target}'.format(target=target), |
| 130 '--sandbox={sb}'.format(sb='1' if sb=='sandbox' |
| 131 else '0'), |
| 132 '--dir={dir}'.format(dir=args.dir), |
| 133 '--output={exe}'.format(exe=exe), |
| 134 '--driver={drv}'.format(drv=tests.get(test, 'driver')), |
| 135 ] + extra + \ |
| 136 [ '--test=' + t |
| 137 for t in tests.get(test, 'test').split(' ') ] |
| 138 run_cmd_base = os.path.join(args.dir, exe) |
| 139 # Generate the run command. |
| 140 run_cmd = run_cmd_base |
| 141 if sb == 'sandbox': |
| 142 run_cmd = '{root}/run.py -q '.format(root=root) + run_cmd |
| 143 if args.lit: |
| 144 # Create a file to drive the lit test. |
| 145 with open(run_cmd_base + '.xtest', 'w') as f: |
| 146 f.write('# RUN: sh %s | FileCheck %s\n') |
| 147 f.write('cd ' + crosstest_dir + ' && \\\n') |
| 148 f.write(' '.join(cmp_cmd) + ' && \\\n') |
| 149 f.write(run_cmd + '\n') |
| 150 f.write('echo Recreate a failure using ' + __file__ + |
| 151 ' --include=' + ','.join(desc) + '\n') |
| 152 f.write('# CHECK: Failures=0\n') |
| 153 else: |
| 154 if not args.no_compile: |
| 155 shellcmd(cmp_cmd, |
| 156 echo=args.verbose) |
| 157 if (args.defer): |
| 158 deferred_cmds.append(run_cmd) |
| 159 else: |
| 160 shellcmd(run_cmd, echo=True) |
| 161 for run_cmd in deferred_cmds: |
| 162 shellcmd(run_cmd, echo=True) |
| 163 |
| 164 if __name__ == '__main__': |
| 165 main() |
OLD | NEW |