[lldb/Reproducers] Add a flag to always generating a reproducer
authorJonas Devlieghere <jonas@devlieghere.com>
Thu, 16 Jan 2020 03:44:46 +0000 (19:44 -0800)
committerJonas Devlieghere <jonas@devlieghere.com>
Thu, 16 Jan 2020 03:45:54 +0000 (19:45 -0800)
Add a flag which always generates a reproducer when normally it would be
discarded. This is meant for testing purposes to capture a debugger
session without modification the session itself.

lldb/include/lldb/API/SBReproducer.h
lldb/include/lldb/Utility/Reproducer.h
lldb/source/API/SBReproducer.cpp
lldb/source/Utility/Reproducer.cpp
lldb/test/Shell/Reproducer/TestDriverOptions.test
lldb/tools/driver/Driver.cpp
lldb/tools/driver/Options.td

index 93d78f55fd76a91cf88ead8a114847852c4ea1fb..0a25bcbf541e7da4ae588fd978ca6797583a3fc0 100644 (file)
@@ -23,6 +23,7 @@ public:
   static const char *Replay(const char *path);
   static const char *Replay(const char *path, bool skip_version_check);
   static const char *GetPath();
+  static bool SetAutoGenerate(bool b);
   static bool Generate();
 };
 
index 0d23fe8571ffb098465e37841a8ce54812e8de21..0524bcf6b24d5c8483677d0bcbc33cbaa5917959 100644 (file)
@@ -231,6 +231,9 @@ public:
   /// might need to clean up files already written to disk.
   void Discard();
 
+  /// Enable or disable auto generate.
+  void SetAutoGenerate(bool b);
+
   /// Create and register a new provider.
   template <typename T> T *Create() {
     std::unique_ptr<ProviderBase> provider = std::make_unique<T>(m_root);
@@ -272,6 +275,9 @@ private:
 
   /// Flag to ensure that we never call both keep and discard.
   bool m_done = false;
+
+  /// Flag to auto generate a reproducer when it would otherwise be discarded.
+  bool m_auto_generate = false;
 };
 
 class Loader final {
index 3d2de0727444835923595eb68d314e50b95ca92b..6d78eba52efb58983e98a08f574456ec4ad79ce7 100644 (file)
@@ -178,6 +178,15 @@ bool SBReproducer::Generate() {
   return false;
 }
 
+bool SBReproducer::SetAutoGenerate(bool b) {
+  auto &r = Reproducer::Instance();
+  if (auto generator = r.GetGenerator()) {
+    generator->SetAutoGenerate(b);
+    return true;
+  }
+  return false;
+}
+
 const char *SBReproducer::GetPath() {
   static std::string path;
   auto &r = Reproducer::Instance();
index e243d784d185b44bde5cdf092126f1b2ad33207b..8957763b7fd54145cf83e223c30da8ec879c4226 100644 (file)
@@ -167,8 +167,12 @@ Generator::Generator(FileSpec root) : m_root(MakeAbsolute(std::move(root))) {
 }
 
 Generator::~Generator() {
-  if (!m_done)
-    Discard();
+  if (!m_done) {
+    if (m_auto_generate)
+      Keep();
+    else
+      Discard();
+  }
 }
 
 ProviderBase *Generator::Register(std::unique_ptr<ProviderBase> provider) {
@@ -199,6 +203,8 @@ void Generator::Discard() {
   llvm::sys::fs::remove_directories(m_root.GetPath());
 }
 
+void Generator::SetAutoGenerate(bool b) { m_auto_generate = b; }
+
 const FileSpec &Generator::GetRoot() const { return m_root; }
 
 void Generator::AddProvidersToIndex() {
index 4b5dfbf063cad4f693f5f1cb074276fa90478abc..e249a401d15b4716746c81aabd421dfb33760f43 100644 (file)
 # RUN: %lldb --capture --capture-path %t.repro -b -o 'reproducer status' 2>&1 | FileCheck %s --check-prefix NO-WARNING --check-prefix STATUS-CAPTURE
 # RUN: %lldb --capture -b -o 'reproducer status' 2>&1 | FileCheck %s --check-prefix NO-WARNING --check-prefix STATUS-CAPTURE
 # RUN: %lldb --capture-path %t.repro -b -o 'reproducer status' 2>&1 | FileCheck %s --check-prefix WARNING --check-prefix STATUS-CAPTURE
+# RUN: %lldb --capture-path %t.repro -b -o 'reproducer status' --reproducer-auto-generate  2>&1 | FileCheck %s --check-prefix WARNING2
 #
 # NO-WARNING-NOT: warning: -capture-path specified without -capture
 # WARNING: warning: -capture-path specified without -capture
+# WARNING2: warning: -reproducer-auto-generate specified without -capture
 # STATUS-CAPTURE: Reproducer is in capture mode.
+
+# Check auto generate.
+# RUN: rm -rf %t.repro
+# RUN: %lldb --capture --capture-path %t.repro -b --reproducer-auto-generate -o 'reproducer status' 2>&1 | FileCheck %s --check-prefix NO-WARNING
+# RUN: cat %t.repro/index.yaml
index 73874389aa1bb6c8ad5df7cf12e7bcbb3cf12bd2..670361787f1feb1c09ce5d59b293c1f4a07c60a8 100644 (file)
@@ -807,8 +807,14 @@ llvm::Optional<int> InitializeReproducer(opt::InputArgList &input_args) {
   }
 
   bool capture = input_args.hasArg(OPT_capture);
+  bool auto_generate = input_args.hasArg(OPT_auto_generate);
   auto *capture_path = input_args.getLastArg(OPT_capture_path);
 
+  if (auto_generate && !capture) {
+    WithColor::warning()
+        << "-reproducer-auto-generate specified without -capture\n";
+  }
+
   if (capture || capture_path) {
     if (capture_path) {
       if (!capture)
@@ -824,6 +830,8 @@ llvm::Optional<int> InitializeReproducer(opt::InputArgList &input_args) {
         return 1;
       }
     }
+    if (auto_generate)
+      SBReproducer::SetAutoGenerate(true);
   }
 
   return llvm::None;
index c237f568f64c404b819cd5d45febd305ba1e68af..e459a153d61854ba8e8c850c3d7953e178066775 100644 (file)
@@ -234,5 +234,7 @@ def replay: Separate<["--", "-"], "replay">,
   HelpText<"Tells the debugger to replay a reproducer from <filename>.">;
 def skip_version_check: F<"reproducer-skip-version-check">,
   HelpText<"Skip the reproducer version check.">;
+def auto_generate: F<"reproducer-auto-generate">,
+  HelpText<"Generate reproducer on exit.">;
 
 def REM : R<["--"], "">;