[Lldb-commits] [lldb] fc41013 - [lldb/Reproducers] Capture reproducers from the API test suite.

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Tue Apr 14 09:24:30 PDT 2020


Author: Jonas Devlieghere
Date: 2020-04-14T09:24:23-07:00
New Revision: fc410138939fbc98d7eb700e0e898500a00efc4d

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

LOG: [lldb/Reproducers] Capture reproducers from the API test suite.

Make it possible to capture reproducers from the API test suite. Given
the symmetry between capture and replay, this patch also adds the
necessary code for replay. For now this is a NO-OP until the
corresponding reproducer instrumentation changes land.

For more info please refer to the RFC on lldb-dev:
http://lists.llvm.org/pipermail/lldb-dev/2020-April/016100.html

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

Added: 
    lldb/bindings/interface/SBReproducer.i

Modified: 
    lldb/bindings/headers.swig
    lldb/bindings/interfaces.swig
    lldb/include/lldb/API/SBReproducer.h
    lldb/packages/Python/lldbsuite/test/configuration.py
    lldb/packages/Python/lldbsuite/test/decorators.py
    lldb/packages/Python/lldbsuite/test/dotest.py
    lldb/packages/Python/lldbsuite/test/dotest_args.py
    lldb/source/API/SBReproducer.cpp
    lldb/test/API/functionalities/reproducers/attach/TestReproducerAttach.py
    lldb/test/API/lit.cfg.py
    lldb/test/API/lldbtest.py

Removed: 
    


################################################################################
diff  --git a/lldb/bindings/headers.swig b/lldb/bindings/headers.swig
index 7371e1a3873b..42ccd36c9607 100644
--- a/lldb/bindings/headers.swig
+++ b/lldb/bindings/headers.swig
@@ -47,6 +47,7 @@
 #include "lldb/API/SBProcessInfo.h"
 #include "lldb/API/SBQueue.h"
 #include "lldb/API/SBQueueItem.h"
+#include "lldb/API/SBReproducer.h"
 #include "lldb/API/SBSection.h"
 #include "lldb/API/SBSourceManager.h"
 #include "lldb/API/SBStream.h"

diff  --git a/lldb/bindings/interface/SBReproducer.i b/lldb/bindings/interface/SBReproducer.i
new file mode 100644
index 000000000000..e976863f15c5
--- /dev/null
+++ b/lldb/bindings/interface/SBReproducer.i
@@ -0,0 +1,17 @@
+//===-- SWIG Interface for SBReproducer--------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+namespace lldb {
+class SBReproducer
+{
+    public:
+        static const char *Capture(const char *path);
+        static const char *PassiveReplay(const char *path);
+        static bool SetAutoGenerate(bool b);
+};
+}

diff  --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig
index e906bb9e5656..025a3e33c024 100644
--- a/lldb/bindings/interfaces.swig
+++ b/lldb/bindings/interfaces.swig
@@ -54,6 +54,7 @@
 %include "./interface/SBProcessInfo.i"
 %include "./interface/SBQueue.i"
 %include "./interface/SBQueueItem.i"
+%include "./interface/SBReproducer.i"
 %include "./interface/SBSection.i"
 %include "./interface/SBSourceManager.i"
 %include "./interface/SBStream.i"

