Skip to content

Commit

Permalink
Make the test runner understand Windows command shell execution.
Browse files Browse the repository at this point in the history
Currently, the test runner makes the assumption that it will run
commands through /bin/sh.  This is obviously not true on Windows,
so this patch abstracts this logic out somewhat.  Instead of
having the caller build the command string himself, the caller
will now pass in argument list of the form [[a, b], [c, d], ...]
which will get converted into a string of the form a b; c d or
a b && c d, depending on the platform.

Reviewed by: Todd Fiala

Differential Revision: http://reviews.llvm.org/D4590

git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@213669 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Zachary Turner committed Jul 22, 2014
1 parent 9ebe97c commit 1e36446
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def cleanup():
# Skip the following tests if the condition is met.
if self.getCompiler().endswith('gcc') and not self.getCompiler().endswith('llvm-gcc'):
import re
gcc_version_output = system([lldbutil.which(self.getCompiler()), "-v"])[1]
gcc_version_output = system([[lldbutil.which(self.getCompiler()), "-v"]])[1]
#print "my output:", gcc_version_output
for line in gcc_version_output.split(os.linesep):
m = re.search('\(Apple Inc\. build ([0-9]+)\)', line)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def test_lldb_invocation_with_single_quote_in_filename(self):
"""Test that 'lldb my_file_name' works where my_file_name is a string with a single quote char in it."""
import pexpect
self.buildDefault()
system(["/bin/sh", "-c", "cp a.out \"%s\"" % self.myexe])
system([["cp", "a.out", "\"%s\"" % self.myexe]])

# The default lldb prompt.
prompt = "(lldb) "
Expand Down
2 changes: 1 addition & 1 deletion test/lang/cpp/virtual/TestVirtual.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def virtual_madness_test(self):

# First, capture the golden output emitted by the oracle, i.e., the
# series of printf statements.
go = system("./a.out", sender=self)[0]
go = system([["./a.out"]], sender=self)[0]
# This golden list contains a list of "my_expr = 'value' pairs extracted
# from the golden output.
gl = []
Expand Down
28 changes: 15 additions & 13 deletions test/lldbtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def __exit__(self, type, value, tb):

# From 2.7's subprocess.check_output() convenience function.
# Return a tuple (stdoutdata, stderrdata).
def system(*popenargs, **kwargs):
def system(commands, **kwargs):
r"""Run an os command with arguments and return its output as a byte string.
If the exit code was non-zero it raises a CalledProcessError. The
Expand All @@ -257,20 +257,25 @@ def system(*popenargs, **kwargs):
# Assign the sender object to variable 'test' and remove it from kwargs.
test = kwargs.pop('sender', None)

separator = None
separator = " && " if os.name == "nt" else "; "
# [['make', 'clean', 'foo'], ['make', 'foo']] -> ['make clean foo', 'make foo']
commandList = [' '.join(x) for x in commands]
# ['make clean foo', 'make foo'] -> 'make clean foo; make foo'
shellCommand = separator.join(commandList)

if 'stdout' in kwargs:
raise ValueError('stdout argument not allowed, it will be overridden.')
process = Popen(stdout=PIPE, stderr=PIPE, *popenargs, **kwargs)
if 'shell' in kwargs and kwargs['shell']==False:
raise ValueError('shell=False not allowed')
process = Popen(shellCommand, stdout=PIPE, stderr=PIPE, shell=True, **kwargs)
pid = process.pid
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, "os command:", shellCommand
print >> sbuf, "with pid:", pid
print >> sbuf, "stdout:", output
print >> sbuf, "stderr:", error
Expand All @@ -280,7 +285,7 @@ def system(*popenargs, **kwargs):
if retcode:
cmd = kwargs.get("args")
if cmd is None:
cmd = popenargs[0]
cmd = shellCommand
raise CalledProcessError(retcode, cmd)
return (output, error)

Expand Down Expand Up @@ -963,8 +968,8 @@ def tearDown(self):

# This is for the case of directly spawning 'lldb' and interacting with it
# using pexpect.
import pexpect
if self.child and self.child.isalive():
import pexpect
with recording(self, traceAlways) as sbuf:
print >> sbuf, "tearing down the child process...."
try:
Expand Down Expand Up @@ -1103,9 +1108,6 @@ def dumpSessionInfo(self):
else:
benchmarks = False

# This records the compiler version used for the test.
system([self.getCompiler(), "-v"], sender=self)

dname = os.path.join(os.environ["LLDB_TEST"],
os.environ["LLDB_SESSION_DIRNAME"])
if not os.path.isdir(dname):
Expand Down Expand Up @@ -1144,7 +1146,7 @@ def getCompilerVersion(self):
version = 'unknown'

compiler = self.getCompiler()
version_output = system([which(compiler), "-v"])[1]
version_output = system([[which(compiler), "-v"]])[1]
for line in version_output.split(os.linesep):
m = re.search('version ([0-9\.]+)', line)
if m:
Expand Down
59 changes: 22 additions & 37 deletions test/plugins/builder_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,18 @@ def getArchFlag():
elif "gcc" in compiler:
archflag = "-m"
elif "clang" in compiler:
archflag = "-arch "
archflag = "-arch"
else:
archflag = None

return (" ARCHFLAG=" + archflag) if archflag else ""
return ("ARCHFLAG=" + archflag) if archflag else ""

def getMake():
"""Returns the name for GNU make"""
if platform.system() == "FreeBSD":
return "gmake "
return "gmake"
else:
return "make "
return "make"

def getArchSpec(architecture):
"""
Expand All @@ -54,8 +54,7 @@ def getArchSpec(architecture):
if not arch and "ARCH" in os.environ:
arch = os.environ["ARCH"]

