Bug 1769110 - Add support to mochitest harness for conditioned profiles to be used while testing. r=gbrown,asuth

Differential Revision: https://phabricator.services.mozilla.com/D146317
This commit is contained in:
Joel Maher 2022-06-06 14:32:04 +00:00
Родитель 0e50e38f5d
Коммит e09607114a
5 изменённых файлов: 120 добавлений и 6 удалений

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

@ -406,6 +406,15 @@ class MochitestArguments(ArgumentContainer):
"suppress": True,
},
],
[
["--conditioned-profile"],
{
"dest": "conditionedProfile",
"action": "store_true",
"default": False,
"help": "Download and run with a full conditioned profile.",
},
],
[
["--testing-modules-dir"],
{

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

@ -128,7 +128,7 @@ class MessageLogger(object):
BUFFERING_THRESHOLD = 100
# This is a delimiter used by the JS side to avoid logs interleaving
DELIMITER = u"\ue175\uee31\u2c32\uacbf"
DELIMITER = "\ue175\uee31\u2c32\uacbf"
BUFFERED_ACTIONS = set(["test_status", "log"])
VALID_ACTIONS = set(
[
@ -959,6 +959,7 @@ class MochitestDesktop(object):
self.extraPrefs = {}
self.extraEnv = {}
self.extraTestsDirs = []
self.conditioned_profile_dir = None
if logger_options.get("log"):
self.log = logger_options["log"]
@ -1578,6 +1579,12 @@ toolbar#nav-bar {
subsuite(options.subsuite),
]
# Allow for only running tests/manifests which match this tag
if options.conditionedProfile:
if not options.test_tags:
options.test_tags = []
options.test_tags.append("condprof")
if options.test_tags:
filters.append(tags(options.test_tags))
@ -2129,6 +2136,64 @@ toolbar#nav-bar {
path = os.path.join(profile_data_dir, profile)
self.profile.merge(path, interpolation=interpolation)
@property
def conditioned_profile_copy(self):
"""Returns a copy of the original conditioned profile that was created."""
condprof_copy = os.path.join(tempfile.mkdtemp(), "profile")
shutil.copytree(
self.conditioned_profile_dir,
condprof_copy,
ignore=shutil.ignore_patterns("lock"),
)
self.log.info("Created a conditioned-profile copy: %s" % condprof_copy)
return condprof_copy
def downloadConditionedProfile(self, profile_scenario):
from condprof.client import get_profile
from condprof.util import get_current_platform
if self.conditioned_profile_dir:
# We already have a directory, so provide a copy that
# will get deleted after it's done with
return self.conditioned_profile_copy
temp_download_dir = tempfile.mkdtemp()
# Call condprof's client API to yield our platform-specific
# conditioned-profile binary
platform = get_current_platform()
if not profile_scenario:
profile_scenario = "settled"
cond_prof_target_dir = get_profile(
temp_download_dir,
platform,
profile_scenario,
repo="mozilla-central",
)
# Now get the full directory path to our fetched conditioned profile
self.conditioned_profile_dir = os.path.join(
temp_download_dir, cond_prof_target_dir
)
if not os.path.exists(cond_prof_target_dir):
self.log.critical(
"Can't find target_dir {}, from get_profile()"
"temp_download_dir {}, platform {}, scenario {}".format(
cond_prof_target_dir, temp_download_dir, platform, profile_scenario
)
)
raise OSError
self.log.info(
"Original self.conditioned_profile_dir is now set: {}".format(
self.conditioned_profile_dir
)
)
return self.conditioned_profile_copy
def buildProfile(self, options):
"""create the profile and add optional chrome bits and files if requested"""
# get extensions to install
@ -2146,6 +2211,20 @@ toolbar#nav-bar {
os.path.join(p, "") for p in sandbox_whitelist_paths
]
if options.conditionedProfile:
if options.profilePath and os.path.exists(options.profilePath):
shutil.rmtree(options.profilePath, ignore_errors=True)
options.profilePath = self.downloadConditionedProfile("full")
# This is causing `certutil -N -d -f`` to not use -f (pwd file)
try:
os.remove(os.path.join(options.profilePath, "key4.db"))
except Exception as e:
self.log.info(
"Caught exception while removing key4.db"
"during setup of conditioned profile: %s" % e
)
# Create the profile
self.profile = Profile(
profile=options.profilePath,
@ -2736,6 +2815,12 @@ toolbar#nav-bar {
This method is used to clear the contents before each run of for loop.
This method is used for --run-by-dir and --bisect-chunk.
"""
if options.conditionedProfile:
if options.profilePath and os.path.exists(options.profilePath):
shutil.rmtree(options.profilePath, ignore_errors=True)
if options.manifestFile and os.path.exists(options.manifestFile):
os.remove(options.manifestFile)
self.expectedError.clear()
self.result.clear()
options.manifestFile = None
@ -3042,6 +3127,7 @@ toolbar#nav-bar {
"verify_fission": options.verify_fission,
"webgl_ipc": self.extraPrefs.get("webgl.out-of-process", False),
"xorigin": options.xOriginTests,
"condprof": options.conditionedProfile,
}
)
@ -3363,6 +3449,9 @@ toolbar#nav-bar {
if options.timeoutAsPass:
testURL += "&timeoutAsPass=true"
if options.conditionedProfile:
testURL += "&conditionedProfile=true"
self.log.info("runtests.py | Running with scheme: {}".format(scheme))
self.log.info(
"runtests.py | Running with e10s: {}".format(options.e10s)

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

@ -1433,11 +1433,22 @@ SimpleTest.finish = function() {
);
}
} else if (workers.length > 0) {
SimpleTest.ok(
false,
"This test left a service worker registered without cleaning it up"
);
let FULL_PROFILE_WORKERS_TO_IGNORE = [];
if (parentRunner.conditionedProfile) {
// Full profile has service workers in the profile, without clearing the profile
// service workers will be leftover, in all my testing youtube is the only one.
FULL_PROFILE_WORKERS_TO_IGNORE = ["https://www.youtube.com/sw.js"];
} else {
SimpleTest.ok(
false,
"This test left a service worker registered without cleaning it up"
);
}
for (let worker of workers) {
if (FULL_PROFILE_WORKERS_TO_IGNORE.includes(worker.scriptSpec)) {
continue;
}
SimpleTest.ok(
false,
`Left over worker: ${worker.scriptSpec} (scope: ${worker.scope})`

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

@ -120,7 +120,8 @@ TestRunner.slowestTestTime = 0;
TestRunner.slowestTestURL = "";
TestRunner.interactiveDebugger = false;
TestRunner.cleanupCrashes = false;
TestRunner.timeoutAspass = false;
TestRunner.timeoutAsPass = false;
TestRunner.conditionedProfile = false;
TestRunner._expectingProcessCrash = false;
TestRunner._structuredFormatter = new StructuredFormatter();

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

@ -189,6 +189,10 @@ if (params.timeoutAsPass) {
TestRunner.timeoutAsPass = true;
}
if (params.conditionedProfile) {
TestRunner.conditionedProfile = true;
}
// Log things to the console if appropriate.
TestRunner.logger.addListener("dumpListener", consoleLevel + "", function(msg) {
dump(msg.info.join(" ") + "\n");