# 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 io
import json
import os
from argparse
import Namespace
import mozinfo
import pytest
from manifestparser
import TestManifest, expression
from moztest.selftest.fixtures
import binary_fixture, setup_test_harness
# noqa
here = os.path.abspath(os.path.dirname(__file__))
setup_args = [os.path.join(here,
"files"),
"mochitest",
"testing/mochitest"]
@pytest.fixture
def create_manifest(tmpdir, build_obj):
def inner(string, name=
"manifest.ini"):
manifest = tmpdir.join(name)
manifest.write(string, ensure=
True)
path = str(manifest)
return TestManifest(manifests=(path,), strict=
False, rootdir=tmpdir.strpath)
return inner
@pytest.fixture(scope=
"function")
def parser(request):
parser = pytest.importorskip(
"mochitest_options")
app = getattr(request.module,
"APP",
"generic")
return parser.MochitestArgumentParser(app=app)
@pytest.fixture(scope=
"function")
def runtests(setup_test_harness, binary, parser, request):
"""Creates an easy to use entry point into the mochitest harness.
:returns: A function
with the signature `*tests, **opts`. Each test
is a file name
(relative to the `files` dir). At least one
is required. The opts are
used to override the default mochitest options, they are optional.
"""
flavor =
"plain"
if "flavor" in request.fixturenames:
flavor = request.getfixturevalue(
"flavor")
runFailures =
""
if "runFailures" in request.fixturenames:
runFailures = request.getfixturevalue(
"runFailures")
restartAfterFailure =
False
if "restartAfterFailure" in request.fixturenames:
restartAfterFailure = request.getfixturevalue(
"restartAfterFailure")
setup_test_harness(*setup_args, flavor=flavor)
runtests = pytest.importorskip(
"runtests")
mochitest_root = runtests.SCRIPT_DIR
if flavor ==
"plain":
test_root = os.path.join(mochitest_root,
"tests",
"selftests")
manifest_name =
"mochitest.ini"
elif flavor ==
"browser-chrome":
test_root = os.path.join(mochitest_root,
"browser",
"tests",
"selftests")
manifest_name =
"browser.ini"
else:
raise Exception(f
"Invalid flavor {flavor}!")
buf = io.StringIO()
options = vars(parser.parse_args([]))
options.update(
{
"app": binary,
"flavor": flavor,
"runFailures": runFailures,
"restartAfterFailure": restartAfterFailure,
"keep_open":
False,
"log_raw": [buf],
}
)
if runFailures ==
"selftest":
options[
"crashAsPass"] =
True
options[
"timeoutAsPass"] =
True
runtests.mozinfo.update({
"selftest":
True})
if not os.path.isdir(runtests.build_obj.bindir):
package_root = os.path.dirname(mochitest_root)
options.update(
{
"certPath": os.path.join(package_root,
"certs"),
"utilityPath": os.path.join(package_root,
"bin"),
}
)
options[
"extraProfileFiles"].append(
os.path.join(package_root,
"bin",
"plugins")
)
options.update(getattr(request.module,
"OPTIONS", {}))
def normalize(test):
if isinstance(test, str):
test = [test]
return [
{
"name": t,
"relpath": t,
"path": os.path.join(test_root, t),
# add a dummy manifest file because mochitest expects it
"manifest": os.path.join(test_root, manifest_name),
"manifest_relpath": manifest_name,
"skip-if": runFailures,
}
for t
in test
]
def inner(*tests, **opts):
assert len(tests) > 0
# Inject a TestManifest in the runtests option if one
# has not been already included by the caller.
if not isinstance(options[
"manifestFile"], TestManifest):
manifest = TestManifest()
options[
"manifestFile"] = manifest
# pylint --py3k: W1636
manifest.tests.extend(list(map(normalize, tests))[0])
options.update(opts)
result = runtests.run_test_harness(parser, Namespace(**options))
out = json.loads(
"[" +
",".join(buf.getvalue().splitlines()) +
"]")
buf.close()
return result, out
return inner
@pytest.fixture
def build_obj(setup_test_harness):
setup_test_harness(*setup_args)
mochitest_options = pytest.importorskip(
"mochitest_options")
return mochitest_options.build_obj
@pytest.fixture(autouse=
True)
def skip_using_mozinfo(request, setup_test_harness):
"""Gives tests the ability to skip based on values from mozinfo.
Example:
@pytest.mark.skip_mozinfo(
"!e10s || os == 'linux'")
def test_foo():
pass
"""
setup_test_harness(*setup_args)
runtests = pytest.importorskip(
"runtests")
runtests.update_mozinfo()
skip_mozinfo = request.node.get_closest_marker(
"skip_mozinfo")
if skip_mozinfo:
value = skip_mozinfo.args[0]
if expression.parse(value, **mozinfo.info):
pytest.skip(
"skipped due to mozinfo match: \n{}".format(value))