|
1 # This Source Code Form is subject to the terms of the Mozilla Public |
|
2 # License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
4 |
|
5 from __future__ import print_function, unicode_literals |
|
6 |
|
7 import os |
|
8 |
|
9 from mach.decorators import ( |
|
10 CommandArgument, |
|
11 CommandProvider, |
|
12 Command, |
|
13 ) |
|
14 |
|
15 from mozbuild.base import MachCommandBase |
|
16 |
|
17 |
|
18 HANDLE_FILE_ERROR = ''' |
|
19 %s is a file. |
|
20 However, I do not yet know how to run tests from files. You'll need to run |
|
21 the mach command for the test type you are trying to run. e.g. |
|
22 $ mach xpcshell-test path/to/file |
|
23 '''.strip() |
|
24 |
|
25 HANDLE_DIR_ERROR = ''' |
|
26 %s is a directory. |
|
27 However, I do not yet know how to run tests from directories. You can try |
|
28 running the mach command for the tests in that directory. e.g. |
|
29 $ mach xpcshell-test path/to/directory |
|
30 '''.strip() |
|
31 |
|
32 UNKNOWN_TEST = ''' |
|
33 I don't know how to run the test: %s |
|
34 |
|
35 You need to specify a test suite name or abbreviation. It's possible I just |
|
36 haven't been told about this test suite yet. If you suspect that's the issue, |
|
37 please file a bug at https://bugzilla.mozilla.org/enter_bug.cgi?product=Testing&component=General |
|
38 and request support be added. |
|
39 '''.strip() |
|
40 |
|
41 MOCHITEST_CHUNK_BY_DIR = 4 |
|
42 MOCHITEST_TOTAL_CHUNKS = 5 |
|
43 |
|
44 TEST_SUITES = { |
|
45 'cppunittest': { |
|
46 'aliases': ('Cpp', 'cpp'), |
|
47 'mach_command': 'cppunittest', |
|
48 'kwargs': {'test_file': None}, |
|
49 }, |
|
50 'crashtest': { |
|
51 'aliases': ('C', 'Rc', 'RC', 'rc'), |
|
52 'mach_command': 'crashtest', |
|
53 'kwargs': {'test_file': None}, |
|
54 }, |
|
55 'crashtest-ipc': { |
|
56 'aliases': ('Cipc', 'cipc'), |
|
57 'mach_command': 'crashtest-ipc', |
|
58 'kwargs': {'test_file': None}, |
|
59 }, |
|
60 'jetpack': { |
|
61 'aliases': ('J',), |
|
62 'mach_command': 'jetpack-test', |
|
63 'kwargs': {}, |
|
64 }, |
|
65 'jittest': { |
|
66 'aliases': ('Jit', 'jit'), |
|
67 'mach_command': 'jittest', |
|
68 'kwargs': {'test_file': None}, |
|
69 }, |
|
70 'mochitest-a11y': { |
|
71 'mach_command': 'mochitest-a11y', |
|
72 'kwargs': {'test_file': None}, |
|
73 }, |
|
74 'mochitest-browser': { |
|
75 'aliases': ('bc', 'BC', 'Bc'), |
|
76 'mach_command': 'mochitest-browser', |
|
77 'kwargs': {'test_file': None}, |
|
78 }, |
|
79 'mochitest-chrome': { |
|
80 'mach_command': 'mochitest-chrome', |
|
81 'kwargs': {'test_file': None}, |
|
82 }, |
|
83 'mochitest-devtools': { |
|
84 'aliases': ('dt', 'DT', 'Dt'), |
|
85 'mach_command': 'mochitest-browser --subsuite=devtools', |
|
86 'kwargs': {'test_file': None}, |
|
87 }, |
|
88 'mochitest-ipcplugins': { |
|
89 'make_target': 'mochitest-ipcplugins', |
|
90 }, |
|
91 'mochitest-plain': { |
|
92 'mach_command': 'mochitest-plain', |
|
93 'kwargs': {'test_file': None}, |
|
94 }, |
|
95 'reftest': { |
|
96 'aliases': ('RR', 'rr', 'Rr'), |
|
97 'mach_command': 'reftest', |
|
98 'kwargs': {'test_file': None}, |
|
99 }, |
|
100 'reftest-ipc': { |
|
101 'aliases': ('Ripc',), |
|
102 'mach_command': 'reftest-ipc', |
|
103 'kwargs': {'test_file': None}, |
|
104 }, |
|
105 'valgrind': { |
|
106 'aliases': ('V', 'v'), |
|
107 'mach_command': 'valgrind-test', |
|
108 'kwargs': {}, |
|
109 }, |
|
110 'xpcshell': { |
|
111 'aliases': ('X', 'x'), |
|
112 'mach_command': 'xpcshell-test', |
|
113 'kwargs': {'test_file': 'all'}, |
|
114 }, |
|
115 } |
|
116 |
|
117 for i in range(1, MOCHITEST_TOTAL_CHUNKS + 1): |
|
118 TEST_SUITES['mochitest-%d' %i] = { |
|
119 'aliases': ('M%d' % i, 'm%d' % i), |
|
120 'mach_command': 'mochitest-plain', |
|
121 'kwargs': { |
|
122 'chunk_by_dir': MOCHITEST_CHUNK_BY_DIR, |
|
123 'total_chunks': MOCHITEST_TOTAL_CHUNKS, |
|
124 'this_chunk': i, |
|
125 'test_file': None, |
|
126 }, |
|
127 } |
|
128 |
|
129 TEST_HELP = ''' |
|
130 Test or tests to run. Tests can be specified by test suite name or alias. |
|
131 The following test suites and aliases are supported: %s |
|
132 ''' % ', '.join(sorted(TEST_SUITES)) |
|
133 TEST_HELP = TEST_HELP.strip() |
|
134 |
|
135 |
|
136 @CommandProvider |
|
137 class Test(MachCommandBase): |
|
138 @Command('test', category='testing', description='Run tests.') |
|
139 @CommandArgument('what', default=None, nargs='*', help=TEST_HELP) |
|
140 def test(self, what): |
|
141 status = None |
|
142 for entry in what: |
|
143 status = self._run_test(entry) |
|
144 |
|
145 if status: |
|
146 break |
|
147 |
|
148 return status |
|
149 |
|
150 def _run_test(self, what): |
|
151 suite = None |
|
152 if what in TEST_SUITES: |
|
153 suite = TEST_SUITES[what] |
|
154 else: |
|
155 for v in TEST_SUITES.values(): |
|
156 if what in v.get('aliases', []): |
|
157 suite = v |
|
158 break |
|
159 |
|
160 if suite: |
|
161 if 'mach_command' in suite: |
|
162 return self._mach_context.commands.dispatch( |
|
163 suite['mach_command'], self._mach_context, **suite['kwargs']) |
|
164 |
|
165 if 'make_target' in suite: |
|
166 return self._run_make(target=suite['make_target'], |
|
167 pass_thru=True) |
|
168 |
|
169 raise Exception('Do not know how to run suite. This is a logic ' |
|
170 'error in this mach command.') |
|
171 |
|
172 if os.path.isfile(what): |
|
173 print(HANDLE_FILE_ERROR % what) |
|
174 return 1 |
|
175 |
|
176 if os.path.isdir(what): |
|
177 print(HANDLE_DIR_ERROR % what) |
|
178 return 1 |
|
179 |
|
180 print(UNKNOWN_TEST % what) |
|
181 return 1 |
|
182 |
|
183 @CommandProvider |
|
184 class MachCommands(MachCommandBase): |
|
185 @Command('cppunittest', category='testing', |
|
186 description='Run cpp unit tests.') |
|
187 @CommandArgument('test_files', nargs='*', metavar='N', |
|
188 help='Test to run. Can be specified as one or more files or ' \ |
|
189 'directories, or omitted. If omitted, the entire test suite is ' \ |
|
190 'executed.') |
|
191 |
|
192 def run_cppunit_test(self, **params): |
|
193 import runcppunittests as cppunittests |
|
194 import logging |
|
195 |
|
196 if len(params['test_files']) == 0: |
|
197 testdir = os.path.join(self.distdir, 'cppunittests') |
|
198 progs = cppunittests.extract_unittests_from_args([testdir], None) |
|
199 else: |
|
200 progs = cppunittests.extract_unittests_from_args(params['test_files'], None) |
|
201 |
|
202 # See if we have crash symbols |
|
203 symbols_path = os.path.join(self.distdir, 'crashreporter-symbols') |
|
204 if not os.path.isdir(symbols_path): |
|
205 symbols_path = None |
|
206 |
|
207 tester = cppunittests.CPPUnitTests() |
|
208 try: |
|
209 result = tester.run_tests(progs, self.bindir, symbols_path) |
|
210 except Exception, e: |
|
211 self.log(logging.ERROR, 'cppunittests', |
|
212 {'exception': str(e)}, |
|
213 'Caught exception running cpp unit tests: {exception}') |
|
214 result = False |
|
215 |
|
216 return 0 if result else 1 |
|
217 |
|
218 @CommandProvider |
|
219 class JittestCommand(MachCommandBase): |
|
220 @Command('jittest', category='testing', description='Run jit-test tests.') |
|
221 @CommandArgument('--valgrind', action='store_true', help='Run jit-test suite with valgrind flag') |
|
222 |
|
223 def run_jittest(self, **params): |
|
224 import subprocess |
|
225 import sys |
|
226 |
|
227 if sys.platform.startswith('win'): |
|
228 js = os.path.join(self.bindir, 'js.exe') |
|
229 else: |
|
230 js = os.path.join(self.bindir, 'js') |
|
231 cmd = [os.path.join(self.topsrcdir, 'js', 'src', 'jit-test', 'jit_test.py'), |
|
232 js, '--no-slow', '--no-progress', '--tinderbox', '--tbpl'] |
|
233 |
|
234 if params['valgrind']: |
|
235 cmd.append('--valgrind') |
|
236 |
|
237 return subprocess.call(cmd) |