summaryrefslogtreecommitdiffstats
path: root/testing/mochitest/tests/python/test_mochitest_integration.py
diff options
context:
space:
mode:
Diffstat (limited to 'testing/mochitest/tests/python/test_mochitest_integration.py')
-rw-r--r--testing/mochitest/tests/python/test_mochitest_integration.py314
1 files changed, 314 insertions, 0 deletions
diff --git a/testing/mochitest/tests/python/test_mochitest_integration.py b/testing/mochitest/tests/python/test_mochitest_integration.py
new file mode 100644
index 0000000000..e2ae89bdaf
--- /dev/null
+++ b/testing/mochitest/tests/python/test_mochitest_integration.py
@@ -0,0 +1,314 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import os
+from functools import partial
+
+import mozunit
+import pytest
+from conftest import setup_args
+from manifestparser import TestManifest
+from mozharness.base.log import ERROR, INFO, WARNING
+from mozharness.mozilla.automation import TBPL_FAILURE, TBPL_SUCCESS, TBPL_WARNING
+from moztest.selftest.output import filter_action, get_mozharness_status
+
+here = os.path.abspath(os.path.dirname(__file__))
+get_mozharness_status = partial(get_mozharness_status, "mochitest")
+
+
+@pytest.fixture
+def test_name(request):
+ flavor = request.getfixturevalue("flavor")
+
+ def inner(name):
+ if flavor == "plain":
+ return f"test_{name}.html"
+ elif flavor == "browser-chrome":
+ return f"browser_{name}.js"
+
+ return inner
+
+
+@pytest.fixture
+def test_manifest(setup_test_harness, request):
+ flavor = request.getfixturevalue("flavor")
+ test_root = setup_test_harness(*setup_args, flavor=flavor)
+ assert test_root
+
+ def inner(manifestFileNames):
+ return TestManifest(
+ manifests=[os.path.join(test_root, name) for name in manifestFileNames],
+ strict=False,
+ rootdir=test_root,
+ )
+
+ return inner
+
+
+@pytest.mark.parametrize(
+ "flavor,manifest",
+ [
+ ("plain", "mochitest-args.ini"),
+ ("browser-chrome", "browser-args.ini"),
+ ],
+)
+def test_output_extra_args(flavor, manifest, runtests, test_manifest, test_name):
+ # Explicitly provide a manifestFile property that includes the
+ # manifest file that contains command line arguments.
+ extra_opts = {
+ "manifestFile": test_manifest([manifest]),
+ "runByManifest": True,
+ }
+
+ results = {
+ "status": 0,
+ "tbpl_status": TBPL_SUCCESS,
+ "log_level": (INFO, WARNING),
+ }
+
+ status, lines = runtests(test_name("pass"), **extra_opts)
+ assert status == results["status"]
+
+ tbpl_status, log_level, _ = get_mozharness_status(lines, status)
+ assert tbpl_status == results["tbpl_status"]
+ assert log_level in results["log_level"]
+
+ # Filter log entries for the application command including the used
+ # command line arguments.
+ lines = filter_action("log", lines)
+ command = next(
+ l["message"] for l in lines if l["message"].startswith("Application command")
+ )
+ assert "--headless --window-size 800,600 --new-tab http://example.org" in command
+
+
+@pytest.mark.parametrize("runFailures", ["selftest", ""])
+@pytest.mark.parametrize("flavor", ["plain", "browser-chrome"])
+def test_output_pass(flavor, runFailures, runtests, test_name):
+ extra_opts = {}
+ results = {
+ "status": 1 if runFailures else 0,
+ "tbpl_status": TBPL_WARNING if runFailures else TBPL_SUCCESS,
+ "log_level": (INFO, WARNING),
+ "lines": 2 if runFailures else 1,
+ "line_status": "PASS",
+ }
+ if runFailures:
+ extra_opts["runFailures"] = runFailures
+ extra_opts["crashAsPass"] = True
+ extra_opts["timeoutAsPass"] = True
+
+ status, lines = runtests(test_name("pass"), **extra_opts)
+ assert status == results["status"]
+
+ tbpl_status, log_level, summary = get_mozharness_status(lines, status)
+ assert tbpl_status == results["tbpl_status"]
+ assert log_level in results["log_level"]
+
+ lines = filter_action("test_status", lines)
+ assert len(lines) == results["lines"]
+ assert lines[0]["status"] == results["line_status"]
+
+
+@pytest.mark.parametrize("runFailures", ["selftest", ""])
+@pytest.mark.parametrize("flavor", ["plain", "browser-chrome"])
+def test_output_fail(flavor, runFailures, runtests, test_name):
+ extra_opts = {}
+ results = {
+ "status": 0 if runFailures else 1,
+ "tbpl_status": TBPL_SUCCESS if runFailures else TBPL_WARNING,
+ "log_level": (INFO, WARNING),
+ "lines": 1,
+ "line_status": "PASS" if runFailures else "FAIL",
+ }
+ if runFailures:
+ extra_opts["runFailures"] = runFailures
+ extra_opts["crashAsPass"] = True
+ extra_opts["timeoutAsPass"] = True
+
+ status, lines = runtests(test_name("fail"), **extra_opts)
+ assert status == results["status"]
+
+ tbpl_status, log_level, summary = get_mozharness_status(lines, status)
+ assert tbpl_status == results["tbpl_status"]
+ assert log_level in results["log_level"]
+
+ lines = filter_action("test_status", lines)
+ assert len(lines) == results["lines"]
+ assert lines[0]["status"] == results["line_status"]
+
+
+@pytest.mark.skip_mozinfo("!crashreporter")
+@pytest.mark.parametrize("runFailures", ["selftest", ""])
+@pytest.mark.parametrize("flavor", ["plain", "browser-chrome"])
+def test_output_crash(flavor, runFailures, runtests, test_name):
+ extra_opts = {}
+ results = {
+ "status": 0 if runFailures else 1,
+ "tbpl_status": TBPL_FAILURE,
+ "log_level": ERROR,
+ "lines": 1,
+ }
+ if runFailures:
+ extra_opts["runFailures"] = runFailures
+ extra_opts["crashAsPass"] = True
+ extra_opts["timeoutAsPass"] = True
+ # bug 1443327 - we do not set MOZ_CRASHREPORTER_SHUTDOWN for browser-chrome
+ # the error regex's don't pick this up as a failure
+ if flavor == "browser-chrome":
+ results["tbpl_status"] = TBPL_SUCCESS
+ results["log_level"] = (INFO, WARNING)
+
+ status, lines = runtests(
+ test_name("crash"), environment=["MOZ_CRASHREPORTER_SHUTDOWN=1"], **extra_opts
+ )
+ assert status == results["status"]
+
+ tbpl_status, log_level, summary = get_mozharness_status(lines, status)
+ assert tbpl_status == results["tbpl_status"]
+ assert log_level in results["log_level"]
+
+ if not runFailures:
+ crash = filter_action("crash", lines)
+ assert len(crash) == 1
+ assert crash[0]["action"] == "crash"
+ assert crash[0]["signature"]
+ assert crash[0]["minidump_path"]
+
+ lines = filter_action("test_end", lines)
+ assert len(lines) == results["lines"]
+
+
+@pytest.mark.skip_mozinfo("!asan")
+@pytest.mark.parametrize("runFailures", [""])
+@pytest.mark.parametrize("flavor", ["plain"])
+def test_output_asan(flavor, runFailures, runtests, test_name):
+ extra_opts = {}
+ results = {
+ "status": 245,
+ "tbpl_status": TBPL_FAILURE,
+ "log_level": ERROR,
+ "lines": 0,
+ }
+
+ status, lines = runtests(
+ test_name("crash"), environment=["MOZ_CRASHREPORTER_SHUTDOWN=1"], **extra_opts
+ )
+ assert status == results["status"]
+
+ tbpl_status, log_level, summary = get_mozharness_status(lines, status)
+ assert tbpl_status == results["tbpl_status"]
+ assert log_level == results["log_level"]
+
+ crash = filter_action("crash", lines)
+ assert len(crash) == results["lines"]
+
+ process_output = filter_action("process_output", lines)
+ assert any("ERROR: AddressSanitizer" in l["data"] for l in process_output)
+
+
+@pytest.mark.skip_mozinfo("!debug")
+@pytest.mark.parametrize("runFailures", [""])
+@pytest.mark.parametrize("flavor", ["plain"])
+def test_output_assertion(flavor, runFailures, runtests, test_name):
+ extra_opts = {}
+ results = {
+ "status": 0,
+ "tbpl_status": TBPL_WARNING,
+ "log_level": WARNING,
+ "lines": 1,
+ "assertions": 1,
+ }
+
+ status, lines = runtests(test_name("assertion"), **extra_opts)
+ # TODO: mochitest should return non-zero here
+ assert status == results["status"]
+
+ tbpl_status, log_level, summary = get_mozharness_status(lines, status)
+ assert tbpl_status == results["tbpl_status"]
+ assert log_level == results["log_level"]
+
+ test_end = filter_action("test_end", lines)
+ assert len(test_end) == results["lines"]
+ # TODO: this should be ASSERT, but moving the assertion check before
+ # the test_end action caused a bunch of failures.
+ assert test_end[0]["status"] == "OK"
+
+ assertions = filter_action("assertion_count", lines)
+ assert len(assertions) == results["assertions"]
+ assert assertions[0]["count"] == results["assertions"]
+
+
+@pytest.mark.skip_mozinfo("!debug")
+@pytest.mark.parametrize("runFailures", [""])
+@pytest.mark.parametrize("flavor", ["plain"])
+def test_output_leak(flavor, runFailures, runtests, test_name):
+ extra_opts = {}
+ results = {"status": 0, "tbpl_status": TBPL_WARNING, "log_level": WARNING}
+
+ status, lines = runtests(test_name("leak"), **extra_opts)
+ # TODO: mochitest should return non-zero here
+ assert status == results["status"]
+
+ tbpl_status, log_level, summary = get_mozharness_status(lines, status)
+ assert tbpl_status == results["tbpl_status"]
+ assert log_level == results["log_level"]
+
+ leak_totals = filter_action("mozleak_total", lines)
+ found_leaks = False
+ for lt in leak_totals:
+ if lt["bytes"] == 0:
+ # No leaks in this process.
+ assert len(lt["objects"]) == 0
+ continue
+
+ assert not found_leaks, "Only one process should have leaked"
+ found_leaks = True
+ assert lt["process"] == "tab"
+ assert lt["bytes"] == 1
+ assert lt["objects"] == ["IntentionallyLeakedObject"]
+
+ assert found_leaks, "At least one process should have leaked"
+
+
+@pytest.mark.parametrize("flavor", ["plain"])
+def test_output_testfile_in_dupe_manifests(flavor, runtests, test_name, test_manifest):
+ results = {
+ "status": 0,
+ "tbpl_status": TBPL_SUCCESS,
+ "log_level": (INFO, WARNING),
+ "line_status": "PASS",
+ # We expect the test to be executed exactly 2 times,
+ # once for each manifest where the test file has been included.
+ "lines": 2,
+ }
+
+ # Explicitly provide a manifestFile property that includes the
+ # two manifest files that share the same test file.
+ extra_opts = {
+ "manifestFile": test_manifest(
+ [
+ "mochitest-dupemanifest-1.ini",
+ "mochitest-dupemanifest-2.ini",
+ ]
+ ),
+ "runByManifest": True,
+ }
+
+ # Execute mochitest by explicitly request the test file listed
+ # in two manifest files to be executed.
+ status, lines = runtests(test_name("pass"), **extra_opts)
+ assert status == results["status"]
+
+ tbpl_status, log_level, summary = get_mozharness_status(lines, status)
+ assert tbpl_status == results["tbpl_status"]
+ assert log_level in results["log_level"]
+
+ lines = filter_action("test_status", lines)
+ assert len(lines) == results["lines"]
+ assert lines[0]["status"] == results["line_status"]
+
+
+if __name__ == "__main__":
+ mozunit.main()