commit 458596e38ee00e8b467a4c5f4fa4954ec79a3310
parent 2cf5206b999774523b49ba698abcd26d14c8f50a
Author: serge-sans-paille <sguelton@mozilla.com>
Date: Tue, 14 Oct 2025 07:32:42 +0000
Bug 1981951 - Add support for running generic tests from moz.build r=glandium
The syntax is pretty simple: Add a LegacyTest(*args, **keywords) to moz.build
and the test described by its parameters *args will be added to the
`check` target. `keywords` controls environment variable, current
working directory and test dependencies.
Differential Revision: https://phabricator.services.mozilla.com/D260441
Diffstat:
7 files changed, 107 insertions(+), 0 deletions(-)
diff --git a/build/templates.mozbuild b/build/templates.mozbuild
@@ -257,6 +257,19 @@ def GeneratedFile(name, *names, **kwargs):
@template
+def LegacyTest(*args, **kwargs):
+ """Add one test to LEGACY_RUN_TESTS with the given attributes."""
+
+ LEGACY_RUN_TESTS += [{"args": args}]
+ test = LEGACY_RUN_TESTS[-1]
+ test["env"] = kwargs.pop("env", None)
+ test["description"] = kwargs.pop("description", None)
+ test["depends"] = kwargs.pop("depends", ())
+ if kwargs:
+ error("Unrecognized argument(s) to LegacyTest: %s" % ", ".join(kwargs))
+
+
+@template
def CbindgenHeader(name, inputs):
"""Add one GENERATED_FILES by running RunCbindgen.py"""
diff --git a/python/mozbuild/mozbuild/backend/recursivemake.py b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -47,6 +47,7 @@ from ..frontend.data import (
HostSources,
InstallationTarget,
JARManifest,
+ LegacyRunTests,
Linkable,
LocalInclude,
LocalizedFiles,
@@ -590,6 +591,9 @@ class RecursiveMakeBackend(MakeBackend):
elif isinstance(obj, RustTests):
self._process_rust_tests(obj, backend_file)
+ elif isinstance(obj, LegacyRunTests):
+ self._process_legacy_run_tests(obj, backend_file)
+
elif isinstance(obj, Program):
self._process_program(obj, backend_file)
self._process_linked_libraries(obj, backend_file)
@@ -1238,6 +1242,45 @@ class RecursiveMakeBackend(MakeBackend):
backend_file.write_once("RUST_TESTS := %s\n" % " ".join(obj.names))
backend_file.write_once("RUST_TEST_FEATURES := %s\n" % " ".join(obj.features))
+ def _process_legacy_run_tests(self, obj, backend_file):
+ self._no_skip["check"].add(backend_file.relobjdir)
+ rules = Makefile()
+ for i, test in enumerate(obj.tests):
+ backend_file.write(f"check:: force-run-test{i}\n")
+ program, *args = test["args"]
+ program = self._pretty_path(Path(obj._context, program), backend_file)
+ args = [
+ (
+ arg
+ if arg.startswith("-")
+ else self._pretty_path(Path(obj._context, arg), backend_file)
+ )
+ for arg in args
+ ]
+ args = [shell_quote(arg) for arg in args]
+ rule = rules.create_rule([f"force-run-test{i}"])
+ depends = [program] + [
+ self._pretty_path(Path(obj._context, dep), backend_file)
+ for dep in test["depends"]
+ ]
+ rule.add_dependencies(depends)
+
+ commands = []
+ if description := test["description"]:
+ commands.append(f"@echo Running {description}")
+ if env := test["env"]:
+ envargs = " ".join(
+ make_quote(shell_quote(f"{k}={v}")) for k, v in env.items()
+ )
+ command = f"env {envargs} "
+ else:
+ command = ""
+ command += f"{program} "
+ command += " ".join(args)
+ commands.append(command)
+ rule.add_commands(commands)
+ rules.dump(backend_file.fh)
+
def _process_simple_program(self, obj, backend_file):
if obj.is_unit_test:
backend_file.write("CPP_UNIT_TESTS += %s\n" % obj.program)
diff --git a/python/mozbuild/mozbuild/frontend/context.py b/python/mozbuild/mozbuild/frontend/context.py
@@ -2082,6 +2082,17 @@ VARIABLES = {
"""Extra flags passed to the dumpsymbols utility when generating symbols for the crash reporter.
""",
),
+ "LEGACY_RUN_TESTS": (
+ TypedList(dict),
+ list,
+ """Scripts to run during check phase.
+
+ This variable holds scripts that used to be part of ``make check`` rule
+ and which should probably migrate to another test target.
+
+ Please don't add new values to it.
+ """,
+ ),
"JAR_MANIFESTS": (
ContextDerivedTypedList(SourcePath, StrictOrderingOnAppendList),
list,
diff --git a/python/mozbuild/mozbuild/frontend/data.py b/python/mozbuild/mozbuild/frontend/data.py
@@ -610,6 +610,15 @@ class RustTests(ContextDerived):
self.output_category = "rusttests"
+class LegacyRunTests(ContextDerived):
+ __slots__ = ("tests", "output_category")
+
+ def __init__(self, context, tests):
+ ContextDerived.__init__(self, context)
+ self.tests = tests
+ self.output_category = "runtests"
+
+
class BaseLibrary(Linkable):
"""Generic context derived container object for libraries."""
diff --git a/python/mozbuild/mozbuild/frontend/emitter.py b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -44,6 +44,7 @@ from .data import (
InstallationTarget,
IPDLCollection,
JARManifest,
+ LegacyRunTests,
Library,
Linkable,
LocalInclude,
@@ -1602,6 +1603,9 @@ class TreeMetadataEmitter(LoggingMixin):
Manifest("components", mozpath.basename(c)),
)
+ if run_tests := context.get("LEGACY_RUN_TESTS", []):
+ yield LegacyRunTests(context, run_tests)
+
rust_tests = context.get("RUST_TESTS", [])
if rust_tests:
# TODO: more sophisticated checking of the declared name vs.
diff --git a/python/mozbuild/mozbuild/test/python.toml b/python/mozbuild/mozbuild/test/python.toml
@@ -93,6 +93,8 @@ subsuite = "mozbuild"
["test_jarmaker.py"]
+["test_legacy_test.py"]
+
["test_licenses.py"]
["test_line_endings.py"]
diff --git a/python/mozbuild/mozbuild/test/test_legacy_test.py b/python/mozbuild/mozbuild/test/test_legacy_test.py
@@ -0,0 +1,25 @@
+# Any copyright is dedicated to the Public Domain.
+# http://creativecommons.org/publicdomain/zero/1.0/
+
+import buildconfig
+import mozunit
+import mozversioncontrol
+
+# List of moz.build that currently hold a LegacyTest
+# *Don't touch that dial!*
+
+allowlist = {}
+
+
+def test_extra_legacy_tests():
+ repo = mozversioncontrol.get_repository_object(buildconfig.topsrcdir)
+ for src, fd in repo.get_tracked_files_finder().find("**/moz.build"):
+ if src in allowlist:
+ continue
+ assert (
+ b"LegacyTest(" not in fd.read()
+ ), f"LegacyTest used in {src}, please refrain and use another test kind."
+
+
+if __name__ == "__main__":
+ mozunit.main()