# Note the leading space character.
return (" ARCH=" + arch) if arch else ""
return ("ARCH=" + arch) if arch else ""

def getCCSpec(compiler):
"""
Expand All @@ -65,9 +64,10 @@ def getCCSpec(compiler):
cc = compiler if compiler else None
if not cc and "CC" in os.environ:
cc = os.environ["CC"]

# Note the leading space character.
return (" CC=" + cc) if cc else ""
if cc:
return "CC=\"%s\"" % cc
else:
return ""

def getCmdLine(d):
"""
Expand All @@ -81,55 +81,40 @@ def getCmdLine(d):

cmdline = " ".join(["%s='%s'" % (k, v) for k, v in d.items()])

# Note the leading space character.
return " " + cmdline
return cmdline


def buildDefault(sender=None, architecture=None, compiler=None, dictionary=None, clean=True):
"""Build the binaries the default way."""
commands = []
if clean:
lldbtest.system(["/bin/sh", "-c",
getMake() + "clean" + getCmdLine(dictionary) + ";"
+ getMake()
+ getArchSpec(architecture) + getCCSpec(compiler)
+ getCmdLine(dictionary)],
sender=sender)
else:
lldbtest.system(["/bin/sh", "-c",
getMake() + getArchSpec(architecture) + getCCSpec(compiler)
+ getCmdLine(dictionary)],
sender=sender)
commands.append([getMake(), "clean", getCmdLine(dictionary)])
commands.append([getMake(), getArchSpec(architecture), getCCSpec(compiler), getCmdLine(dictionary)])

lldbtest.system(commands, sender=sender)

# True signifies that we can handle building default.
return True

def buildDwarf(sender=None, architecture=None, compiler=None, dictionary=None, clean=True):
"""Build the binaries with dwarf debug info."""
commands = []
if clean:
lldbtest.system(["/bin/sh", "-c",
getMake() + "clean" + getCmdLine(dictionary)
+ ";" + getMake() + "MAKE_DSYM=NO"
+ getArchSpec(architecture) + getCCSpec(compiler)
+ getCmdLine(dictionary)],
sender=sender)
else:
lldbtest.system(["/bin/sh", "-c",
getMake() + "MAKE_DSYM=NO"
+ getArchSpec(architecture) + getCCSpec(compiler)
+ getCmdLine(dictionary)],
sender=sender)
commands.append([getMake(), "clean", getCmdLine(dictionary)])
commands.append([getMake(), "MAKE_DSYM=NO", getArchSpec(architecture), getCCSpec(compiler), getCmdLine(dictionary)])

lldbtest.system(commands, sender=sender)
# True signifies that we can handle building dwarf.
return True

def cleanup(sender=None, dictionary=None):
"""Perform a platform-specific cleanup after the test."""
#import traceback
#traceback.print_stack()
commands = []
if os.path.isfile("Makefile"):
lldbtest.system(["/bin/sh", "-c",
getMake() + "clean" + getCmdLine(dictionary)],
sender=sender)
commands.append([getMake(), "clean", getCmdLine(dictionary)])

lldbtest.system(commands, sender=sender)
# True signifies that we can handle cleanup.
return True
18 changes: 6 additions & 12 deletions test/plugins/builder_darwin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,13 @@

def buildDsym(sender=None, architecture=None, compiler=None, dictionary=None, clean=True):
"""Build the binaries with dsym debug info."""
commands = []

if clean:
lldbtest.system(["/bin/sh", "-c",
"make clean" + getCmdLine(dictionary)
+ "; make MAKE_DSYM=YES"
+ getArchSpec(architecture) + getCCSpec(compiler)
+ getCmdLine(dictionary)],
sender=sender)
else:
lldbtest.system(["/bin/sh", "-c",
"make MAKE_DSYM=YES"
+ getArchSpec(architecture) + getCCSpec(compiler)
+ getCmdLine(dictionary)],
sender=sender)
commands.append(["make", "clean", getCmdLine(dictionary)])
commands.append(["make", "MAKE_DSYM=YES", getArchSpec(architecture), getCCSpec(compiler), getCmdLine(dictionary)])

lldbtest.system(commands, sender=sender)

# True signifies that we can handle building dsym.
return True
4 changes: 2 additions & 2 deletions test/source-manager/TestSourceManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ def move_and_then_display_source(self):
os.rename(main_c, main_c_hidden)

if self.TraceOn():
system(["ls"])
system(["ls", "hidden"])
system([["ls"]])
system([["ls", "hidden"]])

# Restore main.c after the test.
self.addTearDownHook(lambda: os.rename(main_c_hidden, main_c))
Expand Down

0 comments on commit 1e36446

Please sign in to comment.