forked from OSchip/llvm-project
Some re-achitecturing of the plugins interface. The caller is now required to
pass in a 'sender' arg to the buildDefault(), buildDsym(), buildDwarf(), and cleanup() functions. The sender arg will be the test instance itself (i.e., an instance of TestBase). This is so that the relevant command execution can be recorded in the TestBase.session object if sender is available. The lldbtest.system() command has been modified to pop the 'sender' arg out of the keyword arguments dictionary and use it as the test instance to facilitate seesion recordings. An example is in test/types/AbstractBase.py: def generic_type_tester(self, atoms, quotedDisplay=False): """Test that variables with basic types are displayed correctly.""" # First, capture the golden output emitted by the oracle, i.e., the # series of printf statements. go = system("./a.out", sender=self) There are cases when sender is None. This is the case when the @classmethod is involved in the use of these APIs. When this happens, there is no recording into a session object, but printing on the sys.stderr is still honored if the trace flag is ON. An example is in test/settings/TestSettings.py: @classmethod def classCleanup(cls): system(["/bin/sh", "-c", "rm -f output.txt"]) system(["/bin/sh", "-c", "rm -f stdout.txt"]) llvm-svn: 116648
This commit is contained in:
parent
1f81ced14c
commit
690fcef762
|
@ -185,52 +185,6 @@ def CMD_MSG(str, exe):
|
|||
def EnvArray():
|
||||
return map(lambda k,v: k+"="+v, os.environ.keys(), os.environ.values())
|
||||
|
||||
# From 2.7's subprocess.check_output() convenience function.
|
||||
def system(*popenargs, **kwargs):
|
||||
r"""Run command with arguments and return its output as a byte string.
|
||||
|
||||
If the exit code was non-zero it raises a CalledProcessError. The
|
||||
CalledProcessError object will have the return code in the returncode
|
||||
attribute and output in the output attribute.
|
||||
|
||||
The arguments are the same as for the Popen constructor. Example:
|
||||
|
||||
>>> check_output(["ls", "-l", "/dev/null"])
|
||||
'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
|
||||
|
||||
The stdout argument is not allowed as it is used internally.
|
||||
To capture standard error in the result, use stderr=STDOUT.
|
||||
|
||||
>>> check_output(["/bin/sh", "-c",
|
||||
... "ls -l non_existent_file ; exit 0"],
|
||||
... stderr=STDOUT)
|
||||
'ls: non_existent_file: No such file or directory\n'
|
||||
"""
|
||||
if 'stdout' in kwargs:
|
||||
raise ValueError('stdout argument not allowed, it will be overridden.')
|
||||
process = Popen(stdout=PIPE, *popenargs, **kwargs)
|
||||
output, error = process.communicate()
|
||||
retcode = process.poll()
|
||||
|
||||
if traceAlways:
|
||||
if isinstance(popenargs, types.StringTypes):
|
||||
args = [popenargs]
|
||||
else:
|
||||
args = list(popenargs)
|
||||
print >> sys.stderr
|
||||
print >> sys.stderr, "os command:", args
|
||||
print >> sys.stderr, "stdout:", output
|
||||
print >> sys.stderr, "stderr:", error
|
||||
print >> sys.stderr, "retcode:", retcode
|
||||
print >> sys.stderr
|
||||
|
||||
if retcode:
|
||||
cmd = kwargs.get("args")
|
||||
if cmd is None:
|
||||
cmd = popenargs[0]
|
||||
raise CalledProcessError(retcode, cmd)
|
||||
return output
|
||||
|
||||
def line_number(filename, string_to_match):
|
||||
"""Helper function to return the line number of the first matched string."""
|
||||
with open(filename, 'r') as f:
|
||||
|
@ -254,10 +208,9 @@ class recording(StringIO.StringIO):
|
|||
into the stderr.
|
||||
"""
|
||||
def __init__(self, test, trace):
|
||||
"""Create a StringIO instance; record session, stderr, and trace."""
|
||||
"""Create a StringIO instance; record the session obj and trace flag."""
|
||||
StringIO.StringIO.__init__(self)
|
||||
self.session = test.session
|
||||
self.stderr = test.old_stderr
|
||||
self.session = test.session if test else None
|
||||
self.trace = trace
|
||||
|
||||
def __enter__(self):
|
||||
|
@ -274,10 +227,61 @@ class recording(StringIO.StringIO):
|
|||
recordings to our session object. And close the StringIO object, too.
|
||||
"""
|
||||
if self.trace:
|
||||
print >> self.stderr, self.getvalue()
|
||||
print >> self.session, self.getvalue()
|
||||
print >> sys.stderr, self.getvalue()
|
||||
if self.session:
|
||||
print >> self.session, self.getvalue()
|
||||
self.close()
|
||||
|
||||
# From 2.7's subprocess.check_output() convenience function.
|
||||
def system(*popenargs, **kwargs):
|
||||
r"""Run command with arguments and return its output as a byte string.
|
||||
|
||||
If the exit code was non-zero it raises a CalledProcessError. The
|
||||
CalledProcessError object will have the return code in the returncode
|
||||
attribute and output in the output attribute.
|
||||
|
||||
The arguments are the same as for the Popen constructor. Example:
|
||||
|
||||
>>> check_output(["ls", "-l", "/dev/null"])
|
||||
'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
|
||||
|
||||
The stdout argument is not allowed as it is used internally.
|
||||
To capture standard error in the result, use stderr=STDOUT.
|
||||
|
||||
>>> check_output(["/bin/sh", "-c",
|
||||
... "ls -l non_existent_file ; exit 0"],
|
||||
... stderr=STDOUT)
|
||||
'ls: non_existent_file: No such file or directory\n'
|
||||
"""
|
||||
|
||||
# Assign the sender object to variable 'test' and remove it from kwargs.
|
||||
test = kwargs.pop('sender', None)
|
||||
|
||||
if 'stdout' in kwargs:
|
||||
raise ValueError('stdout argument not allowed, it will be overridden.')
|
||||
process = Popen(stdout=PIPE, *popenargs, **kwargs)
|
||||
output, error = process.communicate()
|
||||
retcode = process.poll()
|
||||
|
||||
with recording(test, traceAlways) as sbuf:
|
||||
if isinstance(popenargs, types.StringTypes):
|
||||
args = [popenargs]
|
||||
else:
|
||||
args = list(popenargs)
|
||||
print >> sbuf
|
||||
print >> sbuf, "os command:", args
|
||||
print >> sbuf, "stdout:", output
|
||||
print >> sbuf, "stderr:", error
|
||||
print >> sbuf, "retcode:", retcode
|
||||
print >> sbuf
|
||||
|
||||
if retcode:
|
||||
cmd = kwargs.get("args")
|
||||
if cmd is None:
|
||||
cmd = popenargs[0]
|
||||
raise CalledProcessError(retcode, cmd)
|
||||
return output
|
||||
|
||||
class TestBase(unittest2.TestCase):
|
||||
"""This LLDB abstract base class is meant to be subclassed."""
|
||||
|
||||
|
@ -403,16 +407,10 @@ class TestBase(unittest2.TestCase):
|
|||
self.dict = None
|
||||
self.doTearDownCleanup = False
|
||||
|
||||
# Create a string buffer to record the session info.
|
||||
# Create a string buffer to record the session info, to be dumped into a
|
||||
# test case specific file if test failure is encountered.
|
||||
self.session = StringIO.StringIO()
|
||||
|
||||
# Substitute self.session as the sys.stderr and restore it at the end of
|
||||
# the test during tearDown(). If trace is ON, we dump the session info
|
||||
# into the real stderr as well. The session info will be dumped into a
|
||||
# test case specific file if a failure is encountered.
|
||||
self.old_stderr = sys.stderr
|
||||
sys.stderr = self.session
|
||||
|
||||
# Optimistically set self.__failed__ to False initially. If the test
|
||||
# failed, the session info (self.session) is then dumped into a session
|
||||
# specific file for diagnosis.
|
||||
|
@ -469,9 +467,6 @@ class TestBase(unittest2.TestCase):
|
|||
if self.__failed__:
|
||||
self.dumpSessionInfo()
|
||||
|
||||
# Restore the sys.stderr to what it was before.
|
||||
sys.stderr = self.old_stderr
|
||||
|
||||
def runCmd(self, cmd, msg=None, check=True, trace=False, setCookie=True):
|
||||
"""
|
||||
Ask the command interpreter to handle the command and then check its
|
||||
|
@ -656,19 +651,19 @@ class TestBase(unittest2.TestCase):
|
|||
def buildDefault(self, architecture=None, compiler=None, dictionary=None):
|
||||
"""Platform specific way to build the default binaries."""
|
||||
module = __import__(sys.platform)
|
||||
if not module.buildDefault(architecture, compiler, dictionary):
|
||||
if not module.buildDefault(self, architecture, compiler, dictionary):
|
||||
raise Exception("Don't know how to build default binary")
|
||||
|
||||
def buildDsym(self, architecture=None, compiler=None, dictionary=None):
|
||||
"""Platform specific way to build binaries with dsym info."""
|
||||
module = __import__(sys.platform)
|
||||
if not module.buildDsym(architecture, compiler, dictionary):
|
||||
if not module.buildDsym(self, architecture, compiler, dictionary):
|
||||
raise Exception("Don't know how to build binary with dsym")
|
||||
|
||||
def buildDwarf(self, architecture=None, compiler=None, dictionary=None):
|
||||
"""Platform specific way to build binaries with dwarf maps."""
|
||||
module = __import__(sys.platform)
|
||||
if not module.buildDwarf(architecture, compiler, dictionary):
|
||||
if not module.buildDwarf(self, architecture, compiler, dictionary):
|
||||
raise Exception("Don't know how to build binary with dwarf")
|
||||
|
||||
def DebugSBValue(self, frame, val):
|
||||
|
|
|
@ -57,43 +57,46 @@ def getCmdLine(d):
|
|||
return " " + cmdline
|
||||
|
||||
|
||||
def buildDefault(architecture=None, compiler=None, dictionary=None):
|
||||
def buildDefault(sender=None, architecture=None, compiler=None, dictionary=None):
|
||||
"""Build the binaries the default way."""
|
||||
lldbtest.system(["/bin/sh", "-c",
|
||||
"make clean" + getCmdLine(dictionary) + "; make"
|
||||
+ getArchSpec(architecture) + getCCSpec(compiler)
|
||||
+ getCmdLine(dictionary)])
|
||||
+ getCmdLine(dictionary)],
|
||||
sender=sender)
|
||||
|
||||
# True signifies that we can handle building default.
|
||||
return True
|
||||
|
||||
def buildDsym(architecture=None, compiler=None, dictionary=None):
|
||||
def buildDsym(sender=None, architecture=None, compiler=None, dictionary=None):
|
||||
"""Build the binaries with dsym debug info."""
|
||||
lldbtest.system(["/bin/sh", "-c",
|
||||
"make clean" + getCmdLine(dictionary)
|
||||
+ "; make MAKE_DSYM=YES"
|
||||
+ getArchSpec(architecture) + getCCSpec(compiler)
|
||||
+ getCmdLine(dictionary)])
|
||||
+ getCmdLine(dictionary)],
|
||||
sender=sender)
|
||||
|
||||
# True signifies that we can handle building dsym.
|
||||
return True
|
||||
|
||||
def buildDwarf(architecture=None, compiler=None, dictionary=None):
|
||||
def buildDwarf(sender=None, architecture=None, compiler=None, dictionary=None):
|
||||
"""Build the binaries with dwarf debug info."""
|
||||
lldbtest.system(["/bin/sh", "-c",
|
||||
"make clean" + getCmdLine(dictionary)
|
||||
+ "; make MAKE_DSYM=NO"
|
||||
+ getArchSpec(architecture) + getCCSpec(compiler)
|
||||
+ getCmdLine(dictionary)])
|
||||
+ getCmdLine(dictionary)],
|
||||
sender=sender)
|
||||
|
||||
# True signifies that we can handle building dsym.
|
||||
return True
|
||||
|
||||
def cleanup(dictionary=None):
|
||||
def cleanup(sender=None, dictionary=None):
|
||||
"""Perform a platform-specific cleanup after the test."""
|
||||
if os.path.isfile("Makefile"):
|
||||
lldbtest.system(["/bin/sh", "-c", "make clean" + getCmdLine(dictionary)]
|
||||
)
|
||||
lldbtest.system(["/bin/sh", "-c", "make clean"+getCmdLine(dictionary)],
|
||||
sender=sender)
|
||||
|
||||
# True signifies that we can handle building dsym.
|
||||
return True
|
||||
|
|
|
@ -24,7 +24,7 @@ class GenericTester(TestBase):
|
|||
|
||||
# First, capture the golden output emitted by the oracle, i.e., the
|
||||
# series of printf statements.
|
||||
go = system("./a.out")
|
||||
go = system("./a.out", sender=self)
|
||||
# This golden list contains a list of (variable, value) pairs extracted
|
||||
# from the golden output.
|
||||
gl = []
|
||||
|
@ -102,7 +102,7 @@ class GenericTester(TestBase):
|
|||
|
||||
# First, capture the golden output emitted by the oracle, i.e., the
|
||||
# series of printf statements.
|
||||
go = system("./a.out")
|
||||
go = system("./a.out", sender=self)
|
||||
# This golden list contains a list of (variable, value) pairs extracted
|
||||
# from the golden output.
|
||||
gl = []
|
||||
|
|
Loading…
Reference in New Issue