зеркало из https://github.com/mozilla/pjs.git
Bug 521457. Add debugger options to runreftest.py and runxpcshelltests.py. r=ted
--HG-- extra : rebase_source : 420b33b1d44aae7361c25d8bcc15032c303aa80d
This commit is contained in:
Родитель
58b4be83b6
Коммит
83f87cc724
|
@ -44,8 +44,28 @@ __all__ = [
|
|||
"checkForCrashes",
|
||||
"dumpLeakLog",
|
||||
"processLeakLog",
|
||||
"getDebuggerInfo",
|
||||
"DEBUGGER_INFO",
|
||||
]
|
||||
|
||||
# Map of debugging programs to information about them, like default arguments
|
||||
# and whether or not they are interactive.
|
||||
DEBUGGER_INFO = {
|
||||
# gdb requires that you supply the '--args' flag in order to pass arguments
|
||||
# after the executable name to the executable.
|
||||
"gdb": {
|
||||
"interactive": True,
|
||||
"args": "-q --args"
|
||||
},
|
||||
|
||||
# valgrind doesn't explain much about leaks unless you set the
|
||||
# '--leak-check=full' flag.
|
||||
"valgrind": {
|
||||
"interactive": False,
|
||||
"args": "--leak-check=full"
|
||||
}
|
||||
}
|
||||
|
||||
log = logging.getLogger()
|
||||
|
||||
def addCommonOptions(parser, defaults={}):
|
||||
|
@ -60,6 +80,17 @@ def addCommonOptions(parser, defaults={}):
|
|||
action = "store", type = "string", dest = "symbolsPath",
|
||||
default = defaults['SYMBOLS_PATH'],
|
||||
help = "absolute path to directory containing breakpad symbols")
|
||||
parser.add_option("--debugger",
|
||||
action = "store", dest = "debugger",
|
||||
help = "use the given debugger to launch the application")
|
||||
parser.add_option("--debugger-args",
|
||||
action = "store", dest = "debuggerArgs",
|
||||
help = "pass the given args to the debugger _before_ "
|
||||
"the application on the command line")
|
||||
parser.add_option("--debugger-interactive",
|
||||
action = "store_true", dest = "debuggerInteractive",
|
||||
help = "prevents the test harness from redirecting "
|
||||
"stdout and stderr for interactive debuggers")
|
||||
|
||||
def checkForCrashes(dumpDir, symbolsPath, testName=None):
|
||||
stackwalkPath = os.environ.get('MINIDUMP_STACKWALK', None)
|
||||
|
@ -91,6 +122,57 @@ def checkForCrashes(dumpDir, symbolsPath, testName=None):
|
|||
foundCrash = True
|
||||
|
||||
return foundCrash
|
||||
|
||||
def getFullPath(directory, path):
|
||||
"Get an absolute path relative to 'directory'."
|
||||
return os.path.normpath(os.path.join(directory, os.path.expanduser(path)))
|
||||
|
||||
def searchPath(directory, path):
|
||||
"Go one step beyond getFullPath and try the various folders in PATH"
|
||||
# Try looking in the current working directory first.
|
||||
newpath = getFullPath(directory, path)
|
||||
if os.path.exists(newpath):
|
||||
return newpath
|
||||
|
||||
# At this point we have to fail if a directory was given (to prevent cases
|
||||
# like './gdb' from matching '/usr/bin/./gdb').
|
||||
if not os.path.dirname(path):
|
||||
for dir in os.environ['PATH'].split(os.pathsep):
|
||||
newpath = os.path.join(dir, path)
|
||||
if os.path.exists(newpath):
|
||||
return newpath
|
||||
return None
|
||||
|
||||
def getDebuggerInfo(directory, debugger, debuggerArgs, debuggerInteractive = False):
|
||||
|
||||
debuggerInfo = None
|
||||
|
||||
if debugger:
|
||||
debuggerPath = searchPath(directory, debugger)
|
||||
if not debuggerPath:
|
||||
print "Error: Path %s doesn't exist." % debugger
|
||||
sys.exit(1)
|
||||
|
||||
debuggerName = os.path.basename(debuggerPath).lower()
|
||||
|
||||
def getDebuggerInfo(type, default):
|
||||
if debuggerName in DEBUGGER_INFO and type in DEBUGGER_INFO[debuggerName]:
|
||||
return DEBUGGER_INFO[debuggerName][type]
|
||||
return default
|
||||
|
||||
debuggerInfo = {
|
||||
"path": debuggerPath,
|
||||
"interactive" : getDebuggerInfo("interactive", False),
|
||||
"args": getDebuggerInfo("args", "").split()
|
||||
}
|
||||
|
||||
if debuggerArgs:
|
||||
debuggerInfo["args"] = debuggerArgs.split()
|
||||
if debuggerInteractive:
|
||||
debuggerInfo["interactive"] = debuggerInteractive
|
||||
|
||||
return debuggerInfo
|
||||
|
||||
|
||||
def dumpLeakLog(leakLogFile, filter = False):
|
||||
"""Process the leak log, without parsing it.
|
||||
|
|
|
@ -45,7 +45,7 @@ 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, processLeakLog
|
||||
from automationutils import *
|
||||
from optparse import OptionParser
|
||||
from tempfile import mkdtemp
|
||||
|
||||
|
@ -127,6 +127,9 @@ Are you executing $objdir/_tests/reftest/runreftest.py?""" \
|
|||
options.symbolsPath = getFullPath(options.symbolsPath)
|
||||
options.utilityPath = getFullPath(options.utilityPath)
|
||||
|
||||
debuggerInfo = getDebuggerInfo(oldcwd, options.debugger, options.debuggerArgs,
|
||||
options.debuggerInteractive);
|
||||
|
||||
profileDir = None
|
||||
try:
|
||||
profileDir = mkdtemp()
|
||||
|
@ -165,6 +168,7 @@ Are you executing $objdir/_tests/reftest/runreftest.py?""" \
|
|||
["-reftest", reftestlist],
|
||||
utilityPath = options.utilityPath,
|
||||
xrePath=options.xrePath,
|
||||
debuggerInfo=debuggerInfo,
|
||||
symbolsPath=options.symbolsPath)
|
||||
processLeakLog(leakLogFile, options.leakThreshold)
|
||||
automation.log.info("\nREFTEST INFO | runreftest.py | Running tests: end.")
|
||||
|
|
|
@ -53,7 +53,7 @@ from urllib import quote_plus as encodeURIComponent
|
|||
import urllib2
|
||||
import commands
|
||||
import automation
|
||||
from automationutils import addCommonOptions, processLeakLog
|
||||
from automationutils import *
|
||||
|
||||
# Path to the test script on the server
|
||||
TEST_SERVER_HOST = "localhost:8888"
|
||||
|
@ -87,24 +87,6 @@ PROFILE_DIRECTORY = os.path.abspath("./mochitesttestingprofile")
|
|||
|
||||
LEAK_REPORT_FILE = os.path.join(PROFILE_DIRECTORY, "runtests_leaks.log")
|
||||
|
||||
# Map of debugging programs to information about them, like default arguments
|
||||
# and whether or not they are interactive.
|
||||
DEBUGGER_INFO = {
|
||||
# gdb requires that you supply the '--args' flag in order to pass arguments
|
||||
# after the executable name to the executable.
|
||||
"gdb": {
|
||||
"interactive": True,
|
||||
"args": "-q --args"
|
||||
},
|
||||
|
||||
# valgrind doesn't explain much about leaks unless you set the
|
||||
# '--leak-check=full' flag.
|
||||
"valgrind": {
|
||||
"interactive": False,
|
||||
"args": "--leak-check=full"
|
||||
}
|
||||
}
|
||||
|
||||
#######################
|
||||
# COMMANDLINE OPTIONS #
|
||||
#######################
|
||||
|
@ -251,20 +233,6 @@ class MochitestOptions(optparse.OptionParser):
|
|||
help = "copy specified files/dirs to testing profile")
|
||||
defaults["extraProfileFiles"] = []
|
||||
|
||||
self.add_option("--debugger",
|
||||
action = "store", dest = "debugger",
|
||||
help = "use the given debugger to launch the application")
|
||||
|
||||
self.add_option("--debugger-args",
|
||||
action = "store", dest = "debuggerArgs",
|
||||
help = "pass the given args to the debugger _before_ "
|
||||
"the application on the command line")
|
||||
|
||||
self.add_option("--debugger-interactive",
|
||||
action = "store_true", dest = "debuggerInteractive",
|
||||
help = "prevents the test harness from redirecting stdout "
|
||||
"and stderr for interactive debuggers")
|
||||
|
||||
# -h, --help are automatically handled by OptionParser
|
||||
|
||||
self.set_defaults(**defaults)
|
||||
|
@ -342,22 +310,6 @@ def getFullPath(path):
|
|||
"Get an absolute path relative to oldcwd."
|
||||
return os.path.normpath(os.path.join(oldcwd, os.path.expanduser(path)))
|
||||
|
||||
def searchPath(path):
|
||||
"Go one step beyond getFullPath and try the various folders in PATH"
|
||||
# Try looking in the current working directory first.
|
||||
newpath = getFullPath(path)
|
||||
if os.path.exists(newpath):
|
||||
return newpath
|
||||
|
||||
# At this point we have to fail if a directory was given (to prevent cases
|
||||
# like './gdb' from matching '/usr/bin/./gdb').
|
||||
if not os.path.dirname(path):
|
||||
for dir in os.environ['PATH'].split(os.pathsep):
|
||||
newpath = os.path.join(dir, path)
|
||||
if os.path.exists(newpath):
|
||||
return newpath
|
||||
return None
|
||||
|
||||
#################
|
||||
# MAIN FUNCTION #
|
||||
#################
|
||||
|
@ -397,31 +349,8 @@ Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
|
|||
options.certPath = getFullPath(options.certPath)
|
||||
options.symbolsPath = getFullPath(options.symbolsPath)
|
||||
|
||||
debuggerInfo = None
|
||||
|
||||
if options.debugger:
|
||||
debuggerPath = searchPath(options.debugger)
|
||||
if not debuggerPath:
|
||||
print "Error: Path %s doesn't exist." % options.debugger
|
||||
sys.exit(1)
|
||||
|
||||
debuggerName = os.path.basename(debuggerPath).lower()
|
||||
|
||||
def getDebuggerInfo(type, default):
|
||||
if debuggerName in DEBUGGER_INFO and type in DEBUGGER_INFO[debuggerName]:
|
||||
return DEBUGGER_INFO[debuggerName][type]
|
||||
return default
|
||||
|
||||
debuggerInfo = {
|
||||
"path": debuggerPath,
|
||||
"interactive" : getDebuggerInfo("interactive", False),
|
||||
"args": getDebuggerInfo("args", "").split()
|
||||
}
|
||||
|
||||
if options.debuggerArgs:
|
||||
debuggerInfo["args"] = options.debuggerArgs.split()
|
||||
if options.debuggerInteractive:
|
||||
debuggerInfo["interactive"] = options.debuggerInteractive
|
||||
debuggerInfo = getDebuggerInfo(oldcwd, options.debugger, options.debuggerArgs,
|
||||
options.debuggerInteractive);
|
||||
|
||||
# browser environment
|
||||
browserEnv = automation.environment(xrePath = options.xrePath)
|
||||
|
|
|
@ -43,7 +43,7 @@ from optparse import OptionParser
|
|||
from subprocess import Popen, PIPE, STDOUT
|
||||
from tempfile import mkdtemp
|
||||
|
||||
from automationutils import addCommonOptions, checkForCrashes, dumpLeakLog
|
||||
from automationutils import *
|
||||
|
||||
# Init logging
|
||||
log = logging.getLogger()
|
||||
|
@ -51,6 +51,8 @@ handler = logging.StreamHandler(sys.stdout)
|
|||
log.setLevel(logging.INFO)
|
||||
log.addHandler(handler)
|
||||
|
||||
oldcwd = os.getcwd()
|
||||
|
||||
def readManifest(manifest):
|
||||
"""Given a manifest file containing a list of test directories,
|
||||
return a list of absolute paths to the directories contained within."""
|
||||
|
@ -70,7 +72,8 @@ def readManifest(manifest):
|
|||
|
||||
def runTests(xpcshell, xrePath=None, symbolsPath=None,
|
||||
manifest=None, testdirs=[], testPath=None,
|
||||
interactive=False, logfiles=True):
|
||||
interactive=False, logfiles=True,
|
||||
debuggerInfo=None):
|
||||
"""Run xpcshell tests.
|
||||
|
||||
|xpcshell|, is the xpcshell executable to use to run the tests.
|
||||
|
@ -86,6 +89,8 @@ def runTests(xpcshell, xrePath=None, symbolsPath=None,
|
|||
instead of automatically executing the test.
|
||||
|logfiles|, if set to False, indicates not to save output to log files.
|
||||
Non-interactive only option.
|
||||
|debuggerInfo|, if set, specifies the debugger and debugger arguments
|
||||
that will be used to launch xpcshell.
|
||||
"""
|
||||
|
||||
if not testdirs and not manifest:
|
||||
|
@ -131,17 +136,24 @@ def runTests(xpcshell, xrePath=None, symbolsPath=None,
|
|||
pStderr = None
|
||||
else:
|
||||
xpcsRunArgs = ['-e', '_execute_test();']
|
||||
if sys.platform == 'os2emx':
|
||||
if (debuggerInfo and debuggerInfo["interactive"]):
|
||||
pStdout = None
|
||||
pStderr = None
|
||||
else:
|
||||
pStdout = PIPE
|
||||
pStderr = STDOUT
|
||||
if sys.platform == 'os2emx':
|
||||
pStdout = None
|
||||
else:
|
||||
pStdout = PIPE
|
||||
pStderr = STDOUT
|
||||
|
||||
# <head.js> has to be loaded by xpchell: it can't load itself.
|
||||
xpcsCmd = [xpcshell, '-g', xrePath, '-j', '-s'] + \
|
||||
['-e', 'const _HTTPD_JS_PATH = "%s";' % httpdJSPath,
|
||||
'-f', os.path.join(testharnessdir, 'head.js')]
|
||||
|
||||
if debuggerInfo:
|
||||
xpcsCmd = [debuggerInfo["path"]] + debuggerInfo["args"] + xpcsCmd
|
||||
|
||||
# |testPath| will be the optional path only, or |None|.
|
||||
# |singleFile| will be the optional test only, or |None|.
|
||||
singleFile = None
|
||||
|
@ -295,6 +307,9 @@ def main():
|
|||
sys.argv[0])
|
||||
sys.exit(1)
|
||||
|
||||
debuggerInfo = getDebuggerInfo(oldcwd, options.debugger, options.debuggerArgs,
|
||||
options.debuggerInteractive);
|
||||
|
||||
if options.interactive and not options.testPath:
|
||||
print >>sys.stderr, "Error: You must specify a test filename in interactive mode!"
|
||||
sys.exit(1)
|
||||
|
@ -306,7 +321,8 @@ def main():
|
|||
testdirs=args[1:],
|
||||
testPath=options.testPath,
|
||||
interactive=options.interactive,
|
||||
logfiles=options.logfiles):
|
||||
logfiles=options.logfiles,
|
||||
debuggerInfo=debuggerInfo):
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Загрузка…
Ссылка в новой задаче