Backed out changeset 53627e59f761 (bug 932898) for mochitest-mc timeouts.

This commit is contained in:
Ryan VanderMeulen 2013-11-20 14:30:30 -05:00
parent 8f4ee1cb7d
commit 33443de679
4 changed files with 6 additions and 176 deletions

View File

@ -840,8 +840,7 @@ class Automation(object):
runSSLTunnel = False, utilityPath = None,
xrePath = None, certPath = None,
debuggerInfo = None, symbolsPath = None,
timeout = -1, maxTime = None, onLaunch = None,
webapprtChrome = False):
timeout = -1, maxTime = None, onLaunch = 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.

View File

@ -8,7 +8,6 @@ import glob, logging, os, platform, shutil, subprocess, sys, tempfile, urllib2,
import base64
import re
from urlparse import urlparse
from operator import itemgetter
try:
import mozinfo
@ -47,7 +46,6 @@ __all__ = [
'systemMemory',
'environment',
'dumpScreen',
"ShutdownLeaks"
]
# Map of debugging programs to information about them, like default arguments
@ -529,121 +527,3 @@ def dumpScreen(utilityPath):
uri = "data:image/png;base64,%s" % encoded
log.info("SCREENSHOT: %s", uri)
return uri
class ShutdownLeaks(object):
"""
Parses the mochitest run log when running a debug build, assigns all leaked
DOM windows (that are still around after test suite shutdown, despite running
the GC) to the tests that created them and prints leak statistics.
"""
def __init__(self, logger):
self.logger = logger
self.tests = []
self.leakedWindows = {}
self.leakedDocShells = set()
self.currentTest = None
self.seenShutdown = False
def log(self, line):
if line[2:11] == "DOMWINDOW":
self._logWindow(line)
elif line[2:10] == "DOCSHELL":
self._logDocShell(line)
elif line.startswith("TEST-START"):
fileName = line.split(" ")[-1].strip().replace("chrome://mochitests/content/browser/", "")
self.currentTest = {"fileName": fileName, "windows": set(), "docShells": set()}
elif line.startswith("INFO TEST-END"):
# don't track a test if no windows or docShells leaked
if self.currentTest and (self.currentTest["windows"] or self.currentTest["docShells"]):
self.tests.append(self.currentTest)
self.currentTest = None
elif line.startswith("INFO TEST-START | Shutdown"):
self.seenShutdown = True
def process(self):
leakingTests = self._parseLeakingTests()
if leakingTests:
totalWindows = sum(len(test["leakedWindows"]) for test in leakingTests)
totalDocShells = sum(len(test["leakedDocShells"]) for test in leakingTests)
self.logger("TEST-UNEXPECTED-FAIL | ShutdownLeaks | leaked %d DOMWindow(s) and %d DocShell(s) until shutdown", totalWindows, totalDocShells)
for test in leakingTests:
for url, count in self._zipLeakedWindows(test["leakedWindows"]):
self.logger("TEST-UNEXPECTED-FAIL | %s | leaked %d window(s) until shutdown [url = %s]", test["fileName"], count, url)
if test["leakedDocShells"]:
self.logger("TEST-UNEXPECTED-FAIL | %s | leaked %d docShell(s) until shutdown", test["fileName"], len(test["leakedDocShells"]))
def _logWindow(self, line):
created = line[:2] == "++"
pid = self._parseValue(line, "pid")
serial = self._parseValue(line, "serial")
# log line has invalid format
if not pid or not serial:
self.logger("TEST-UNEXPECTED-FAIL | ShutdownLeaks | failed to parse line <%s>", line)
return
key = pid + "." + serial
if self.currentTest:
windows = self.currentTest["windows"]
if created:
windows.add(key)
else:
windows.discard(key)
elif self.seenShutdown and not created:
self.leakedWindows[key] = self._parseValue(line, "url")
def _logDocShell(self, line):
created = line[:2] == "++"
pid = self._parseValue(line, "pid")
id = self._parseValue(line, "id")
# log line has invalid format
if not pid or not id:
self.logger("TEST-UNEXPECTED-FAIL | ShutdownLeaks | failed to parse line <%s>", line)
return
key = pid + "." + id
if self.currentTest:
docShells = self.currentTest["docShells"]
if created:
docShells.add(key)
else:
docShells.discard(key)
elif self.seenShutdown and not created:
self.leakedDocShells.add(key)
def _parseValue(self, line, name):
match = re.search("\[%s = (.+?)\]" % name, line)
if match:
return match.group(1)
return None
def _parseLeakingTests(self):
leakingTests = []
for test in self.tests:
test["leakedWindows"] = [self.leakedWindows[id] for id in test["windows"] if id in self.leakedWindows]
test["leakedDocShells"] = [id for id in test["docShells"] if id in self.leakedDocShells]
test["leakCount"] = len(test["leakedWindows"]) + len(test["leakedDocShells"])
if test["leakCount"]:
leakingTests.append(test)
return sorted(leakingTests, key=itemgetter("leakCount"), reverse=True)
def _zipLeakedWindows(self, leakedWindows):
counts = []
counted = set()
for url in leakedWindows:
if not url in counted:
counts.append((url, leakedWindows.count(url)))
counted.add(url)
return sorted(counts, key=itemgetter(1), reverse=True)

