tor-browser

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

mach_test_package_initialize.py (7895B)


      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 json
      6 import os
      7 import sys
      8 import types
      9 
     10 SEARCH_PATHS = [
     11    "gtest",
     12    "marionette/client",
     13    "marionette/harness",
     14    "mochitest",
     15    "mozbase/manifestparser",
     16    "mozbase/mozcrash",
     17    "mozbase/mozdebug",
     18    "mozbase/mozdevice",
     19    "mozbase/mozfile",
     20    "mozbase/mozgeckoprofile",
     21    "mozbase/mozhttpd",
     22    "mozbase/mozinfo",
     23    "mozbase/mozinstall",
     24    "mozbase/mozleak",
     25    "mozbase/mozlog",
     26    "mozbase/moznetwork",
     27    "mozbase/mozpower",
     28    "mozbase/mozprocess",
     29    "mozbase/mozprofile",
     30    "mozbase/mozrunner",
     31    "mozbase/mozscreenshot",
     32    "mozbase/mozserve",
     33    "mozbase/mozshellutil",
     34    "mozbase/mozsystemmonitor",
     35    "mozbase/moztest",
     36    "mozbase/mozversion",
     37    "reftest",
     38    "tools/mach",
     39    "tools/mozterm",
     40    "tools/geckoprocesstypes_generator",
     41    "tools/six",
     42    "tools/wptserve",
     43    "web-platform",
     44    "web-platform/tests/tools/wptrunner",
     45    "xpcshell",
     46 ]
     47 
     48 
     49 CATEGORIES = {
     50    "testing": {
     51        "short": "Testing",
     52        "long": "Run tests.",
     53        "priority": 30,
     54    },
     55    "devenv": {
     56        "short": "Development Environment",
     57        "long": "Set up and configure your development environment.",
     58        "priority": 20,
     59    },
     60    "misc": {
     61        "short": "Potpourri",
     62        "long": "Potent potables and assorted snacks.",
     63        "priority": 10,
     64    },
     65    "disabled": {
     66        "short": "Disabled",
     67        "long": "The disabled commands are hidden by default. Use -v to display them. "
     68        "These commands are unavailable for your current context, "
     69        'run "mach <command>" to see why.',
     70        "priority": 0,
     71    },
     72 }
     73 
     74 
     75 IS_WIN = sys.platform in ("win32", "cygwin")
     76 
     77 
     78 def ancestors(path, depth=0):
     79    """Emit the parent directories of a path."""
     80    count = 1
     81    while path and count != depth:
     82        yield path
     83        newpath = os.path.dirname(path)
     84        if newpath == path:
     85            break
     86        path = newpath
     87        count += 1
     88 
     89 
     90 def activate_mozharness_venv(context):
     91    """Activate the mozharness virtualenv in-process."""
     92    venv = os.path.join(
     93        context.mozharness_workdir,
     94        context.mozharness_config.get("virtualenv_path", "venv"),
     95    )
     96 
     97    if not os.path.isdir(venv):
     98        print(f"No mozharness virtualenv detected at '{venv}'.")
     99        return 1
    100 
    101    venv_bin = os.path.join(venv, "Scripts" if IS_WIN else "bin")
    102    activate_path = os.path.join(venv_bin, "activate_this.py")
    103 
    104    exec(open(activate_path).read(), dict(__file__=activate_path))
    105 
    106    if isinstance(os.environ["PATH"], str):
    107        os.environ["PATH"] = os.environ["PATH"].encode("utf-8")
    108 
    109    # sys.executable is used by mochitest-media to start the websocketprocessbridge,
    110    # for some reason it doesn't get set when calling `activate_this.py` so set it
    111    # here instead.
    112    binary = "python"
    113    if IS_WIN:
    114        binary += ".exe"
    115    sys.executable = os.path.join(venv_bin, binary)
    116 
    117 
    118 def find_firefox(context):
    119    """Try to automagically find the firefox binary."""
    120    import mozinstall
    121 
    122    search_paths = []
    123 
    124    # Check for a mozharness setup
    125    config = context.mozharness_config
    126    if config and "binary_path" in config:
    127        return config["binary_path"]
    128    elif config:
    129        search_paths.append(os.path.join(context.mozharness_workdir, "application"))
    130 
    131    # Check for test-stage setup
    132    dist_bin = os.path.join(os.path.dirname(context.package_root), "bin")
    133    if os.path.isdir(dist_bin):
    134        search_paths.append(dist_bin)
    135 
    136    for path in search_paths:
    137        try:
    138            return mozinstall.get_binary(path, "firefox")
    139        except mozinstall.InvalidBinary:
    140            continue
    141 
    142 
    143 def find_hostutils(context):
    144    workdir = context.mozharness_workdir
    145    hostutils = os.path.join(workdir, "hostutils")
    146    for fname in os.listdir(hostutils):
    147        fpath = os.path.join(hostutils, fname)
    148        if os.path.isdir(fpath) and fname.startswith("host-utils"):
    149            return fpath
    150 
    151 
    152 def normalize_test_path(test_root, path):
    153    if os.path.isabs(path) or os.path.exists(path):
    154        return os.path.normpath(os.path.abspath(path))
    155 
    156    for parent in ancestors(test_root):
    157        test_path = os.path.join(parent, path)
    158        if os.path.exists(test_path):
    159            return os.path.normpath(os.path.abspath(test_path))
    160    # Not a valid path? Return as is and let test harness deal with it
    161    return path
    162 
    163 
    164 def bootstrap(test_package_root):
    165    test_package_root = os.path.abspath(test_package_root)
    166 
    167    sys.path[0:0] = [os.path.join(test_package_root, path) for path in SEARCH_PATHS]
    168    import mach.main
    169    from mach.command_util import MachCommandReference, load_commands_from_spec
    170 
    171    # Centralized registry of available mach commands
    172    MACH_COMMANDS = {
    173        "gtest": MachCommandReference("gtest/mach_test_package_commands.py"),
    174        "marionette-test": MachCommandReference(
    175            "marionette/mach_test_package_commands.py"
    176        ),
    177        "mochitest": MachCommandReference("mochitest/mach_test_package_commands.py"),
    178        "geckoview-junit": MachCommandReference(
    179            "mochitest/mach_test_package_commands.py"
    180        ),
    181        "reftest": MachCommandReference("reftest/mach_test_package_commands.py"),
    182        "mach-commands": MachCommandReference(
    183            "python/mach/mach/commands/commandinfo.py"
    184        ),
    185        "mach-debug-commands": MachCommandReference(
    186            "python/mach/mach/commands/commandinfo.py"
    187        ),
    188        "mach-completion": MachCommandReference(
    189            "python/mach/mach/commands/commandinfo.py"
    190        ),
    191        "web-platform-tests": MachCommandReference(
    192            "web-platform/mach_test_package_commands.py"
    193        ),
    194        "wpt": MachCommandReference("web-platform/mach_test_package_commands.py"),
    195        "xpcshell-test": MachCommandReference("xpcshell/mach_test_package_commands.py"),
    196    }
    197 
    198    def populate_context(context, key=None):
    199        # These values will be set lazily, and cached after first being invoked.
    200        if key == "package_root":
    201            return test_package_root
    202 
    203        if key == "bin_dir":
    204            return os.path.join(test_package_root, "bin")
    205 
    206        if key == "certs_dir":
    207            return os.path.join(test_package_root, "certs")
    208 
    209        if key == "module_dir":
    210            return os.path.join(test_package_root, "modules")
    211 
    212        if key == "ancestors":
    213            return ancestors
    214 
    215        if key == "normalize_test_path":
    216            return normalize_test_path
    217 
    218        if key == "firefox_bin":
    219            return find_firefox(context)
    220 
    221        if key == "hostutils":
    222            return find_hostutils(context)
    223 
    224        if key == "mozharness_config":
    225            for dir_path in ancestors(context.package_root):
    226                mozharness_config = os.path.join(dir_path, "logs", "localconfig.json")
    227                if os.path.isfile(mozharness_config):
    228                    with open(mozharness_config, "rb") as f:
    229                        return json.load(f)
    230            return {}
    231 
    232        if key == "mozharness_workdir":
    233            config = context.mozharness_config
    234            if config:
    235                return os.path.join(config["base_work_dir"], config["work_dir"])
    236 
    237        if key == "activate_mozharness_venv":
    238            return types.MethodType(activate_mozharness_venv, context)
    239 
    240    mach = mach.main.Mach(os.getcwd())
    241    mach.populate_context_handler = populate_context
    242 
    243    for category, meta in CATEGORIES.items():
    244        mach.define_category(category, meta["short"], meta["long"], meta["priority"])
    245 
    246    # Depending on which test zips were extracted,
    247    # the command module might not exist
    248    load_commands_from_spec(MACH_COMMANDS, test_package_root, missing_ok=True)
    249 
    250    return mach