Bug 1451159 - [mochitest] Load profile data from testing/profiles/common r=gbrown

This makes mochitest use mozprofile's new 'merge' feature instead of
explicitly loading the user.js preference file.

This means that any extensions that get dropped into
testing/profiles/common/extensions, will automatically run as part of the
mochitest run. This can be useful for testing how extensions impact tests
locally or on try.

In the near future, all our other test harnesses will also start using this
profile directory.

MozReview-Commit-ID: 34aSqdnkHqx

--HG--
extra : rebase_source : 52b9c02aa712ac5136b6535e5b07fb56eae2412c
This commit is contained in:
Andrew Halberstadt 2018-04-19 16:12:49 -04:00
Родитель 6a9ff8c01b
Коммит a8c00743a6
4 изменённых файлов: 173 добавлений и 106 удалений

Просмотреть файл

@ -3,7 +3,6 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import argparse
import json
import os
import posixpath
import re
@ -17,7 +16,7 @@ import mozinfo
import mozlog
import moznetwork
from mozdevice import ADBAndroid
from mozprofile import Profile, Preferences, DEFAULT_PORTS
from mozprofile import Profile, DEFAULT_PORTS
from mozprofile.permissions import ServerLocations
from runtests import MochitestDesktop, update_mozinfo
@ -99,29 +98,14 @@ class JUnitTestRunner(MochitestDesktop):
Create a local profile with test prefs and proxy definitions and
push it to the remote device.
"""
preferences = [os.path.join(here, 'profile_data', 'common', 'user.js')]
prefs = {}
for path in preferences:
prefs.update(Preferences.read_prefs(path))
interpolation = {
"server": "%s:%s" %
(self.options.webServer, self.options.httpPort)}
prefs = json.loads(json.dumps(prefs).format(**interpolation))
for pref in prefs:
prefs[pref] = Preferences.cast(prefs[pref])
proxy = {'remote': self.options.webServer,
'http': self.options.httpPort,
'https': self.options.sslPort,
'ws': self.options.sslPort
}
self.profile = Profile(locations=self.locations, preferences=prefs,
proxy=proxy)
self.profile = Profile(locations=self.locations, proxy=self.proxy(self.options))
self.options.profilePath = self.profile.profile
# Set preferences
self.merge_base_profiles(self.options)
self.profile.set_preferences(self.extraPrefs(self.options.extraPrefs))
if self.fillCertificateDB(self.options):
self.log.error("Certificate integration failed")

Просмотреть файл

@ -52,7 +52,6 @@ from manifestparser.filters import (
subsuite,
tags,
)
from six import string_types
try:
from marionette_driver.addons import Addons
@ -852,6 +851,7 @@ class MochitestDesktop(object):
mediaDevices = None
patternFiles = {}
base_profiles = ('common',)
# XXX use automation.py for test name to avoid breaking legacy
# TODO: replace this with 'runtests.py' or 'mochitest' or the like
@ -910,15 +910,20 @@ class MochitestDesktop(object):
kwargs['log'] = self.log
return test_environment(**kwargs)
def extraPrefs(self, extraPrefs):
"""interpolate extra preferences from option strings"""
def extraPrefs(self, prefs):
"""Interpolate extra preferences from option strings"""
try:
return dict(parseKeyValue(extraPrefs, context='--setpref='))
prefs = dict(parseKeyValue(prefs, context='--setpref='))
except KeyValueParseError as e:
print(str(e))
sys.exit(1)
for pref, value in prefs.items():
value = Preferences.cast(value)
prefs[pref] = value
return prefs
def getFullPath(self, path):
" Get an absolute path relative to self.oldcwd."
return os.path.normpath(
@ -1820,57 +1825,46 @@ toolbar#nav-bar {
os.unlink(pwfilePath)
return 0
def proxy(self, options):
# proxy
# use SSL port for legacy compatibility; see
# - https://bugzilla.mozilla.org/show_bug.cgi?id=688667#c66
# - https://bugzilla.mozilla.org/show_bug.cgi?id=899221
# - https://github.com/mozilla/mozbase/commit/43f9510e3d58bfed32790c82a57edac5f928474d
# 'ws': str(self.webSocketPort)
return {
'remote': options.webServer,
'http': options.httpPort,
'https': options.sslPort,
'ws': options.sslPort,
}
def merge_base_profiles(self, options):
"""Merge extra profile data from testing/profiles."""
profile_data_dir = os.path.join(SCRIPT_DIR, 'profile_data')
# If possible, read profile data from topsrcdir. This prevents us from
# requiring a re-build to pick up newly added extensions in the
# <profile>/extensions directory.
if build_obj:
path = os.path.join(build_obj.topsrcdir, 'testing', 'profiles')
if os.path.isdir(path):
profile_data_dir = path
# values to use when interpolating preferences
interpolation = {
"server": "%s:%s" % (options.webServer, options.httpPort),
}
for profile in self.base_profiles:
path = os.path.join(profile_data_dir, profile)
self.profile.merge(path, interpolation=interpolation)
def buildProfile(self, options):
""" create the profile and add optional chrome bits and files if requested """
if options.flavor == 'browser' and options.timeout:
options.extraPrefs.append(
"testing.browserTestHarness.timeout=%d" %
options.timeout)
# browser-chrome tests use a fairly short default timeout of 45 seconds;
# this is sometimes too short on asan and debug, where we expect reduced
# performance.
if (mozinfo.info["asan"] or mozinfo.info["debug"]) and \
options.flavor == 'browser' and options.timeout is None:
self.log.info("Increasing default timeout to 90 seconds")
options.extraPrefs.append("testing.browserTestHarness.timeout=90")
options.extraPrefs.append(
"browser.tabs.remote.autostart=%s" %
('true' if options.e10s else 'false'))
options.extraPrefs.append(
"dom.ipc.tabs.nested.enabled=%s" %
('true' if options.nested_oop else 'false'))
options.extraPrefs.append(
"idle.lastDailyNotification=%d" %
int(time.time()))
# Enable tracing output for detailed failures in case of
# failing connection attempts, and hangs (bug 1397201)
options.extraPrefs.append("marionette.log.level=%s" % "TRACE")
if getattr(self, 'testRootAbs', None):
options.extraPrefs.append(
"mochitest.testRoot=%s" %
self.testRootAbs)
# get extensions to install
extensions = self.getExtensionsToInstall(options)
# preferences
preferences = [os.path.join(SCRIPT_DIR, 'profile_data', 'common', 'user.js')]
prefs = {}
for path in preferences:
prefs.update(Preferences.read_prefs(path))
prefs.update(self.extraPrefs(options.extraPrefs))
# Bug 1262954: For windows XP + e10s disable acceleration
if platform.system() in ("Windows", "Microsoft") and \
'5.1' in platform.version() and options.e10s:
prefs['layers.acceleration.disabled'] = True
# Whitelist the _tests directory (../..) so that TESTING_JS_MODULES work
tests_dir = os.path.dirname(os.path.dirname(SCRIPT_DIR))
sandbox_whitelist_paths = [tests_dir] + options.sandboxReadWhitelist
@ -1880,42 +1874,12 @@ toolbar#nav-bar {
sandbox_whitelist_paths = map(lambda p: os.path.join(p, ""),
sandbox_whitelist_paths)
# interpolate preferences
interpolation = {
"server": "%s:%s" %
(options.webServer, options.httpPort)}
for pref in prefs:
if isinstance(prefs[pref], string_types):
prefs[pref] = prefs[pref].format(**interpolation)
prefs[pref] = Preferences.cast(prefs[pref])
# TODO: make this less hacky
# https://bugzilla.mozilla.org/show_bug.cgi?id=913152
# proxy
# use SSL port for legacy compatibility; see
# - https://bugzilla.mozilla.org/show_bug.cgi?id=688667#c66
# - https://bugzilla.mozilla.org/show_bug.cgi?id=899221
# - https://github.com/mozilla/mozbase/commit/43f9510e3d58bfed32790c82a57edac5f928474d
# 'ws': str(self.webSocketPort)
proxy = {'remote': options.webServer,
'http': options.httpPort,
'https': options.sslPort,
'ws': options.sslPort
}
# See if we should use fake media devices.
if options.useTestMediaDevices:
prefs['media.audio_loopback_dev'] = self.mediaDevices['audio']
prefs['media.video_loopback_dev'] = self.mediaDevices['video']
# create a profile
# Create the profile
self.profile = Profile(profile=options.profilePath,
addons=extensions,
locations=self.locations,
preferences=prefs,
proxy=proxy,
whitelistpaths=sandbox_whitelist_paths
proxy=self.proxy(options),
whitelistpaths=sandbox_whitelist_paths,
)
# Fix options.profilePath for legacy consumers.
@ -1932,6 +1896,47 @@ toolbar#nav-bar {
"TEST-UNEXPECTED-FAIL | runtests.py | Certificate integration failed")
return None
# Set preferences in the following order (latter overrides former):
# 1) Preferences from base profile (e.g from testing/profiles)
# 2) Prefs hardcoded in this function
# 3) Prefs from --setpref
# Prefs from base profiles
self.merge_base_profiles(options)
# Hardcoded prefs (TODO move these into a base profile)
prefs = {
"browser.tabs.remote.autostart": options.e10s,
"dom.ipc.tabs.nested.enabled": options.nested_oop,
"idle.lastDailyNotification": int(time.time()),
# Enable tracing output for detailed failures in case of
# failing connection attempts, and hangs (bug 1397201)
"marionette.log.level": "TRACE",
}
if options.flavor == 'browser' and options.timeout:
prefs["testing.browserTestHarness.timeout"] = options.timeout
# browser-chrome tests use a fairly short default timeout of 45 seconds;
# this is sometimes too short on asan and debug, where we expect reduced
# performance.
if (mozinfo.info["asan"] or mozinfo.info["debug"]) and \
options.flavor == 'browser' and options.timeout is None:
self.log.info("Increasing default timeout to 90 seconds")
prefs["testing.browserTestHarness.timeout"] = 90
if getattr(self, 'testRootAbs', None):
prefs['mochitest.testRoot'] = self.testRootAbs
# See if we should use fake media devices.
if options.useTestMediaDevices:
prefs['media.audio_loopback_dev'] = self.mediaDevices['audio']
prefs['media.video_loopback_dev'] = self.mediaDevices['video']
self.profile.set_preferences(prefs)
# Extra prefs from --setpref
self.profile.set_preferences(self.extraPrefs(options.extraPrefs))
return manifest
def getGMPPluginPath(self, options):

Просмотреть файл

@ -1,6 +1,7 @@
[DEFAULT]
subsuite = mochitest
sequential = true
[test_basic_mochitest_plain.py]
sequential = true
[test_get_active_tests.py]
[test_build_profile.py]

Просмотреть файл

@ -0,0 +1,77 @@
# 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/.
from __future__ import print_function, unicode_literals
import os
from argparse import Namespace
from mozprofile.prefs import Preferences
from mozprofile import Profile
from six import string_types
import mozunit
import pytest
from conftest import setup_args
@pytest.fixture
def build_profile(setup_test_harness, parser):
setup_test_harness(*setup_args)
runtests = pytest.importorskip('runtests')
md = runtests.MochitestDesktop('plain', {'log_tbpl': '-'})
options = parser.parse_args([])
parser.validate(options)
options = vars(options)
def inner(**kwargs):
opts = options.copy()
opts.update(kwargs)
return md, md.buildProfile(Namespace(**opts))
return inner
@pytest.fixture
def profile_data_dir(build_obj):
return os.path.join(build_obj.topsrcdir, 'testing', 'profiles')
def test_common_prefs_are_all_set(build_profile, profile_data_dir):
# We set e10s=False here because MochitestDesktop.buildProfile overwrites
# the value defined in the base profile.
# TODO stop setting browser.tabs.remote.autostart in the base profile
md, result = build_profile(e10s=False)
# build the expected prefs
expected_prefs = {}
for profile in md.base_profiles:
for name in Profile.preference_file_names:
path = os.path.join(profile_data_dir, profile, name)
if os.path.isfile(path):
expected_prefs.update(Preferences.read_prefs(path))
# read the actual prefs
actual_prefs = {}
for name in Profile.preference_file_names:
path = os.path.join(md.profile.profile, name)
if os.path.isfile(path):
actual_prefs.update(Preferences.read_prefs(path))
# keep this in sync with the values in MochitestDesktop.merge_base_profiles
interpolation = {
'server': '127.0.0.1:8888',
}
for k, v in expected_prefs.items():
if isinstance(v, string_types):
v = v.format(**interpolation)
assert k in actual_prefs
assert k and actual_prefs[k] == v
if __name__ == '__main__':
mozunit.main()