diff  --git a/lldb/include/lldb/API/SBReproducer.h b/lldb/include/lldb/API/SBReproducer.h
index 0a25bcbf541e..5a298d1bcf43 100644
--- a/lldb/include/lldb/API/SBReproducer.h
+++ b/lldb/include/lldb/API/SBReproducer.h
@@ -22,6 +22,7 @@ class LLDB_API SBReproducer {
   static const char *Capture(const char *path);
   static const char *Replay(const char *path);
   static const char *Replay(const char *path, bool skip_version_check);
+  static const char *PassiveReplay(const char *path);
   static const char *GetPath();
   static bool SetAutoGenerate(bool b);
   static bool Generate();

diff  --git a/lldb/packages/Python/lldbsuite/test/configuration.py b/lldb/packages/Python/lldbsuite/test/configuration.py
index ce6f46ae476f..9d6943813cb8 100644
--- a/lldb/packages/Python/lldbsuite/test/configuration.py
+++ b/lldb/packages/Python/lldbsuite/test/configuration.py
@@ -87,7 +87,6 @@
 
 # Set this flag if there is any session info dumped during the test run.
 sdir_has_content = False
-
 # svn_info stores the output from 'svn info lldb.base.dir'.
 svn_info = ''
 
@@ -124,6 +123,10 @@
 results_formatter_options = None
 test_result = None
 
+# Reproducers
+capture_path = None
+replay_path = None
+
 # Test rerun configuration vars
 rerun_all_issues = False
 

diff  --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py
index cc28ae901634..65b63b4b40a8 100644
--- a/lldb/packages/Python/lldbsuite/test/decorators.py
+++ b/lldb/packages/Python/lldbsuite/test/decorators.py
@@ -854,3 +854,11 @@ def is_asan():
             return "ASAN unsupported"
         return None
     return skipTestIfFn(is_asan)(func)
+
+def skipIfReproducer(func):
+    """Skip this test if the environment is set up to run LLDB with reproducers."""
+    def is_reproducer():
+        if configuration.capture_path or configuration.replay_path:
+            return "reproducers unsupported"
+        return None
+    return skipTestIfFn(is_reproducer)(func)

diff  --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py
index 31c617c1f311..b5666ecded2e 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest.py
@@ -429,6 +429,17 @@ def parseOptionsAndInitTestdirs():
         configuration.results_formatter_name = (
             "lldbsuite.test_event.formatter.results_formatter.ResultsFormatter")
 
+    # Reproducer arguments
+    if args.capture_path and args.replay_path:
+        logging.error('Cannot specify both a capture and a replay path.')
+        sys.exit(-1)
+
+    if args.capture_path:
+        configuration.capture_path = args.capture_path
+
+    if args.replay_path:
+        configuration.replay_path = args.replay_path
+
     # rerun-related arguments
     configuration.rerun_all_issues = args.rerun_all_issues
 
@@ -955,8 +966,19 @@ def run_suite():
     setupSysPath()
 
     import lldbconfig
+    if configuration.capture_path or configuration.replay_path:
+        lldbconfig.INITIALIZE = False
     import lldb
 
+    if configuration.capture_path:
+        lldb.SBReproducer.Capture(configuration.capture_path)
+        lldb.SBReproducer.SetAutoGenerate(True)
+    elif configuration.replay_path:
+        lldb.SBReproducer.PassiveReplay(configuration.replay_path)
+
+    if not lldbconfig.INITIALIZE:
+        lldb.SBDebugger.Initialize()
+
     # Use host platform by default.
     lldb.selected_platform = lldb.SBPlatform.GetHostPlatform()
 

diff  --git a/lldb/packages/Python/lldbsuite/test/dotest_args.py b/lldb/packages/Python/lldbsuite/test/dotest_args.py
index 385f65f42583..ad9508d70394 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest_args.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest_args.py
@@ -196,6 +196,17 @@ def create_parser():
         metavar='platform-working-dir',
         help='The directory to use on the remote platform.')
 
+    # Reproducer options
+    group = parser.add_argument_group('Reproducer options')
+    group.add_argument(
+        '--capture-path',
+        metavar='reproducer path',
+        help='The reproducer capture path')
+    group.add_argument(
+        '--replay-path',
+        metavar='reproducer path',
+        help='The reproducer replay path')
+
     # Test-suite behaviour
     group = parser.add_argument_group('Runtime behaviour options')
     X('-d', 'Suspend the process after launch to wait indefinitely for a debugger to attach')

diff  --git a/lldb/source/API/SBReproducer.cpp b/lldb/source/API/SBReproducer.cpp
index 15ad887f11f3..ba9127962ebd 100644
--- a/lldb/source/API/SBReproducer.cpp
+++ b/lldb/source/API/SBReproducer.cpp
@@ -124,6 +124,15 @@ const char *SBReproducer::Capture(const char *path) {
   return nullptr;
 }
 
