[Lldb-commits] [lldb] 67420f1 - [lldb/Util] Add a utility to run transparently capture and replay tests.

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Mon Jan 20 10:30:29 PST 2020


Author: Jonas Devlieghere
Date: 2020-01-20T10:30:19-08:00
New Revision: 67420f1b0e9c673ee638f2680fa83f468019004f

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

LOG: [lldb/Util] Add a utility to run transparently capture and replay tests.

This patch introduces a small new utility (lldb-repro) to transparently
capture and replay debugger sessions through the command line driver.
Its used to test the reproducers by running the test suite twice.

During the first run, it captures a reproducer for every lldb invocation
and saves it to a well-know location derived from the arguments and
current working directory. During the second run, the test suite is run
again but this time every invocation of lldb replays the previously
recorded session.

Differential revision: https://reviews.llvm.org/D72823

Added: 
    lldb/utils/lldb-repro/CMakeLists.txt
    lldb/utils/lldb-repro/lldb-repro.py

Modified: 
    lldb/test/Shell/Reproducer/lit.local.cfg
    lldb/test/Shell/helper/toolchain.py
    lldb/test/Shell/lit.cfg.py
    lldb/utils/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/lldb/test/Shell/Reproducer/lit.local.cfg b/lldb/test/Shell/Reproducer/lit.local.cfg
index dbb37b199d78..51a744a6607c 100644
--- a/lldb/test/Shell/Reproducer/lit.local.cfg
+++ b/lldb/test/Shell/Reproducer/lit.local.cfg
@@ -2,5 +2,9 @@
 if 'LLVM_DISABLE_CRASH_REPORT' in config.environment:
   del config.environment['LLVM_DISABLE_CRASH_REPORT']
 
+# Unset the always capture environment override.
 if 'LLDB_CAPTURE_REPRODUCER' in config.environment:
   del config.environment['LLDB_CAPTURE_REPRODUCER']
+
+if config.skip_reproducer_test:
+  config.unsupported = True

diff  --git a/lldb/test/Shell/helper/toolchain.py b/lldb/test/Shell/helper/toolchain.py
index 9d144bb5992a..97fdb7e0f188 100644
--- a/lldb/test/Shell/helper/toolchain.py
+++ b/lldb/test/Shell/helper/toolchain.py
@@ -9,6 +9,11 @@
 from lit.llvm.subst import FindTool
 from lit.llvm.subst import ToolSubst
 
+
+def _get_lldb_init_path(config):
+    return os.path.join(config.test_exec_root, 'Shell', 'lit-lldb-init')
+
+
 def use_lldb_substitutions(config):
     # Set up substitutions for primary tools.  These tools must come from config.lldb_tools_dir
     # which is basically the build output directory.  We do not want to find these in path or
@@ -29,7 +34,7 @@ def use_lldb_substitutions(config):
     if config.llvm_libs_dir:
         build_script_args.append('--libs-dir={0}'.format(config.llvm_libs_dir))
 
