Bug 597064 - Add timeout logic to xpcshell test runner. r=ted

This commit is contained in:
Josh Matthews 2012-12-20 03:43:19 -05:00
parent 1781e6fbf9
commit 3bdacf49cb
8 changed files with 63 additions and 15 deletions

View File

@ -83,13 +83,21 @@ else:
import errno
def getGlobalLog():
return _log
def resetGlobalLog(log):
while _log.handlers:
_log.removeHandler(_log.handlers[0])
handler = logging.StreamHandler(log)
_log.setLevel(logging.INFO)
_log.addHandler(handler)
# We use the logging system here primarily because it'll handle multiple
# threads, which is needed to process the output of the server and application
# processes simultaneously.
_log = logging.getLogger()
handler = logging.StreamHandler(sys.stdout)
_log.setLevel(logging.INFO)
_log.addHandler(handler)
resetGlobalLog(sys.stdout)
#################
@ -904,10 +912,14 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t
self.log.info("SCREENSHOT: data:image/png;base64,%s", encoded)
def killAndGetStack(self, processPID, utilityPath, debuggerInfo):
"""Kill the process, preferrably in a way that gets us a stack trace."""
"""Kill the process, preferrably in a way that gets us a stack trace.
Also attempts to obtain a screenshot before killing the process."""
if not debuggerInfo:
self.dumpScreen(utilityPath)
self.killAndGetStackNoScreenshot(self, processPID, utilityPath, debuggerInfo)
def killAndGetStackNoScreenshot(self, processPID, utilityPath, debuggerInfo):
"""Kill the process, preferrably in a way that gets us a stack trace."""
if self.CRASHREPORTER and not debuggerInfo:
if self.UNIXISH:
# ABRT will get picked up by Breakpad's signal handler

View File

