diff --git a/python/servo/testing_commands.py b/python/servo/testing_commands.py
index c9be0b02181..91e7fb09089 100644
--- a/python/servo/testing_commands.py
+++ b/python/servo/testing_commands.py
@@ -30,6 +30,15 @@ from wptrunner import wptcommandline
from update import updatecommandline
import tidy
+here = os.path.split(__file__)[0]
+
+
+def create_parser_wpt():
+ parser = wptcommandline.create_parser()
+ parser.add_argument('--release', default=False, action="store_true",
+ help="Run with a release build of servo")
+ return parser
+
@CommandProvider
class MachCommands(CommandBase):
@@ -325,9 +334,7 @@ class MachCommands(CommandBase):
@Command('test-css',
description='Run the web platform tests',
category='testing',
- parser=wptcommandline.create_parser())
- @CommandArgument('--release', default=False, action="store_true",
- help="Run with a release build of servo")
+ parser=create_parser_wpt)
def test_css(self, **kwargs):
self.ensure_bootstrapped()
@@ -448,3 +455,147 @@ class MachCommands(CommandBase):
return subprocess.check_call(
[run_file, "|".join(tests), bin_path, base_dir])
+
+
+def create_parser_create():
+ import argparse
+ p = argparse.ArgumentParser()
+ p.add_argument("--no-editor", action="store_true",
+ help="Don't try to open the test in an editor")
+ p.add_argument("-e", "--editor", action="store", help="Editor to use")
+ p.add_argument("--no-run", action="store_true",
+ help="Don't try to update the wpt manifest or open the test in a browser")
+ p.add_argument('--release', action="store_true",
+ help="Run with a release build of servo")
+ p.add_argument("--long-timeout", action="store_true",
+ help="Test should be given a long timeout (typically 60s rather than 10s,"
+ "but varies depending on environment)")
+ p.add_argument("--overwrite", action="store_true",
+ help="Allow overwriting an existing test file")
+ p.add_argument("-r", "--reftest", action="store_true",
+ help="Create a reftest rather than a testharness (js) test"),
+ p.add_argument("-ref", "--reference", dest="ref", help="Path to the reference file")
+ p.add_argument("--mismatch", action="store_true",
+ help="Create a mismatch reftest")
+ p.add_argument("--wait", action="store_true",
+ help="Create a reftest that waits until takeScreenshot() is called")
+ p.add_argument("path", action="store", help="Path to the test file")
+ return p
+
+
+@CommandProvider
+class WebPlatformTestsCreator(CommandBase):
+ template_prefix = """
+%(documentElement)s
+"""
+ template_long_timeout = "\n"
+
+ template_body_th = """
+
+
+
+"""
+
+ template_body_reftest = """
+
+"""
+
+ template_body_reftest_wait = """
+"""
+
+ def rel_path(self, path):
+ if path is None:
+ return
+
+ abs_path = os.path.normpath(os.path.abspath(path))
+ return os.path.relpath(abs_path, os.path.abspath(os.path.join(here, "..", "..")))
+
+ def rel_url(self, rel_path):
+ upstream_path = os.path.join("tests", "wpt", "web-platform-tests")
+ local_path = os.path.join("tests", "wpt", "mozilla", "tests")
+
+ if rel_path.startswith(upstream_path):
+ return rel_path[len(upstream_path):].replace(os.path.sep, "/")
+ elif rel_path.startswith(local_path):
+ return "/_mozilla" + rel_path[len(local_path):].replace(os.path.sep, "/")
+ else:
+ return None
+
+ @Command("create-wpt",
+ category="testing",
+ parser=create_parser_create)
+ def run_create(self, **kwargs):
+ import subprocess
+
+ path = self.rel_path(kwargs["path"])
+ ref_path = self.rel_path(kwargs["ref"])
+
+ if kwargs["ref"]:
+ kwargs["reftest"] = True
+
+ if self.rel_url(path) is None:
+ print("""Test path %s is not in wpt directories:
+tests/wpt/web-platform-tests for tests that may be shared
+tests/wpt/mozilla/tests for Servo-only tests""" % path)
+ return 1
+
+ if ref_path and self.rel_url(ref_path) is None:
+ print("""Reference path %s is not in wpt directories:
+testing/web-platform/tests for tests that may be shared
+testing/web-platform/mozilla/tests for Servo-only tests""" % ref_path)
+ return 1
+
+ if os.path.exists(path) and not kwargs["overwrite"]:
+ print("Test path already exists, pass --overwrite to replace")
+ return 1
+
+ if kwargs["mismatch"] and not kwargs["reftest"]:
+ print("--mismatch only makes sense for a reftest")
+ return 1
+
+ if kwargs["wait"] and not kwargs["reftest"]:
+ print("--wait only makes sense for a reftest")
+ return 1
+
+ args = {"documentElement": "\n" if kwargs["wait"] else ""}
+ template = self.template_prefix % args
+ if kwargs["long_timeout"]:
+ template += self.template_long_timeout
+
+ if kwargs["reftest"]:
+ args = {"match": "match" if not kwargs["mismatch"] else "mismatch",
+ "ref": self.rel_url(ref_path) if kwargs["ref"] else '""'}
+ template += self.template_body_reftest % args
+ if kwargs["wait"]:
+ template += self.template_body_reftest_wait
+ else:
+ template += self.template_body_th
+ with open(path, "w") as f:
+ f.write(template)
+
+ if kwargs["no_editor"]:
+ editor = None
+ elif kwargs["editor"]:
+ editor = kwargs["editor"]
+ elif "VISUAL" in os.environ:
+ editor = os.environ["VISUAL"]
+ elif "EDITOR" in os.environ:
+ editor = os.environ["EDITOR"]
+ else:
+ editor = None
+
+ if editor:
+ proc = subprocess.Popen("%s %s" % (editor, path), shell=True)
+
+ if not kwargs["no_run"]:
+ p = create_parser_wpt()
+ args = ["--manifest-update"]
+ if kwargs["release"]:
+ args.append("--release")
+ args.append(path)
+ wpt_kwargs = vars(p.parse_args(args))
+ self.context.commands.dispatch("test-wpt", self.context, **wpt_kwargs)
+
+ proc.wait()