mirror of
https://github.com/servo/servo.git
synced 2025-06-21 23:59:00 +01:00
This is a quick and dirty workaround for issue #3928. Basically, `cargo test` is deleting `./target/servo`, which is clearly not ideal if we want to do anything with servo after running the unit tests. This PR makes sure to rebuild after running `./mach test-unit`. I'm not familiar enough with cargo yet to know why it's doing this or what better alternatives there are to fixing this. Having to rebuild afterwards feels pretty ugly to me, but my rationalization right now is that the time it takes to build is negligible in comparison to the time it takes to run the tests. Ideally, this should be something we could take care of in Cargo.toml, but again, I'm new to this (and the documentation seems less than helpful from what I can tell so far). I won't be available for the rest of the day, so if anyone has suggestions, or wants to wait for a better solution, I'll get back to it tomorrow probably. Otherwise, this PR at least makes `./mach test` work properly, so there's that.
224 lines
7.9 KiB
Python
224 lines
7.9 KiB
Python
from __future__ import print_function, unicode_literals
|
|
|
|
import argparse
|
|
import os
|
|
import os.path as path
|
|
import subprocess
|
|
from time import time
|
|
|
|
from mach.registrar import Registrar
|
|
from mach.decorators import (
|
|
CommandArgument,
|
|
CommandProvider,
|
|
Command,
|
|
)
|
|
|
|
from servo.command_base import CommandBase
|
|
import tidy
|
|
|
|
|
|
@CommandProvider
|
|
class MachCommands(CommandBase):
|
|
def __init__(self, context):
|
|
CommandBase.__init__(self, context)
|
|
if not hasattr(self.context, "built_tests"):
|
|
self.context.built_tests = False
|
|
|
|
def ensure_built_tests(self):
|
|
if self.context.built_tests:
|
|
return
|
|
Registrar.dispatch('build-tests', context=self.context)
|
|
self.context.built_tests = True
|
|
|
|
def find_test(self, prefix):
|
|
target_contents = os.listdir(path.join(
|
|
self.context.topdir, "components", "servo", "target"))
|
|
for filename in target_contents:
|
|
if filename.startswith(prefix + "-"):
|
|
filepath = path.join(
|
|
self.context.topdir, "components", "servo",
|
|
"target", filename)
|
|
|
|
if path.isfile(filepath) and os.access(filepath, os.X_OK):
|
|
return filepath
|
|
|
|
def run_test(self, prefix, args=[]):
|
|
t = self.find_test(prefix)
|
|
if t:
|
|
return subprocess.call([t] + args, env=self.build_env())
|
|
|
|
def infer_test_by_dir(self, params):
|
|
maybe_path = path.normpath(params[0])
|
|
mach_command = path.join(self.context.topdir, "mach")
|
|
args = None
|
|
|
|
if not path.exists(maybe_path):
|
|
print("%s is not a valid file or directory" % maybe_path)
|
|
return 1
|
|
|
|
test_dirs = [
|
|
# path, mach test command, optional flag for path argument
|
|
(path.join("tests", "content"), "test-content", None),
|
|
(path.join("tests", "wpt"), "test-wpt", None),
|
|
(path.join("tests", "ref"), "test-ref", ["--name"]),
|
|
]
|
|
|
|
for test_dir, test_name, path_flag in test_dirs:
|
|
if not path_flag:
|
|
path_flag = []
|
|
if test_dir in maybe_path:
|
|
args = ([mach_command, test_name] + path_flag +
|
|
[maybe_path] + params[1:])
|
|
break
|
|
else:
|
|
print("%s is not a valid test file or directory" % maybe_path)
|
|
return 1
|
|
|
|
return subprocess.call(args, env=self.build_env())
|
|
|
|
@Command('test',
|
|
description='Run all Servo tests',
|
|
category='testing')
|
|
@CommandArgument('params', default=None, nargs="...",
|
|
help="Optionally select test based on "
|
|
"test file directory")
|
|
def test(self, params):
|
|
if params:
|
|
return self.infer_test_by_dir(params)
|
|
|
|
test_start = time()
|
|
for t in ["tidy", "ref", "content", "wpt", "unit"]:
|
|
Registrar.dispatch("test-%s" % t, context=self.context)
|
|
elapsed = time() - test_start
|
|
|
|
print("Tests completed in %0.2fs" % elapsed)
|
|
|
|
@Command('test-unit',
|
|
description='Run unit tests',
|
|
category='testing')
|
|
@CommandArgument('--component', '-c', default=None,
|
|
help="Specific component to test")
|
|
@CommandArgument('test_name', nargs=argparse.REMAINDER,
|
|
help="Only run tests that match this pattern")
|
|
def test_unit(self, test_name=None, component=None):
|
|
if test_name is None:
|
|
test_name = []
|
|
|
|
self.ensure_bootstrapped()
|
|
self.ensure_built_tests()
|
|
|
|
ret = self.run_test("servo", test_name) != 0
|
|
|
|
def cargo_test(component):
|
|
return 0 != subprocess.call(
|
|
["cargo", "test", "-p", component]
|
|
+ test_name, env=self.build_env(), cwd=self.servo_crate())
|
|
|
|
if component is not None:
|
|
ret = ret or cargo_test(component)
|
|
else:
|
|
for c in os.listdir("components"):
|
|
if c != "servo":
|
|
ret = ret or cargo_test(c)
|
|
|
|
print("WARNING: test-unit has probably destroyed your servo binary "
|
|
" (see https://github.com/rust-lang/cargo/issues/961 ). You "
|
|
" may want to rebuild now.")
|
|
return ret
|
|
|
|
@Command('test-ref',
|
|
description='Run the reference tests',
|
|
category='testing')
|
|
@CommandArgument('--kind', '-k', default=None,
|
|
help="'cpu' or 'gpu' (default both)")
|
|
@CommandArgument('--name', default=None,
|
|
help="Only run tests that match this pattern. If the "
|
|
"path to the ref test directory is included, it "
|
|
"will automatically be trimmed out.")
|
|
@CommandArgument(
|
|
'servo_params', default=None, nargs=argparse.REMAINDER,
|
|
help="Command-line arguments to be passed through to Servo")
|
|
def test_ref(self, kind=None, name=None, servo_params=None):
|
|
self.ensure_bootstrapped()
|
|
self.ensure_built_tests()
|
|
|
|
kinds = ["cpu", "gpu"] if kind is None else [kind]
|
|
test_path = path.join(self.context.topdir, "tests", "ref")
|
|
error = False
|
|
|
|
test_start = time()
|
|
for k in kinds:
|
|
print("Running %s reftests..." % k)
|
|
test_args = [k, test_path]
|
|
if name is not None:
|
|
maybe_path = path.normpath(name)
|
|
ref_path = path.join("tests", "ref")
|
|
|
|
# Check to see if we were passed something leading with the
|
|
# path to the ref test directory, and trim it so that reftest
|
|
# knows how to filter it.
|
|
if ref_path in maybe_path:
|
|
test_args.append(path.relpath(maybe_path, ref_path))
|
|
else:
|
|
test_args.append(name)
|
|
if servo_params is not None:
|
|
test_args += ["--"] + servo_params
|
|
ret = self.run_test("reftest", test_args)
|
|
error = error or ret != 0
|
|
elapsed = time() - test_start
|
|
|
|
print("Reference tests completed in %0.2fs" % elapsed)
|
|
|
|
if error:
|
|
return 1
|
|
|
|
@Command('test-content',
|
|
description='Run the content tests',
|
|
category='testing')
|
|
@CommandArgument('test_name', default=None, nargs="?",
|
|
help="Only run tests that match this pattern")
|
|
def test_content(self, test_name=None):
|
|
self.ensure_bootstrapped()
|
|
self.ensure_built_tests()
|
|
|
|
test_path = path.join(self.context.topdir, "tests", "content")
|
|
test_args = ["--source-dir=%s" % test_path]
|
|
|
|
if test_name is not None:
|
|
test_args.append(test_name)
|
|
|
|
test_start = time()
|
|
ret = self.run_test("contenttest", test_args)
|
|
elapsed = time() - test_start
|
|
|
|
print("Content tests completed in %0.2fs" % elapsed)
|
|
return ret
|
|
|
|
@Command('test-tidy',
|
|
description='Run the source code tidiness check',
|
|
category='testing')
|
|
def test_tidy(self):
|
|
return tidy.scan()
|
|
|
|
@Command('test-wpt',
|
|
description='Run the web platform tests',
|
|
category='testing')
|
|
@CommandArgument(
|
|
'params', default=None, nargs='...',
|
|
help="Command-line arguments to be passed through to wpt/run.sh")
|
|
def test_wpt(self, params=None):
|
|
if params is None:
|
|
params = []
|
|
else:
|
|
# Allow the first argument to be a relative path from Servo's root
|
|
# directory, converting it to `--include some/wpt/test.html`
|
|
maybe_path = path.normpath(params[0])
|
|
wpt_path = path.join('tests', 'wpt', 'web-platform-tests')
|
|
|
|
if path.exists(maybe_path) and wpt_path in maybe_path:
|
|
params = ["--include",
|
|
path.relpath(maybe_path, wpt_path)] + params[1:]
|
|
|
|
return subprocess.call(
|
|
["bash", path.join("tests", "wpt", "run.sh")] + params,
|
|
env=self.build_env())
|