Bug 1251633 - Install all mochitest extensions as temporary addons
MozReview-Commit-ID: HkX4Drn4tFT
--- a/testing/marionette/driver/marionette_driver/addons.py
+++ b/testing/marionette/driver/marionette_driver/addons.py
@@ -1,12 +1,15 @@
# 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 os
+from zipfile import ZipFile
+
from .errors import MarionetteException
__all__ = ['Addons', 'AddonInstallException']
# From https://developer.mozilla.org/en-US/Add-ons/Add-on_Manager/AddonManager#AddonInstall_errors
ADDON_INSTALL_ERRORS = {
-1: "ERROR_NETWORK_FAILURE: A network error occured.",
@@ -47,16 +50,17 @@ class Addons(object):
:param path: A file path to the extension to be installed.
:param temp: Install a temporary addon. Temporary addons will
automatically be uninstalled on shutdown and do not need
to be signed, though they must be restartless.
:returns: The addon ID string of the newly installed addon.
:raises: :exc:`AddonInstallException`
"""
+ print(temp)
with self._mn.using_context('chrome'):
addon_id, status = self._mn.execute_async_script("""
let FileUtils = Components.utils.import("resource://gre/modules/FileUtils.jsm").FileUtils;
Components.utils.import("resource://gre/modules/AddonManager.jsm");
let listener = {
onInstallEnded: function(install, addon) {
marionetteScriptFinished([addon.id, 0]);
},
@@ -110,8 +114,24 @@ class Addons(object):
with self._mn.using_context('chrome'):
return self._mn.execute_async_script("""
Components.utils.import("resource://gre/modules/AddonManager.jsm");
AddonManager.getAddonByID(arguments[0], function(addon) {
addon.uninstall();
marionetteScriptFinished(0);
});
""", script_args=[addon_id])
+
+ @classmethod
+ def is_signed(cls, path):
+ """Determine whether an addon path is signed or not.
+
+ :param path: The path to the addon. Can be a directory or an xpi.
+ :return: True if the addon is signed, otherwise False.
+ """
+ if os.path.isdir(path):
+ return False
+
+ assert path.endswith('.xpi')
+ with ZipFile(path, 'r') as zfile:
+ print('foobar')
+ print(zfile.namelist())
+
--- a/testing/mochitest/mochitest_options.py
+++ b/testing/mochitest/mochitest_options.py
@@ -573,17 +573,17 @@ class MochitestArguments(ArgumentContain
"suppress": True,
}],
]
defaults = {
# Bug 1065098 - The geckomediaplugin process fails to produce a leak
# log for some reason.
'ignoreMissingLeaks': ["geckomediaplugin"],
- 'extensionsToExclude': ['specialpowers'],
+ 'extensionsToExclude': [],
# Set server information on the args object
'webServer': '127.0.0.1',
'httpPort': DEFAULT_PORTS['http'],
'sslPort': DEFAULT_PORTS['https'],
'webSocketPort': '9988',
# The default websocket port is incorrect in mozprofile; it is
# set to the SSL proxy setting. See:
# see https://bugzilla.mozilla.org/show_bug.cgi?id=916517
@@ -925,18 +925,16 @@ class B2GArguments(ArgumentContainer):
}],
]
defaults = {
'logFile': 'mochitest.log',
# Specialpowers is integrated with marionette for b2g,
# see marionette's jar.mn.
'extensionsToExclude': ['specialpowers'],
- # mochijar doesn't get installed via marionette on android
- 'extensionsToInstall': [os.path.join(here, 'mochijar')],
# See dependencies of bug 1038943.
'defaultLeakThreshold': 5536,
}
def validate(self, parser, options, context):
"""Validate b2g options."""
if options.remoteWebServer is None:
@@ -1079,20 +1077,16 @@ class AndroidArguments(ArgumentContainer
"help": "remote directory to use as test root \
(eg. /mnt/sdcard/tests or /data/local/tests)",
"suppress": True,
}],
]
defaults = {
'dm': None,
- # we don't want to exclude specialpowers on android just yet
- 'extensionsToExclude': [],
- # mochijar doesn't get installed via marionette on android
- 'extensionsToInstall': [os.path.join(here, 'mochijar')],
'logFile': 'mochitest.log',
'utilityPath': None,
}
def validate(self, parser, options, context):
"""Validate android options."""
if build_obj:
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -974,16 +974,17 @@ toolbar#nav-bar {
if os.path.isdir(extensionDir):
for dirEntry in os.listdir(extensionDir):
if dirEntry not in options.extensionsToExclude:
path = os.path.join(extensionDir, dirEntry)
if os.path.isdir(path) or (
os.path.isfile(path) and path.endswith(".xpi")):
extensions.append(path)
extensions.extend(options.extensionsToInstall)
+ extensions.append(self.mochijar)
return extensions
def logPreamble(self, tests):
"""Logs a suite_start message and test_start/test_end at the beginning of a run.
"""
self.log.suite_start([t['path'] for t in tests])
for test in tests:
if 'disabled' in test:
@@ -1611,18 +1612,20 @@ class MochitestDesktop(MochitestBase):
"browser.tabs.remote.autostart=%s" %
('true' if options.e10s else 'false'))
if options.strictContentSandbox:
options.extraPrefs.append("security.sandbox.content.level=1")
options.extraPrefs.append(
"dom.ipc.tabs.nested.enabled=%s" %
('true' if options.nested_oop else 'false'))
- # get extensions to install
- extensions = self.getExtensionsToInstall(options)
+ extensions = None
+ if mozinfo.info.get('os').lower() == 'android':
+ # Android can't install addons via marionette yet
+ extensions = self.getExtensionsToInstall(options)
# web apps
appsPath = os.path.join(
SCRIPT_DIR,
'profile_data',
'webapps_mochitest.json')
if os.path.exists(appsPath):
with open(appsPath) as apps_file:
@@ -1854,17 +1857,18 @@ class MochitestDesktop(MochitestBase):
valgrindArgs=None,
valgrindSuppFiles=None,
symbolsPath=None,
timeout=-1,
detectShutdownLeaks=False,
screenshotOnFail=False,
bisectChunk=None,
quiet=False,
- marionette_args=None):
+ marionette_args=None,
+ extensions=None):
"""
Run the app, log the duration it took to execute, return the status code.
Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.
"""
# configure the message logger buffering
self.message_logger.buffering = quiet
@@ -1999,18 +2003,21 @@ class MochitestDesktop(MochitestBase):
port_timeout = marionette_args.pop('port_timeout')
self.marionette = Marionette(**marionette_args)
self.marionette.start_session(timeout=port_timeout)
# install specialpowers and mochikit as temporary addons
addons = Addons(self.marionette)
if mozinfo.info.get('toolkit') != 'gonk':
- addons.install(os.path.join(here, 'extensions', 'specialpowers'), temp=True)
- addons.install(self.mochijar, temp=True)
+ for ext in extensions:
+ print(ext)
+ # if an extension is signed, it doesn't need to be installed temporarily
+ signed = addons.is_signed(ext)
+ addons.install(ext, temp=not signed)
self.execute_start_script()
# an open marionette session interacts badly with mochitest,
# delete it until we figure out why.
self.marionette.delete_session()
del self.marionette
@@ -2375,16 +2382,17 @@ class MochitestDesktop(MochitestBase):
valgrindSuppFiles=valgrindSuppFiles,
symbolsPath=options.symbolsPath,
timeout=timeout,
detectShutdownLeaks=detectShutdownLeaks,
screenshotOnFail=options.screenshotOnFail,
bisectChunk=options.bisectChunk,
quiet=options.quiet,
marionette_args=marionette_args,
+ extensions=self.getExtensionsToInstall(options),
)
except KeyboardInterrupt:
self.log.info("runtests.py | Received keyboard interrupt.\n")
status = -1
except:
traceback.print_exc()
self.log.error(
"Automation Error: Received unexpected exception while running application\n")