[Lldb-commits] [lldb] eee887e - [lldb/test] Print build commands in trace mode

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Fri Oct 29 02:33:55 PDT 2021


Author: Pavel Labath
Date: 2021-10-29T11:33:31+02:00
New Revision: eee887e03551685bc03657a61c2f36ff1b522919

URL: https://github.com/llvm/llvm-project/commit/eee887e03551685bc03657a61c2f36ff1b522919
DIFF: https://github.com/llvm/llvm-project/commit/eee887e03551685bc03657a61c2f36ff1b522919.diff

LOG: [lldb/test] Print build commands in trace mode

Running tests with -t prints all lldb commands being run. It makes sense
to print all the build commands as well.

Differential Revision: https://reviews.llvm.org/D112212

Added: 
    lldb/test/API/test_utils/base/Makefile
    lldb/test/API/test_utils/base/TestBaseTest.py
    lldb/test/API/test_utils/base/return0.cpp

Modified: 
    lldb/packages/Python/lldbsuite/test/builders/builder.py
    lldb/packages/Python/lldbsuite/test/lldbtest.py
    lldb/packages/Python/lldbsuite/test_event/build_exception.py

Removed: 
    


################################################################################
diff  --git a/lldb/packages/Python/lldbsuite/test/builders/builder.py b/lldb/packages/Python/lldbsuite/test/builders/builder.py
index 8b17b585ae6c8..98057066f3f3c 100644
--- a/lldb/packages/Python/lldbsuite/test/builders/builder.py
+++ b/lldb/packages/Python/lldbsuite/test/builders/builder.py
@@ -82,15 +82,6 @@ def setOrAppendVariable(k, v):
 
         return cmdline
 
-    def runBuildCommands(self, commands):
-        try:
-            lldbtest.system(commands)
-        except subprocess.CalledProcessError as called_process_error:
-            # Convert to a build-specific error.
-            # We don't do that in lldbtest.system() since that
-            # is more general purpose.
-            raise build_exception.BuildError(called_process_error)
-
     def getArchSpec(self, architecture):
         """
         Helper function to return the key-value string to specify the architecture
@@ -140,11 +131,11 @@ def _getDebugInfoArgs(self, debug_info):
             return ["MAKE_DSYM=NO", "MAKE_GMODULES=YES"]
         return None
 
-    def build(self, debug_info, architecture=None, compiler=None,
+    def getBuildCommand(self, debug_info, architecture=None, compiler=None,
             dictionary=None, testdir=None, testname=None):
         debug_info_args = self._getDebugInfoArgs(debug_info)
         if debug_info_args is None:
-            return False
+            return None
 
         command_parts = [
             self.getMake(testdir, testname), debug_info_args, ["all"],
@@ -154,8 +145,7 @@ def build(self, debug_info, architecture=None, compiler=None,
             self.getCmdLine(dictionary)]
         command = list(itertools.chain(*command_parts))
 
-        self.runBuildCommands([command])
-        return True
+        return command
 
     def cleanup(self, dictionary=None):
         """Perform a platform-specific cleanup after the test."""

diff  --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py
index d8940b996f8dc..92d7887e670ac 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -45,6 +45,7 @@
 import re
 import shutil
 import signal
+import shlex
 from subprocess import *
 import sys
 import time
@@ -68,6 +69,7 @@
 from lldbsuite.support import encoded_file
 from lldbsuite.support import funcutils
 from lldbsuite.test.builders import get_builder
+from lldbsuite.test_event import build_exception
 
 # See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
 # LLDB_COMMAND_TRACE is set from '-t' option.
@@ -470,61 +472,6 @@ def launch(self, executable, args, extra_env):
     def terminate(self):
         lldb.remote_platform.Kill(self._pid)
 
-# From 2.7's subprocess.check_output() convenience function.
-# Return a tuple (stdoutdata, stderrdata).
-
-
-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
-    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'
-    """
-
-    output = ""
-    error = ""
-    for shellCommand in commands:
-        if 'stdout' in kwargs:
-            raise ValueError(
-                'stdout argument not allowed, it will be overridden.')
-        process = Popen(
-            shellCommand,
-            stdout=PIPE,
-            stderr=STDOUT,
-            **kwargs)
-        pid = process.pid
-        this_output, this_error = process.communicate()
-        retcode = process.poll()
-
-        if retcode:
-            cmd = kwargs.get("args")
-            if cmd is None:
-                cmd = shellCommand
-            cpe = CalledProcessError(retcode, cmd)
-            # Ensure caller can access the stdout/stderr.
-            cpe.lldb_extensions = {
-                "combined_output": this_output,
-                "command": shellCommand
-            }
-            raise cpe
-        output = output + this_output.decode("utf-8", errors='ignore')
-    return output
-
-
 def getsource_if_available(obj):
     """
     Return the text of the source code for an object if available.  Otherwise,
@@ -1335,11 +1282,10 @@ def getCompilerVersion(self):
             Supports: llvm, clang.
         """
         compiler = self.getCompilerBinary()
