Bug 1207377 - Add a |mach mozharness| command for running tests locally in mozharness, r=ahal
authorJames Graham <james@hoppipolla.co.uk>
Mon, 07 Dec 2015 12:28:40 +0000
changeset 309981 cb1a697de90dd77aa7e0a9d3e94fedd4a39d6f96
parent 309980 5a587fbae89b27c66d28b6871cc54fba766958b9
child 309982 1009be1b37ec484d73361487a11ec7cf05d5fb35
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersahal
bugs1207377
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1207377 - Add a |mach mozharness| command for running tests locally in mozharness, r=ahal
build/mach_bootstrap.py
testing/mozharness/configs/marionette/test_config.py
testing/mozharness/mach_commands.py
testing/mozharness/mozharness/mozilla/testing/testbase.py
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -115,16 +115,17 @@ MACH_MODULES = [
     'python/mozbuild/mozbuild/compilation/codecomplete.py',
     'python/mozbuild/mozbuild/frontend/mach_commands.py',
     'services/common/tests/mach_commands.py',
     'testing/luciddream/mach_commands.py',
     'testing/mach_commands.py',
     'testing/taskcluster/mach_commands.py',
     'testing/marionette/mach_commands.py',
     'testing/mochitest/mach_commands.py',
+    'testing/mozharness/mach_commands.py',
     'testing/xpcshell/mach_commands.py',
     'testing/talos/mach_commands.py',
     'testing/web-platform/mach_commands.py',
     'testing/xpcshell/mach_commands.py',
     'tools/docs/mach_commands.py',
     'tools/mercurial/mach_commands.py',
     'tools/mach_commands.py',
     'tools/power/mach_commands.py',
--- a/testing/mozharness/configs/marionette/test_config.py
+++ b/testing/mozharness/configs/marionette/test_config.py
@@ -1,20 +1,16 @@
 # This is a template config file for marionette test.
 
 config = {
     # marionette options
     "test_type": "browser",
     "marionette_address": "localhost:2828",
     "test_manifest": "unit-tests.ini",
 
-    # XXX: replace these with something appropriate to your system
-    "installer_url": "http://archive.mozilla.org/pub/firefox/tinderbox-builds/mozilla-central-linux-debug/1344372927/firefox-17.0a1.en-US.linux-i686.tar.bz2",
-    "test_url": "http://archive.mozilla.org/pub/firefox/tinderbox-builds/mozilla-central-linux-debug/1344372927/firefox-17.0a1.en-US.linux-i686.tests.zip",
-
     "default_actions": [
         'clobber',
         'download-and-extract',
         'create-virtualenv',
         'install',
         'run-marionette',
     ],
     "suite_definitions": {
new file mode 100644
--- /dev/null
+++ b/testing/mozharness/mach_commands.py
@@ -0,0 +1,205 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+import argparse
+import os
+import re
+import subprocess
+import sys
+import urllib
+import urlparse
+
+import mozinfo
+
+from mach.decorators import (
+    CommandArgument,
+    CommandProvider,
+    Command,
+)
+
+from mozbuild.base import MachCommandBase, MozbuildObject
+from mozbuild.base import MachCommandConditions as conditions
+from argparse import ArgumentParser
+
+def get_parser():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("suite_name", nargs=1, type=str, action="store",
+                        help="Suite to run in mozharness")
+    parser.add_argument("mozharness_args", nargs=argparse.REMAINDER,
+                        help="Extra arguments to pass to mozharness")
+    return parser
+
+class MozharnessRunner(MozbuildObject):
+    def __init__(self, *args, **kwargs):
+        MozbuildObject.__init__(self, *args, **kwargs)
+
+
+        self.test_packages_url = os.path.join(self.topobjdir, "dist", "test_packages.json")
+        self.installer_url = self._installer_url()
+
+        desktop_unittest_config = [
+            "--config-file", lambda: self.config_path("unittests",
+                                                      "%s_unittest.py" % mozinfo.info['os']),
+            "--config-file", lambda: self.config_path("developer_config.py")]
+
+        self.config = {
+            "__defaults__": {
+                "config": ["--no-read-buildbot-config",
+                           "--download-symbols", "ondemand",
+                           "--installer-url", self.installer_url,
+                           "--test-packages-url", self.test_packages_url]
+            },
+
+            "mochitest": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--mochitest-suite", "plain"]
+            },
+            "mochitest-chrome": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--mochitest-suite", "chrome"]
+            },
+            "mochitest-browser-chrome": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--mochitest-suite", "browser-chrome"]
+            },
+            "mochitest-devtools-chrome": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--mochitest-suite", "mochitest-devtools-chrome"]
+            },
+            "reftest": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--reftest-suite", "reftest"]
+            },
+            "crashtest": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--reftest-suite", "crashtest"]
+            },
+            "jsreftest": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--reftest-suite", "jsreftest"]
+            },
+            "reftest-ipc": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--reftest-suite", "reftest-ipc"]
+            },
+            "reftest-no-accel": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--reftest-suite", "reftest-no-accel"]
+            },
+            "crashtest-ipc": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--reftest-suite", "crashtest-ipc"]
+            },
+            "cppunittest": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--cppunittest-suite", "cppunittest"]
+            },
+            "webapprt-chrome": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--webapprt-suite", "chrome"]
+            },
+            "webapprt-content": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--webapprt-suite", "content"]
+            },
+            "xpcshell": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--xpcshell-suite", "xpcshell"]
+            },
+            "xpcshell-addons": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--xpcshell-suite", "xpcshell-addons"]
+            },
+            "jittest": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--jittest-suite", "jittest"]
+            },
+            "mozbase": {
+                "script": "desktop_unittest.py",
+                "config": desktop_unittest_config + [
+                    "--mozbase-suite", "mozbase"]
+            },
+            "marionette": {
+                "script": "marionette.py",
+                "config": ["--config-file", self.config_path("marionette",
+                                                             "test_config.py")]
+            },
+            "web-platform-tests": {
+                "script": "web_platform_tests.py",
+                "config": ["--config-file", self.config_path("web_platform_tests",
+                                                             self.wpt_config)]
+            },
+        }
+
+
+    def path_to_url(self, path):
+        return urlparse.urljoin('file:', urllib.pathname2url(path))
+
+    def _installer_url(self):
+        package_re = {
+            "linux": re.compile("^firefox-\d+\..+\.tar\.bz2$"),
+            "win": re.compile("^firefox-\d+\..+\.installer\.exe$"),
+            "mac": re.compile("^firefox-\d+\..+\.mac(?:64)?\.dmg$"),
+        }[mozinfo.info['os']]
+        dist_path = os.path.join(self.topobjdir, "dist")
+        filenames = [item for item in os.listdir(dist_path) if
+                     package_re.match(item)]
+        assert len(filenames) == 1
+        return self.path_to_url(os.path.join(dist_path, filenames[0]))
+
+
+    def config_path(self, *parts):
+        return self.path_to_url(os.path.join(self.topsrcdir, "testing", "mozharness",
+                                             "configs", *parts))
+
+    @property
+    def wpt_config(self):
+        return "test_config.py" if mozinfo.info['os'] != "win" else "test_config_windows.py"
+
+    def run_suite(self, suite, **kwargs):
+        default_config = self.config.get("__defaults__")
+        suite_config = self.config.get(suite)
+
+        if suite_config is None:
+            print("Unknown suite %s" % suite)
+            return 1
+
+        script = os.path.join(self.topsrcdir, "testing", "mozharness",
+                              "scripts", suite_config["script"])
+        options = [item() if callable(item) else item
+                   for item in default_config["config"] + suite_config["config"]]
+
+        cmd = [script] + options
+
+        rv = subprocess.call(cmd, cwd=os.path.dirname(script))
+        return rv
+
+
+@CommandProvider
+class MozharnessCommands(MachCommandBase):
+    @Command('mozharness', category='testing',
+             description='Run tests using mozharness.',
+             conditions=[conditions.is_firefox],
+             parser=get_parser)
+    def mozharness(self, **kwargs):
+        runner = self._spawn(MozharnessRunner)
+        return runner.run_suite(kwargs.pop("suite_name")[0], **kwargs)
--- a/testing/mozharness/mozharness/mozilla/testing/testbase.py
+++ b/testing/mozharness/mozharness/mozilla/testing/testbase.py
@@ -533,17 +533,17 @@ 2. running via buildbot and running the 
                 setattr(self, attr, new_url)
 
         if 'test_url' in self.config:
             # A user has specified a test_url directly, any test_packages_url will
             # be ignored.
             if self.test_packages_url:
                 self.error('Test data will be downloaded from "%s", the specified test '
                            ' package data at "%s" will be ignored.' %
-                           (self.config('test_url'), self.test_packages_url))
+                           (self.config.get('test_url'), self.test_packages_url))
 
             self._download_test_zip()
             self._extract_test_zip(target_unzip_dirs=target_unzip_dirs)
         else:
             if not self.test_packages_url:
                 # The caller intends to download harness specific packages, but doesn't know
                 # where the packages manifest is located. This is the case when the
                 # test package manifest isn't set as a buildbot property, which is true