tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mach_commands.py (10121B)


      1 # This Source Code Form is subject to the terms of the Mozilla Public
      2 # License, v. 2.0. If a copy of the MPL was not distributed with this
      3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
      4 
      5 import os
      6 import re
      7 import sys
      8 from argparse import Namespace
      9 
     10 from mach.decorators import Command
     11 from mozbuild.base import MachCommandConditions as conditions
     12 from mozbuild.base import MozbuildObject
     13 
     14 parser = None
     15 
     16 
     17 class ReftestRunner(MozbuildObject):
     18    """Easily run reftests.
     19 
     20    This currently contains just the basics for running reftests. We may want
     21    to hook up result parsing, etc.
     22    """
     23 
     24    def __init__(self, *args, **kwargs):
     25        MozbuildObject.__init__(self, *args, **kwargs)
     26 
     27        # TODO Bug 794506 remove once mach integrates with virtualenv.
     28        build_path = os.path.join(self.topobjdir, "build")
     29        if build_path not in sys.path:
     30            sys.path.append(build_path)
     31 
     32        self.tests_dir = os.path.join(self.topobjdir, "_tests")
     33        self.reftest_dir = os.path.join(self.tests_dir, "reftest")
     34 
     35    def _make_shell_string(self, s):
     36        return "'%s'" % re.sub("'", r"'\''", s)
     37 
     38    def _setup_objdir(self, args):
     39        # reftest imports will happen from the objdir
     40        sys.path.insert(0, self.reftest_dir)
     41 
     42        tests = os.path.join(self.reftest_dir, "tests")
     43        if not os.path.isdir(tests) and not os.path.islink(tests):
     44            # This symbolic link is used by the desktop tests to
     45            # locate the actual test files when running using file:.
     46            os.symlink(self.topsrcdir, tests)
     47 
     48    def run_desktop_test(self, **kwargs):
     49        """Runs a reftest, in desktop Firefox."""
     50        import runreftest
     51 
     52        args = Namespace(**kwargs)
     53        if args.suite not in ("reftest", "crashtest", "jstestbrowser"):
     54            raise Exception("None or unrecognized reftest suite type.")
     55 
     56        default_manifest = {
     57            "reftest": (self.topsrcdir, "layout", "reftests", "reftest.list"),
     58            "crashtest": (self.topsrcdir, "testing", "crashtest", "crashtests.list"),
     59            "jstestbrowser": (
     60                self.topobjdir,
     61                "dist",
     62                "test-stage",
     63                "jsreftest",
     64                "tests",
     65                "js",
     66                "src",
     67                "tests",
     68                "jstests.list",
     69            ),
     70        }
     71 
     72        args.extraProfileFiles.append(os.path.join(self.topobjdir, "dist", "plugins"))
     73        args.symbolsPath = os.path.join(self.topobjdir, "dist", "crashreporter-symbols")
     74        args.sandboxReadWhitelist.extend([self.topsrcdir, self.topobjdir])
     75 
     76        if not args.tests:
     77            args.tests = [os.path.join(*default_manifest[args.suite])]
     78 
     79        if args.suite == "jstestbrowser":
     80            args.extraProfileFiles.append(
     81                os.path.join(
     82                    self.topobjdir,
     83                    "dist",
     84                    "test-stage",
     85                    "jsreftest",
     86                    "tests",
     87                    "js",
     88                    "src",
     89                    "tests",
     90                    "user.js",
     91                )
     92            )
     93 
     94        self.log_manager.enable_unstructured()
     95        try:
     96            rv = runreftest.run_test_harness(parser, args)
     97        finally:
     98            self.log_manager.disable_unstructured()
     99 
    100        return rv
    101 
    102    def run_android_test(self, **kwargs):
    103        """Runs a reftest, in an Android application."""
    104 
    105        args = Namespace(**kwargs)
    106        if args.suite not in ("reftest", "crashtest", "jstestbrowser"):
    107            raise Exception("None or unrecognized reftest suite type.")
    108 
    109        self._setup_objdir(args)
    110        import remotereftest
    111 
    112        default_manifest = {
    113            "reftest": (self.topsrcdir, "layout", "reftests", "reftest.list"),
    114            "crashtest": (self.topsrcdir, "testing", "crashtest", "crashtests.list"),
    115            "jstestbrowser": (
    116                self.topobjdir,
    117                "dist",
    118                "test-stage",
    119                "jsreftest",
    120                "tests",
    121                "js",
    122                "src",
    123                "tests",
    124                "jstests.list",
    125            ),
    126        }
    127 
    128        if not args.tests:
    129            args.tests = [os.path.join(*default_manifest[args.suite])]
    130 
    131        args.extraProfileFiles.append(
    132            os.path.join(self.topsrcdir, "mobile", "android", "fonts")
    133        )
    134 
    135        hyphenation_path = os.path.join(self.topsrcdir, "intl", "locales")
    136 
    137        for dirpath, dirnames, filenames in os.walk(hyphenation_path):
    138            for filename in filenames:
    139                if filename.endswith(".dic"):
    140                    args.extraProfileFiles.append(os.path.join(dirpath, filename))
    141 
    142        if not args.httpdPath:
    143            args.httpdPath = os.path.join(self.tests_dir, "modules")
    144        if not args.symbolsPath:
    145            args.symbolsPath = os.path.join(self.topobjdir, "crashreporter-symbols")
    146        if not args.xrePath:
    147            args.xrePath = os.environ.get("MOZ_HOST_BIN")
    148        if not args.app:
    149            args.app = "org.mozilla.geckoview.test_runner"
    150        if not args.utilityPath:
    151            args.utilityPath = args.xrePath
    152        args.ignoreWindowSize = True
    153 
    154        from mozrunner.devices.android_device import get_adb_path
    155 
    156        if not args.adb_path:
    157            args.adb_path = get_adb_path(self)
    158 
    159        if "geckoview" not in args.app:
    160            args.e10s = False
    161            print("using e10s=False for non-geckoview app")
    162 
    163        # A symlink and some path manipulations are required so that test
    164        # manifests can be found both locally and remotely (via a url)
    165        # using the same relative path.
    166        if args.suite == "jstestbrowser":
    167            staged_js_dir = os.path.join(
    168                self.topobjdir, "dist", "test-stage", "jsreftest"
    169            )
    170            tests = os.path.join(self.reftest_dir, "jsreftest")
    171            if not os.path.isdir(tests) and not os.path.islink(tests):
    172                os.symlink(staged_js_dir, tests)
    173            args.extraProfileFiles.append(
    174                os.path.join(staged_js_dir, "tests", "js", "src", "tests", "user.js")
    175            )
    176        else:
    177            tests = os.path.join(self.reftest_dir, "tests")
    178            if not os.path.isdir(tests) and not os.path.islink(tests):
    179                os.symlink(self.topsrcdir, tests)
    180            for i, path in enumerate(args.tests):
    181                # Non-absolute paths are relative to the packaged directory, which
    182                # has an extra tests/ at the start
    183                if os.path.exists(os.path.abspath(path)):
    184                    path = os.path.relpath(path, os.path.join(self.topsrcdir))
    185                args.tests[i] = os.path.join("tests", path)
    186 
    187        self.log_manager.enable_unstructured()
    188        try:
    189            rv = remotereftest.run_test_harness(parser, args)
    190        finally:
    191            self.log_manager.disable_unstructured()
    192 
    193        return rv
    194 
    195 
    196 def process_test_objects(kwargs):
    197    """|mach test| works by providing a test_objects argument, from
    198    which the test path must be extracted and converted into a normal
    199    reftest tests argument."""
    200 
    201    if "test_objects" in kwargs:
    202        if kwargs["tests"] is None:
    203            kwargs["tests"] = []
    204        kwargs["tests"].extend(item["path"] for item in kwargs["test_objects"])
    205        del kwargs["test_objects"]
    206 
    207 
    208 def get_parser():
    209    import reftestcommandline
    210 
    211    global parser
    212    here = os.path.abspath(os.path.dirname(__file__))
    213    build_obj = MozbuildObject.from_environment(cwd=here)
    214    if conditions.is_android(build_obj):
    215        parser = reftestcommandline.RemoteArgumentsParser()
    216    else:
    217        parser = reftestcommandline.DesktopArgumentsParser()
    218    return parser
    219 
    220 
    221 @Command(
    222    "reftest",
    223    category="testing",
    224    description="Run reftests (layout and graphics correctness).",
    225    parser=get_parser,
    226 )
    227 def run_reftest(command_context, **kwargs):
    228    kwargs["suite"] = "reftest"
    229    return _run_reftest(command_context, **kwargs)
    230 
    231 
    232 @Command(
    233    "jstestbrowser",
    234    category="testing",
    235    description="Run js/src/tests in the browser.",
    236    parser=get_parser,
    237 )
    238 def run_jstestbrowser(command_context, **kwargs):
    239    if command_context.substs.get("JS_DISABLE_SHELL"):
    240        raise Exception(
    241            "jstestbrowser requires --enable-js-shell be specified in mozconfig."
    242        )
    243    command_context._mach_context.commands.dispatch(
    244        "build", command_context._mach_context, what=["stage-jstests"]
    245    )
    246    kwargs["suite"] = "jstestbrowser"
    247    return _run_reftest(command_context, **kwargs)
    248 
    249 
    250 @Command(
    251    "crashtest",
    252    category="testing",
    253    description="Run crashtests (Check if crashes on a page).",
    254    parser=get_parser,
    255 )
    256 def run_crashtest(command_context, **kwargs):
    257    kwargs["suite"] = "crashtest"
    258    return _run_reftest(command_context, **kwargs)
    259 
    260 
    261 def _run_reftest(command_context, **kwargs):
    262    kwargs["topsrcdir"] = command_context.topsrcdir
    263    process_test_objects(kwargs)
    264    reftest = command_context._spawn(ReftestRunner)
    265    # Unstructured logging must be enabled prior to calling
    266    # adb which uses an unstructured logger in its constructor.
    267    reftest.log_manager.enable_unstructured()
    268    if conditions.is_android(command_context):
    269        from mozrunner.devices.android_device import (
    270            InstallIntent,
    271            verify_android_device,
    272        )
    273 
    274        install = InstallIntent.NO if kwargs.get("no_install") else InstallIntent.YES
    275        verbose = False
    276        if (
    277            kwargs.get("log_mach_verbose")
    278            or kwargs.get("log_tbpl_level") == "debug"
    279            or kwargs.get("log_mach_level") == "debug"
    280            or kwargs.get("log_raw_level") == "debug"
    281        ):
    282            verbose = True
    283        verify_android_device(
    284            command_context,
    285            install=install,
    286            xre=True,
    287            network=True,
    288            app=kwargs["app"],
    289            device_serial=kwargs["deviceSerial"],
    290            verbose=verbose,
    291        )
    292        return reftest.run_android_test(**kwargs)
    293    return reftest.run_desktop_test(**kwargs)