Bug 1067664, part 1 - Allow different leak thresholds for different types of processes. r=jmaher

This commit is contained in:
Andrew McCreight 2014-09-30 09:54:25 -07:00
parent e381d1456d
commit 3a5312793b
6 changed files with 45 additions and 17 deletions

View File

@ -311,7 +311,7 @@ def processSingleLeakFile(leakLogFileName, processType, leakThreshold):
log.info("%s | leakcheck | %s %d bytes leaked (%s)"
% (prefix, processString, totalBytesLeaked, leakedObjectSummary))
def processLeakLog(leakLogFile, leakThreshold = 0):
def processLeakLog(leakLogFile, leakThresholds):
"""Process the leak log, including separate leak logs created
by child processes.
@ -326,14 +326,28 @@ def processLeakLog(leakLogFile, leakThreshold = 0):
optional.
All other file names are treated as being for default processes.
leakThresholds should be a dict mapping process types to leak thresholds,
in bytes. If a process type is not present in the dict the threshold
will be 0.
"""
if not os.path.exists(leakLogFile):
log.info("WARNING | leakcheck | refcount logging is off, so leaks can't be detected!")
return
if leakThreshold != 0:
log.info("TEST-INFO | leakcheck | threshold set at %d bytes" % leakThreshold)
# This list is based on kGeckoProcessTypeString. ipdlunittest processes likely
# are not going to produce leak logs we will ever see.
knownProcessTypes = ["default", "plugin", "tab", "geckomediaplugin"]
for processType in knownProcessTypes:
log.info("TEST-INFO | leakcheck | %s process: leak threshold set at %d bytes"
% (processType, leakThresholds.get(processType, 0)))
for processType in leakThresholds:
if not processType in knownProcessTypes:
log.info("TEST-UNEXPECTED-FAIL | leakcheck | Unknown process type %s in leakThresholds"
% processType)
(leakLogFileDir, leakFileBase) = os.path.split(leakLogFile)
if leakFileBase[-4:] == ".log":
@ -350,6 +364,10 @@ def processLeakLog(leakLogFile, leakThreshold = 0):
processType = m.group(1)
else:
processType = "default"
if not processType in knownProcessTypes:
log.info("TEST-UNEXPECTED-FAIL | leakcheck | Leak log with unknown process type %s"
% processType)
leakThreshold = leakThresholds.get(processType, 0)
processSingleLeakFile(thisFile, processType, leakThreshold)
def replaceBackSlashes(input):

View File

@ -162,6 +162,9 @@ class RemoteOptions(ReftestOptions):
if not options.httpdPath:
options.httpdPath = os.path.join(options.utilityPath, "components")
# Android does not run leak tests, but set some reasonable defaults to avoid errors.
options.leakThresholds = {}
# TODO: Copied from main, but I think these are no longer used in a post xulrunner world
#options.xrePath = options.remoteTestRoot + self.automation._product + '/xulrunner'
#options.utilityPath = options.testRoot + self.automation._product + '/bin'

View File

@ -344,7 +344,7 @@ class RefTest(object):
# give the JS harness 30 seconds to deal
# with its own timeouts
timeout=options.timeout + 30.0)
processLeakLog(self.leakLogFile, options.leakThreshold)
processLeakLog(self.leakLogFile, options.leakThresholds)
self.automation.log.info("\nREFTEST INFO | runreftest.py | Running tests: end.")
finally:
self.cleanup(profileDir)
@ -394,12 +394,12 @@ class ReftestOptions(OptionParser):
default = 5 * 60, # 5 minutes per bug 479518
help = "reftest will timeout in specified number of seconds. [default %default s].")
self.add_option("--leak-threshold",
action = "store", type = "int", dest = "leakThreshold",
action = "store", type = "int", dest = "defaultLeakThreshold",
default = 0,
help = "fail if the number of bytes leaked through "
"refcounted objects (or bytes in classes with "
"MOZ_COUNT_CTOR and MOZ_COUNT_DTOR) is greater "
"than the given number")
help = "fail if the number of bytes leaked in default "
"processes through refcounted objects (or bytes "
"in classes with MOZ_COUNT_CTOR and MOZ_COUNT_DTOR) "
"is greater than the given number")
self.add_option("--utility-path",
action = "store", type = "string", dest = "utilityPath",
default = self.automation.DIST_BIN,
@ -511,6 +511,8 @@ class ReftestOptions(OptionParser):
if options.debugger is not None:
self.error("cannot specify a debugger with parallel tests")
options.leakThresholds = {"default": options.defaultLeakThreshold}
return options
def main():

View File

@ -223,12 +223,12 @@ class MochitestOptions(optparse.OptionParser):
[["--leak-threshold"],
{ "action": "store",
"type": "int",
"dest": "leakThreshold",
"dest": "defaultLeakThreshold",
"metavar": "THRESHOLD",
"help": "fail if the number of bytes leaked through "
"refcounted objects (or bytes in classes with "
"MOZ_COUNT_CTOR and MOZ_COUNT_DTOR) is greater "
"than the given number",
"help": "fail if the number of bytes leaked in default "
"processes through refcounted objects (or bytes "
"in classes with MOZ_COUNT_CTOR and MOZ_COUNT_DTOR) "
"is greater than the given number",
"default": 0,
}],
[["--fatal-assertions"],
@ -610,6 +610,11 @@ class MochitestOptions(optparse.OptionParser):
if not os.path.isfile(f):
self.error('Missing binary %s required for --use-test-media-devices')
options.leakThresholds = {
"default": options.defaultLeakThreshold,
"tab": 10000, # See dependencies of bug 1051230.
}
return options
@ -767,7 +772,7 @@ class B2GOptions(MochitestOptions):
defaults["testPath"] = ""
defaults["extensionsToExclude"] = ["specialpowers"]
# See dependencies of bug 1038943.
defaults["leakThreshold"] = 5180
defaults["defaultLeakThreshold"] = 5180
self.set_defaults(**defaults)
def verifyRemoteOptions(self, options):

View File

@ -1842,7 +1842,7 @@ class Mochitest(MochitestUtilsMixin):
self.stopVMwareRecording();
self.stopServers()
processLeakLog(self.leak_report_file, options.leakThreshold)
processLeakLog(self.leak_report_file, options.leakThresholds)
if self.nsprLogs:
with zipfile.ZipFile("%s/nsprlog.zip" % browserEnv["MOZ_UPLOAD_DIR"], "w", zipfile.ZIP_DEFLATED) as logzip:

View File

@ -202,7 +202,7 @@ class B2GMochitest(MochitestUtilsMixin):
self.app_ctx.dm.getFile(self.leak_report_file, local_leak_file.name)
self.app_ctx.dm.removeFile(self.leak_report_file)
processLeakLog(local_leak_file.name, options.leakThreshold)
processLeakLog(local_leak_file.name, options.leakThresholds)
except KeyboardInterrupt:
self.log.info("runtests.py | Received keyboard interrupt.\n");
status = -1