author | Josh Matthews <josh@joshmatthews.net> |
Thu, 20 Dec 2012 03:43:19 -0500 | |
changeset 142307 | 4a1cbbb07ce23516c12662db6b154f95439bbca0 |
parent 142306 | 5d965d4738971517722400c7db36aa87b82d048c |
child 142308 | 6c48ce88a31ad3476e3403008a02b589ac44e2ba |
child 142327 | 98e5c35041c0086535b46e8a159d2445c5973721 |
push id | 2579 |
push user | akeybl@mozilla.com |
push date | Mon, 24 Jun 2013 18:52:47 +0000 |
treeherder | mozilla-beta@b69b7de8a05a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | ted |
bugs | 597064 |
milestone | 23.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/build/automation.py.in +++ b/build/automation.py.in @@ -78,23 +78,31 @@ except: if _IS_WIN32: import ctypes, ctypes.wintypes, time, msvcrt 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) ################# # PROFILE SETUP # ################# class SyntaxError(Exception): "Signifies a syntax error on a particular line in server-locations.txt." @@ -900,20 +908,24 @@ user_pref("camino.use_system_proxy_setti except IOError, err: self.log.info("Failed to read image from %s", imgoutput) import base64 encoded = base64.b64encode(image) 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 os.kill(processPID, signal.SIGABRT) return elif self.IS_WIN32: # We should have a "crashinject" program in our utility path crashinject = os.path.normpath(os.path.join(utilityPath, "crashinject.exe"))
--- a/build/macosx/universal/flight.mk +++ b/build/macosx/universal/flight.mk @@ -39,16 +39,18 @@ ifdef ENABLE_TESTS # automation.py differs because it hardcodes a path to # dist/bin. It doesn't matter which one we use. if test -d $(DIST_ARCH_1)/test-package-stage -a \ -d $(DIST_ARCH_2)/test-package-stage; then \ cp $(DIST_ARCH_1)/test-package-stage/mochitest/automation.py \ $(DIST_ARCH_2)/test-package-stage/mochitest/; \ cp -RL $(DIST_ARCH_1)/test-package-stage/mochitest/extensions/specialpowers \ $(DIST_ARCH_2)/test-package-stage/mochitest/extensions/; \ + cp $(DIST_ARCH_1)/test-package-stage/xpcshell/automation.py \ + $(DIST_ARCH_2)/test-package-stage/xpcshell/; \ cp $(DIST_ARCH_1)/test-package-stage/reftest/automation.py \ $(DIST_ARCH_2)/test-package-stage/reftest/; \ cp -RL $(DIST_ARCH_1)/test-package-stage/reftest/specialpowers \ $(DIST_ARCH_2)/test-package-stage/reftest/; \ $(TOPSRCDIR)/build/macosx/universal/unify \ --unify-with-sort "\.manifest$$" \ --unify-with-sort "all-test-dirs\.list$$" \ $(DIST_ARCH_1)/test-package-stage \
--- a/config/makefiles/xpcshell.mk +++ b/config/makefiles/xpcshell.mk @@ -35,64 +35,69 @@ ifndef NO_XPCSHELL_MANIFEST_CHECK #{ $(addprefix $(MOZILLA_DIR)/$(relativesrcdir)/,$(XPCSHELL_TESTS)) endif #} NO_XPCSHELL_MANIFEST_CHECK ########################################################################### # Execute all tests in the $(XPCSHELL_TESTS) directories. # See also testsuite-targets.mk 'xpcshell-tests' target for global execution. xpcshell-tests: $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ + -I$(DEPTH)/build \ -I$(topsrcdir)/build \ -I$(DEPTH)/_tests/mozbase/mozinfo \ $(testxpcsrcdir)/runxpcshelltests.py \ --symbols-path=$(DIST)/crashreporter-symbols \ --build-info-json=$(DEPTH)/mozinfo.json \ --tests-root-dir=$(testxpcobjdir) \ --testing-modules-dir=$(DEPTH)/_tests/modules \ --xunit-file=$(testxpcobjdir)/$(relativesrcdir)/results.xml \ --xunit-suite-name=xpcshell \ --test-plugin-path=$(DIST)/plugins \ $(EXTRA_TEST_ARGS) \ $(LIBXUL_DIST)/bin/xpcshell \ $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) xpcshell-tests-remote: DM_TRANS?=adb xpcshell-tests-remote: - $(PYTHON) -u $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \ + $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ + -I$(DEPTH)/build \ + $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \ --symbols-path=$(DIST)/crashreporter-symbols \ --build-info-json=$(DEPTH)/mozinfo.json \ --testing-modules-dir=$(DEPTH)/_tests/modules \ $(EXTRA_TEST_ARGS) \ --dm_trans=$(DM_TRANS) \ --deviceIP=${TEST_DEVICE} \ --objdir=$(DEPTH) \ $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(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 $(topsrcdir)/config/pythonpath.py \ + -I$(DEPTH)/build \ -I$(topsrcdir)/build \ -I$(DEPTH)/_tests/mozbase/mozinfo \ $(testxpcsrcdir)/runxpcshelltests.py \ --symbols-path=$(DIST)/crashreporter-symbols \ --build-info-json=$(DEPTH)/mozinfo.json \ --test-path=$(SOLO_FILE) \ --testing-modules-dir=$(DEPTH)/_tests/modules \ --profile-name=$(MOZ_APP_NAME) \ --test-plugin-path=$(DIST)/plugins \ --interactive \ $(LIBXUL_DIST)/bin/xpcshell \ $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) # Execute a single test, specified in $(SOLO_FILE) check-one: $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ + -I$(DEPTH)/build \ -I$(topsrcdir)/build \ -I$(DEPTH)/_tests/mozbase/mozinfo \ $(testxpcsrcdir)/runxpcshelltests.py \ --symbols-path=$(DIST)/crashreporter-symbols \ --build-info-json=$(DEPTH)/mozinfo.json \ --test-path=$(SOLO_FILE) \ --testing-modules-dir=$(DEPTH)/_tests/modules \ --profile-name=$(MOZ_APP_NAME) \ @@ -100,16 +105,17 @@ check-one: --verbose \ $(EXTRA_TEST_ARGS) \ $(LIBXUL_DIST)/bin/xpcshell \ $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) check-one-remote: DM_TRANS?=adb check-one-remote: $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ + -I$(DEPTH)/build \ -I$(topsrcdir)/build \ -I$(topsrcdir)/build/mobile \ -I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \ $(testxpcsrcdir)/remotexpcshelltests.py \ --symbols-path=$(DIST)/crashreporter-symbols \ --build-info-json=$(DEPTH)/mozinfo.json \ --test-path=$(SOLO_FILE) \ --testing-modules-dir=$(DEPTH)/_tests/modules \
--- a/js/src/config/makefiles/xpcshell.mk +++ b/js/src/config/makefiles/xpcshell.mk @@ -35,64 +35,69 @@ ifndef NO_XPCSHELL_MANIFEST_CHECK #{ $(addprefix $(MOZILLA_DIR)/$(relativesrcdir)/,$(XPCSHELL_TESTS)) endif #} NO_XPCSHELL_MANIFEST_CHECK ########################################################################### # Execute all tests in the $(XPCSHELL_TESTS) directories. # See also testsuite-targets.mk 'xpcshell-tests' target for global execution. xpcshell-tests: $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ + -I$(DEPTH)/build \ -I$(topsrcdir)/build \ -I$(DEPTH)/_tests/mozbase/mozinfo \ $(testxpcsrcdir)/runxpcshelltests.py \ --symbols-path=$(DIST)/crashreporter-symbols \ --build-info-json=$(DEPTH)/mozinfo.json \ --tests-root-dir=$(testxpcobjdir) \ --testing-modules-dir=$(DEPTH)/_tests/modules \ --xunit-file=$(testxpcobjdir)/$(relativesrcdir)/results.xml \ --xunit-suite-name=xpcshell \ --test-plugin-path=$(DIST)/plugins \ $(EXTRA_TEST_ARGS) \ $(LIBXUL_DIST)/bin/xpcshell \ $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) xpcshell-tests-remote: DM_TRANS?=adb xpcshell-tests-remote: - $(PYTHON) -u $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \ + $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ + -I$(DEPTH)/build \ + $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \ --symbols-path=$(DIST)/crashreporter-symbols \ --build-info-json=$(DEPTH)/mozinfo.json \ --testing-modules-dir=$(DEPTH)/_tests/modules \ $(EXTRA_TEST_ARGS) \ --dm_trans=$(DM_TRANS) \ --deviceIP=${TEST_DEVICE} \ --objdir=$(DEPTH) \ $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(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 $(topsrcdir)/config/pythonpath.py \ + -I$(DEPTH)/build \ -I$(topsrcdir)/build \ -I$(DEPTH)/_tests/mozbase/mozinfo \ $(testxpcsrcdir)/runxpcshelltests.py \ --symbols-path=$(DIST)/crashreporter-symbols \ --build-info-json=$(DEPTH)/mozinfo.json \ --test-path=$(SOLO_FILE) \ --testing-modules-dir=$(DEPTH)/_tests/modules \ --profile-name=$(MOZ_APP_NAME) \ --test-plugin-path=$(DIST)/plugins \ --interactive \ $(LIBXUL_DIST)/bin/xpcshell \ $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) # Execute a single test, specified in $(SOLO_FILE) check-one: $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ + -I$(DEPTH)/build \ -I$(topsrcdir)/build \ -I$(DEPTH)/_tests/mozbase/mozinfo \ $(testxpcsrcdir)/runxpcshelltests.py \ --symbols-path=$(DIST)/crashreporter-symbols \ --build-info-json=$(DEPTH)/mozinfo.json \ --test-path=$(SOLO_FILE) \ --testing-modules-dir=$(DEPTH)/_tests/modules \ --profile-name=$(MOZ_APP_NAME) \ @@ -100,16 +105,17 @@ check-one: --verbose \ $(EXTRA_TEST_ARGS) \ $(LIBXUL_DIST)/bin/xpcshell \ $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir)) check-one-remote: DM_TRANS?=adb check-one-remote: $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ + -I$(DEPTH)/build \ -I$(topsrcdir)/build \ -I$(topsrcdir)/build/mobile \ -I$(topsrcdir)/testing/mozbase/mozdevice/mozdevice \ $(testxpcsrcdir)/remotexpcshelltests.py \ --symbols-path=$(DIST)/crashreporter-symbols \ --build-info-json=$(DEPTH)/mozinfo.json \ --test-path=$(SOLO_FILE) \ --testing-modules-dir=$(DEPTH)/_tests/modules \
--- a/testing/testsuite-targets.mk +++ b/testing/testsuite-targets.mk @@ -266,32 +266,35 @@ jstestbrowser: GARBAGE += $(addsuffix .log,$(MOCHITESTS) reftest crashtest jstestbrowser) # 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 $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build -I$(DEPTH)/_tests/mozbase/mozinfo \ + -I$(DEPTH)/build \ + -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 \ --no-logfiles \ --tests-root-dir=$(call core_abspath,_tests/xpcshell) \ --testing-modules-dir=$(call core_abspath,_tests/modules) \ --xunit-file=$(call core_abspath,_tests/xpcshell/results.xml) \ --xunit-suite-name=xpcshell \ $(SYMBOLS_PATH) \ $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS) \ $(LIBXUL_DIST)/bin/xpcshell B2G_XPCSHELL = \ rm -f ./@.log && \ $(PYTHON) -u $(topsrcdir)/config/pythonpath.py \ + -I$(DEPTH)/build \ -I$(topsrcdir)/build \ $(topsrcdir)/testing/xpcshell/runtestsb2g.py \ --manifest=$(DEPTH)/_tests/xpcshell/xpcshell.ini \ --build-info-json=$(DEPTH)/mozinfo.json \ --no-logfiles \ --use-device-libs \ --no-clean \ --objdir=$(DEPTH) \
--- a/testing/xpcshell/Makefile.in +++ b/testing/xpcshell/Makefile.in @@ -52,19 +52,20 @@ libs:: $(INSTALL) $(srcdir)/xpcshell.ini $(DEPTH)/_tests/xpcshell $(INSTALL) $(srcdir)/xpcshell_b2g.ini $(DEPTH)/_tests/xpcshell $(INSTALL) $(srcdir)/xpcshell_android.ini $(DEPTH)/_tests/xpcshell cp $(srcdir)/xpcshell.ini $(DEPTH)/_tests/xpcshell/all-test-dirs.list # Run selftests check:: OBJDIR=$(DEPTH) $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/build -I$(topsrcdir)/testing/mozbase/mozinfo/mozinfo $(srcdir)/selftest.py + -I$(DEPTH)/build -I$(topsrcdir)/build -I$(topsrcdir)/testing/mozbase/mozinfo/mozinfo $(srcdir)/selftest.py stage-package: $(NSINSTALL) -D $(PKG_STAGE)/xpcshell/tests @(cd $(topsrcdir)/testing/mozbase/mozinfo/mozinfo && tar $(TAR_CREATE_FLAGS) - $(MOZINFO_FILES)) | (cd $(PKG_STAGE)/xpcshell && tar -xf -) @(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 -)
--- a/testing/xpcshell/mach_commands.py +++ b/testing/xpcshell/mach_commands.py @@ -42,16 +42,20 @@ class XPCShellRunner(MozbuildObject): manifest = os.path.join(self.topobjdir, '_tests', 'xpcshell', 'xpcshell.ini') return self._run_xpcshell_harness(manifest=manifest, **kwargs) 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, keep_going=keep_going, shuffle=shuffle) return path_arg = self._wrap_path_argument(test_file)
--- a/testing/xpcshell/runxpcshelltests.py +++ b/testing/xpcshell/runxpcshelltests.py @@ -5,24 +5,28 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. import re, sys, os, os.path, logging, shutil, signal, math, time, traceback import xml.dom.minidom 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 * +HARNESS_TIMEOUT = 5 * 60 + # -------------------------------------------------------------- # TODO: this is a hack for mozbase without virtualenv, remove with bug 849900 # here = os.path.dirname(__file__) mozbase = os.path.realpath(os.path.join(os.path.dirname(here), 'mozbase')) try: import mozcrash @@ -47,24 +51,23 @@ def parse_json(j): """ Control-C handling """ gotSIGINT = False def markGotSIGINT(signum, stackFrame): global gotSIGINT gotSIGINT = True 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): """ read the xpcshell.ini manifest and set self.alltests to be an array of test objects. if we are chunking tests, it will be done here as well @@ -568,16 +571,20 @@ class XPCShellTests(object): testsuite.appendChild(testcase) testsuite.setAttribute("tests", str(total)) testsuite.setAttribute("failures", str(failed)) testsuite.setAttribute("skip", str(skipped)) 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 context = TestContext( testgroup='b2g xpcshell testsuite', operating_system='android', arch='emulator', @@ -878,16 +885,21 @@ class XPCShellTests(object): cmdT = self.buildCmdTestFile(name) args = self.xpcsRunArgs[:] if 'debug' in test: args.insert(0, '-d') completeCmd = cmdH + cmdT + args + testTimer = None + if not interactive and not self.debuggerInfo: + testTimer = Timer(HARNESS_TIMEOUT, lambda: self.testTimeout(name, proc.pid)) + testTimer.start() + proc = None try: self.log.info("TEST-INFO | %s | running test ..." % name) if verbose: self.logCommand(name, completeCmd, test_dir) startTime = time.time() @@ -901,17 +913,20 @@ class XPCShellTests(object): # - don't move this line above launchProcess, or child will inherit the SIG_IGN signal.signal(signal.SIGINT, markGotSIGINT) # |stderr == None| as |pStderr| was either |None| or redirected to |stdout|. stdout, stderr = self.communicate(proc) signal.signal(signal.SIGINT, signal.SIG_DFL) 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.""" self.log.info(">>>>>>>") if (stdout): for line in stdout.splitlines(): self.log.info(line) self.log.info("<<<<<<<")