+const char *SBReproducer::PassiveReplay(const char *path) {
+  static std::string error;
+  if (auto e = Reproducer::Initialize(ReproducerMode::Replay, FileSpec(path))) {
+    error = llvm::toString(std::move(e));
+    return error.c_str();
+  }
+  return nullptr;
+}
+
 const char *SBReproducer::Replay(const char *path) {
   return SBReproducer::Replay(path, false);
 }

diff  --git a/lldb/test/API/functionalities/reproducers/attach/TestReproducerAttach.py b/lldb/test/API/functionalities/reproducers/attach/TestReproducerAttach.py
index 968268d6838b..70f8d5842fe4 100644
--- a/lldb/test/API/functionalities/reproducers/attach/TestReproducerAttach.py
+++ b/lldb/test/API/functionalities/reproducers/attach/TestReproducerAttach.py
@@ -20,6 +20,7 @@ class ReproducerAttachTestCase(TestBase):
     @skipIfWindows
     @skipIfRemote
     @skipIfiOSSimulator
+    @skipIfReproducer
     def test_reproducer_attach(self):
         """Test thread creation after process attach."""
         exe = '%s_%d' % (self.testMethodName, os.getpid())

diff  --git a/lldb/test/API/lit.cfg.py b/lldb/test/API/lit.cfg.py
index 10df5600db4c..835e69e39e32 100644
--- a/lldb/test/API/lit.cfg.py
+++ b/lldb/test/API/lit.cfg.py
@@ -60,6 +60,17 @@ def find_shlibpath_var():
   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:
+  lit_config.note("Running API tests in {} mode.".format(lldb_repro_mode))
+  if lldb_repro_mode == 'capture':
+    config.available_features.add('lldb-repro-capture')
+  elif lldb_repro_mode == 'replay':
+    config.available_features.add('lldb-repro-replay')
+
 # Clean the module caches in the test build directory. This is necessary in an
 # incremental build whenever clang changes underneath, so doing it once per
 # lit.py invocation is close enough.

diff  --git a/lldb/test/API/lldbtest.py b/lldb/test/API/lldbtest.py
index 94c0588fd9e6..0831af677829 100644
--- a/lldb/test/API/lldbtest.py
+++ b/lldb/test/API/lldbtest.py
@@ -1,6 +1,6 @@
 from __future__ import absolute_import
 import os
-
+import tempfile
 import subprocess
 import sys
 
@@ -67,14 +67,15 @@ def execute(self, test, litConfig):
         # python exe as the first parameter of the command.
         cmd = [sys.executable] + self.dotest_cmd + [testPath, '-p', testFile]
 
+        builddir = getBuildDir(cmd)
+        mkdir_p(builddir)
+
         # The macOS system integrity protection (SIP) doesn't allow injecting
         # libraries into system binaries, but this can be worked around by
         # copying the binary into a 
diff erent location.
         if 'DYLD_INSERT_LIBRARIES' in test.config.environment and \
                 (sys.executable.startswith('/System/') or \
                 sys.executable.startswith('/usr/bin/')):
-            builddir = getBuildDir(cmd)
-            mkdir_p(builddir)
             copied_python = os.path.join(builddir, 'copied-system-python')
             if not os.path.isfile(copied_python):
                 import shutil, subprocess
@@ -86,6 +87,16 @@ def execute(self, test, litConfig):
                 shutil.copy(python, copied_python)
             cmd[0] = copied_python
 
+        if 'lldb-repro-capture' in test.config.available_features or \
+           'lldb-repro-replay' in test.config.available_features:
+            reproducer_root = os.path.join(builddir, 'reproducers')
+            mkdir_p(reproducer_root)
+            reproducer_path = os.path.join(reproducer_root, testFile)
+            if 'lldb-repro-capture' in test.config.available_features:
+                cmd.extend(['--capture-path', reproducer_path])
+            else:
+                cmd.extend(['--replay-path', reproducer_path])
+
         timeoutInfo = None
         try:
             out, err, exitCode = lit.util.executeCommand(


        


More information about the lldb-commits mailing list