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