View File

@ -13,9 +13,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserNewTabPreloader",
"resource:///modules/BrowserNewTabPreloader.jsm", "BrowserNewTabPreloader");
window.addEventListener("load", testOnLoad, false);
function testOnLoad() {
@ -383,34 +380,6 @@ Tester.prototype = {
gBrowser.removeCurrentTab();
}
// Replace the document currently loaded in the browser's sidebar.
// This will prevent false positives for tests that were the last
// to touch the sidebar. They will thus not be blamed for leaking
// a document.
let sidebar = document.getElementById("sidebar");
sidebar.setAttribute("src", "data:text/html;charset=utf-8,");
sidebar.docShell.createAboutBlankContentViewer(null);
sidebar.setAttribute("src", "about:blank");
// Do the same for the social sidebar.
let socialSidebar = document.getElementById("social-sidebar-browser");
socialSidebar.setAttribute("src", "data:text/html;charset=utf-8,");
socialSidebar.docShell.createAboutBlankContentViewer(null);
socialSidebar.setAttribute("src", "about:blank");
// Destroy BackgroundPageThumbs resources.
let {BackgroundPageThumbs} =
Cu.import("resource://gre/modules/BackgroundPageThumbs.jsm", {});
BackgroundPageThumbs._destroy();
// Uninitialize a few things explicitly so that they can clean up
// frames and browser intentionally kept alive until shutdown to
// eliminate false positives.
BrowserNewTabPreloader.uninit();
SocialFlyout.unload();
SocialShare.uninit();
TabView.uninit();
// Schedule GC and CC runs before finishing in order to detect
// DOM windows leaked by our tests or the tested code.

View File

@ -28,7 +28,7 @@ import time
import traceback
import urllib2
from automationutils import environment, getDebuggerInfo, isURL, KeyValueParseError, parseKeyValue, processLeakLog, systemMemory, dumpScreen, ShutdownLeaks
from automationutils import environment, getDebuggerInfo, isURL, KeyValueParseError, parseKeyValue, processLeakLog, systemMemory, dumpScreen
from datetime import datetime
from manifestparser import TestManifest
from mochitest_options import MochitestOptions
@ -750,8 +750,7 @@ class Mochitest(MochitestUtilsMixin):
debuggerInfo=None,
symbolsPath=None,
timeout=-1,
onLaunch=None,
webapprtChrome=False):
onLaunch=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.
@ -827,17 +826,11 @@ class Mochitest(MochitestUtilsMixin):
if testUrl:
args.append(testUrl)
if mozinfo.info["debug"] and not webapprtChrome:
shutdownLeaks = ShutdownLeaks(log.info)
else:
shutdownLeaks = None
# create an instance to process the output
outputHandler = self.OutputHandler(harness=self,
utilityPath=utilityPath,
symbolsPath=symbolsPath,
dump_screen_on_timeout=not debuggerInfo,
shutdownLeaks=shutdownLeaks,
)
def timeoutHandler():
@ -1013,8 +1006,7 @@ class Mochitest(MochitestUtilsMixin):
debuggerInfo=debuggerInfo,
symbolsPath=options.symbolsPath,
timeout=timeout,
onLaunch=onLaunch,
webapprtChrome=options.webapprtChrome
onLaunch=onLaunch
)
except KeyboardInterrupt:
log.info("runtests.py | Received keyboard interrupt.\n");
@ -1048,7 +1040,7 @@ class Mochitest(MochitestUtilsMixin):
class OutputHandler(object):
"""line output handler for mozrunner"""
def __init__(self, harness, utilityPath, symbolsPath=None, dump_screen_on_timeout=True, shutdownLeaks=None):
def __init__(self, harness, utilityPath, symbolsPath=None, dump_screen_on_timeout=True):
"""
harness -- harness instance
dump_screen_on_timeout -- whether to dump the screen on timeout
@ -1057,7 +1049,6 @@ class Mochitest(MochitestUtilsMixin):
self.utilityPath = utilityPath
self.symbolsPath = symbolsPath
self.dump_screen_on_timeout = dump_screen_on_timeout
self.shutdownLeaks = shutdownLeaks
# perl binary to use
self.perl = which('perl')
@ -1087,7 +1078,6 @@ class Mochitest(MochitestUtilsMixin):
self.record_last_test,
self.dumpScreenOnTimeout,
self.metro_subprocess_id,
self.trackShutdownLeaks,
self.log,
]
@ -1136,9 +1126,6 @@ class Mochitest(MochitestUtilsMixin):
if status and not didTimeout:
log.info("TEST-UNEXPECTED-FAIL | runtests.py | Stack fixer process exited with code %d during test run", status)
if self.shutdownLeaks:
self.shutdownLeaks.process()
# output line handlers:
# these take a line and return a line
@ -1172,11 +1159,6 @@ class Mochitest(MochitestUtilsMixin):
log.info("INFO | runtests.py | metro browser sub process id detected: %s", self.browserProcessId)
return line
def trackShutdownLeaks(self, line):
if self.shutdownLeaks:
self.shutdownLeaks.log(line)
return line
def log(self, line):
log.info(line)
return line