-    lldb_init = os.path.join(config.test_exec_root, 'Shell', 'lit-lldb-init')
+    lldb_init = _get_lldb_init_path(config)
 
     primary_tools = [
         ToolSubst('%lldb',
@@ -135,3 +140,18 @@ def use_support_substitutions(config):
                      'llvm-objcopy', 'lli']
     additional_tool_dirs += [config.lldb_tools_dir, config.llvm_tools_dir]
     llvm_config.add_tool_substitutions(support_tools, additional_tool_dirs)
+
+
+def use_lldb_repro_substitutions(config, mode):
+    lldb_init = _get_lldb_init_path(config)
+    substitutions = [
+        ToolSubst(
+            '%lldb',
+            command=FindTool('lldb-repro'),
+            extra_args=[mode, '--no-lldbinit', '-S', lldb_init]),
+        ToolSubst(
+            '%lldb-init',
+            command=FindTool('lldb-repro'),
+            extra_args=[mode, '-S', lldb_init]),
+    ]
+    llvm_config.add_tool_substitutions(substitutions)

diff  --git a/lldb/test/Shell/lit.cfg.py b/lldb/test/Shell/lit.cfg.py
index cc6155f05cd2..271ca7b2a138 100644
--- a/lldb/test/Shell/lit.cfg.py
+++ b/lldb/test/Shell/lit.cfg.py
@@ -38,16 +38,24 @@
 # test_exec_root: The root path where tests should be run.
 config.test_exec_root = os.path.join(config.lldb_obj_root, 'test')
 
-# Propagate LLDB_CAPTURE_REPRODUCER
+# Propagate reproducer environment vars.
 if 'LLDB_CAPTURE_REPRODUCER' in os.environ:
   config.environment['LLDB_CAPTURE_REPRODUCER'] = os.environ[
       'LLDB_CAPTURE_REPRODUCER']
 
+# Support running the test suite under the lldb-repro wrapper. This makes it
+# possible to capture a test suite run and then rerun all the test from the
+# just captured reproducer.
+lldb_repro_mode = lit_config.params.get('lldb-run-with-repro', None)
+if lldb_repro_mode:
+  config.skip_reproducer_test = True
+  lit_config.note("Running Shell test with lldb-repo in {} mode.".format(lldb_repro_mode))
+  toolchain.use_lldb_repro_substitutions(config, lldb_repro_mode)
+
 llvm_config.use_default_substitutions()
 toolchain.use_lldb_substitutions(config)
 toolchain.use_support_substitutions(config)
 
-
 if re.match(r'^arm(hf.*-linux)|(.*-linux-gnuabihf)', config.target_triple):
     config.available_features.add("armhf-linux")
 

diff  --git a/lldb/utils/CMakeLists.txt b/lldb/utils/CMakeLists.txt
index d08f66f7b6c5..00c81e655b75 100644
--- a/lldb/utils/CMakeLists.txt
+++ b/lldb/utils/CMakeLists.txt
@@ -1,2 +1,3 @@
 add_subdirectory(lit-cpuid)
 add_subdirectory(lldb-dotest)
+add_subdirectory(lldb-repro)

diff  --git a/lldb/utils/lldb-repro/CMakeLists.txt b/lldb/utils/lldb-repro/CMakeLists.txt
new file mode 100644
index 000000000000..0bfcaaa0062e
--- /dev/null
+++ b/lldb/utils/lldb-repro/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_custom_target(lldb-repro)
+add_dependencies(lldb-repro lldb-test-deps)
+set_target_properties(lldb-repro PROPERTIES FOLDER "lldb utils")
+configure_file(lldb-repro.py ${LLVM_RUNTIME_OUTPUT_INTDIR}/lldb-repro COPYONLY)

diff  --git a/lldb/utils/lldb-repro/lldb-repro.py b/lldb/utils/lldb-repro/lldb-repro.py
new file mode 100644
index 000000000000..c925c474619e
--- /dev/null
+++ b/lldb/utils/lldb-repro/lldb-repro.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+"""lldb-repro
+
+lldb-repro is a utility to transparently capture and replay debugger sessions
+through the command line driver. Its used to test the reproducers by running
+the test suite twice.
+
+During the first run, with 'capture' as its first argument, it captures a
+reproducer for every lldb invocation and saves it to a well-know location
+derived from the arguments and current working directory.
+
+During the second run, with 'replay' as its first argument, the test suite is
+run again but this time every invocation of lldb replays the previously
+recorded session.
+"""
+
+import sys
+import os
+import tempfile
+import subprocess
+
+
+def help():
+    print("usage: {} capture|replay [args]".fmt(sys.argv[0]))
+
+
+def main():
+    if len(sys.argv) < 3:
+        help()
+        return 1
+
+    # Compute a hash based on the input arguments and the current working
+    # directory.
+    args = ' '.join(sys.argv[3:])
+    cwd = os.getcwd()
+    input_hash = str(hash((cwd, args)))
+
+    # Use the hash to "uniquely" identify a reproducer path.
+    reproducer_path = os.path.join(tempfile.gettempdir(), input_hash)
+
+    # Create a new lldb invocation with capture or replay enabled.
+    lldb = os.path.join(os.path.dirname(sys.argv[0]), 'lldb')
+    new_args = [sys.argv[1]]
+    if sys.argv[2] == "replay":
+        new_args.extend(['--replay', reproducer_path])
+    elif sys.argv[2] == "capture":
+        new_args.extend([
+            '--capture', '--capture-path', reproducer_path,
+            '--reproducer-auto-generate'
+        ])
+        new_args.extend(sys.argv[1:])
+    else:
+        help()
+        return 1
+
+    return subprocess.call(new_args)
+
+
+if __name__ == '__main__':
+    exit(main())


        


More information about the lldb-commits mailing list