зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset e1d144423657 (bug 1280571) for making leaks hard to diagnose a=backout CLOSED TREE
This commit is contained in:
Родитель
741d9cb870
Коммит
765926408d
2
.flake8
2
.flake8
|
@ -1,5 +1,3 @@
|
|||
[flake8]
|
||||
# See http://pep8.readthedocs.io/en/latest/intro.html#configuration
|
||||
ignore = E121, E123, E126, E133, E226, E241, E242, E704, W503, E402
|
||||
max-line-length = 99
|
||||
filename = *.py, +.lint
|
||||
|
|
|
@ -15,8 +15,7 @@ class Bisect(object):
|
|||
self.max_failures = 3
|
||||
|
||||
def setup(self, tests):
|
||||
"""This method is used to initialize various variables that are required
|
||||
for test bisection"""
|
||||
"This method is used to initialize various variables that are required for test bisection"
|
||||
status = 0
|
||||
self.contents.clear()
|
||||
# We need totalTests key in contents for sanity check
|
||||
|
@ -26,8 +25,7 @@ class Bisect(object):
|
|||
return status
|
||||
|
||||
def reset(self, expectedError, result):
|
||||
"""This method is used to initialize self.expectedError and self.result
|
||||
for each loop in runtests."""
|
||||
"This method is used to initialize self.expectedError and self.result for each loop in runtests."
|
||||
self.expectedError = expectedError
|
||||
self.result = result
|
||||
|
||||
|
@ -42,27 +40,23 @@ class Bisect(object):
|
|||
return bisectlist
|
||||
|
||||
def pre_test(self, options, tests, status):
|
||||
"""This method is used to call other methods for setting up variables and
|
||||
getting the list of tests for bisection."""
|
||||
"This method is used to call other methods for setting up variables and getting the list of tests for bisection."
|
||||
if options.bisectChunk == "default":
|
||||
return tests
|
||||
# The second condition in 'if' is required to verify that the failing
|
||||
# test is the last one.
|
||||
elif ('loop' not in self.contents or not self.contents['tests'][-1].endswith(
|
||||
options.bisectChunk)):
|
||||
elif 'loop' not in self.contents or not self.contents['tests'][-1].endswith(options.bisectChunk):
|
||||
tests = self.get_tests_for_bisection(options, tests)
|
||||
status = self.setup(tests)
|
||||
|
||||
return self.next_chunk_binary(options, status)
|
||||
|
||||
def post_test(self, options, expectedError, result):
|
||||
"""This method is used to call other methods to summarize results and check whether a
|
||||
sanity check is done or not."""
|
||||
"This method is used to call other methods to summarize results and check whether a sanity check is done or not."
|
||||
self.reset(expectedError, result)
|
||||
status = self.summarize_chunk(options)
|
||||
# Check whether sanity check has to be done. Also it is necessary to check whether
|
||||
# options.bisectChunk is present in self.expectedError as we do not want to run
|
||||
# if it is "default".
|
||||
# Check whether sanity check has to be done. Also it is necessary to check whether options.bisectChunk is present
|
||||
# in self.expectedError as we do not want to run if it is "default".
|
||||
if status == -1 and options.bisectChunk in self.expectedError:
|
||||
# In case we have a debug build, we don't want to run a sanity
|
||||
# check, will take too much time.
|
||||
|
@ -219,8 +213,7 @@ class Bisect(object):
|
|||
# is the failing test itself therefore the bleedthrough
|
||||
# test is the first test
|
||||
self.summary.append(
|
||||
"TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the "
|
||||
"root cause for many of the above failures" %
|
||||
"TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the root cause for many of the above failures" %
|
||||
self.contents['testsToRun'][0])
|
||||
status = -1
|
||||
else:
|
||||
|
@ -243,8 +236,7 @@ class Bisect(object):
|
|||
return 0
|
||||
else:
|
||||
if self.failcount > 0:
|
||||
# -1 is being returned as the test is intermittent, so no need to bisect
|
||||
# further.
|
||||
# -1 is being returned as the test is intermittent, so no need to bisect further.
|
||||
return -1
|
||||
# If the test does not fail even once, then proceed to next chunk for bisection.
|
||||
# loop is set to 2 to proceed on bisection.
|
||||
|
@ -262,14 +254,12 @@ class Bisect(object):
|
|||
# limit set, it is a perma-fail.
|
||||
if self.failcount < self.max_failures:
|
||||
if self.repeat == 0:
|
||||
# -1 is being returned as the test is intermittent, so no need to bisect
|
||||
# further.
|
||||
# -1 is being returned as the test is intermittent, so no need to bisect further.
|
||||
return -1
|
||||
return 0
|
||||
else:
|
||||
self.summary.append(
|
||||
"TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the "
|
||||
"root cause for many of the above failures" %
|
||||
"TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the root cause for many of the above failures" %
|
||||
self.contents['testsToRun'][0])
|
||||
return -1
|
||||
|
||||
|
|
|
@ -54,21 +54,17 @@ class ShutdownLeaks(object):
|
|||
for test in self._parseLeakingTests():
|
||||
for url, count in self._zipLeakedWindows(test["leakedWindows"]):
|
||||
self.logger.warning(
|
||||
"TEST-UNEXPECTED-FAIL | %s | leaked %d window(s) until shutdown "
|
||||
"[url = %s]") % (test["fileName"], count, url)
|
||||
"TEST-UNEXPECTED-FAIL | %s | leaked %d window(s) until shutdown [url = %s]" % (test["fileName"], count, url))
|
||||
|
||||
if test["leakedWindowsString"]:
|
||||
self.logger.info("TEST-INFO | %s | windows(s) leaked: %s" %
|
||||
(test["fileName"], test["leakedWindowsString"]))
|
||||
|
||||
if test["leakedDocShells"]:
|
||||
self.logger.warning("TEST-UNEXPECTED-FAIL | %s | leaked %d docShell(s) until "
|
||||
"shutdown" %
|
||||
(test["fileName"], len(test["leakedDocShells"])))
|
||||
self.logger.info("TEST-INFO | %s | docShell(s) leaked: %s" %
|
||||
(test["fileName"], ', '.join(["[pid = %s] [id = %s]" %
|
||||
x for x in test["leakedDocShells"]]
|
||||
)))
|
||||
self.logger.warning("TEST-UNEXPECTED-FAIL | %s | leaked %d docShell(s) until shutdown" % (
|
||||
test["fileName"], len(test["leakedDocShells"])))
|
||||
self.logger.info("TEST-INFO | %s | docShell(s) leaked: %s" % (test["fileName"],
|
||||
', '.join(["[pid = %s] [id = %s]" % x for x in test["leakedDocShells"]])))
|
||||
|
||||
def _logWindow(self, line):
|
||||
created = line[:2] == "++"
|
||||
|
@ -233,14 +229,12 @@ class LSANLeaks(object):
|
|||
|
||||
def process(self):
|
||||
if self.fatalError:
|
||||
self.logger.warning("TEST-UNEXPECTED-FAIL | LeakSanitizer | LeakSanitizer "
|
||||
"has encountered a fatal error.")
|
||||
self.logger.warning(
|
||||
"TEST-UNEXPECTED-FAIL | LeakSanitizer | LeakSanitizer has encountered a fatal error.")
|
||||
|
||||
if self.foundFrames:
|
||||
self.logger.info("TEST-INFO | LeakSanitizer | To show the "
|
||||
"addresses of leaked objects add report_objects=1 to LSAN_OPTIONS")
|
||||
self.logger.info("TEST-INFO | LeakSanitizer | This can be done "
|
||||
"in testing/mozbase/mozrunner/mozrunner/utils.py")
|
||||
self.logger.info("TEST-INFO | LeakSanitizer | To show the addresses of leaked objects add report_objects=1 to LSAN_OPTIONS")
|
||||
self.logger.info("TEST-INFO | LeakSanitizer | This can be done in testing/mozbase/mozrunner/mozrunner/utils.py")
|
||||
|
||||
for f in self.foundFrames:
|
||||
self.logger.warning(
|
||||
|
|
|
@ -9,6 +9,7 @@ from collections import defaultdict
|
|||
from itertools import chain
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
|
@ -349,8 +350,7 @@ def verify_host_bin():
|
|||
# validate MOZ_HOST_BIN environment variables for Android tests
|
||||
MOZ_HOST_BIN = os.environ.get('MOZ_HOST_BIN')
|
||||
if not MOZ_HOST_BIN:
|
||||
print('environment variable MOZ_HOST_BIN must be set to a directory containing host '
|
||||
'xpcshell')
|
||||
print('environment variable MOZ_HOST_BIN must be set to a directory containing host xpcshell')
|
||||
return 1
|
||||
elif not os.path.isdir(MOZ_HOST_BIN):
|
||||
print('$MOZ_HOST_BIN does not specify a directory')
|
||||
|
|
|
@ -376,9 +376,9 @@ class RobocopTestRunner(MochitestDesktop):
|
|||
for key, value in browserEnv.items():
|
||||
try:
|
||||
value.index(',')
|
||||
self.log.error("setupRobotiumConfig: browserEnv - Found a ',' "
|
||||
"in our value, unable to process value. key=%s,value=%s" %
|
||||
(key, value))
|
||||
self.log.error(
|
||||
"setupRobotiumConfig: browserEnv - Found a ',' in our value, unable to process value. key=%s,value=%s" %
|
||||
(key, value))
|
||||
self.log.error("browserEnv=%s" % browserEnv)
|
||||
except ValueError:
|
||||
envstr += "%s%s=%s" % (delim, key, value)
|
||||
|
@ -445,9 +445,9 @@ class RobocopTestRunner(MochitestDesktop):
|
|||
# This does not launch a test at all. It launches an activity
|
||||
# that starts Fennec and then waits indefinitely, since cat
|
||||
# never returns.
|
||||
browserArgs = ["start", "-n",
|
||||
"org.mozilla.roboexample.test/org.mozilla."
|
||||
"gecko.LaunchFennecWithConfigurationActivity", "&&", "cat"]
|
||||
browserArgs = ["start",
|
||||
"-n", "org.mozilla.roboexample.test/org.mozilla.gecko.LaunchFennecWithConfigurationActivity",
|
||||
"&&", "cat"]
|
||||
self.dm.default_timeout = sys.maxint # Forever.
|
||||
self.log.info("")
|
||||
self.log.info("Serving mochi.test Robocop root at http://%s:%s/tests/robocop/" %
|
||||
|
|
|
@ -157,8 +157,7 @@ class MessageLogger(object):
|
|||
self.errors = []
|
||||
|
||||
def valid_message(self, obj):
|
||||
"""True if the given object is a valid structured message
|
||||
(only does a superficial validation)"""
|
||||
"""True if the given object is a valid structured message (only does a superficial validation)"""
|
||||
return isinstance(obj, dict) and 'action' in obj and obj[
|
||||
'action'] in MessageLogger.VALID_ACTIONS
|
||||
|
||||
|
@ -180,8 +179,7 @@ class MessageLogger(object):
|
|||
message['message'] = unicode(message['message'])
|
||||
|
||||
def parse_line(self, line):
|
||||
"""Takes a given line of input (structured or not) and
|
||||
returns a list of structured messages"""
|
||||
"""Takes a given line of input (structured or not) and returns a list of structured messages"""
|
||||
line = line.rstrip().decode("UTF-8", "replace")
|
||||
|
||||
messages = []
|
||||
|
@ -415,9 +413,7 @@ class MochitestServer(object):
|
|||
self._httpdPath,
|
||||
"httpd.js"),
|
||||
"-e",
|
||||
"const _PROFILE_PATH = '%(profile)s'; const _SERVER_PORT = '%(port)s'; "
|
||||
"const _SERVER_ADDR = '%(server)s'; const _TEST_PREFIX = %(testPrefix)s; "
|
||||
"const _DISPLAY_RESULTS = %(displayResults)s;" % {
|
||||
"""const _PROFILE_PATH = '%(profile)s'; const _SERVER_PORT = '%(port)s'; const _SERVER_ADDR = '%(server)s'; const _TEST_PREFIX = %(testPrefix)s; const _DISPLAY_RESULTS = %(displayResults)s;""" % {
|
||||
"profile": self._profileDir.replace(
|
||||
'\\',
|
||||
'\\\\'),
|
||||
|
@ -559,6 +555,7 @@ class MochitestBase(object):
|
|||
|
||||
self.message_logger = MessageLogger(logger=self.log)
|
||||
|
||||
|
||||
def update_mozinfo(self):
|
||||
"""walk up directories to find mozinfo.json update the info"""
|
||||
# TODO: This should go in a more generic place, e.g. mozinfo
|
||||
|
@ -818,7 +815,7 @@ class MochitestBase(object):
|
|||
% self.websocketProcessBridge.pid)
|
||||
|
||||
# ensure the server is up, wait for at most ten seconds
|
||||
for i in range(1, 100):
|
||||
for i in range(1,100):
|
||||
if self.websocketProcessBridge.proc.poll() is not None:
|
||||
self.log.error("runtests.py | websocket/process bridge failed "
|
||||
"to launch. Are all the dependencies installed?")
|
||||
|
@ -954,8 +951,7 @@ class MochitestBase(object):
|
|||
|
||||
# Write userChrome.css.
|
||||
chrome = """
|
||||
/* set default namespace to XUL */
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
|
||||
toolbar,
|
||||
toolbarpalette {
|
||||
background-color: rgb(235, 235, 235) !important;
|
||||
|
@ -1139,8 +1135,7 @@ toolbar#nav-bar {
|
|||
manifestFileAbs = os.path.abspath(options.manifestFile)
|
||||
assert manifestFileAbs.startswith(SCRIPT_DIR)
|
||||
manifest = TestManifest([options.manifestFile], strict=False)
|
||||
elif (options.manifestFile and
|
||||
os.path.isfile(os.path.join(SCRIPT_DIR, options.manifestFile))):
|
||||
elif options.manifestFile and os.path.isfile(os.path.join(SCRIPT_DIR, options.manifestFile)):
|
||||
manifestFileAbs = os.path.abspath(
|
||||
os.path.join(
|
||||
SCRIPT_DIR,
|
||||
|
@ -1283,7 +1278,8 @@ toolbar#nav-bar {
|
|||
script = self.start_script
|
||||
|
||||
with self.marionette.using_context('chrome'):
|
||||
return self.marionette.execute_script(script, script_args=self.start_script_args)
|
||||
return self.marionette.execute_script(script,
|
||||
script_args=self.start_script_args)
|
||||
|
||||
|
||||
class SSLTunnel:
|
||||
|
@ -1694,14 +1690,14 @@ class MochitestDesktop(MochitestBase):
|
|||
# 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,
|
||||
# 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)
|
||||
'ws': options.sslPort
|
||||
}
|
||||
|
||||
|
@ -1860,8 +1856,9 @@ class MochitestDesktop(MochitestBase):
|
|||
processPID)
|
||||
if isPidAlive(processPID):
|
||||
foundZombie = True
|
||||
self.log.info("TEST-UNEXPECTED-FAIL | zombiecheck | child process "
|
||||
"%d still alive after shutdown" % processPID)
|
||||
self.log.info(
|
||||
"TEST-UNEXPECTED-FAIL | zombiecheck | child process %d still alive after shutdown" %
|
||||
processPID)
|
||||
self.killAndGetStack(
|
||||
processPID,
|
||||
utilityPath,
|
||||
|
@ -1890,8 +1887,7 @@ class MochitestDesktop(MochitestBase):
|
|||
marionette_args=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.
|
||||
Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.
|
||||
"""
|
||||
|
||||
# configure the message logger buffering
|
||||
|
@ -1917,8 +1913,7 @@ class MochitestDesktop(MochitestBase):
|
|||
|
||||
valgrindSuppFiles_final = []
|
||||
if valgrindSuppFiles is not None:
|
||||
valgrindSuppFiles_final = ["--suppressions=" +
|
||||
path for path in valgrindSuppFiles.split(",")]
|
||||
valgrindSuppFiles_final = ["--suppressions=" + path for path in valgrindSuppFiles.split(",")]
|
||||
|
||||
debug_args = ([valgrindPath]
|
||||
+ mozdebug.get_default_valgrind_args()
|
||||
|
@ -2167,9 +2162,8 @@ class MochitestDesktop(MochitestBase):
|
|||
# To inform that we are in the process of bisection, and to
|
||||
# look for bleedthrough
|
||||
if options.bisectChunk != "default" and not bisection_log:
|
||||
self.log.info("TEST-UNEXPECTED-FAIL | Bisection | Please ignore repeats "
|
||||
"and look for 'Bleedthrough' (if any) at the end of "
|
||||
"the failure list")
|
||||
self.log.info(
|
||||
"TEST-UNEXPECTED-FAIL | Bisection | Please ignore repeats and look for 'Bleedthrough' (if any) at the end of the failure list")
|
||||
bisection_log = 1
|
||||
|
||||
result = self.doTests(options, testsToRun)
|
||||
|
@ -2230,8 +2224,8 @@ class MochitestDesktop(MochitestBase):
|
|||
tests_in_dir = [t for t in testsToRun if os.path.dirname(t) == d]
|
||||
|
||||
# If we are using --run-by-dir, we should not use the profile path (if) provided
|
||||
# by the user, since we need to create a new directory for each run. We would face
|
||||
# problems if we use the directory provided by the user.
|
||||
# by the user, since we need to create a new directory for each run. We would face problems
|
||||
# if we use the directory provided by the user.
|
||||
result = self.runMochitests(options, tests_in_dir)
|
||||
|
||||
# Dump the logging buffer
|
||||
|
@ -2338,8 +2332,7 @@ class MochitestDesktop(MochitestBase):
|
|||
return 1
|
||||
|
||||
if self.mozLogs:
|
||||
self.browserEnv["MOZ_LOG_FILE"] = "{}/moz-pid=%PID-uid={}.log".format(
|
||||
self.browserEnv["MOZ_UPLOAD_DIR"], str(uuid.uuid4()))
|
||||
self.browserEnv["MOZ_LOG_FILE"] = "{}/moz-pid=%PID-uid={}.log".format(self.browserEnv["MOZ_UPLOAD_DIR"], str(uuid.uuid4()))
|
||||
|
||||
try:
|
||||
self.startServers(options, debuggerInfo)
|
||||
|
@ -2455,12 +2448,12 @@ class MochitestDesktop(MochitestBase):
|
|||
"""handle process output timeout"""
|
||||
# TODO: bug 913975 : _processOutput should call self.processOutputLine
|
||||
# one more time one timeout (I think)
|
||||
error_message = ("TEST-UNEXPECTED-TIMEOUT | %s | application timed out after "
|
||||
"%d seconds with no output") % (self.lastTestSeen, int(timeout))
|
||||
error_message = "TEST-UNEXPECTED-TIMEOUT | %s | application timed out after %d seconds with no output" % (
|
||||
self.lastTestSeen, int(timeout))
|
||||
self.message_logger.dump_buffered()
|
||||
self.message_logger.buffering = False
|
||||
self.log.info(error_message)
|
||||
self.log.error("Force-terminating active process(es).")
|
||||
self.log.error("Force-terminating active process(es).");
|
||||
|
||||
browser_pid = browser_pid or proc.pid
|
||||
child_pids = self.extract_child_pids(processLog, browser_pid)
|
||||
|
@ -2517,10 +2510,10 @@ class MochitestDesktop(MochitestBase):
|
|||
self.lsanLeaks = lsanLeaks
|
||||
self.bisectChunk = bisectChunk
|
||||
|
||||
# With metro browser runs this script launches the metro test harness which launches
|
||||
# the browser. The metro test harness hands back the real browser process id via log
|
||||
# output which we need to pick up on and parse out. This variable tracks the real
|
||||
# browser process id if we find it.
|
||||
# With metro browser runs this script launches the metro test harness which launches the browser.
|
||||
# The metro test harness hands back the real browser process id via log output which we need to
|
||||
# pick up on and parse out. This variable tracks the real browser
|
||||
# process id if we find it.
|
||||
self.browserProcessId = None
|
||||
|
||||
self.stackFixerFunction = self.stackFixer()
|
||||
|
|
|
@ -219,8 +219,7 @@ class MochitestB2G(MochitestBase):
|
|||
""")
|
||||
|
||||
self.marionette.execute_script("""
|
||||
let SECURITY_PREF = "security.turn_off_all_security_" +
|
||||
"so_that_viruses_can_take_over_this_computer";
|
||||
let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
|
||||
Services.prefs.setBoolPref(SECURITY_PREF, true);
|
||||
|
||||
if (!testUtils.hasOwnProperty("specialPowersObserver")) {
|
||||
|
@ -313,8 +312,7 @@ class MochitestB2G(MochitestBase):
|
|||
os.remove(options.pidFile)
|
||||
os.remove(options.pidFile + ".xpcshell.pid")
|
||||
except:
|
||||
print("Warning: cleaning up pidfile '%s' was unsuccessful "
|
||||
"from the test harness") % options.pidFile
|
||||
print "Warning: cleaning up pidfile '%s' was unsuccessful from the test harness" % options.pidFile
|
||||
|
||||
# stop and clean up the runner
|
||||
if getattr(self, 'runner', False):
|
||||
|
|
|
@ -194,8 +194,7 @@ class MochiRemote(MochitestDesktop):
|
|||
# Runtime (webapp).
|
||||
if options.flavor == 'chrome':
|
||||
# append overlay to chrome.manifest
|
||||
chrome = ("overlay chrome://browser/content/browser.xul "
|
||||
"chrome://mochikit/content/browser-test-overlay.xul")
|
||||
chrome = "overlay chrome://browser/content/browser.xul chrome://mochikit/content/browser-test-overlay.xul"
|
||||
path = os.path.join(options.profilePath, 'extensions', 'staged',
|
||||
'mochikit@mozilla.org', 'chrome.manifest')
|
||||
with open(path, "a") as f:
|
||||
|
|
|
@ -135,12 +135,11 @@ LINTER = {
|
|||
'testing/firefox-ui',
|
||||
'testing/marionette/client',
|
||||
'testing/marionette/harness',
|
||||
'testing/mochitest',
|
||||
'testing/puppeteer',
|
||||
'testing/talos/',
|
||||
'tools/lint',
|
||||
],
|
||||
'exclude': ['testing/mochitest/pywebsocket'],
|
||||
'exclude': [],
|
||||
'extensions': EXTENSIONS,
|
||||
'type': 'external',
|
||||
'payload': lint,
|
||||
|
|
Загрузка…
Ссылка в новой задаче