@ -40,6 +40,7 @@ endif #} NO_XPCSHELL_MANIFEST_CHECK
# See also testsuite-targets.mk 'xpcshell-tests' target for global execution.
xpcshell-tests:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(testxpcobjdir) \
-I$(topsrcdir)/build \
-I$(DEPTH)/_tests/mozbase/mozinfo \
$(testxpcsrcdir)/runxpcshelltests.py \
@ -56,7 +57,9 @@ xpcshell-tests:
xpcshell-tests-remote: DM_TRANS?=adb
xpcshell-tests-remote:
$(PYTHON) -u $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(testxpcobjdir) \
$(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
--symbols-path=$(DIST)/crashreporter-symbols \
--build-info-json=$(DEPTH)/mozinfo.json \
--testing-modules-dir=$(DEPTH)/_tests/modules \
@ -72,6 +75,7 @@ xpcshell-tests-remote:
# attach a debugger and then start the test.
check-interactive:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(testxpcobjdir) \
-I$(topsrcdir)/build \
-I$(DEPTH)/_tests/mozbase/mozinfo \
$(testxpcsrcdir)/runxpcshelltests.py \
@ -88,6 +92,7 @@ check-interactive:
# Execute a single test, specified in $(SOLO_FILE)
check-one:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(testxpcobjdir) \
-I$(topsrcdir)/build \
-I$(DEPTH)/_tests/mozbase/mozinfo \
$(testxpcsrcdir)/runxpcshelltests.py \
@ -105,6 +110,7 @@ check-one:
check-one-remote: DM_TRANS?=adb
check-one-remote:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(testxpcobjdir) \
-I$(topsrcdir)/build \
-I$(topsrcdir)/build/mobile \
-I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \

View File

@ -40,6 +40,7 @@ endif #} NO_XPCSHELL_MANIFEST_CHECK
# See also testsuite-targets.mk 'xpcshell-tests' target for global execution.
xpcshell-tests:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(testxpcobjdir) \
-I$(topsrcdir)/build \
-I$(DEPTH)/_tests/mozbase/mozinfo \
$(testxpcsrcdir)/runxpcshelltests.py \
@ -56,7 +57,9 @@ xpcshell-tests:
xpcshell-tests-remote: DM_TRANS?=adb
xpcshell-tests-remote:
$(PYTHON) -u $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(testxpcobjdir) \
$(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
--symbols-path=$(DIST)/crashreporter-symbols \
--build-info-json=$(DEPTH)/mozinfo.json \
--testing-modules-dir=$(DEPTH)/_tests/modules \
@ -72,6 +75,7 @@ xpcshell-tests-remote:
# attach a debugger and then start the test.
check-interactive:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(testxpcobjdir) \
-I$(topsrcdir)/build \
-I$(DEPTH)/_tests/mozbase/mozinfo \
$(testxpcsrcdir)/runxpcshelltests.py \
@ -88,6 +92,7 @@ check-interactive:
# Execute a single test, specified in $(SOLO_FILE)
check-one:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(testxpcobjdir) \
-I$(topsrcdir)/build \
-I$(DEPTH)/_tests/mozbase/mozinfo \
$(testxpcsrcdir)/runxpcshelltests.py \
@ -105,6 +110,7 @@ check-one:
check-one-remote: DM_TRANS?=adb
check-one-remote:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(testxpcobjdir) \
-I$(topsrcdir)/build \
-I$(topsrcdir)/build/mobile \
-I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \

View File

@ -111,7 +111,7 @@ function checkRequestResponse(request, data, context) {
response = channel.getResponseHeader("Proxy-Authenticate");
do_check_eq(response, "line 1\nline 2\nline 3");
channel.contentCharset = "UTF-8";
do_check_eq(channel.contentCharset, "UTF-8");
do_check_eq(channel.contentType, "text/plain");

View File

@ -271,7 +271,9 @@ GARBAGE += $(addsuffix .log,$(MOCHITESTS) reftest crashtest jstestbrowser)
# Usage: |make [TEST_PATH=...] [EXTRA_TEST_ARGS=...] xpcshell-tests|.
xpcshell-tests:
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(topsrcdir)/build -I$(DEPTH)/_tests/mozbase/mozinfo \
-I$(DEPTH)/_tests/xpcshell \
-I$(topsrcdir)/build \
-I$(DEPTH)/_tests/mozbase/mozinfo \
$(topsrcdir)/testing/xpcshell/runxpcshelltests.py \
--manifest=$(DEPTH)/_tests/xpcshell/xpcshell.ini \
--build-info-json=$(DEPTH)/mozinfo.json \
@ -287,6 +289,7 @@ xpcshell-tests:
B2G_XPCSHELL = \
rm -f ./@.log && \
$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
-I$(DEPTH)/_tests/xpcshell \
-I$(topsrcdir)/build \
$(topsrcdir)/testing/xpcshell/runtestsb2g.py \
--manifest=$(DEPTH)/_tests/xpcshell/xpcshell.ini \

View File

@ -54,10 +54,13 @@ libs::
$(INSTALL) $(srcdir)/xpcshell_android.ini $(DEPTH)/_tests/xpcshell
cp $(srcdir)/xpcshell.ini $(DEPTH)/_tests/xpcshell/all-test-dirs.list
libs:: $(DEPTH)/build/automation.py
$(INSTALL) $^ $(DEPTH)/_tests/xpcshell
# Run selftests
check::
OBJDIR=$(DEPTH) $(PYTHON) $(topsrcdir)/config/pythonpath.py \
-I$(topsrcdir)/build -I$(topsrcdir)/testing/mozbase/mozinfo/mozinfo $(srcdir)/selftest.py
-I$(DEPTH)/_tests/xpcshell -I$(topsrcdir)/build -I$(topsrcdir)/testing/mozbase/mozinfo/mozinfo $(srcdir)/selftest.py
stage-package:
$(NSINSTALL) -D $(PKG_STAGE)/xpcshell/tests
@ -65,6 +68,7 @@ stage-package:
@(cd $(srcdir) && tar $(TAR_CREATE_FLAGS) - $(TEST_HARNESS_FILES)) | (cd $(PKG_STAGE)/xpcshell && tar -xf -)
@(cd $(topsrcdir)/build && tar $(TAR_CREATE_FLAGS) - $(EXTRA_BUILD_FILES)) | (cd $(PKG_STAGE)/xpcshell && tar -xf -)
@cp $(DEPTH)/mozinfo.json $(PKG_STAGE)/xpcshell
@cp $(DEPTH)/build/automation.py $(PKG_STAGE)/xpcshell
@(cd $(topsrcdir)/testing/mozbase/mozdevice/mozdevice && tar $(TAR_CREATE_FLAGS) - $(MOZDEVICE_FILES)) | (cd $(PKG_STAGE)/xpcshell && tar -xf -)
(cd $(DEPTH)/_tests/xpcshell/ && tar $(TAR_CREATE_FLAGS_QUIET) - *) | (cd $(PKG_STAGE)/xpcshell/tests && tar -xf -)
@(cd $(DIST)/bin/components && tar $(TAR_CREATE_FLAGS) - $(TEST_HARNESS_COMPONENTS)) | (cd $(PKG_STAGE)/bin/components && tar -xf -)

View File

@ -47,6 +47,10 @@ class XPCShellRunner(MozbuildObject):
def run_test(self, test_file, debug=False, interactive=False,
keep_going=False, shuffle=False):
"""Runs an individual xpcshell test."""
# TODO Bug 794506 remove once mach integrates with virtualenv.
build_path = os.path.join(self.topobjdir, 'build')
if build_path not in sys.path:
sys.path.append(build_path)
if test_file == 'all':
self.run_suite(debug=debug, interactive=interactive,

View File

@ -10,12 +10,14 @@ from glob import glob
from optparse import OptionParser
from subprocess import Popen, PIPE, STDOUT
from tempfile import mkdtemp, gettempdir
from threading import Timer
import manifestparser
import mozinfo
import random
import socket
import time
from automation import Automation, getGlobalLog, resetGlobalLog
from automationutils import *
# --------------------------------------------------------------
@ -52,14 +54,13 @@ def markGotSIGINT(signum, stackFrame):
class XPCShellTests(object):
log = logging.getLogger()
log = getGlobalLog()
oldcwd = os.getcwd()
def __init__(self, log=sys.stdout):
def __init__(self, log=None):
""" Init logging and node status """
handler = logging.StreamHandler(log)
self.log.setLevel(logging.INFO)
self.log.addHandler(handler)
if log:
resetGlobalLog(log)
self.nodeProc = None
def buildTestList(self):
@ -573,6 +574,10 @@ class XPCShellTests(object):
doc.writexml(fh, addindent=" ", newl="\n", encoding="utf-8")
def testTimeout(self, test, processPID):
self.log.error("TEST-UNEXPECTED-FAIL | %s | Test timed out" % test)
Automation().killAndGetStackNoScreenshot(processPID, self.appPath, None)
def post_to_autolog(self, results, name):
from moztest.results import TestContext, TestResult, TestResultCollection
from moztest.output.autolog import AutologOutput
@ -883,6 +888,11 @@ class XPCShellTests(object):
completeCmd = cmdH + cmdT + args
testTimer = None
if not interactive and not self.debuggerInfo:
testTimer = Timer(120.0, lambda: self.testTimeout(name, proc.pid))
testTimer.start()
proc = None
try:
@ -906,7 +916,10 @@ class XPCShellTests(object):
if interactive:
# Not sure what else to do here...
return True
return True, xunit_result
if testTimer:
testTimer.cancel()
def print_stdout(stdout):
"""Print stdout line-by-line to avoid overflowing buffers."""