--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -69,16 +69,17 @@ include $(topsrcdir)/config/rules.mk
# we install to _leaktest/
TARGET_DEPTH = ..
include $(srcdir)/automation-build.mk
_LEAKTEST_DIR = $(DEPTH)/_leaktest
_LEAKTEST_FILES = \
automation.py \
+ automationutils.py \
leaktest.py \
bloatcycle.html \
$(topsrcdir)/build/pgo/server-locations.txt \
$(NULL)
leaktest.py: leaktest.py.in
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $^ > $@
chmod +x $@
--- a/build/automation-build.mk
+++ b/build/automation-build.mk
@@ -59,11 +59,16 @@ AUTOMATION_PPARGS += -DIS_TEST_BUILD=0
endif
ifeq ($(MOZ_DEBUG), 1)
AUTOMATION_PPARGS += -DIS_DEBUG_BUILD=1
else
AUTOMATION_PPARGS += -DIS_DEBUG_BUILD=0
endif
-automation.py: $(topsrcdir)/build/automation.py.in $(topsrcdir)/build/automation-build.mk
+automationutils.py:
+ $(INSTALL) $(topsrcdir)/build/automationutils.py .
+
+automation.py: $(topsrcdir)/build/automation.py.in $(topsrcdir)/build/automation-build.mk automationutils.py
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
+
+GARBAGE += automation.py automationutils.py
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -43,17 +43,18 @@ import itertools
import logging
import os
import re
import shutil
import signal
import subprocess
import sys
import threading
-import glob
+
+from automationutils import checkForCrashes
"""
Runs the browser from a script, and provides useful utilities
for setting up the browser environment.
"""
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
@@ -66,16 +67,19 @@ SCRIPT_DIR = os.path.abspath(os.path.rea
"Process",
"initializeProfile",
"DIST_BIN",
"DEFAULT_APP",
"CERTS_SRC_DIR",
"environment",
"dumpLeakLog",
"processLeakLog",
+ "IS_TEST_BUILD",
+ "IS_DEBUG_BUILD",
+ "SYMBOLS_PATH",
]
# These are generated in mozilla/build/Makefile.in
#expand DIST_BIN = __XPC_BIN_PATH__
#expand IS_WIN32 = len("__WIN32__") != 0
#expand IS_MAC = __IS_MAC__ != 0
#ifdef IS_CYGWIN
#expand IS_CYGWIN = __IS_CYGWIN__ == 1
@@ -120,17 +124,17 @@ class Process(subprocess.Popen):
if IS_WIN32:
import platform
pid = "%i" % self.pid
if platform.release() == "2000":
# Windows 2000 needs 'kill.exe' from the 'Windows 2000 Resource Kit tools'. (See bug 475455.)
try:
subprocess.Popen(["kill", "-f", pid]).wait()
except:
- log.info("TEST-UNEXPECTED-FAIL | (automation.py) | Missing 'kill' utility to kill process with pid=%s. Kill it manually!", pid)
+ log.info("TEST-UNEXPECTED-FAIL | automation.py | Missing 'kill' utility to kill process with pid=%s. Kill it manually!", pid)
else:
# Windows XP and later.
subprocess.Popen(["taskkill", "/F", "/PID", pid]).wait()
else:
os.kill(self.pid, signal.SIGKILL)
#################
@@ -404,31 +408,16 @@ def environment(env = None, xrePath = DI
elif IS_WIN32:
env["PATH"] = env["PATH"] + ";" + ldLibraryPath
env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
env['MOZ_CRASHREPORTER'] = '1'
return env
-def checkForCrashes(profileDir, symbolsPath):
- stackwalkPath = os.environ.get('MINIDUMP_STACKWALK', None)
-
- foundCrash = False
- dumps = glob.glob(os.path.join(profileDir, 'minidumps', '*.dmp'))
- for d in dumps:
- log.info("TEST-UNEXPECTED-FAIL | (automation.py) | Browser crashed (minidump found)")
- if symbolsPath and stackwalkPath:
- nullfd = open(os.devnull, 'w')
- # eat minidump_stackwalk errors
- subprocess.call([stackwalkPath, d, symbolsPath], stderr=nullfd)
- nullfd.close()
- os.remove(d)
- foundCrash = True
- return foundCrash
###############
# RUN THE APP #
###############
def dumpLeakLog(leakLogFile, filter = False):
"""Process the leak log, without parsing it.
@@ -537,23 +526,23 @@ def runApp(testURL, env, app, profileDir
xrePath = DIST_BIN, certPath = CERTS_SRC_DIR,
debuggerInfo = None, symbolsPath = SYMBOLS_PATH):
"Run the app, log the duration it took to execute, return the status code."
if IS_TEST_BUILD and runSSLTunnel:
# create certificate database for the profile
certificateStatus = fillCertificateDB(profileDir, certPath, utilityPath, xrePath)
if certificateStatus != 0:
- log.info("TEST-UNEXPECTED FAIL | (automation.py) | Certificate integration failed")
+ log.info("TEST-UNEXPECTED FAIL | automation.py | Certificate integration failed")
return certificateStatus
# start ssltunnel to provide https:// URLs capability
ssltunnel = os.path.join(utilityPath, "ssltunnel" + BIN_SUFFIX)
ssltunnelProcess = Process([ssltunnel, os.path.join(profileDir, "ssltunnel.cfg")], env = environment(xrePath = xrePath))
- log.info("INFO | (automation.py) | SSL tunnel pid: %d", ssltunnelProcess.pid)
+ log.info("INFO | automation.py | SSL tunnel pid: %d", ssltunnelProcess.pid)
# now run with the profile we created
cmd = app
if IS_MAC and not IS_CAMINO and not cmd.endswith("-bin"):
cmd += "-bin"
cmd = os.path.abspath(cmd)
args = []
@@ -583,30 +572,30 @@ def runApp(testURL, env, app, profileDir
# Don't redirect stdout and stderr if an interactive debugger is attached
if debuggerInfo and debuggerInfo["interactive"]:
outputPipe = None
else:
outputPipe = subprocess.PIPE
proc = Process([cmd] + args, env = environment(env), stdout = outputPipe, stderr = subprocess.STDOUT)
- log.info("INFO | (automation.py) | Application pid: %d", proc.pid)
+ log.info("INFO | automation.py | Application pid: %d", proc.pid)
if outputPipe is None:
log.info("TEST-INFO: Not logging stdout or stderr due to debugger connection")
else:
line = proc.stdout.readline()
while line != "":
log.info(line.rstrip())
line = proc.stdout.readline()
status = proc.wait()
if status != 0:
- log.info("TEST-UNEXPECTED-FAIL | (automation.py) | Exited with code %d during test run", status)
- log.info("INFO | (automation.py) | Application ran for: %s", str(datetime.now() - startTime))
+ log.info("TEST-UNEXPECTED-FAIL | automation.py | Exited with code %d during test run", status)
+ log.info("INFO | automation.py | Application ran for: %s", str(datetime.now() - startTime))
- if checkForCrashes(profileDir, symbolsPath):
+ if checkForCrashes(os.path.join(profileDir, "minidumps"), symbolsPath):
status = -1
if IS_TEST_BUILD and runSSLTunnel:
ssltunnelProcess.kill()
return status
new file mode 100644
--- /dev/null
+++ b/build/automationutils.py
@@ -0,0 +1,46 @@
+import sys, glob, os, subprocess, logging
+
+__all__ = [
+ "addCommonOptions",
+ "checkForCrashes",
+ ]
+
+log = logging.getLogger()
+
+def addCommonOptions(parser, defaults={}):
+ parser.add_option("--xre-path",
+ action = "store", type = "string", dest = "xrePath",
+ # individual scripts will set a sane default
+ default = None,
+ help = "absolute path to directory containing XRE (probably xulrunner)")
+ if 'SYMBOLS_PATH' not in defaults:
+ defaults['SYMBOLS_PATH'] = None
+ parser.add_option("--symbols-path",
+ action = "store", type = "string", dest = "symbolsPath",
+ default = defaults['SYMBOLS_PATH'],
+ help = "absolute path to directory containing breakpad symbols")
+
+def checkForCrashes(dumpDir, symbolsPath, testName=None):
+ stackwalkPath = os.environ.get('MINIDUMP_STACKWALK', None)
+ # try to get the caller's filename if no test name is given
+ if testName is None:
+ try:
+ testName = os.path.basename(sys._getframe(1).f_code.co_filename)
+ except:
+ testName = "unknown"
+
+ foundCrash = False
+ dumps = glob.glob(os.path.join(dumpDir, '*.dmp'))
+ for d in dumps:
+ log.info("TEST-UNEXPECTED-FAIL | %s | application crashed (minidump found)", testName)
+ if symbolsPath and stackwalkPath:
+ nullfd = open(os.devnull, 'w')
+ # eat minidump_stackwalk errors
+ subprocess.call([stackwalkPath, d, symbolsPath], stderr=nullfd)
+ nullfd.close()
+ os.remove(d)
+ extra = os.path.splitext(d)[0] + ".extra"
+ if os.path.exists(extra):
+ os.remove(extra)
+ foundCrash = True
+ return foundCrash
--- a/build/pgo/Makefile.in
+++ b/build/pgo/Makefile.in
@@ -54,30 +54,31 @@ include $(topsrcdir)/config/rules.mk
# We install to _profile/pgo
TARGET_DEPTH = ../..
include $(topsrcdir)/build/automation-build.mk
# Stuff to make a build with a profile
_PGO_FILES = \
automation.py \
+ automationutils.py \
profileserver.py \
genpgocert.py \
index.html \
server-locations.txt \
favicon.ico \
$(NULL)
genpgocert.py: genpgocert.py.in
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $^ > $@
profileserver.py: profileserver.py.in
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $^ > $@
chmod +x $@
-GARBAGE += automation.py profileserver.py genpgocert.py
+GARBAGE += profileserver.py genpgocert.py
libs:: $(_PGO_FILES)
$(INSTALL) $^ $(_PROFILE_DIR)
genservercert::
$(PYTHON) $(DEPTH)/_profile/pgo/genpgocert.py --gen-server
--- a/config/pythonpath.py
+++ b/config/pythonpath.py
@@ -32,9 +32,9 @@ while True:
continue
break
sys.argv.pop(0)
script = sys.argv[0]
sys.path[0:0] = [os.path.dirname(script)] + paths
-execfile(script, {'__name__': '__main__'})
+execfile(script, {'__name__': '__main__', '__file__': script})
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -151,36 +151,42 @@ libs::
$(testxpcobjdir)/all-test-dirs.list \
$(addprefix $(MODULE)/,$(XPCSHELL_TESTS))
testxpcsrcdir = $(topsrcdir)/testing/xpcshell
# Execute all tests in the $(XPCSHELL_TESTS) directories.
# See also testsuite-targets.mk 'xpcshell-tests' target for global execution.
xpcshell-tests:
- $(PYTHON) -u \
+ $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+ -I$(topsrcdir)/build \
$(testxpcsrcdir)/runxpcshelltests.py \
+ --symbols-path=$(DIST)/crashreporter-symbols \
$(DIST)/bin/xpcshell \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(MODULE)/$(dir))
# Execute a single test, specified in $(SOLO_FILE), but don't automatically
# start the test. Instead, present the xpcshell prompt so the user can
# attach a debugger and then start the test.
check-interactive:
- $(PYTHON) -u \
+ $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+ -I$(topsrcdir)/build \
$(testxpcsrcdir)/runxpcshelltests.py \
+ --symbols-path=$(DIST)/crashreporter-symbols \
--test=$(SOLO_FILE) \
--interactive \
$(DIST)/bin/xpcshell \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(MODULE)/$(dir))
# Execute a single test, specified in $(SOLO_FILE)
check-one:
- $(PYTHON) -u \
+ $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+ -I$(topsrcdir)/build \
$(testxpcsrcdir)/runxpcshelltests.py \
+ --symbols-path=$(DIST)/crashreporter-symbols \
--test=$(SOLO_FILE) \
$(DIST)/bin/xpcshell \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(MODULE)/$(dir))
endif # XPCSHELL_TESTS
ifdef CPP_UNIT_TESTS
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -151,36 +151,42 @@ libs::
$(testxpcobjdir)/all-test-dirs.list \
$(addprefix $(MODULE)/,$(XPCSHELL_TESTS))
testxpcsrcdir = $(topsrcdir)/testing/xpcshell
# Execute all tests in the $(XPCSHELL_TESTS) directories.
# See also testsuite-targets.mk 'xpcshell-tests' target for global execution.
xpcshell-tests:
- $(PYTHON) -u \
+ $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+ -I$(topsrcdir)/build \
$(testxpcsrcdir)/runxpcshelltests.py \
+ --symbols-path=$(DIST)/crashreporter-symbols \
$(DIST)/bin/xpcshell \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(MODULE)/$(dir))
# Execute a single test, specified in $(SOLO_FILE), but don't automatically
# start the test. Instead, present the xpcshell prompt so the user can
# attach a debugger and then start the test.
check-interactive:
- $(PYTHON) -u \
+ $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+ -I$(topsrcdir)/build \
$(testxpcsrcdir)/runxpcshelltests.py \
+ --symbols-path=$(DIST)/crashreporter-symbols \
--test=$(SOLO_FILE) \
--interactive \
$(DIST)/bin/xpcshell \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(MODULE)/$(dir))
# Execute a single test, specified in $(SOLO_FILE)
check-one:
- $(PYTHON) -u \
+ $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+ -I$(topsrcdir)/build \
$(testxpcsrcdir)/runxpcshelltests.py \
+ --symbols-path=$(DIST)/crashreporter-symbols \
--test=$(SOLO_FILE) \
$(DIST)/bin/xpcshell \
$(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(MODULE)/$(dir))
endif # XPCSHELL_TESTS
ifdef CPP_UNIT_TESTS
--- a/layout/tools/reftest/Makefile.in
+++ b/layout/tools/reftest/Makefile.in
@@ -70,20 +70,19 @@ make-xpi:
+$(MAKE) -C $(CURDIR) libs XPI_NAME=reftest
copy-harness: make-xpi
libs:: copy-harness
endif
_HARNESS_FILES = \
$(srcdir)/runreftest.py \
automation.py \
+ automationutils.py \
$(NULL)
-GARBAGE += automation.py
-
$(_DEST_DIR):
$(NSINSTALL) -D $@
$(_HARNESS_FILES): $(_DEST_DIR)
# copy harness and the reftest extension bits to $(_DEST_DIR)
copy-harness: $(_HARNESS_FILES)
$(INSTALL) $(_HARNESS_FILES) $(_DEST_DIR)
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -39,16 +39,17 @@
"""
Runs the reftest test harness.
"""
import sys, shutil, os, os.path
SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
sys.path.append(SCRIPT_DIRECTORY)
import automation
+from automationutils import addCommonOptions
from optparse import OptionParser
from tempfile import mkdtemp
oldcwd = os.getcwd()
os.chdir(SCRIPT_DIRECTORY)
def getFullPath(path):
"Get an absolute path relative to oldcwd."
@@ -70,32 +71,27 @@ def createReftestProfile(profileDir):
os.mkdir(profileExtensionsPath)
reftestExtensionPath = os.path.join(SCRIPT_DIRECTORY, "reftest")
extFile = open(os.path.join(profileExtensionsPath, "reftest@mozilla.org"), "w")
extFile.write(reftestExtensionPath)
extFile.close()
def main():
parser = OptionParser()
+
+ # we want to pass down everything from automation.__all__
+ addCommonOptions(parser, defaults=dict(zip(automation.__all__, [getattr(automation, x) for x in automation.__all__])))
parser.add_option("--appname",
action = "store", type = "string", dest = "app",
default = os.path.join(SCRIPT_DIRECTORY, automation.DEFAULT_APP),
help = "absolute path to application, overriding default")
- parser.add_option("--xre-path",
- action = "store", type = "string", dest = "xrePath",
- default = None, # default is set below
- help = "absolute path to directory containing XRE (probably xulrunner)")
parser.add_option("--extra-profile-file",
action = "append", dest = "extraProfileFiles",
default = [],
help = "copy specified files/dirs to testing profile")
- parser.add_option("--symbols-path",
- action = "store", type = "string", dest = "symbolsPath",
- default = automation.SYMBOLS_PATH,
- help = "absolute path to directory containing breakpad symbols")
parser.add_option("--leak-threshold",
action = "store", type = "int", dest = "leakThreshold",
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")
--- a/testing/mochitest/Makefile.in
+++ b/testing/mochitest/Makefile.in
@@ -55,16 +55,17 @@ include $(topsrcdir)/config/rules.mk
# necessary for relative objdir paths.
TARGET_DEPTH = ../../..
include $(topsrcdir)/build/automation-build.mk
# files that get copied into $objdir/_tests/
_SERV_FILES = \
runtests.py \
automation.py \
+ automationutils.py \
gen_template.pl \
server.js \
harness-a11y.xul \
harness-overlay.xul \
harness.xul \
browser-test-overlay.xul \
browser-test.js \
browser-harness.xul \
@@ -78,17 +79,17 @@ include $(topsrcdir)/build/automation-bu
_DEST_DIR = $(DEPTH)/_tests/$(relativesrcdir)
runtests.py: runtests.py.in
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
$(DEFINES) $(ACDEFINES) $^ > $@
-GARBAGE += automation.py runtests.py
+GARBAGE += runtests.py
libs:: $(_SERV_FILES)
$(INSTALL) $^ $(_DEST_DIR)
# Binaries that don't get packaged with the build,
# but that we need for the test harness
TEST_HARNESS_BINS := \
xpcshell$(BIN_SUFFIX) \
--- a/testing/mochitest/runtests.py.in
+++ b/testing/mochitest/runtests.py.in
@@ -47,16 +47,17 @@ import os
import os.path
import sys
import time
import shutil
from urllib import quote_plus as encodeURIComponent
import urllib2
import commands
import automation
+from automationutils import addCommonOptions
# Path to the test script on the server
TEST_SERVER_HOST = "localhost:8888"
TEST_PATH = "/tests/"
CHROME_PATH = "/redirect.html";
A11Y_PATH = "/redirect-a11y.html"
TESTS_URL = "http://" + TEST_SERVER_HOST + TEST_PATH
CHROMETESTS_URL = "http://" + TEST_SERVER_HOST + CHROME_PATH
@@ -105,42 +106,34 @@ DEBUGGER_INFO = {
#######################
class MochitestOptions(optparse.OptionParser):
"""Parses Mochitest commandline options."""
def __init__(self, **kwargs):
optparse.OptionParser.__init__(self, **kwargs)
defaults = {}
+ # we want to pass down everything from automation.__all__
+ addCommonOptions(self, defaults=dict(zip(automation.__all__, [getattr(automation, x) for x in automation.__all__])))
+
self.add_option("--close-when-done",
action = "store_true", dest = "closeWhenDone",
help = "close the application when tests are done running")
defaults["closeWhenDone"] = False
self.add_option("--appname",
action = "store", type = "string", dest = "app",
help = "absolute path to application, overriding default")
defaults["app"] = os.path.join(SCRIPT_DIRECTORY, automation.DEFAULT_APP)
- self.add_option("--xre-path",
- action = "store", type = "string", dest = "xrePath",
- help = "absolute path to directory containing XRE (probably xulrunner)")
- # we'll default this to the directory of app below
- defaults["xrePath"] = None
-
self.add_option("--utility-path",
action = "store", type = "string", dest = "utilityPath",
help = "absolute path to directory containing utility programs (xpcshell, ssltunnel, certutil)")
defaults["utilityPath"] = automation.DIST_BIN
- self.add_option("--symbols-path",
- action = "store", type = "string", dest = "symbolsPath",
- help = "absolute path to directory containing breakpad symbols")
- defaults["symbolsPath"] = automation.SYMBOLS_PATH
-
self.add_option("--certificate-path",
action = "store", type = "string", dest = "certPath",
help = "absolute path to directory containing certificate store to use testing profile")
defaults["certPath"] = automation.CERTS_SRC_DIR
self.add_option("--log-file",
action = "store", type = "string",
dest = "logFile", metavar = "FILE",
--- a/testing/testsuite-targets.mk
+++ b/testing/testsuite-targets.mk
@@ -92,17 +92,18 @@ crashtest:
$(call RUN_REFTEST,$(topsrcdir)/testing/crashtest/crashtests.list)
$(CHECK_TEST_ERROR)
# Execute all xpcshell tests in the directories listed in the manifest.
# See also config/rules.mk 'xpcshell-tests' target for local execution.
# Usage: |make [TEST_PATH=...] [EXTRA_TEST_ARGS=...] xpcshell-tests|.
xpcshell-tests:
- $(PYTHON) -u \
+ $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+ -I$(topsrcdir)/build \
$(topsrcdir)/testing/xpcshell/runxpcshelltests.py \
--manifest=$(DEPTH)/_tests/xpcshell/all-test-dirs.list \
$(TEST_PATH_ARG) $(EXTRA_TEST_ARGS) \
$(DIST)/bin/xpcshell
# Package up the tests and test harnesses
include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
--- a/testing/xpcshell/head.js
+++ b/testing/xpcshell/head.js
@@ -51,16 +51,28 @@ var _tests_pending = 0;
// Disable automatic network detection, so tests work correctly when
// not connected to a network.
let (ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService2)) {
ios.manageOfflineStatus = false;
ios.offline = false;
}
+// Enable crash reporting, if possible
+// We rely on the Python harness to set MOZ_CRASHREPORTER_NO_REPORT
+// and handle checking for minidumps.
+if ("@mozilla.org/toolkit/crash-reporter;1" in Components.classes) {
+ let (crashReporter =
+ Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
+ .getService(Components.interfaces.nsICrashReporter)) {
+ crashReporter.enabled = true;
+ crashReporter.minidumpPath = do_get_cwd();
+ }
+}
+
function _TimerCallback(expr) {
this._expr = expr;
}
_TimerCallback.prototype = {
_expr: "",
QueryInterface: function(iid) {
if (iid.Equals(Components.interfaces.nsITimerCallback) ||
iid.Equals(Components.interfaces.nsISupports))
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -31,22 +31,30 @@
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK ***** */
-import sys, os, os.path
+import sys, os, os.path, logging
import tempfile
from glob import glob
from optparse import OptionParser
from subprocess import Popen, PIPE, STDOUT
+from automationutils import addCommonOptions, checkForCrashes
+
+# Init logging
+log = logging.getLogger()
+handler = logging.StreamHandler(sys.stdout)
+log.setLevel(logging.INFO)
+log.addHandler(handler)
+
def readManifest(manifest):
"""Given a manifest file containing a list of test directories,
return a list of absolute paths to the directories contained within."""
manifestdir = os.path.dirname(manifest)
testdirs = []
try:
f = open(manifest, "r")
for line in f:
@@ -55,40 +63,44 @@ def readManifest(manifest):
if os.path.isdir(path):
testdirs.append(path)
f.close()
except:
pass # just eat exceptions
return testdirs
def runTests(xpcshell, testdirs=[], xrePath=None, testPath=None,
- manifest=None, interactive=False):
+ manifest=None, interactive=False, symbolsPath=None):
"""Run the tests in |testdirs| using the |xpcshell| executable.
|xrePath|, if provided, is the path to the XRE to use.
|testPath|, if provided, indicates a single path and/or test to run.
|manifest|, if provided, is a file containing a list of
test directories to run.
|interactive|, if set to True, indicates to provide an xpcshell prompt
instead of automatically executing the test.
+ |symbolsPath|, if provided is the path to a directory containing
+ breakpad symbols for processing crashes in tests.
"""
if not testdirs and not manifest:
# nothing to test!
print >>sys.stderr, "Error: No test dirs or test manifest specified!"
return False
testharnessdir = os.path.dirname(os.path.abspath(__file__))
xpcshell = os.path.abspath(xpcshell)
# we assume that httpd.js lives in components/ relative to xpcshell
httpdJSPath = os.path.join(os.path.dirname(xpcshell), "components", "httpd.js").replace("\\", "/");
env = dict(os.environ)
# Make assertions fatal
env["XPCOM_DEBUG_BREAK"] = "stack-and-abort"
+ # Don't launch the crash reporter client
+ env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
# Enable leaks (only) detection to its own log file.
# Each test will overwrite it.
leakLogFile = os.path.join(tempfile.gettempdir(), "runxpcshelltests_leaks.log")
env["XPCOM_MEM_LEAK_LOG"] = leakLogFile
def processLeakLog(leakLogFile):
"""Process the leak log."""
@@ -196,16 +208,17 @@ def runTests(xpcshell, testdirs=[], xreP
# not sure what else to do here...
return True
if proc.returncode != 0 or stdout.find("*** PASS") == -1:
print """TEST-UNEXPECTED-FAIL | %s | test failed (with xpcshell return code: %d), see following log:
>>>>>>>
%s
<<<<<<<""" % (test, proc.returncode, stdout)
+ checkForCrashes(testdir, symbolsPath, testName=test)
success = False
else:
print "TEST-PASS | %s | all tests passed" % test
leakReport = processLeakLog(leakLogFile)
try:
f = open(test + '.log', 'w')
@@ -221,19 +234,18 @@ def runTests(xpcshell, testdirs=[], xreP
if os.path.exists(leakLogFile):
os.remove(leakLogFile)
return success
def main():
"""Process command line arguments and call runTests() to do the real work."""
parser = OptionParser()
- parser.add_option("--xre-path",
- action="store", type="string", dest="xrePath", default=None,
- help="absolute path to directory containing XRE (probably xulrunner)")
+
+ addCommonOptions(parser)
parser.add_option("--test-path",
action="store", type="string", dest="testPath",
default=None, help="single path and/or test filename to test")
parser.add_option("--interactive",
action="store_true", dest="interactive", default=False,
help="don't automatically run tests, drop to an xpcshell prompt")
parser.add_option("--manifest",
action="store", type="string", dest="manifest",
@@ -250,13 +262,14 @@ def main():
if options.interactive and not options.testPath:
print >>sys.stderr, "Error: You must specify a test filename in interactive mode!"
sys.exit(1)
if not runTests(args[0], testdirs=args[1:],
xrePath=options.xrePath,
testPath=options.testPath,
interactive=options.interactive,
- manifest=options.manifest):
+ manifest=options.manifest,
+ symbolsPath=options.symbolsPath):
sys.exit(1)
if __name__ == '__main__':
main()
--- a/toolkit/crashreporter/test/unit/test_crashreporter.js
+++ b/toolkit/crashreporter/test/unit/test_crashreporter.js
@@ -5,17 +5,16 @@ function run_test()
return;
}
var cr = Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
.getService(Components.interfaces.nsICrashReporter);
do_check_neq(cr, null);
// check that we can enable the crashreporter
- do_check_false(cr.enabled);
cr.enabled = true;
do_check_true(cr.enabled);
// ensure that double-enabling doesn't error
cr.enabled = true;
// check setting/getting serverURL
var ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);