Bug 1300163 - Lazy load certain mach context attributes using the 'key' mechanism, r?armenzg
You can set attributes on a mach context by using the 'key' argument to the context_handler. Basically,
whatever gets returned by the handler when <key> is passed in, will get set (i.e cached) on the context
object for fast retrieval next time. This is a way to lazy load these attributes.
Previously I was setting functions like 'find_firefox()' on the context object, and then having the
mach_commands call that directly. But this way is much cleaner.
Now, the loaded 'mozharness_config' can be stored as an attribute on the context. Also 'find_firefox()'
is now an attribute called 'firefox_bin'.
MozReview-Commit-ID: 4lsKGpizfH7
--- a/layout/tools/reftest/mach_test_package_commands.py
+++ b/layout/tools/reftest/mach_test_package_commands.py
@@ -9,25 +9,21 @@ from functools import partial
from mach.decorators import (
CommandProvider,
Command,
)
def run_reftest(context, **kwargs):
+ kwargs['app'] = kwargs['app'] or context.firefox_bin
kwargs['certPath'] = context.certs_dir
kwargs['utilityPath'] = context.bin_dir
kwargs['extraProfileFiles'].append(os.path.join(context.bin_dir, 'plugins'))
- if not kwargs['app']:
- # This could still return None in which case --appname must be used
- # to specify the firefox binary.
- kwargs['app'] = context.find_firefox()
-
if not kwargs['tests']:
kwargs['tests'] = [os.path.join('layout', 'reftests', 'reftest.list')]
test_root = os.path.join(context.package_root, 'reftest', 'tests')
normalize = partial(context.normalize_test_path, test_root)
kwargs['tests'] = map(normalize, kwargs['tests'])
from runreftest import run as run_test_harness
--- a/testing/marionette/mach_test_package_commands.py
+++ b/testing/marionette/mach_test_package_commands.py
@@ -19,19 +19,17 @@ def run_marionette(context, **kwargs):
from marionette.runtests import (
MarionetteTestRunner,
MarionetteHarness
)
from mozlog.structured import commandline
args = argparse.Namespace(**kwargs)
-
- if not args.binary:
- args.binary = context.find_firefox()
+ args.binary = args.binary or context.firefox_bin
test_root = os.path.join(context.package_root, 'marionette', 'tests')
if not args.tests:
args.tests = [os.path.join(test_root, 'testing', 'marionette', 'harness',
'marionette', 'tests', 'unit-tests.ini')]
normalize = partial(context.normalize_test_path, test_root)
args.tests = map(normalize, args.tests)
--- a/testing/mochitest/mach_test_package_commands.py
+++ b/testing/mochitest/mach_test_package_commands.py
@@ -14,27 +14,30 @@ from mach.decorators import (
)
parser = None
def run_mochitest(context, **kwargs):
args = Namespace(**kwargs)
args.certPath = context.certs_dir
- args.utilityPath = context.bin_dir
- args.extraProfileFiles.append(os.path.join(context.bin_dir, 'plugins'))
-
- if not args.app:
- args.app = context.find_firefox()
if args.test_paths:
test_root = os.path.join(context.package_root, 'mochitest', 'tests')
normalize = partial(context.normalize_test_path, test_root)
args.test_paths = map(normalize, args.test_paths)
+ return run_mochitest_desktop(context, args)
+
+
+def run_mochitest_desktop(context, args):
+ args.app = args.app or context.firefox_bin
+ args.utilityPath = context.bin_dir
+ args.extraProfileFiles.append(os.path.join(context.bin_dir, 'plugins'))
+
from runtests import run_test_harness
return run_test_harness(parser, args)
def setup_argument_parser():
from mochitest_options import MochitestArgumentParser
global parser
parser = MochitestArgumentParser(app='generic')
--- a/testing/tools/mach_test_package_bootstrap.py
+++ b/testing/tools/mach_test_package_bootstrap.py
@@ -89,21 +89,21 @@ def ancestors(path, depth=0):
def find_firefox(context):
"""Try to automagically find the firefox binary."""
import mozinstall
search_paths = []
# Check for a mozharness setup
- if context.mozharness_config:
- with open(context.mozharness_config, 'r') as f:
- config = json.load(f)
- workdir = os.path.join(config['base_work_dir'], config['work_dir'])
- search_paths.append(os.path.join(workdir, 'application'))
+ config = context.mozharness_config
+ if config and 'binary_path' in config:
+ return config['binary_path']
+ elif config:
+ search_paths.append(os.path.join(context.mozharness_workdir, 'application'))
# Check for test-stage setup
dist_bin = os.path.join(os.path.dirname(context.package_root), 'bin')
if os.path.isdir(dist_bin):
search_paths.append(dist_bin)
for path in search_paths:
try:
@@ -132,35 +132,43 @@ def bootstrap(test_package_root):
print('Python 2.7 or above (but not Python 3) is required to run mach.')
print('You are running Python', platform.python_version())
sys.exit(1)
sys.path[0:0] = [os.path.join(test_package_root, path) for path in SEARCH_PATHS]
import mach.main
def populate_context(context, key=None):
- if key is not None:
+ if key is None:
+ context.package_root = test_package_root
+ context.bin_dir = os.path.join(test_package_root, 'bin')
+ context.certs_dir = os.path.join(test_package_root, 'certs')
+ context.module_dir = os.path.join(test_package_root, 'modules')
+ context.ancestors = ancestors
+ context.normalize_test_path = normalize_test_path
return
- context.package_root = test_package_root
- context.bin_dir = os.path.join(test_package_root, 'bin')
- context.certs_dir = os.path.join(test_package_root, 'certs')
- context.modules_dir = os.path.join(test_package_root, 'modules')
+ # The values for the following 'key's will be set lazily, and cached
+ # after first being invoked.
+ if key == 'firefox_bin':
+ return find_firefox(context)
+
- context.ancestors = ancestors
- context.find_firefox = types.MethodType(find_firefox, context)
- context.normalize_test_path = normalize_test_path
+ if key == 'mozharness_config':
+ for dir_path in ancestors(context.package_root):
+ mozharness_config = os.path.join(dir_path, 'logs', 'localconfig.json')
+ if os.path.isfile(mozharness_config):
+ with open(mozharness_config, 'rb') as f:
+ return json.load(f)
+ return {}
- # Search for a mozharness localconfig.json
- context.mozharness_config = None
- for dir_path in ancestors(test_package_root):
- mozharness_config = os.path.join(dir_path, 'logs', 'localconfig.json')
- if os.path.isfile(mozharness_config):
- context.mozharness_config = mozharness_config
- break
+ if key == 'mozharness_workdir':
+ config = context.mozharness_config
+ if config:
+ return os.path.join(config['base_work_dir'], config['work_dir'])
mach = mach.main.Mach(os.getcwd())
mach.populate_context_handler = populate_context
for category, meta in CATEGORIES.items():
mach.define_category(category, meta['short'], meta['long'],
meta['priority'])
--- a/testing/xpcshell/mach_test_package_commands.py
+++ b/testing/xpcshell/mach_test_package_commands.py
@@ -16,22 +16,20 @@ from xpcshellcommandline import parser_d
from mach.decorators import (
CommandProvider,
Command,
)
def run_xpcshell(context, **kwargs):
args = Namespace(**kwargs)
+ args.appPath = args.appPath or os.path.dirname(context.firefox_bin)
args.utility_path = context.bin_dir
args.testingModulesDir = context.modules_dir
- if not args.appPath:
- args.appPath = os.path.dirname(context.find_firefox())
-
if not args.xpcshell:
args.xpcshell = os.path.join(args.appPath, 'xpcshell')
if not args.pluginsPath:
for path in context.ancestors(args.appPath, depth=2):
test = os.path.join(path, 'plugins')
if os.path.isdir(test):
args.pluginsPath = test