michael@0: # This Source Code Form is subject to the terms of the Mozilla Public michael@0: # License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: # file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: michael@0: from __future__ import print_function, unicode_literals michael@0: michael@0: import os michael@0: michael@0: from mach.decorators import ( michael@0: CommandArgument, michael@0: CommandProvider, michael@0: Command, michael@0: ) michael@0: michael@0: from mozbuild.base import MachCommandBase michael@0: michael@0: michael@0: HANDLE_FILE_ERROR = ''' michael@0: %s is a file. michael@0: However, I do not yet know how to run tests from files. You'll need to run michael@0: the mach command for the test type you are trying to run. e.g. michael@0: $ mach xpcshell-test path/to/file michael@0: '''.strip() michael@0: michael@0: HANDLE_DIR_ERROR = ''' michael@0: %s is a directory. michael@0: However, I do not yet know how to run tests from directories. You can try michael@0: running the mach command for the tests in that directory. e.g. michael@0: $ mach xpcshell-test path/to/directory michael@0: '''.strip() michael@0: michael@0: UNKNOWN_TEST = ''' michael@0: I don't know how to run the test: %s michael@0: michael@0: You need to specify a test suite name or abbreviation. It's possible I just michael@0: haven't been told about this test suite yet. If you suspect that's the issue, michael@0: please file a bug at https://bugzilla.mozilla.org/enter_bug.cgi?product=Testing&component=General michael@0: and request support be added. michael@0: '''.strip() michael@0: michael@0: MOCHITEST_CHUNK_BY_DIR = 4 michael@0: MOCHITEST_TOTAL_CHUNKS = 5 michael@0: michael@0: TEST_SUITES = { michael@0: 'cppunittest': { michael@0: 'aliases': ('Cpp', 'cpp'), michael@0: 'mach_command': 'cppunittest', michael@0: 'kwargs': {'test_file': None}, michael@0: }, michael@0: 'crashtest': { michael@0: 'aliases': ('C', 'Rc', 'RC', 'rc'), michael@0: 'mach_command': 'crashtest', michael@0: 'kwargs': {'test_file': None}, michael@0: }, michael@0: 'crashtest-ipc': { michael@0: 'aliases': ('Cipc', 'cipc'), michael@0: 'mach_command': 'crashtest-ipc', michael@0: 'kwargs': {'test_file': None}, michael@0: }, michael@0: 'jetpack': { michael@0: 'aliases': ('J',), michael@0: 'mach_command': 'jetpack-test', michael@0: 'kwargs': {}, michael@0: }, michael@0: 'jittest': { michael@0: 'aliases': ('Jit', 'jit'), michael@0: 'mach_command': 'jittest', michael@0: 'kwargs': {'test_file': None}, michael@0: }, michael@0: 'mochitest-a11y': { michael@0: 'mach_command': 'mochitest-a11y', michael@0: 'kwargs': {'test_file': None}, michael@0: }, michael@0: 'mochitest-browser': { michael@0: 'aliases': ('bc', 'BC', 'Bc'), michael@0: 'mach_command': 'mochitest-browser', michael@0: 'kwargs': {'test_file': None}, michael@0: }, michael@0: 'mochitest-chrome': { michael@0: 'mach_command': 'mochitest-chrome', michael@0: 'kwargs': {'test_file': None}, michael@0: }, michael@0: 'mochitest-devtools': { michael@0: 'aliases': ('dt', 'DT', 'Dt'), michael@0: 'mach_command': 'mochitest-browser --subsuite=devtools', michael@0: 'kwargs': {'test_file': None}, michael@0: }, michael@0: 'mochitest-ipcplugins': { michael@0: 'make_target': 'mochitest-ipcplugins', michael@0: }, michael@0: 'mochitest-plain': { michael@0: 'mach_command': 'mochitest-plain', michael@0: 'kwargs': {'test_file': None}, michael@0: }, michael@0: 'reftest': { michael@0: 'aliases': ('RR', 'rr', 'Rr'), michael@0: 'mach_command': 'reftest', michael@0: 'kwargs': {'test_file': None}, michael@0: }, michael@0: 'reftest-ipc': { michael@0: 'aliases': ('Ripc',), michael@0: 'mach_command': 'reftest-ipc', michael@0: 'kwargs': {'test_file': None}, michael@0: }, michael@0: 'valgrind': { michael@0: 'aliases': ('V', 'v'), michael@0: 'mach_command': 'valgrind-test', michael@0: 'kwargs': {}, michael@0: }, michael@0: 'xpcshell': { michael@0: 'aliases': ('X', 'x'), michael@0: 'mach_command': 'xpcshell-test', michael@0: 'kwargs': {'test_file': 'all'}, michael@0: }, michael@0: } michael@0: michael@0: for i in range(1, MOCHITEST_TOTAL_CHUNKS + 1): michael@0: TEST_SUITES['mochitest-%d' %i] = { michael@0: 'aliases': ('M%d' % i, 'm%d' % i), michael@0: 'mach_command': 'mochitest-plain', michael@0: 'kwargs': { michael@0: 'chunk_by_dir': MOCHITEST_CHUNK_BY_DIR, michael@0: 'total_chunks': MOCHITEST_TOTAL_CHUNKS, michael@0: 'this_chunk': i, michael@0: 'test_file': None, michael@0: }, michael@0: } michael@0: michael@0: TEST_HELP = ''' michael@0: Test or tests to run. Tests can be specified by test suite name or alias. michael@0: The following test suites and aliases are supported: %s michael@0: ''' % ', '.join(sorted(TEST_SUITES)) michael@0: TEST_HELP = TEST_HELP.strip() michael@0: michael@0: michael@0: @CommandProvider michael@0: class Test(MachCommandBase): michael@0: @Command('test', category='testing', description='Run tests.') michael@0: @CommandArgument('what', default=None, nargs='*', help=TEST_HELP) michael@0: def test(self, what): michael@0: status = None michael@0: for entry in what: michael@0: status = self._run_test(entry) michael@0: michael@0: if status: michael@0: break michael@0: michael@0: return status michael@0: michael@0: def _run_test(self, what): michael@0: suite = None michael@0: if what in TEST_SUITES: michael@0: suite = TEST_SUITES[what] michael@0: else: michael@0: for v in TEST_SUITES.values(): michael@0: if what in v.get('aliases', []): michael@0: suite = v michael@0: break michael@0: michael@0: if suite: michael@0: if 'mach_command' in suite: michael@0: return self._mach_context.commands.dispatch( michael@0: suite['mach_command'], self._mach_context, **suite['kwargs']) michael@0: michael@0: if 'make_target' in suite: michael@0: return self._run_make(target=suite['make_target'], michael@0: pass_thru=True) michael@0: michael@0: raise Exception('Do not know how to run suite. This is a logic ' michael@0: 'error in this mach command.') michael@0: michael@0: if os.path.isfile(what): michael@0: print(HANDLE_FILE_ERROR % what) michael@0: return 1 michael@0: michael@0: if os.path.isdir(what): michael@0: print(HANDLE_DIR_ERROR % what) michael@0: return 1 michael@0: michael@0: print(UNKNOWN_TEST % what) michael@0: return 1 michael@0: michael@0: @CommandProvider michael@0: class MachCommands(MachCommandBase): michael@0: @Command('cppunittest', category='testing', michael@0: description='Run cpp unit tests.') michael@0: @CommandArgument('test_files', nargs='*', metavar='N', michael@0: help='Test to run. Can be specified as one or more files or ' \ michael@0: 'directories, or omitted. If omitted, the entire test suite is ' \ michael@0: 'executed.') michael@0: michael@0: def run_cppunit_test(self, **params): michael@0: import runcppunittests as cppunittests michael@0: import logging michael@0: michael@0: if len(params['test_files']) == 0: michael@0: testdir = os.path.join(self.distdir, 'cppunittests') michael@0: progs = cppunittests.extract_unittests_from_args([testdir], None) michael@0: else: michael@0: progs = cppunittests.extract_unittests_from_args(params['test_files'], None) michael@0: michael@0: # See if we have crash symbols michael@0: symbols_path = os.path.join(self.distdir, 'crashreporter-symbols') michael@0: if not os.path.isdir(symbols_path): michael@0: symbols_path = None michael@0: michael@0: tester = cppunittests.CPPUnitTests() michael@0: try: michael@0: result = tester.run_tests(progs, self.bindir, symbols_path) michael@0: except Exception, e: michael@0: self.log(logging.ERROR, 'cppunittests', michael@0: {'exception': str(e)}, michael@0: 'Caught exception running cpp unit tests: {exception}') michael@0: result = False michael@0: michael@0: return 0 if result else 1 michael@0: michael@0: @CommandProvider michael@0: class JittestCommand(MachCommandBase): michael@0: @Command('jittest', category='testing', description='Run jit-test tests.') michael@0: @CommandArgument('--valgrind', action='store_true', help='Run jit-test suite with valgrind flag') michael@0: michael@0: def run_jittest(self, **params): michael@0: import subprocess michael@0: import sys michael@0: michael@0: if sys.platform.startswith('win'): michael@0: js = os.path.join(self.bindir, 'js.exe') michael@0: else: michael@0: js = os.path.join(self.bindir, 'js') michael@0: cmd = [os.path.join(self.topsrcdir, 'js', 'src', 'jit-test', 'jit_test.py'), michael@0: js, '--no-slow', '--no-progress', '--tinderbox', '--tbpl'] michael@0: michael@0: if params['valgrind']: michael@0: cmd.append('--valgrind') michael@0: michael@0: return subprocess.call(cmd)