-        version_output = system([[compiler, "--version"]])
-        for line in version_output.split(os.linesep):
-            m = re.search('version ([0-9.]+)', line)
-            if m:
-                return m.group(1)
+        version_output = check_output([compiler, "--version"], errors="replace")
+        m = re.search('version ([0-9.]+)', version_output)
+        if m:
+            return m.group(1)
         return 'unknown'
 
     def getDwarfVersion(self):
@@ -1469,10 +1415,22 @@ def build(
         testname = self.getBuildDirBasename()
 
         module = builder_module()
-        if not module.build(debug_info, architecture, compiler, dictionary,
-                testdir, testname):
+        command = builder_module().getBuildCommand(debug_info, architecture,
+                compiler, dictionary, testdir, testname)
+        if command is None:
             raise Exception("Don't know how to build binary")
 
+        self.runBuildCommand(command)
+
+    def runBuildCommand(self, command):
+        self.trace(shlex.join(command))
+        try:
+            output = check_output(command, stderr=STDOUT, errors="replace")
+        except CalledProcessError as cpe:
+            raise build_exception.BuildError(cpe)
+        self.trace(output)
+
+
     # ==================================================
     # Build methods supported through a plugin interface
     # ==================================================
@@ -1619,7 +1577,7 @@ def yaml2obj(self, yaml_path, obj_path):
         if not yaml2obj_bin:
             self.assertTrue(False, "No valid yaml2obj executable specified")
         command = [yaml2obj_bin, "-o=%s" % obj_path, yaml_path]
-        system([command])
+        self.runBuildCommand(command)
 
     def getBuildFlags(
             self,

diff  --git a/lldb/packages/Python/lldbsuite/test_event/build_exception.py b/lldb/packages/Python/lldbsuite/test_event/build_exception.py
index e08b632eb9a91..e1924ad86cde5 100644
--- a/lldb/packages/Python/lldbsuite/test_event/build_exception.py
+++ b/lldb/packages/Python/lldbsuite/test_event/build_exception.py
@@ -1,10 +1,11 @@
+import shlex
+
 class BuildError(Exception):
 
     def __init__(self, called_process_error):
         super(BuildError, self).__init__("Error when building test subject")
-        self.command = called_process_error.lldb_extensions.get(
-            "command", "<command unavailable>")
-        self.build_error = called_process_error.lldb_extensions["combined_output"]
+        self.command = shlex.join(called_process_error.cmd)
+        self.build_error = called_process_error.output
 
     def __str__(self):
         return self.format_build_error(self.command, self.build_error)
@@ -12,4 +13,4 @@ def __str__(self):
     @staticmethod
     def format_build_error(command, command_output):
         return "Error when building test subject.\n\nBuild Command:\n{}\n\nBuild Command Output:\n{}".format(
-            command, command_output.decode("utf-8", errors='ignore'))
+            command, command_output)

diff  --git a/lldb/test/API/test_utils/base/Makefile b/lldb/test/API/test_utils/base/Makefile
new file mode 100644
index 0000000000000..22f1051530f87
--- /dev/null
+++ b/lldb/test/API/test_utils/base/Makefile
@@ -0,0 +1 @@
+include Makefile.rules

diff  --git a/lldb/test/API/test_utils/base/TestBaseTest.py b/lldb/test/API/test_utils/base/TestBaseTest.py
new file mode 100644
index 0000000000000..4aceca7d5fb57
--- /dev/null
+++ b/lldb/test/API/test_utils/base/TestBaseTest.py
@@ -0,0 +1,35 @@
+"""
+Test TestBase test functions.
+"""
+
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test_event import build_exception
+import six
+
+class TestBuildMethod(Base):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def setUp(self):
+        super().setUp()
+        self._traces = []
+        self.traceAlways = True
+
+    # override the parent trace method
+    def trace(self, *args, **kwargs):
+        io = six.StringIO()
+        print(*args, file=io, **kwargs)
+        self._traces.append(io.getvalue())
+
+    def test_build_fails_helpfully(self):
+        try:
+            self.build(dictionary={"CXX_SOURCES": "nonexisting-file.cpp"})
+        except build_exception.BuildError as e:
+            self.assertIn("nonexisting-file.cpp", str(e))
+        else:
+            self.fail("BuildError not raised!")
+
+    def test_build_logs_traces(self):
+        self.build(dictionary={"CXX_SOURCES": "return0.cpp"})
+        self.assertIn("CXX_SOURCES", self._traces[0])
+        self.assertIn("return0.o", self._traces[1])

diff  --git a/lldb/test/API/test_utils/base/return0.cpp b/lldb/test/API/test_utils/base/return0.cpp
new file mode 100644
index 0000000000000..76e8197013aab
--- /dev/null
+++ b/lldb/test/API/test_utils/base/return0.cpp
@@ -0,0 +1 @@
+int main() { return 0; }


        


More information about the lldb-commits mailing list