Bug 1370203 - Change wptrun to raise an exception instead of exiting directly, r=farre draft
authorJames Graham <james@hoppipolla.co.uk>
Mon, 05 Jun 2017 13:28:49 +0100
changeset 589008 b60663f08f7f98109d479fb64e32d08dd8fff473
parent 589004 6d4b65abc362bd5f7b6406d3b98fa538a1f492eb
child 589009 38095a3238916fcfde68f39c2dbfa61c1b0a897d
push id62219
push userbmo:james@hoppipolla.co.uk
push dateMon, 05 Jun 2017 12:34:46 +0000
reviewersfarre
bugs1370203
milestone55.0a1
Bug 1370203 - Change wptrun to raise an exception instead of exiting directly, r=farre This makes integration with other frontends a little easier. MozReview-Commit-ID: 3gGeJqMPiZf
testing/web-platform/tests/tools/wptrun.py
--- a/testing/web-platform/tests/tools/wptrun.py
+++ b/testing/web-platform/tests/tools/wptrun.py
@@ -9,16 +9,19 @@ from distutils.spawn import find_executa
 
 import localpaths
 from browserutils import browser, utils, virtualenv
 logger = None
 
 wpt_root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
 
 
+class WptrunError(Exception):
+    pass
+
 class WptrunnerHelpAction(argparse.Action):
     def __init__(self,
                  option_strings,
                  dest=argparse.SUPPRESS,
                  default=argparse.SUPPRESS,
                  help=None):
         super(WptrunnerHelpAction, self).__init__(
             option_strings=option_strings,
@@ -59,79 +62,86 @@ def exit(msg):
 def args_general(kwargs):
     kwargs.set_if_none("tests_root", wpt_root)
     kwargs.set_if_none("metadata_root", wpt_root)
     kwargs.set_if_none("manifest_update", True)
 
     if kwargs["ssl_type"] == "openssl":
         if not find_executable(kwargs["openssl_binary"]):
             if os.uname()[0] == "Windows":
-                exit("""OpenSSL binary not found. If you need HTTPS tests, install OpenSSL from
+                raise WptrunError("""OpenSSL binary not found. If you need HTTPS tests, install OpenSSL from
 
 https://slproweb.com/products/Win32OpenSSL.html
 
 Ensuring that libraries are added to /bin and add the resulting bin directory to
 your PATH.
 
 Otherwise run with --ssl-type=none""")
             else:
-                exit("""OpenSSL not found. If you don't need HTTPS support run with --ssl-type=none,
+                raise WptrunError("""OpenSSL not found. If you don't need HTTPS support run with --ssl-type=none,
 otherwise install OpenSSL and ensure that it's on your $PATH.""")
 
 
 def check_environ(product):
     if product != "firefox":
-        expected_hosts = set(["web-platform.test",
-                              "www.web-platform.test",
-                              "www1.web-platform.test",
-                              "www2.web-platform.test",
-                              "xn--n8j6ds53lwwkrqhv28a.web-platform.test",
-                              "xn--lve-6lad.web-platform.test",
-                              "nonexistent-origin.web-platform.test"])
+        expected_hosts = ["web-platform.test",
+                          "www.web-platform.test",
+                          "www1.web-platform.test",
+                          "www2.web-platform.test",
+                          "xn--n8j6ds53lwwkrqhv28a.web-platform.test",
+                          "xn--lve-6lad.web-platform.test",
+                          "nonexistent-origin.web-platform.test"]
+        missing_hosts = set(expected_hosts)
         if platform.uname()[0] != "Windows":
             hosts_path = "/etc/hosts"
         else:
             hosts_path = "C:\Windows\System32\drivers\etc\hosts"
         with open(hosts_path, "r") as f:
             for line in f:
                 line = line.split("#", 1)[0].strip()
                 parts = line.split()
                 if len(parts) == 2:
                     host = parts[1]
-                    expected_hosts.discard(host)
-            if expected_hosts:
-                exit("""Missing hosts file configuration for %s.
-See README.md for more details.""" % ",".join(expected_hosts))
+                    missing_hosts.discard(host)
+            if missing_hosts:
+                raise WptrunError("""Missing hosts file configuration. Expected entries like:
+
+%s
+
+See README.md for more details.""" % "\n".join("%s\t%s" %
+                                               ("127.0.0.1" if "nonexistent" not in host else "0.0.0.0", host)
+                                               for host in expected_hosts))
+
 
 def prompt_install(component, prompt):
     if not prompt:
         return True
     while True:
         resp = raw_input("Download and install %s [Y/n]? " % component).strip().lower()
         if not resp or resp == "y":
             return True
         elif resp == "n":
             return False
 
 
 def args_firefox(venv, kwargs, firefox, prompt=True):
     if kwargs["binary"] is None:
         binary = firefox.find_binary()
         if binary is None:
-            exit("""Firefox binary not found on $PATH.
+            raise WptrunError("""Firefox binary not found on $PATH.
 
 Install Firefox or use --binary to set the binary path""")
         kwargs["binary"] = binary
 
     if kwargs["certutil_binary"] is None and kwargs["ssl_type"] != "none":
         certutil = firefox.find_certutil()
 
         if certutil is None:
             # Can't download this for now because it's missing the libnss3 library
-            exit("""Can't find certutil.
+            raise WptrunError("""Can't find certutil.
 
 This must be installed using your OS package manager or directly e.g.
 
 Debian/Ubuntu:
 sudo apt install libnss3-tools
 
 macOS/Homebrew:
 brew install nss
@@ -194,31 +204,31 @@ def args_chrome(venv, kwargs, chrome, pr
                 print("Downloading chromedriver")
                 webdriver_binary = chrome.install_webdriver(dest=venv.bin_path)
         else:
             print("Using webdriver binary %s" % webdriver_binary)
 
         if webdriver_binary:
             kwargs["webdriver_binary"] = webdriver_binary
         else:
-            exit("Unable to locate or install chromedriver binary")
+            raise WptrunError("Unable to locate or install chromedriver binary")
 
 
 def setup_chrome(venv, kwargs, prompt=True):
     chrome = browser.Chrome()
     args_chrome(venv, kwargs, chrome, prompt)
     venv.install_requirements(os.path.join(wpt_root, "tools", "wptrunner", chrome.requirements))
 
 
 def args_edge(venv, kwargs, edge, prompt=True):
     if kwargs["webdriver_binary"] is None:
         webdriver_binary = edge.find_webdriver()
 
         if webdriver_binary is None:
-            exit("""Unable to find WebDriver and we aren't yet clever enough to work out which
+            raise WptrunError("""Unable to find WebDriver and we aren't yet clever enough to work out which
 version to download. Please go to the following URL and install the correct
 version for your Edge/Windows release somewhere on the %PATH%:
 
 https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
  """)
         kwargs["webdriver_binary"] = webdriver_binary
 
 
@@ -232,17 +242,17 @@ def setup_sauce(kwargs):
     raise NotImplementedError
 
 
 def args_servo(venv, kwargs, servo, prompt=True):
     if kwargs["binary"] is None:
         binary = servo.find_binary()
 
         if binary is None:
-            exit("Unable to find servo binary on the PATH")
+            raise WptrunError("Unable to find servo binary on the PATH")
         kwargs["binary"] = binary
 
 
 def setup_servo(venv, kwargs, prompt=True):
     servo = browser.Servo()
     args_servo(venv, kwargs, servo, prompt)
     venv.install_requirements(os.path.join(wpt_root, "tools", "wptrunner", servo.requirements))
 
@@ -268,41 +278,44 @@ def setup_wptrunner(venv, product, tests
 
     kwargs["product"] = product
     kwargs["test_list"] = tests
 
     check_environ(product)
     args_general(kwargs)
 
     if product not in product_setup:
-        exit("Unsupported product %s" % product)
+        raise WptrunError("Unsupported product %s" % product)
 
     product_setup[product](venv, kwargs, prompt)
 
     wptcommandline.check_args(kwargs)
 
     wptrunner_path = os.path.join(wpt_root, "tools", "wptrunner")
 
     venv.install_requirements(os.path.join(wptrunner_path, "requirements.txt"))
 
     return kwargs
 
 
 def main():
-    parser = create_parser()
-    args = parser.parse_args()
+    try:
+        parser = create_parser()
+        args = parser.parse_args()
 
-    venv = virtualenv.Virtualenv(os.path.join(wpt_root, "_venv_%s") % platform.uname()[0])
-    venv.start()
-    venv.install_requirements(os.path.join(wpt_root, "tools", "wptrunner", "requirements.txt"))
-    venv.install("requests")
+        venv = virtualenv.Virtualenv(os.path.join(wpt_root, "_venv_%s") % platform.uname()[0])
+        venv.start()
+        venv.install_requirements(os.path.join(wpt_root, "tools", "wptrunner", "requirements.txt"))
+        venv.install("requests")
 
-    kwargs = setup_wptrunner(venv, args.product, args.tests, args.wptrunner_args, prompt=args.prompt)
-    from wptrunner import wptrunner
-    wptrunner.start(**kwargs)
+        kwargs = setup_wptrunner(venv, args.product, args.tests, args.wptrunner_args, prompt=args.prompt)
+        from wptrunner import wptrunner
+        wptrunner.start(**kwargs)
+    except WptrunError as e:
+        exit(e.message)
 
 
 if __name__ == "__main__":
     import pdb
     try:
         main()
     except:
         pdb.post_mortem()