Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/env python2 | |
| 2 | |
| 3 import argparse | |
| 4 import os | |
| 5 import shutil | |
| 6 import sys | |
| 7 | |
| 8 from utils import shellcmd | |
| 9 from utils import FindBaseNaCl | |
| 10 | |
| 11 def Match(desc, includes, excludes, default_match): | |
| 12 """Determines whether desc is a match against includes and excludes. | |
| 13 | |
| 14 'desc' is a set of attributes, and 'includes' and 'excludes' are lists of sets | |
| 15 of attributes. | |
| 16 | |
| 17 If 'desc' matches any element from 'excludes', the result is False. | |
| 18 Otherwise, if 'desc' matches any element from 'includes', the result is True. | |
| 19 Otherwise, the 'default_match' value is returned. | |
| 20 """ | |
| 21 for exclude in excludes: | |
| 22 if exclude < desc: | |
| 23 return False | |
| 24 for include in includes: | |
| 25 if include < desc: | |
| 26 return True | |
| 27 return default_match | |
| 28 | |
| 29 def main(): | |
| 30 """Framework for cross test generation and execution. | |
| 31 | |
| 32 Builds and executes cross tests from the space of all possible attribute | |
| 33 combinations. The space can be restricted by providing subsets of attributes | |
| 34 to specifically include or exclude. | |
| 35 """ | |
| 36 # Defines the set of tests and each test's inputs. Each test maps to a | |
| 37 # dictionary containing a single driver file, one or more test source files, | |
| 38 # and an optional list of crosstest.py flags for special cases. | |
| 39 tests = { | |
|
Mircea Trofin
2015/03/08 16:23:30
will this list potentially grow? If so, is the exp
Jim Stichnoth
2015/03/09 18:16:16
Good point that I should try not to hard-code the
| |
| 40 'simple_loop' : { | |
| 41 'driver' : 'simple_loop_main.c', | |
| 42 'test' : [ 'simple_loop.c' ] | |
| 43 }, | |
| 44 'mem_intrin' : { | |
| 45 'driver' : 'mem_intrin_main.cpp', | |
| 46 'test' : [ 'mem_intrin.cpp' ] | |
| 47 }, | |
| 48 'test_arith' : { | |
| 49 'driver' : 'test_arith_main.cpp', | |
| 50 'test' : [ 'test_arith.cpp', 'test_arith_frem.ll', 'test_arith_sqrt.ll' ] | |
| 51 }, | |
| 52 'test_bitmanip' : { | |
| 53 'driver' : 'test_bitmanip_main.cpp', | |
| 54 'test' : [ 'test_bitmanip.cpp', 'test_bitmanip_intrin.ll' ] | |
| 55 }, | |
| 56 'test_calling_conv' : { | |
| 57 'driver' : 'test_calling_conv_main.cpp', | |
| 58 'test' : [ 'test_calling_conv.cpp' ] | |
| 59 }, | |
| 60 'test_cast' : { | |
| 61 'driver' : 'test_cast_main.cpp', | |
| 62 'test' : [ 'test_cast.cpp', 'test_cast_to_u1.ll', 'test_cast_vectors.ll' ] | |
| 63 }, | |
| 64 'test_fcmp' : { | |
| 65 'driver' : 'test_fcmp_main.cpp', | |
| 66 'test' : [ 'test_fcmp.pnacl.ll' ] | |
| 67 }, | |
| 68 'test_global' : { | |
| 69 'driver' : 'test_global_main.cpp', | |
| 70 'test' : [ 'test_global.cpp' ] | |
| 71 }, | |
| 72 'test_icmp' : { | |
| 73 'driver' : 'test_icmp_main.cpp', | |
| 74 'test' : [ 'test_icmp.cpp', 'test_icmp_i1vec.ll' ] | |
| 75 }, | |
| 76 'test_select' : { | |
| 77 'driver' : 'test_select_main.cpp', | |
| 78 'test' : [ 'test_select.ll' ] | |
| 79 }, | |
| 80 'test_stacksave' : { | |
| 81 'driver' : 'test_stacksave_main.c', | |
| 82 'test' : [ 'test_stacksave.c' ] | |
| 83 }, | |
| 84 'test_sync_atomic' : { | |
| 85 'driver' : 'test_sync_atomic_main.cpp', | |
| 86 # Compile the non-subzero object files straight from source since the | |
| 87 # native LLVM backend does not understand how to lower NaCl-specific | |
| 88 # intrinsics. | |
| 89 'flags' : [ '--crosstest-bitcode=0' ], | |
| 90 'test' : [ 'test_sync_atomic.cpp' ] | |
| 91 }, | |
| 92 'test_vector_ops' : { | |
| 93 'driver' : 'test_vector_ops_main.cpp', | |
| 94 'test' : [ 'test_vector_ops.ll' ] | |
| 95 }, | |
| 96 } | |
| 97 # The rest of the attribute sets. | |
| 98 targets = [ 'x8632' ] | |
| 99 sandboxing = [ 'native', 'sandbox' ] | |
| 100 opt_levels = [ 'Om1', 'O2' ] | |
| 101 arch_attrs = [ 'sse2', 'sse4.1' ] | |
| 102 # all_keys is only used in the help text. | |
| 103 all_keys = '; '.join([' '.join(sorted(tests.keys())), ' '.join(targets), | |
| 104 ' '.join(sandboxing), ' '.join(opt_levels), | |
| 105 ' '.join(arch_attrs)]) | |
| 106 | |
| 107 root = FindBaseNaCl() | |
| 108 argparser = argparse.ArgumentParser( | |
| 109 description=' ' + main.__doc__ + | |
| 110 'The set of attributes is the following:\n\n' + all_keys, | |
| 111 formatter_class=argparse.RawTextHelpFormatter) | |
| 112 argparser.add_argument('--include', '-i', default=[], dest='include', | |
| 113 action='append', metavar='ATTR_LIST', | |
| 114 help='Attributes to include (comma-separated). ' + | |
| 115 'Can be used multiple times.') | |
| 116 argparser.add_argument('--exclude', '-e', default=[], dest='exclude', | |
| 117 action='append', metavar='ATTR_LIST', | |
| 118 help='Attributes to include (comma-separated). ' + | |
| 119 'Can be used multiple times.') | |
| 120 argparser.add_argument('--verbose', '-v', default=False, action='store_true', | |
| 121 help='Use verbose output') | |
| 122 argparser.add_argument('--defer', default=False, action='store_true', | |
| 123 help='Defer execution until all executables are built') | |
| 124 argparser.add_argument('--no-compile', '-n', default=False, | |
| 125 action='store_true', | |
| 126 help="Don't build; reuse binaries from the last run") | |
| 127 argparser.add_argument('--dir', dest='dir', metavar='DIRECTORY', | |
| 128 default=('{root}/toolchain_build/src/subzero/' + | |
| 129 'crosstest/Output').format(root=root), | |
| 130 help='Output directory') | |
| 131 argparser.add_argument('--lit', default=False, action='store_true', | |
| 132 help='Generate files for lit testing') | |
| 133 args = argparser.parse_args() | |
| 134 # includes and excludes are both lists of sets. | |
| 135 includes = [ set(item.split(',')) for item in args.include ] | |
| 136 excludes = [ set(item.split(',')) for item in args.exclude ] | |
| 137 # If any --include args are provided, the default is to not match. | |
| 138 default_match = not args.include | |
| 139 | |
| 140 # Delete and recreate the output directory, unless --no-compile was specified. | |
| 141 if not args.no_compile: | |
| 142 if os.path.exists(args.dir): | |
| 143 if os.path.isdir(args.dir): | |
| 144 shutil.rmtree(args.dir) | |
| 145 else: | |
| 146 os.remove(args.dir) | |
| 147 if not os.path.exists(args.dir): | |
| 148 os.makedirs(args.dir) | |
| 149 | |
| 150 # pypath is where to find other Subzero python scripts. | |
| 151 pypath = os.path.abspath(os.path.dirname(sys.argv[0])) | |
| 152 # Run from the crosstest directory to make it easy to grab inputs. | |
| 153 crosstest_dir = '{root}/toolchain_build/src/subzero/crosstest'.format( | |
| 154 root=root) | |
| 155 os.chdir(crosstest_dir) | |
| 156 # If --defer is specified, collect the run commands into deferred_cmds for | |
| 157 # later execution. | |
| 158 deferred_cmds = [] | |
| 159 for test in sorted(tests.keys()): | |
| 160 for target in targets: | |
| 161 for sb in sandboxing: | |
| 162 for opt in opt_levels: | |
| 163 for attr in arch_attrs: | |
| 164 desc = [ test, target, sb, opt, attr ] | |
| 165 if Match(set(desc), includes, excludes, default_match): | |
| 166 exe = '{test}_{target}_{sb}_{opt}_{attr}'.format( | |
| 167 test=test, target=target, sb=sb, opt=opt, | |
| 168 attr=attr) | |
| 169 extra = tests[test]['flags'] if 'flags' in tests[test] else [] | |
|
jvoung (off chromium)
2015/03/09 17:34:21
Could probably have done "tests[test].get('flags',
Jim Stichnoth
2015/03/09 18:16:16
Hmm, nice. Unfortunately, I don't think there's a
jvoung (off chromium)
2015/03/09 20:34:59
Hmm I don't see anything like that for ConfigParse
| |
| 170 # Generate the compile command. | |
| 171 cmp_cmd = ['{path}/crosstest.py'.format(path=pypath), | |
| 172 '-{opt}'.format(opt=opt), | |
| 173 '--mattr={attr}'.format(attr=attr), | |
| 174 '--prefix=Subzero_', | |
| 175 '--target={target}'.format(target=target), | |
| 176 '--sandbox={sb}'.format(sb='1' if sb=='sandbox' | |
| 177 else '0'), | |
| 178 '--dir={dir}'.format(dir=args.dir), | |
| 179 '--output={exe}'.format(exe=exe), | |
| 180 '--driver={drv}'.format(drv=tests[test]['driver']), | |
| 181 ] + extra + \ | |
| 182 [ '--test=' + t for t in tests[test]['test'] ] | |
| 183 run_cmd_base = os.path.join(args.dir, exe) | |
| 184 # Generate the run command. | |
| 185 run_cmd = run_cmd_base | |
| 186 if sb == 'sandbox': | |
| 187 run_cmd = '{root}/run.py -q '.format(root=root) + run_cmd | |
| 188 if args.lit: | |
| 189 # Create a file to drive the lit test. | |
| 190 with open(run_cmd_base + '.xtest', 'w') as f: | |
| 191 f.write('# RUN: sh %s | FileCheck %s\n') | |
| 192 f.write('cd ' + crosstest_dir + ' && \\\n') | |
| 193 f.write(' '.join(cmp_cmd) + ' && \\\n') | |
| 194 f.write(run_cmd + '\n') | |
| 195 f.write('echo Recreate a failure using ' + __file__ + | |
| 196 ' --include=' + ','.join(desc) + '\n') | |
| 197 f.write('# CHECK: Failures=0\n') | |
| 198 else: | |
| 199 if not args.no_compile: | |
| 200 shellcmd(cmp_cmd, | |
| 201 echo=args.verbose) | |
| 202 if (args.defer): | |
| 203 deferred_cmds.append(run_cmd) | |
| 204 else: | |
| 205 shellcmd(run_cmd, echo=True) | |
| 206 for run_cmd in deferred_cmds: | |
| 207 shellcmd(run_cmd, echo=True) | |
| 208 | |
| 209 if __name__ == '__main__': | |
| 210 main() | |
| OLD | NEW |