blob: b5d64ab67679d71b5168baeab9c48ccff28e0a37 [file] [log] [blame]
Jim Stichnothdc7c5972015-03-10 11:17:15 -07001#!/usr/bin/env python2
2
3import argparse
4import ConfigParser
5import os
6import shutil
7import sys
8
9from utils import shellcmd
10from utils import FindBaseNaCl
11
12def 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:
Jim Stichnoth833f13f2015-03-18 08:59:23 -070023 if exclude <= desc:
Jim Stichnothdc7c5972015-03-10 11:17:15 -070024 return False
25 for include in includes:
Jim Stichnoth833f13f2015-03-18 08:59:23 -070026 if include <= desc:
Jim Stichnothdc7c5972015-03-10 11:17:15 -070027 return True
28 return default_match
29
Jan Voung8e32fed2015-06-17 10:16:23 -070030
31def 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
Jim Stichnothdc7c5972015-03-10 11:17:15 -070046def main():
47 """Framework for cross test generation and execution.
48
49 Builds and executes cross tests from the space of all possible attribute
50 combinations. The space can be restricted by providing subsets of attributes
51 to specifically include or exclude.
52 """
53 # pypath is where to find other Subzero python scripts.
54 pypath = os.path.abspath(os.path.dirname(sys.argv[0]))
55 root = FindBaseNaCl()
56
57 # The rest of the attribute sets.
Jan Voung8e32fed2015-06-17 10:16:23 -070058 targets = [ 'x8632', 'arm32' ]
Jim Stichnothdc7c5972015-03-10 11:17:15 -070059 sandboxing = [ 'native', 'sandbox' ]
60 opt_levels = [ 'Om1', 'O2' ]
Jan Voung8e32fed2015-06-17 10:16:23 -070061 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'] }
Jim Stichnothdc7c5972015-03-10 11:17:15 -070069 # all_keys is only used in the help text.
70 all_keys = '; '.join([' '.join(targets), ' '.join(sandboxing),
Jan Voung8e32fed2015-06-17 10:16:23 -070071 ' '.join(opt_levels), ' '.join(flat_attrs)])
Jim Stichnothdc7c5972015-03-10 11:17:15 -070072
73 argparser = argparse.ArgumentParser(
74 description=' ' + main.__doc__ +
75 'The set of attributes is the set of tests plus the following:\n' +
76 all_keys, formatter_class=argparse.RawTextHelpFormatter)
77 argparser.add_argument('--config', default='crosstest.cfg', dest='config',
78 metavar='FILE', help='Test configuration file')
79 argparser.add_argument('--print-tests', default=False, action='store_true',
80 help='Print the set of test names and exit')
81 argparser.add_argument('--include', '-i', default=[], dest='include',
82 action='append', metavar='ATTR_LIST',
83 help='Attributes to include (comma-separated). ' +
84 'Can be used multiple times.')
85 argparser.add_argument('--exclude', '-e', default=[], dest='exclude',
86 action='append', metavar='ATTR_LIST',
87 help='Attributes to include (comma-separated). ' +
88 'Can be used multiple times.')
89 argparser.add_argument('--verbose', '-v', default=False, action='store_true',
90 help='Use verbose output')
91 argparser.add_argument('--defer', default=False, action='store_true',
92 help='Defer execution until all executables are built')
93 argparser.add_argument('--no-compile', '-n', default=False,
94 action='store_true',
95 help="Don't build; reuse binaries from the last run")
96 argparser.add_argument('--dir', dest='dir', metavar='DIRECTORY',
97 default=('{root}/toolchain_build/src/subzero/' +
98 'crosstest/Output').format(root=root),
99 help='Output directory')
100 argparser.add_argument('--lit', default=False, action='store_true',
101 help='Generate files for lit testing')
Jan Voung8e32fed2015-06-17 10:16:23 -0700102 argparser.add_argument('--toolchain-root', dest='toolchain_root',
103 help='Path to toolchain binaries.')
Jim Stichnothdc7c5972015-03-10 11:17:15 -0700104 args = argparser.parse_args()
105
106 # Run from the crosstest directory to make it easy to grab inputs.
107 crosstest_dir = '{root}/toolchain_build/src/subzero/crosstest'.format(
108 root=root)
109 os.chdir(crosstest_dir)
110
111 tests = ConfigParser.RawConfigParser()
112 tests.read('crosstest.cfg')
113
114 if args.print_tests:
115 print 'Test name attributes: ' + ' '.join(sorted(tests.sections()))
116 sys.exit(0)
117
118 # includes and excludes are both lists of sets.
119 includes = [ set(item.split(',')) for item in args.include ]
120 excludes = [ set(item.split(',')) for item in args.exclude ]
121 # If any --include args are provided, the default is to not match.
122 default_match = not args.include
123
124 # Delete and recreate the output directory, unless --no-compile was specified.
125 if not args.no_compile:
126 if os.path.exists(args.dir):
127 if os.path.isdir(args.dir):
128 shutil.rmtree(args.dir)
129 else:
130 os.remove(args.dir)
131 if not os.path.exists(args.dir):
132 os.makedirs(args.dir)
133
134 # If --defer is specified, collect the run commands into deferred_cmds for
135 # later execution.
136 deferred_cmds = []
137 for test in sorted(tests.sections()):
138 for target in targets:
139 for sb in sandboxing:
140 for opt in opt_levels:
Jan Voung8e32fed2015-06-17 10:16:23 -0700141 for attr in arch_attrs[target]:
Jim Stichnothdc7c5972015-03-10 11:17:15 -0700142 desc = [ test, target, sb, opt, attr ]
143 if Match(set(desc), includes, excludes, default_match):
144 exe = '{test}_{target}_{sb}_{opt}_{attr}'.format(
145 test=test, target=target, sb=sb, opt=opt,
146 attr=attr)
147 extra = (tests.get(test, 'flags').split(' ')
148 if tests.has_option(test, 'flags') else [])
149 # Generate the compile command.
Jan Voung8e32fed2015-06-17 10:16:23 -0700150 cmp_cmd = (
151 ['{path}/crosstest.py'.format(path=pypath),
152 '-{opt}'.format(opt=opt),
153 '--mattr={attr}'.format(attr=attr),
154 '--prefix=Subzero_',
155 '--target={target}'.format(target=target),
156 '--sandbox={sb}'.format(sb='1' if sb=='sandbox' else '0'),
157 '--dir={dir}'.format(dir=args.dir),
158 '--output={exe}'.format(exe=exe),
159 '--driver={drv}'.format(drv=tests.get(test, 'driver'))] +
160 extra +
161 ['--test=' + t
162 for t in tests.get(test, 'test').split(' ')] +
163 arch_flags[target])
Jim Stichnothdc7c5972015-03-10 11:17:15 -0700164 run_cmd_base = os.path.join(args.dir, exe)
165 # Generate the run command.
166 run_cmd = run_cmd_base
167 if sb == 'sandbox':
168 run_cmd = '{root}/run.py -q '.format(root=root) + run_cmd
Jan Voung8e32fed2015-06-17 10:16:23 -0700169 else:
170 run_cmd = RunNativePrefix(args.toolchain_root, target, run_cmd)
Jim Stichnothdc7c5972015-03-10 11:17:15 -0700171 if args.lit:
172 # Create a file to drive the lit test.
173 with open(run_cmd_base + '.xtest', 'w') as f:
174 f.write('# RUN: sh %s | FileCheck %s\n')
175 f.write('cd ' + crosstest_dir + ' && \\\n')
176 f.write(' '.join(cmp_cmd) + ' && \\\n')
177 f.write(run_cmd + '\n')
178 f.write('echo Recreate a failure using ' + __file__ +
Jim Stichnotha9eeb422015-06-17 22:16:57 -0700179 ' --toolchain-root=' + args.toolchain_root +
Jim Stichnothdc7c5972015-03-10 11:17:15 -0700180 ' --include=' + ','.join(desc) + '\n')
181 f.write('# CHECK: Failures=0\n')
182 else:
183 if not args.no_compile:
184 shellcmd(cmp_cmd,
185 echo=args.verbose)
186 if (args.defer):
187 deferred_cmds.append(run_cmd)
188 else:
189 shellcmd(run_cmd, echo=True)
190 for run_cmd in deferred_cmds:
191 shellcmd(run_cmd, echo=True)
192
193if __name__ == '__main__':
194 main()