mach_commands.py (7848B)
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 import argparse 6 import os 7 import re 8 import subprocess 9 import sys 10 11 import mozinfo 12 from six.moves.urllib.parse import urljoin 13 from six.moves.urllib.request import pathname2url 14 15 from mach.decorators import ( 16 CommandArgument, 17 Command, 18 ) 19 20 from mozbuild.base import MozbuildObject 21 from mozbuild.base import MachCommandConditions as conditions 22 from argparse import ArgumentParser 23 24 25 def get_parser(): 26 parser = argparse.ArgumentParser() 27 parser.add_argument( 28 "suite_name", 29 nargs=1, 30 type=str, 31 action="store", 32 help="Suite to run in mozharness", 33 ) 34 parser.add_argument( 35 "mozharness_args", 36 nargs=argparse.REMAINDER, 37 help="Extra arguments to pass to mozharness", 38 ) 39 return parser 40 41 42 class MozharnessRunner(MozbuildObject): 43 def __init__(self, *args, **kwargs): 44 MozbuildObject.__init__(self, *args, **kwargs) 45 46 self.test_packages_url = self._test_packages_url() 47 self.installer_url = self._installer_url() 48 49 desktop_unittest_config = [ 50 "--config-file", 51 lambda: self.config_path( 52 "unittests", "%s_unittest.py" % mozinfo.info["os"] 53 ), 54 "--config-file", 55 lambda: self.config_path("developer_config.py"), 56 ] 57 58 self.config = { 59 "__defaults__": { 60 "config": [ 61 "--download-symbols", 62 "ondemand", 63 "--installer-url", 64 self.installer_url, 65 "--test-packages-url", 66 self.test_packages_url, 67 ] 68 }, 69 "mochitest-valgrind": { 70 "script": "desktop_unittest.py", 71 "config": desktop_unittest_config 72 + ["--mochitest-suite", "valgrind-plain"], 73 }, 74 "mochitest": { 75 "script": "desktop_unittest.py", 76 "config": desktop_unittest_config + ["--mochitest-suite", "plain"], 77 }, 78 "mochitest-chrome": { 79 "script": "desktop_unittest.py", 80 "config": desktop_unittest_config + ["--mochitest-suite", "chrome"], 81 }, 82 "mochitest-browser-chrome": { 83 "script": "desktop_unittest.py", 84 "config": desktop_unittest_config 85 + ["--mochitest-suite", "browser-chrome"], 86 }, 87 "mochitest-browser-a11y": { 88 "script": "desktop_unittest.py", 89 "config": desktop_unittest_config 90 + ["--mochitest-suite", "mochitest-browser-a11y"], 91 }, 92 "mochitest-browser-media": { 93 "script": "desktop_unittest.py", 94 "config": desktop_unittest_config 95 + ["--mochitest-suite", "mochitest-browser-media"], 96 }, 97 "mochitest-browser-translations": { 98 "script": "desktop_unittest.py", 99 "config": desktop_unittest_config 100 + ["--mochitest-suite", "mochitest-browser-translations"], 101 }, 102 "mochitest-devtools-chrome": { 103 "script": "desktop_unittest.py", 104 "config": desktop_unittest_config 105 + ["--mochitest-suite", "mochitest-devtools-chrome"], 106 }, 107 "mochitest-remote": { 108 "script": "desktop_unittest.py", 109 "config": desktop_unittest_config 110 + ["--mochitest-suite", "mochitest-remote"], 111 }, 112 "crashtest": { 113 "script": "desktop_unittest.py", 114 "config": desktop_unittest_config + ["--reftest-suite", "crashtest"], 115 }, 116 "jsreftest": { 117 "script": "desktop_unittest.py", 118 "config": desktop_unittest_config + ["--reftest-suite", "jsreftest"], 119 }, 120 "reftest": { 121 "script": "desktop_unittest.py", 122 "config": desktop_unittest_config + ["--reftest-suite", "reftest"], 123 }, 124 "cppunittest": { 125 "script": "desktop_unittest.py", 126 "config": desktop_unittest_config 127 + ["--cppunittest-suite", "cppunittest"], 128 }, 129 "xpcshell": { 130 "script": "desktop_unittest.py", 131 "config": desktop_unittest_config + ["--xpcshell-suite", "xpcshell"], 132 }, 133 "xpcshell-addons": { 134 "script": "desktop_unittest.py", 135 "config": desktop_unittest_config 136 + ["--xpcshell-suite", "xpcshell-addons"], 137 }, 138 "jittest": { 139 "script": "desktop_unittest.py", 140 "config": desktop_unittest_config + ["--jittest-suite", "jittest"], 141 }, 142 "marionette": { 143 "script": "marionette.py", 144 "config": [ 145 "--config-file", 146 self.config_path("marionette", "test_config.py"), 147 ], 148 }, 149 "web-platform-tests": { 150 "script": "web_platform_tests.py", 151 "config": [ 152 "--config-file", 153 self.config_path("web_platform_tests", self.wpt_config), 154 ], 155 }, 156 } 157 158 def path_to_url(self, path): 159 return urljoin("file:", pathname2url(path)) 160 161 def _installer_url(self): 162 package_re = { 163 "linux": re.compile(r"^firefox-\d+\..+\.tar\.(bz2|xz)$"), 164 "win": re.compile(r"^firefox-\d+\..+\.installer\.exe$"), 165 "mac": re.compile(r"^firefox-\d+\..+\.mac(?:64)?\.dmg$"), 166 }[mozinfo.info["os"]] 167 dist_path = os.path.join(self.topobjdir, "dist") 168 filenames = [item for item in os.listdir(dist_path) if package_re.match(item)] 169 assert len(filenames) == 1 170 return self.path_to_url(os.path.join(dist_path, filenames[0])) 171 172 def _test_packages_url(self): 173 dist_path = os.path.join(self.topobjdir, "dist") 174 filenames = [ 175 item 176 for item in os.listdir(dist_path) 177 if item.endswith("test_packages.json") 178 ] 179 assert len(filenames) == 1 180 return self.path_to_url(os.path.join(dist_path, filenames[0])) 181 182 def config_path(self, *parts): 183 return self.path_to_url( 184 os.path.join(self.topsrcdir, "testing", "mozharness", "configs", *parts) 185 ) 186 187 @property 188 def wpt_config(self): 189 return ( 190 "test_config.py" 191 if mozinfo.info["os"] != "win" 192 else "test_config_windows.py" 193 ) 194 195 def run_suite(self, suite, **kwargs): 196 default_config = self.config.get("__defaults__") 197 suite_config = self.config.get(suite) 198 199 if suite_config is None: 200 print("Unknown suite %s" % suite) 201 return 1 202 203 script = os.path.join( 204 self.topsrcdir, "testing", "mozharness", "scripts", suite_config["script"] 205 ) 206 options = [ 207 item() if callable(item) else item 208 for item in default_config["config"] + suite_config["config"] 209 ] 210 211 cmd = [script] + options 212 213 rv = subprocess.call(cmd, cwd=os.path.dirname(script)) 214 return rv 215 216 217 @Command( 218 "mozharness", 219 category="testing", 220 description="Run tests using mozharness.", 221 conditions=[conditions.is_firefox_or_android], 222 parser=get_parser, 223 ) 224 def mozharness(command_context, **kwargs): 225 runner = command_context._spawn(MozharnessRunner) 226 return runner.run_suite(kwargs.pop("suite_name")[0], **kwargs)