зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1280571 - Add testing/mochitest to the flake8 linter, r=ahal
This also adds E402 (no imports at top of file) to the global ignore list. The other error codes added were previously ignored by default, but now that we have started a custom ignore list, need to be listed explicitly. MozReview-Commit-ID: RtMuVEX6i5 --HG-- extra : rebase_source : 939bc9354f5891c680513d7e9068d0438e169132
This commit is contained in:
Родитель
e53026e4bf
Коммит
58b6130e52
2
.flake8
2
.flake8
|
@ -1,3 +1,5 @@
|
|||
[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,7 +15,8 @@ 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
|
||||
|
@ -25,7 +26,8 @@ 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
|
||||
|
||||
|
@ -40,23 +42,27 @@ 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.
|
||||
|
@ -213,7 +219,8 @@ 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:
|
||||
|
@ -236,7 +243,8 @@ 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.
|
||||
|
@ -254,12 +262,14 @@ 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,17 +54,21 @@ 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] == "++"
|
||||
|
@ -229,12 +233,14 @@ 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,7 +9,6 @@ from collections import defaultdict
|
|||
from itertools import chain
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
|
@ -350,7 +349,8 @@ 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,7 +157,8 @@ 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
|
||||
|
||||
|
@ -179,7 +180,8 @@ 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 = []
|
||||
|
@ -413,7 +415,9 @@ 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(
|
||||
'\\',
|
||||
'\\\\'),
|
||||
|
@ -555,7 +559,6 @@ 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
|
||||
|
@ -815,7 +818,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?")
|
||||
|
@ -951,7 +954,8 @@ class MochitestBase(object):
|
|||
|
||||
# Write userChrome.css.
|
||||
chrome = """
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
|
||||
/* set default namespace to XUL */
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
toolbar,
|
||||
toolbarpalette {
|
||||
background-color: rgb(235, 235, 235) !important;
|
||||
|
@ -1135,7 +1139,8 @@ 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,
|
||||
|
@ -1278,8 +1283,7 @@ 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:
|
||||
|
@ -1690,14 +1694,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
|
||||
}
|
||||
|
||||
|
@ -1856,9 +1860,8 @@ 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,
|
||||
|
@ -1887,7 +1890,8 @@ 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
|
||||
|
@ -1913,7 +1917,8 @@ 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()
|
||||
|
@ -2162,8 +2167,9 @@ 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)
|
||||
|
@ -2224,8 +2230,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
|
||||
|
@ -2332,7 +2338,8 @@ 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)
|
||||
|
@ -2448,12 +2455,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)
|
||||
|
@ -2510,10 +2517,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,7 +219,8 @@ 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")) {
|
||||
|
@ -312,7 +313,8 @@ 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,7 +194,8 @@ 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,11 +135,12 @@ LINTER = {
|
|||
'testing/firefox-ui',
|
||||
'testing/marionette/client',
|
||||
'testing/marionette/harness',
|
||||
'testing/mochitest',
|
||||
'testing/puppeteer',
|
||||
'testing/talos/',
|
||||
'tools/lint',
|
||||
],
|
||||
'exclude': [],
|
||||
'exclude': ['testing/mochitest/pywebsocket'],
|
||||
'extensions': EXTENSIONS,
|
||||
'type': 'external',
|
||||
'payload': lint,
|
||||
|
|
Загрузка…
Ссылка в новой задаче