tor-browser

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

mach_commands.py (10780B)


      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 argparse
      6 import logging
      7 import os
      8 import sys
      9 
     10 import mozinfo
     11 from mach.decorators import Command, CommandArgument, CommandArgumentGroup
     12 from mozbuild.base import BinaryNotFoundException
     13 from mozbuild.base import MachCommandConditions as conditions
     14 
     15 
     16 def setup_awsy_argument_parser():
     17    from marionette_harness.runtests import MarionetteArguments
     18    from mozlog.structured import commandline
     19 
     20    parser = MarionetteArguments()
     21    commandline.add_logging_group(parser)
     22 
     23    return parser
     24 
     25 
     26 from awsy import ITERATIONS, MAX_TABS, PER_TAB_PAUSE, SETTLE_WAIT_TIME
     27 
     28 
     29 def run_awsy(command_context, tests, binary=None, **kwargs):
     30    import json
     31 
     32    from marionette_harness.runtests import MarionetteHarness, MarionetteTestRunner
     33    from mozlog.structured import commandline
     34 
     35    parser = setup_awsy_argument_parser()
     36 
     37    awsy_source_dir = os.path.join(command_context.topsrcdir, "testing", "awsy")
     38    if not tests:
     39        if kwargs["base"]:
     40            filename = "test_base_memory_usage.py"
     41        else:
     42            filename = "test_memory_usage.py"
     43        tests = [os.path.join(awsy_source_dir, "awsy", filename)]
     44 
     45    args = argparse.Namespace(tests=tests)
     46 
     47    args.binary = binary
     48 
     49    if kwargs["quick"]:
     50        kwargs["entities"] = 3
     51        kwargs["iterations"] = 1
     52        kwargs["perTabPause"] = 1
     53        kwargs["settleWaitTime"] = 1
     54 
     55    runtime_testvars = {}
     56    for arg in (
     57        "webRootDir",
     58        "pageManifest",
     59        "resultsDir",
     60        "entities",
     61        "iterations",
     62        "perTabPause",
     63        "settleWaitTime",
     64        "maxTabs",
     65        "dmd",
     66        "tp5",
     67    ):
     68        if arg in kwargs and kwargs[arg] is not None:
     69            runtime_testvars[arg] = kwargs[arg]
     70 
     71    if "webRootDir" not in runtime_testvars:
     72        awsy_tests_dir = os.path.join(command_context.topobjdir, "_tests", "awsy")
     73        web_root_dir = os.path.join(awsy_tests_dir, "html")
     74        runtime_testvars["webRootDir"] = web_root_dir
     75    else:
     76        web_root_dir = runtime_testvars["webRootDir"]
     77        awsy_tests_dir = os.path.dirname(web_root_dir)
     78 
     79    if "resultsDir" not in runtime_testvars:
     80        runtime_testvars["resultsDir"] = os.path.join(awsy_tests_dir, "results")
     81 
     82    runtime_testvars["bin"] = binary
     83    runtime_testvars["run_local"] = True
     84 
     85    page_load_test_dir = os.path.join(web_root_dir, "page_load_test")
     86    if not os.path.isdir(page_load_test_dir):
     87        os.makedirs(page_load_test_dir)
     88 
     89    if not os.path.isdir(runtime_testvars["resultsDir"]):
     90        os.makedirs(runtime_testvars["resultsDir"])
     91 
     92    runtime_testvars_path = os.path.join(awsy_tests_dir, "runtime-testvars.json")
     93    if kwargs["testvars"]:
     94        kwargs["testvars"].append(runtime_testvars_path)
     95    else:
     96        kwargs["testvars"] = [runtime_testvars_path]
     97 
     98    runtime_testvars_file = open(runtime_testvars_path, "w")
     99    runtime_testvars_file.write(json.dumps(runtime_testvars, indent=2))
    100    runtime_testvars_file.close()
    101 
    102    manifest_file = os.path.join(awsy_source_dir, "tp5n-pageset.manifest")
    103    tooltool_args = {
    104        "args": [
    105            sys.executable,
    106            os.path.join(command_context.topsrcdir, "mach"),
    107            "artifact",
    108            "toolchain",
    109            "-v",
    110            "--tooltool-manifest=%s" % manifest_file,
    111            "--cache-dir=%s"
    112            % os.path.join(command_context._mach_context.state_dir, "tooltool-cache"),
    113        ]
    114    }
    115    command_context.run_process(cwd=page_load_test_dir, **tooltool_args)
    116    tp5nzip = os.path.join(page_load_test_dir, "tp5n.zip")
    117    tp5nmanifest = os.path.join(page_load_test_dir, "tp5n", "tp5n.manifest")
    118    if not os.path.exists(tp5nmanifest):
    119        unzip_args = {"args": ["unzip", "-q", "-o", tp5nzip, "-d", page_load_test_dir]}
    120        try:
    121            command_context.run_process(**unzip_args)
    122        except Exception as exc:
    123            troubleshoot = ""
    124            if mozinfo.os == "win":
    125                troubleshoot = (
    126                    " Try using --web-root to specify a "
    127                    "directory closer to the drive root."
    128                )
    129 
    130            command_context.log(
    131                logging.ERROR,
    132                "awsy",
    133                {"directory": page_load_test_dir, "exception": exc},
    134                "Failed to unzip `tp5n.zip` into "
    135                "`{directory}` with `{exception}`." + troubleshoot,
    136            )
    137            raise exc
    138 
    139    # If '--preferences' was not specified supply our default set.
    140    if not kwargs["prefs_files"]:
    141        kwargs["prefs_files"] = [os.path.join(awsy_source_dir, "conf", "prefs.json")]
    142 
    143    # Setup DMD env vars if necessary.
    144    if kwargs["dmd"]:
    145        bin_dir = os.path.dirname(binary)
    146 
    147        if "DMD" not in os.environ:
    148            os.environ["DMD"] = "1"
    149 
    150        # Work around a startup crash with DMD on windows
    151        if mozinfo.os == "win":
    152            kwargs["pref"] = "security.sandbox.content.level:0"
    153            command_context.log(
    154                logging.WARNING,
    155                "awsy",
    156                {},
    157                "Forcing 'security.sandbox.content.level' = 0 because DMD is enabled.",
    158            )
    159        elif mozinfo.os == "mac":
    160            # On mac binary is in MacOS and dmd.py is in Resources, ie:
    161            #   Name.app/Contents/MacOS/libdmd.dylib
    162            #   Name.app/Contents/Resources/dmd.py
    163            bin_dir = os.path.join(bin_dir, "../Resources/")
    164 
    165        # Also add the bin dir to the python path so we can use dmd.py
    166        if bin_dir not in sys.path:
    167            sys.path.append(bin_dir)
    168 
    169    for k, v in kwargs.items():
    170        setattr(args, k, v)
    171 
    172    parser.verify_usage(args)
    173 
    174    args.logger = commandline.setup_logging(
    175        "Are We Slim Yet Tests", args, {"mach": sys.stdout}
    176    )
    177    failed = MarionetteHarness(MarionetteTestRunner, args=vars(args)).run()
    178    if failed > 0:
    179        return 1
    180    else:
    181        return 0
    182 
    183 
    184 @Command(
    185    "awsy-test",
    186    category="testing",
    187    description="Run Are We Slim Yet (AWSY) memory usage testing using marionette.",
    188    parser=setup_awsy_argument_parser,
    189 )
    190 @CommandArgumentGroup("AWSY")
    191 @CommandArgument(
    192    "--web-root",
    193    group="AWSY",
    194    action="store",
    195    type=str,
    196    dest="webRootDir",
    197    help="Path to web server root directory. If not specified, "
    198    "defaults to topobjdir/_tests/awsy/html.",
    199 )
    200 @CommandArgument(
    201    "--page-manifest",
    202    group="AWSY",
    203    action="store",
    204    type=str,
    205    dest="pageManifest",
    206    help="Path to page manifest text file containing a list "
    207    "of urls to test. The urls must be served from localhost. If not "
    208    "specified, defaults to page_load_test/tp5n/tp5n.manifest under "
    209    "the web root.",
    210 )
    211 @CommandArgument(
    212    "--results",
    213    group="AWSY",
    214    action="store",
    215    type=str,
    216    dest="resultsDir",
    217    help="Path to results directory. If not specified, defaults "
    218    "to the parent directory of the web root.",
    219 )
    220 @CommandArgument(
    221    "--quick",
    222    group="AWSY",
    223    action="store_true",
    224    dest="quick",
    225    default=False,
    226    help="Set --entities=3, --iterations=1, --per-tab-pause=1, "
    227    "--settle-wait-time=1 for a quick test. Overrides any explicit "
    228    "argument settings.",
    229 )
    230 @CommandArgument(
    231    "--entities",
    232    group="AWSY",
    233    action="store",
    234    type=int,
    235    dest="entities",
    236    help="Number of urls to load. Defaults to the total number of urls.",
    237 )
    238 @CommandArgument(
    239    "--max-tabs",
    240    group="AWSY",
    241    action="store",
    242    type=int,
    243    dest="maxTabs",
    244    help="Maximum number of tabs to open. Defaults to %s." % MAX_TABS,
    245 )
    246 @CommandArgument(
    247    "--iterations",
    248    group="AWSY",
    249    action="store",
    250    type=int,
    251    dest="iterations",
    252    help="Number of times to run through the test suite. Defaults to %s." % ITERATIONS,
    253 )
    254 @CommandArgument(
    255    "--per-tab-pause",
    256    group="AWSY",
    257    action="store",
    258    type=int,
    259    dest="perTabPause",
    260    help="Seconds to wait in between opening tabs. Defaults to %s." % PER_TAB_PAUSE,
    261 )
    262 @CommandArgument(
    263    "--settle-wait-time",
    264    group="AWSY",
    265    action="store",
    266    type=int,
    267    dest="settleWaitTime",
    268    help="Seconds to wait for things to settled down. "
    269    "Defaults to %s." % SETTLE_WAIT_TIME,
    270 )
    271 @CommandArgument(
    272    "--dmd",
    273    group="AWSY",
    274    action="store_true",
    275    dest="dmd",
    276    default=False,
    277    help="Enable DMD during testing. Requires a DMD-enabled build.",
    278 )
    279 @CommandArgument(
    280    "--tp5",
    281    group="AWSY",
    282    action="store_true",
    283    dest="tp5",
    284    default=False,
    285    help="Use the tp5 pageset during testing.",
    286 )
    287 @CommandArgument(
    288    "--base",
    289    group="AWSY",
    290    action="store_true",
    291    dest="base",
    292    default=False,
    293    help="Run base memory usage tests.",
    294 )
    295 def run_awsy_test(command_context, tests, **kwargs):
    296    """mach awsy-test runs the in-tree version of the Are We Slim Yet
    297    (AWSY) tests.
    298 
    299    awsy-test is implemented as a marionette test and marionette
    300    test arguments also apply although they are not necessary
    301    since reasonable defaults will be chosen.
    302 
    303    The AWSY specific arguments can be found in the Command
    304    Arguments for AWSY section below.
    305 
    306    awsy-test will automatically download the tp5n.zip talos
    307    pageset from tooltool and install it under
    308    topobjdir/_tests/awsy/html. You can specify your own page set
    309    by specifying --web-root and --page-manifest.
    310 
    311    The results of the test will be placed in the results
    312    directory specified by the --results argument.
    313 
    314    On Windows, you may experience problems due to path length
    315    errors when extracting the tp5n.zip file containing the
    316    test pages or when attempting to write checkpoints to the
    317    results directory. In that case, you should specify both
    318    the --web-root and --results arguments pointing to a location
    319    with a short path. For example:
    320 
    321    --web-root=c:\\\\tmp\\\\html --results=c:\\\\tmp\\\\results
    322 
    323    Note that the double backslashes are required.
    324    """
    325    kwargs["logger_name"] = "Awsy Tests"
    326    if "test_objects" in kwargs:
    327        tests = []
    328        for obj in kwargs["test_objects"]:
    329            tests.append(obj["file_relpath"])
    330        del kwargs["test_objects"]
    331 
    332    if not kwargs.get("binary") and conditions.is_firefox(command_context):
    333        try:
    334            kwargs["binary"] = command_context.get_binary_path("app")
    335        except BinaryNotFoundException as e:
    336            command_context.log(
    337                logging.ERROR, "awsy", {"error": str(e)}, "ERROR: {error}"
    338            )
    339            command_context.log(logging.INFO, "awsy", {"help": e.help()}, "{help}")
    340            return 1
    341    return run_awsy(command_context, tests, **kwargs)