[Lldb-commits] [lldb] 5dca059 - [lldb] Add a SubsystemRAII that takes care of calling Initialize and Terminate in the unit tests

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Mon Dec 23 01:38:49 PST 2019


Author: Raphael Isemann
Date: 2019-12-23T10:38:25+01:00
New Revision: 5dca0596a959217a1c18858a62ed35245a4c42b4

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

LOG: [lldb] Add a SubsystemRAII that takes care of calling Initialize and Terminate in the unit tests

Summary:
Many of our tests need to initialize certain subsystems/plugins of LLDB such as
`FileSystem` or `HostInfo` by calling their static `Initialize` functions before the
test starts and then calling `::Terminate` after the test is done (in reverse order).
This adds a lot of error-prone boilerplate code to our testing code.

This patch adds a RAII called SubsystemRAII that ensures that we always call
::Initialize and then call ::Terminate after the test is done (and that the Terminate
calls are always in the reverse order of the ::Initialize calls). It also gets rid of
all of the boilerplate that we had for these calls.

Per-fixture initialization is still not very nice with this approach as it would
require some kind of static unique_ptr that gets manually assigned/reseted
from the gtest SetUpTestCase/TearDownTestCase functions. Because of that
I changed all per-fixture setup to now do per-test setup which can be done
by just having the SubsystemRAII as a member of the test fixture. This change doesn't
influence our normal test runtime as LIT anyway runs each test case separately
(and the Initialize/Terminate calls are anyway not very expensive). It will however
make running all tests in a single executable slightly slower.

Reviewers: labath, JDevlieghere, martong, espindola, shafik

Reviewed By: labath

Subscribers: mgorny, rnkovacs, emaste, MaskRay, abidh, lldb-commits

Tags: #lldb

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

Added: 
    lldb/unittests/TestingSupport/SubsystemRAII.h
    lldb/unittests/Utility/SubsystemRAIITest.cpp

Modified: 
    lldb/unittests/Core/MangledTest.cpp
    lldb/unittests/Editline/EditlineTest.cpp
    lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp
    lldb/unittests/Expression/ClangParserTest.cpp
    lldb/unittests/Expression/CppModuleConfigurationTest.cpp
    lldb/unittests/Expression/DWARFExpressionTest.cpp
    lldb/unittests/Host/ConnectionFileDescriptorTest.cpp
    lldb/unittests/Host/HostInfoTest.cpp
    lldb/unittests/Host/MainLoopTest.cpp
    lldb/unittests/Host/SocketAddressTest.cpp
    lldb/unittests/Host/SocketTest.cpp
    lldb/unittests/Interpreter/TestCompletion.cpp
    lldb/unittests/Language/Highlighting/HighlighterTest.cpp
    lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp
    lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp
    lldb/unittests/Process/minidump/MinidumpParserTest.cpp
    lldb/unittests/Symbol/LocateSymbolFileTest.cpp
    lldb/unittests/Symbol/TestClangASTContext.cpp
    lldb/unittests/Symbol/TestClangASTImporter.cpp
    lldb/unittests/Symbol/TestDWARFCallFrameInfo.cpp
    lldb/unittests/Symbol/TestLineEntry.cpp
    lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
    lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp
    lldb/unittests/Target/ModuleCacheTest.cpp
    lldb/unittests/Utility/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/lldb/unittests/Core/MangledTest.cpp b/lldb/unittests/Core/MangledTest.cpp
index 2e1f3db8abeb..ffa7b1e5852a 100644
--- a/lldb/unittests/Core/MangledTest.cpp
+++ b/lldb/unittests/Core/MangledTest.cpp
@@ -8,6 +8,7 @@
 
 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
 #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 
 #include "lldb/Core/Mangled.h"
@@ -58,10 +59,8 @@ TEST(MangledTest, EmptyForInvalidName) {
 }
 
 TEST(MangledTest, NameIndexes_FindFunctionSymbols) {
-  FileSystem::Initialize();
-  HostInfo::Initialize();
-  ObjectFileELF::Initialize();
-  SymbolFileSymtab::Initialize();
+  SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab>
+      subsystems;
 
   auto ExpectedFile = TestFile::fromYaml(R"(
 --- !ELF
@@ -251,9 +250,4 @@ TEST(MangledTest, NameIndexes_FindFunctionSymbols) {
   EXPECT_EQ(0, Count("_Z12undemangableEvx42", eFunctionNameTypeMethod));
   EXPECT_EQ(0, Count("undemangable", eFunctionNameTypeBase));
   EXPECT_EQ(0, Count("undemangable", eFunctionNameTypeMethod));
-
-  SymbolFileSymtab::Terminate();
-  ObjectFileELF::Terminate();
-  HostInfo::Terminate();
-  FileSystem::Terminate();
 }

diff  --git a/lldb/unittests/Editline/EditlineTest.cpp b/lldb/unittests/Editline/EditlineTest.cpp
index 7fdd96657d86..41f8e471256a 100644
--- a/lldb/unittests/Editline/EditlineTest.cpp
+++ b/lldb/unittests/Editline/EditlineTest.cpp
@@ -20,6 +20,7 @@
 #include <memory>
 #include <thread>
 
+#include "TestingSupport/SubsystemRAII.h"
 #include "lldb/Host/Editline.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/Pipe.h"
@@ -242,7 +243,7 @@ void EditlineAdapter::ConsumeAllOutput() {
 }
 
 class EditlineTestFixture : public ::testing::Test {
-private:
+  SubsystemRAII<FileSystem> subsystems;
   EditlineAdapter _el_adapter;
   std::shared_ptr<std::thread> _sp_output_thread;
 
@@ -253,8 +254,6 @@ class EditlineTestFixture : public ::testing::Test {
   }
 
   void SetUp() override {
-    FileSystem::Initialize();
-
     // Validate the editline adapter.
     EXPECT_TRUE(_el_adapter.IsValid());
     if (!_el_adapter.IsValid())
@@ -269,8 +268,6 @@ class EditlineTestFixture : public ::testing::Test {
     _el_adapter.CloseInput();
     if (_sp_output_thread)
       _sp_output_thread->join();
-
-    FileSystem::Terminate();
   }
 
   EditlineAdapter &GetEditlineAdapter() { return _el_adapter; }

diff  --git a/lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp b/lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp
index 299c41f1d33e..582aed0378a9 100644
--- a/lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp
+++ b/lldb/unittests/Expression/ClangExpressionDeclMapTest.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/Symbol/ClangTestUtils.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
@@ -54,14 +55,7 @@ struct FakeClangExpressionDeclMap : public ClangExpressionDeclMap {
 
 namespace {
 struct ClangExpressionDeclMapTest : public testing::Test {
-  static void SetUpTestCase() {
-    FileSystem::Initialize();
-    HostInfo::Initialize();
-  }
-  static void TearDownTestCase() {
-    HostInfo::Terminate();
-    FileSystem::Terminate();
-  }
+  SubsystemRAII<FileSystem, HostInfo> subsystems;
 
   /// The ClangASTImporter used during the test.
   ClangASTImporterSP importer;

diff  --git a/lldb/unittests/Expression/ClangParserTest.cpp b/lldb/unittests/Expression/ClangParserTest.cpp
index bc3bb89cbe10..ade0f5387c04 100644
--- a/lldb/unittests/Expression/ClangParserTest.cpp
+++ b/lldb/unittests/Expression/ClangParserTest.cpp
@@ -9,6 +9,7 @@
 #include "clang/Basic/Version.h"
 
 #include "Plugins/ExpressionParser/Clang/ClangHost.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
@@ -20,14 +21,7 @@ using namespace lldb_private;
 
 namespace {
 struct ClangHostTest : public testing::Test {
-  static void SetUpTestCase() {
-    FileSystem::Initialize();
-    HostInfo::Initialize();
-  }
-  static void TearDownTestCase() {
-    HostInfo::Terminate();
-    FileSystem::Terminate();
-  }
+  SubsystemRAII<FileSystem, HostInfo> subsystems;
 };
 } // namespace
 

diff  --git a/lldb/unittests/Expression/CppModuleConfigurationTest.cpp b/lldb/unittests/Expression/CppModuleConfigurationTest.cpp
index 0babf766a3a7..7ef66f60cfbb 100644
--- a/lldb/unittests/Expression/CppModuleConfigurationTest.cpp
+++ b/lldb/unittests/Expression/CppModuleConfigurationTest.cpp
@@ -8,6 +8,7 @@
 
 #include "Plugins/ExpressionParser/Clang/CppModuleConfiguration.h"
 #include "Plugins/ExpressionParser/Clang/ClangHost.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
 
@@ -18,16 +19,7 @@ using namespace lldb_private;
 
 namespace {
 struct CppModuleConfigurationTest : public testing::Test {
-  static void SetUpTestCase() {
-    // Getting the resource directory uses those subsystems, so we should
-    // initialize them.
-    FileSystem::Initialize();
-    HostInfo::Initialize();
-  }
-  static void TearDownTestCase() {
-    HostInfo::Terminate();
-    FileSystem::Terminate();
-  }
+  SubsystemRAII<FileSystem, HostInfo> subsystems;
 };
 } // namespace
 

diff  --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index f6276de4e753..8fad88a93e11 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -9,6 +9,7 @@
 #include "lldb/Expression/DWARFExpression.h"
 #include "../../source/Plugins/SymbolFile/DWARF/DWARFUnit.h"
 #include "../../source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Core/Value.h"
@@ -119,6 +120,7 @@ class YAMLObjectFile : public lldb_private::ObjectFile {
 /// Helper class that can construct a module from YAML and evaluate
 /// DWARF expressions on it.
 class YAMLModuleTester {
+  SubsystemRAII<FileSystem> subsystems;
   llvm::StringMap<std::unique_ptr<llvm::MemoryBuffer>> m_sections_map;
   lldb::ModuleSP m_module_sp;
   lldb::ObjectFileSP m_objfile_sp;
@@ -128,8 +130,6 @@ class YAMLModuleTester {
 public:
   /// Parse the debug info sections from the YAML description.
   YAMLModuleTester(llvm::StringRef yaml_data, llvm::StringRef triple) {
-    FileSystem::Initialize();
-
     auto sections_map = llvm::DWARFYAML::EmitDebugSections(yaml_data, true);
     if (!sections_map)
       return;
@@ -153,7 +153,6 @@ class YAMLModuleTester {
     if (dwarf_unit)
       m_dwarf_unit = dwarf_unit.get();
   }
-  ~YAMLModuleTester() { FileSystem::Terminate(); }
   DWARFUnitSP GetDwarfUnit() { return m_dwarf_unit; }
 
   // Evaluate a raw DWARF expression.

diff  --git a/lldb/unittests/Host/ConnectionFileDescriptorTest.cpp b/lldb/unittests/Host/ConnectionFileDescriptorTest.cpp
index 3e299222c451..a5930f297026 100644
--- a/lldb/unittests/Host/ConnectionFileDescriptorTest.cpp
+++ b/lldb/unittests/Host/ConnectionFileDescriptorTest.cpp
@@ -9,6 +9,7 @@
 #include "SocketTestUtilities.h"
 #include "gtest/gtest.h"
 
+#include "TestingSupport/SubsystemRAII.h"
 #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
 #include "lldb/Utility/UriParser.h"
 
@@ -16,11 +17,7 @@ using namespace lldb_private;
 
 class ConnectionFileDescriptorTest : public testing::Test {
 public:
-  void SetUp() override {
-    ASSERT_THAT_ERROR(Socket::Initialize(), llvm::Succeeded());
-  }
-
-  void TearDown() override { Socket::Terminate(); }
+  SubsystemRAII<Socket> subsystems;
 
   void TestGetURI(std::string ip) {
     std::unique_ptr<TCPSocket> socket_a_up;

diff  --git a/lldb/unittests/Host/HostInfoTest.cpp b/lldb/unittests/Host/HostInfoTest.cpp
index fb50e29eae58..c332606a4dad 100644
--- a/lldb/unittests/Host/HostInfoTest.cpp
+++ b/lldb/unittests/Host/HostInfoTest.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Host/HostInfo.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/lldb-defines.h"
@@ -17,15 +18,7 @@ using namespace llvm;
 
 namespace {
 class HostInfoTest : public ::testing::Test {
-public:
-  void SetUp() override {
-    FileSystem::Initialize();
-    HostInfo::Initialize();
-  }
-  void TearDown() override {
-    HostInfo::Terminate();
-    FileSystem::Terminate();
-  }
+  SubsystemRAII<FileSystem, HostInfo> subsystems;
 };
 } // namespace
 

diff  --git a/lldb/unittests/Host/MainLoopTest.cpp b/lldb/unittests/Host/MainLoopTest.cpp
index 240c6fcd534b..da509b940a13 100644
--- a/lldb/unittests/Host/MainLoopTest.cpp
+++ b/lldb/unittests/Host/MainLoopTest.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Host/MainLoop.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "lldb/Host/ConnectionFileDescriptor.h"
 #include "lldb/Host/PseudoTerminal.h"
 #include "lldb/Host/common/TCPSocket.h"
@@ -19,11 +20,7 @@ using namespace lldb_private;
 namespace {
 class MainLoopTest : public testing::Test {
 public:
-  static void SetUpTestCase() {
-    ASSERT_THAT_ERROR(Socket::Initialize(), llvm::Succeeded());
-  }
-
-  static void TearDownTestCase() { Socket::Terminate(); }
+  SubsystemRAII<Socket> subsystems;
 
   void SetUp() override {
     bool child_processes_inherit = false;

diff  --git a/lldb/unittests/Host/SocketAddressTest.cpp b/lldb/unittests/Host/SocketAddressTest.cpp
index 81bc5dcd03c6..8abf9c3376ed 100644
--- a/lldb/unittests/Host/SocketAddressTest.cpp
+++ b/lldb/unittests/Host/SocketAddressTest.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Host/SocketAddress.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "lldb/Host/Socket.h"
 #include "llvm/Testing/Support/Error.h"
 
@@ -17,10 +18,7 @@ using namespace lldb_private;
 namespace {
 class SocketAddressTest : public testing::Test {
 public:
-  static void SetUpTestCase() {
-    ASSERT_THAT_ERROR(Socket::Initialize(), llvm::Succeeded());
-  }
-  static void TearDownTestCase() { Socket::Terminate(); }
+  SubsystemRAII<Socket> subsystems;
 };
 } // namespace
 

diff  --git a/lldb/unittests/Host/SocketTest.cpp b/lldb/unittests/Host/SocketTest.cpp
index e0546e61239d..d4e8917bf942 100644
--- a/lldb/unittests/Host/SocketTest.cpp
+++ b/lldb/unittests/Host/SocketTest.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "SocketTestUtilities.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "lldb/Host/Config.h"
 #include "lldb/Utility/UriParser.h"
 #include "gtest/gtest.h"
@@ -15,11 +16,7 @@ using namespace lldb_private;
 
 class SocketTest : public testing::Test {
 public:
-  void SetUp() override {
-    ASSERT_THAT_ERROR(Socket::Initialize(), llvm::Succeeded());
-  }
-
-  void TearDown() override { Socket::Terminate(); }
+  SubsystemRAII<Socket> subsystems;
 };
 
 TEST_F(SocketTest, DecodeHostAndPort) {

diff  --git a/lldb/unittests/Interpreter/TestCompletion.cpp b/lldb/unittests/Interpreter/TestCompletion.cpp
index 841bcd898dd8..838a7a9e54d3 100644
--- a/lldb/unittests/Interpreter/TestCompletion.cpp
+++ b/lldb/unittests/Interpreter/TestCompletion.cpp
@@ -15,6 +15,7 @@
 #include "gtest/gtest.h"
 
 #include "TestingSupport/MockTildeExpressionResolver.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/FileSystem.h"
@@ -29,6 +30,8 @@ using namespace lldb_private;
 namespace {
 
 class CompletionTest : public testing::Test {
+  SubsystemRAII<FileSystem> subsystems;
+
 protected:
   /// Unique temporary directory in which all created filesystem entities must
   /// be placed. It is removed at the end of the test suite.
@@ -56,8 +59,6 @@ class CompletionTest : public testing::Test {
   SmallString<128> FileBaz;
 
   void SetUp() override {
-    FileSystem::Initialize();
-
     // chdir back into the original working dir this test binary started with.
     // A previous test may have have changed the working dir.
     ASSERT_NO_ERROR(fs::set_current_path(OriginalWorkingDir));
@@ -100,7 +101,6 @@ class CompletionTest : public testing::Test {
 
   void TearDown() override {
     ASSERT_NO_ERROR(fs::remove_directories(BaseDir));
-    FileSystem::Terminate();
   }
 
   static bool HasEquivalentFile(const Twine &Path, const StringList &Paths) {

diff  --git a/lldb/unittests/Language/Highlighting/HighlighterTest.cpp b/lldb/unittests/Language/Highlighting/HighlighterTest.cpp
index ebcc6122245f..5d155ffdd0d3 100644
--- a/lldb/unittests/Language/Highlighting/HighlighterTest.cpp
+++ b/lldb/unittests/Language/Highlighting/HighlighterTest.cpp
@@ -14,33 +14,18 @@
 #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
 #include "Plugins/Language/ObjC/ObjCLanguage.h"
 #include "Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h"
+#include "TestingSupport/SubsystemRAII.h"
 
 using namespace lldb_private;
 
 namespace {
 class HighlighterTest : public testing::Test {
-public:
-  static void SetUpTestCase();
-  static void TearDownTestCase();
+  SubsystemRAII<FileSystem, CPlusPlusLanguage, ObjCLanguage,
+                ObjCPlusPlusLanguage>
+      subsystems;
 };
 } // namespace
 
-void HighlighterTest::SetUpTestCase() {
-  // The HighlighterManager uses the language plugins under the hood, so we
-  // have to initialize them here for our test process.
-  FileSystem::Initialize();
-  CPlusPlusLanguage::Initialize();
-  ObjCLanguage::Initialize();
-  ObjCPlusPlusLanguage::Initialize();
-}
-
-void HighlighterTest::TearDownTestCase() {
-  CPlusPlusLanguage::Terminate();
-  ObjCLanguage::Terminate();
-  ObjCPlusPlusLanguage::Terminate();
-  FileSystem::Terminate();
-}
-
 static std::string getName(lldb::LanguageType type) {
   HighlighterManager m;
   return m.getHighlighterFor(type, "").GetName().str();

diff  --git a/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp b/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp
index 6bf641847cdc..01ad2ab4d19a 100644
--- a/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp
+++ b/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp
@@ -9,6 +9,7 @@
 
 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
 #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
@@ -29,22 +30,8 @@ using namespace lldb_private;
 using namespace lldb;
 
 class ObjectFileELFTest : public testing::Test {
-public:
-  void SetUp() override {
-    FileSystem::Initialize();
-    HostInfo::Initialize();
-    ObjectFileELF::Initialize();
-    SymbolFileSymtab::Initialize();
-  }
-
-  void TearDown() override {
-    SymbolFileSymtab::Terminate();
-    ObjectFileELF::Terminate();
-    HostInfo::Terminate();
-    FileSystem::Terminate();
-  }
-
-protected:
+  SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab>
+      subsystems;
 };
 
 TEST_F(ObjectFileELFTest, SectionsResolveConsistently) {

diff  --git a/lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp b/lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp
index cb0a2afea675..4e9182ec6a25 100644
--- a/lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp
+++ b/lldb/unittests/ObjectFile/PECOFF/TestPECallFrameInfo.cpp
@@ -11,6 +11,7 @@
 
 #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
 #include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 
 #include "lldb/Core/Module.h"
@@ -22,16 +23,7 @@ using namespace lldb_private;
 using namespace lldb;
 
 class PECallFrameInfoTest : public testing::Test {
-public:
-  void SetUp() override {
-    FileSystem::Initialize();
-    ObjectFilePECOFF::Initialize();
-  }
-
-  void TearDown() override {
-    ObjectFilePECOFF::Terminate();
-    FileSystem::Terminate();
-  }
+  SubsystemRAII<FileSystem, ObjectFilePECOFF> subsystems;
 
 protected:
   void GetUnwindPlan(addr_t file_addr, UnwindPlan &plan) const;

diff  --git a/lldb/unittests/Process/minidump/MinidumpParserTest.cpp b/lldb/unittests/Process/minidump/MinidumpParserTest.cpp
index 51c80ecd5075..94bb1b395f02 100644
--- a/lldb/unittests/Process/minidump/MinidumpParserTest.cpp
+++ b/lldb/unittests/Process/minidump/MinidumpParserTest.cpp
@@ -10,6 +10,7 @@
 #include "Plugins/Process/minidump/MinidumpTypes.h"
 #include "Plugins/Process/minidump/RegisterContextMinidump_x86_32.h"
 #include "Plugins/Process/minidump/RegisterContextMinidump_x86_64.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Target/MemoryRegionInfo.h"
@@ -37,9 +38,7 @@ using namespace minidump;
 
 class MinidumpParserTest : public testing::Test {
 public:
-  void SetUp() override { FileSystem::Initialize(); }
-
-  void TearDown() override { FileSystem::Terminate(); }
+  SubsystemRAII<FileSystem> subsystems;
 
   void SetUpData(const char *minidump_filename) {
     std::string filename = GetInputFilePath(minidump_filename);

diff  --git a/lldb/unittests/Symbol/LocateSymbolFileTest.cpp b/lldb/unittests/Symbol/LocateSymbolFileTest.cpp
index 205c4e442bd1..58a0eeba158d 100644
--- a/lldb/unittests/Symbol/LocateSymbolFileTest.cpp
+++ b/lldb/unittests/Symbol/LocateSymbolFileTest.cpp
@@ -8,6 +8,7 @@
 
 #include "gtest/gtest.h"
 
+#include "TestingSupport/SubsystemRAII.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
@@ -19,14 +20,7 @@ using namespace lldb_private;
 namespace {
 class SymbolsTest : public ::testing::Test {
 public:
-  void SetUp() override {
-    FileSystem::Initialize();
-    HostInfo::Initialize();
-  }
-  void TearDown() override {
-    HostInfo::Terminate();
-    FileSystem::Terminate();
-  }
+  SubsystemRAII<FileSystem, HostInfo> subsystems;
 };
 } // namespace
 

diff  --git a/lldb/unittests/Symbol/TestClangASTContext.cpp b/lldb/unittests/Symbol/TestClangASTContext.cpp
index 5254b99f8b83..2cbd94982aa0 100644
--- a/lldb/unittests/Symbol/TestClangASTContext.cpp
+++ b/lldb/unittests/Symbol/TestClangASTContext.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "TestingSupport/SubsystemRAII.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Symbol/ClangASTContext.h"
@@ -21,15 +22,7 @@ using namespace lldb_private;
 
 class TestClangASTContext : public testing::Test {
 public:
-  static void SetUpTestCase() {
-    FileSystem::Initialize();
-    HostInfo::Initialize();
-  }
-
-  static void TearDownTestCase() {
-    HostInfo::Terminate();
-    FileSystem::Terminate();
-  }
+  SubsystemRAII<FileSystem, HostInfo> subsystems;
 
   void SetUp() override {
     std::string triple = HostInfo::GetTargetTriple();

diff  --git a/lldb/unittests/Symbol/TestClangASTImporter.cpp b/lldb/unittests/Symbol/TestClangASTImporter.cpp
index 09e756572b40..4f99d40d946f 100644
--- a/lldb/unittests/Symbol/TestClangASTImporter.cpp
+++ b/lldb/unittests/Symbol/TestClangASTImporter.cpp
@@ -8,6 +8,7 @@
 
 #include "gtest/gtest.h"
 
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/Symbol/ClangTestUtils.h"
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/HostInfo.h"
@@ -24,15 +25,7 @@ using namespace lldb_private;
 
 class TestClangASTImporter : public testing::Test {
 public:
-  static void SetUpTestCase() {
-    FileSystem::Initialize();
-    HostInfo::Initialize();
-  }
-
-  static void TearDownTestCase() {
-    HostInfo::Terminate();
-    FileSystem::Terminate();
-  }
+  SubsystemRAII<FileSystem, HostInfo> subsystems;
 };
 
 TEST_F(TestClangASTImporter, CanImportInvalidType) {

diff  --git a/lldb/unittests/Symbol/TestDWARFCallFrameInfo.cpp b/lldb/unittests/Symbol/TestDWARFCallFrameInfo.cpp
index 45452c93b4b8..f7180a16fac6 100644
--- a/lldb/unittests/Symbol/TestDWARFCallFrameInfo.cpp
+++ b/lldb/unittests/Symbol/TestDWARFCallFrameInfo.cpp
@@ -12,6 +12,7 @@
 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
 #include "Plugins/Process/Utility/RegisterContext_x86.h"
 #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 
 #include "lldb/Core/Module.h"
@@ -32,20 +33,8 @@ using namespace lldb_private;
 using namespace lldb;
 
 class DWARFCallFrameInfoTest : public testing::Test {
-public:
-  void SetUp() override {
-    FileSystem::Initialize();
-    HostInfo::Initialize();
-    ObjectFileELF::Initialize();
-    SymbolFileSymtab::Initialize();
-  }
-
-  void TearDown() override {
-    SymbolFileSymtab::Terminate();
-    ObjectFileELF::Terminate();
-    HostInfo::Terminate();
-    FileSystem::Terminate();
-  }
+  SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab>
+      subsystems;
 
 protected:
   void TestBasic(DWARFCallFrameInfo::Type type, llvm::StringRef symbol);

diff  --git a/lldb/unittests/Symbol/TestLineEntry.cpp b/lldb/unittests/Symbol/TestLineEntry.cpp
index b6325fa115b7..cb2adba3ece1 100644
--- a/lldb/unittests/Symbol/TestLineEntry.cpp
+++ b/lldb/unittests/Symbol/TestLineEntry.cpp
@@ -14,6 +14,7 @@
 #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
 #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 #include "lldb/Symbol/ClangASTContext.h"
 
@@ -31,17 +32,13 @@ using namespace lldb_private;
 using namespace lldb;
 
 class LineEntryTest : public testing::Test {
+  SubsystemRAII<FileSystem, HostInfo, ObjectFileMachO, SymbolFileDWARF,
+                ClangASTContext>
+      subsystem;
+
 public:
   void SetUp() override;
 
-  void TearDown() override {
-    ClangASTContext::Terminate();
-    SymbolFileDWARF::Terminate();
-    ObjectFileMachO::Terminate();
-    HostInfo::Terminate();
-    FileSystem::Terminate();
-  }
-
 protected:
   llvm::Expected<LineEntry> GetLineEntryForLine(uint32_t line);
   llvm::Optional<TestFile> m_file;
@@ -49,11 +46,6 @@ class LineEntryTest : public testing::Test {
 };
 
 void LineEntryTest::SetUp() {
-  FileSystem::Initialize();
-  HostInfo::Initialize();
-  ObjectFileMachO::Initialize();
-  SymbolFileDWARF::Initialize();
-  ClangASTContext::Initialize();
   auto ExpectedFile = TestFile::fromYamlFile("inlined-functions.yaml");
   ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
   m_file.emplace(std::move(*ExpectedFile));

diff  --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index aaa0af5e3654..1395b1f276a4 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -6,26 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
 #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "TestingSupport/SubsystemRAII.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
 
 using namespace lldb;
 using namespace lldb_private;
 
 class DWARFASTParserClangTests : public testing::Test {
-public:
-  void SetUp() override {
-    FileSystem::Initialize();
-    ClangASTContext::Initialize();
-  }
-
-  void TearDown() override {
-    ClangASTContext::Terminate();
-    FileSystem::Terminate();
-  }
+  SubsystemRAII<FileSystem, ClangASTContext> subsystems;
 };
 
 namespace {

diff  --git a/lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp b/lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp
index 17c33f437371..e971439a8bdc 100644
--- a/lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp
@@ -20,6 +20,7 @@
 #include "Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h"
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
 #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 #include "lldb/Core/Address.h"
 #include "lldb/Core/Module.h"
@@ -40,28 +41,13 @@ using namespace lldb;
 using namespace lldb_private;
 
 class SymbolFileDWARFTests : public testing::Test {
+  SubsystemRAII<FileSystem, HostInfo, ObjectFilePECOFF, SymbolFileDWARF,
+                ClangASTContext, SymbolFilePDB>
+      subsystems;
+
 public:
   void SetUp() override {
-// Initialize and TearDown the plugin every time, so we get a brand new
-// AST every time so that modifications to the AST from each test don't
-// leak into the next test.
-FileSystem::Initialize();
-HostInfo::Initialize();
-ObjectFilePECOFF::Initialize();
-SymbolFileDWARF::Initialize();
-ClangASTContext::Initialize();
-SymbolFilePDB::Initialize();
-
-m_dwarf_test_exe = GetInputFilePath("test-dwarf.exe");
-  }
-
-  void TearDown() override {
-    SymbolFilePDB::Terminate();
-    ClangASTContext::Initialize();
-    SymbolFileDWARF::Terminate();
-    ObjectFilePECOFF::Terminate();
-    HostInfo::Terminate();
-    FileSystem::Terminate();
+    m_dwarf_test_exe = GetInputFilePath("test-dwarf.exe");
   }
 
 protected:

diff  --git a/lldb/unittests/Target/ModuleCacheTest.cpp b/lldb/unittests/Target/ModuleCacheTest.cpp
index bc8c878a5987..60e05379deec 100644
--- a/lldb/unittests/Target/ModuleCacheTest.cpp
+++ b/lldb/unittests/Target/ModuleCacheTest.cpp
@@ -6,6 +6,7 @@
 
 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
 #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
@@ -20,23 +21,21 @@ using namespace lldb;
 namespace {
 
 class ModuleCacheTest : public testing::Test {
-public:
-  static void SetUpTestCase();
+  SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab>
+      subsystems;
 
-  static void TearDownTestCase();
+public:
+  void SetUp() override;
 
 protected:
-  static FileSpec s_cache_dir;
-  static std::string s_test_executable;
+  FileSpec s_cache_dir;
+  std::string s_test_executable;
 
   void TryGetAndPut(const FileSpec &cache_dir, const char *hostname,
                     bool expect_download);
 };
 }
 
-FileSpec ModuleCacheTest::s_cache_dir;
-std::string ModuleCacheTest::s_test_executable;
-
 static const char dummy_hostname[] = "dummy_hostname";
 static const char dummy_remote_dir[] = "bin";
 static const char module_name[] = "TestModule.so";
@@ -66,23 +65,11 @@ static FileSpec GetSysrootView(FileSpec spec, const char *hostname) {
   return spec;
 }
 
-void ModuleCacheTest::SetUpTestCase() {
-  FileSystem::Initialize();
-  HostInfo::Initialize();
-  ObjectFileELF::Initialize();
-  SymbolFileSymtab::Initialize();
-
+void ModuleCacheTest::SetUp() {
   s_cache_dir = HostInfo::GetProcessTempDir();
   s_test_executable = GetInputFilePath(module_name);
 }
 
-void ModuleCacheTest::TearDownTestCase() {
-  SymbolFileSymtab::Terminate();
-  ObjectFileELF::Terminate();
-  HostInfo::Terminate();
-  FileSystem::Terminate();
-}
-
 static void VerifyDiskState(const FileSpec &cache_dir, const char *hostname) {
   FileSpec uuid_view = GetUuidView(cache_dir);
   EXPECT_TRUE(FileSystem::Instance().Exists(uuid_view))
@@ -108,8 +95,8 @@ void ModuleCacheTest::TryGetAndPut(const FileSpec &cache_dir,
 
   Status error = mc.GetAndPut(
       cache_dir, hostname, module_spec,
-      [&download_called](const ModuleSpec &module_spec,
-                         const FileSpec &tmp_download_file_spec) {
+      [&download_called, this](const ModuleSpec &module_spec,
+                               const FileSpec &tmp_download_file_spec) {
         download_called = true;
         EXPECT_STREQ(GetDummyRemotePath().GetCString(),
                      module_spec.GetFileSpec().GetCString());

diff  --git a/lldb/unittests/TestingSupport/SubsystemRAII.h b/lldb/unittests/TestingSupport/SubsystemRAII.h
new file mode 100644
index 000000000000..3df104b8af22
--- /dev/null
+++ b/lldb/unittests/TestingSupport/SubsystemRAII.h
@@ -0,0 +1,90 @@
+//===- SubsystemRAII.h ------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UNITTESTS_TESTINGSUPPORT_SUBSYSTEMRAII_H
+#define LLDB_UNITTESTS_TESTINGSUPPORT_SUBSYSTEMRAII_H
+
+#include "llvm/Support/Error.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+#include <type_traits>
+
+namespace lldb_private {
+
+namespace detail {
+/// Initializes and deinitializes a single subsystem.
+/// @see SubsystemRAII
+template <typename T> struct SubsystemRAIICase {
+
+  /// Calls ::Initialize if it has a void return type.
+  template <typename U = T>
+  typename std::enable_if<
+      std::is_same<decltype(U::Initialize()), void>::value>::type
+  CallInitialize() {
+    T::Initialize();
+  }
+
+  /// Calls ::Initialize if it has a llvm::Error return type and checks
+  /// the Error instance for success.
+  template <typename U = T>
+  typename std::enable_if<
+      std::is_same<decltype(U::Initialize()), llvm::Error>::value>::type
+  CallInitialize() {
+    ASSERT_THAT_ERROR(T::Initialize(), llvm::Succeeded());
+  }
+
+  SubsystemRAIICase() { CallInitialize(); }
+  ~SubsystemRAIICase() { T::Terminate(); }
+};
+} // namespace detail
+
+template <typename... T> class SubsystemRAII {};
+
+/// RAII for initializing and deinitializing LLDB subsystems.
+///
+/// This RAII takes care of calling the Initialize and Terminate functions for
+/// the subsystems specified by its template arguments. The ::Initialize
+/// functions are called on construction for each subsystem template parameter
+/// in the order in which they are passed as template parameters.
+/// The ::Terminate functions are called in the reverse order at destruction
+/// time.
+///
+/// If the ::Initialize function returns an llvm::Error this function handles
+/// the Error instance (by checking that there is no error).
+///
+/// Constructing this RAII in a scope like this:
+///
+///   @code{.cpp}
+///   {
+///     SubsystemRAII<FileSystem, HostInfo, Socket> Subsystems;
+///     DoingTestWork();
+///   }
+///   @endcode
+///
+/// is equivalent to the following code:
+///
+///   @code{.cpp}
+///   {
+///     FileSystem::Initialize();
+///     HostInfo::Initialize();
+///     ASSERT_THAT_ERROR(Socket::Initialize(), llvm::Succeeded());
+///
+///     DoingTestWork();
+///
+///     Socket::Terminate();
+///     FileSystem::Terminate();
+///     HostInfo::Terminate();
+///   }
+///   @endcode
+template <typename T, typename... Ts> class SubsystemRAII<T, Ts...> {
+  detail::SubsystemRAIICase<T> CurrentSubsystem;
+  SubsystemRAII<Ts...> RemainingSubsystems;
+};
+} // namespace lldb_private
+
+#endif // LLDB_UNITTESTS_TESTINGSUPPORT_SUBSYSTEMRAII_H

diff  --git a/lldb/unittests/Utility/CMakeLists.txt b/lldb/unittests/Utility/CMakeLists.txt
index 1021d928b00d..8dc13327b9b0 100644
--- a/lldb/unittests/Utility/CMakeLists.txt
+++ b/lldb/unittests/Utility/CMakeLists.txt
@@ -32,6 +32,7 @@ add_lldb_unittest(UtilityTests
   StringLexerTest.cpp
   StringListTest.cpp
   StructuredDataTest.cpp
+  SubsystemRAIITest.cpp
   TildeExpressionResolverTest.cpp
   TimeoutTest.cpp
   TimerTest.cpp

diff  --git a/lldb/unittests/Utility/SubsystemRAIITest.cpp b/lldb/unittests/Utility/SubsystemRAIITest.cpp
new file mode 100644
index 000000000000..38cb2470c64f
--- /dev/null
+++ b/lldb/unittests/Utility/SubsystemRAIITest.cpp
@@ -0,0 +1,99 @@
+//===-- SubsystemRAIITest.cpp -----------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+
+#include "TestingSupport/SubsystemRAII.h"
+
+using namespace lldb_private;
+
+namespace {
+
+enum class SystemState {
+  /// Start state of the subsystem.
+  Start,
+  /// Initialize has been called but Terminate hasn't been called yet.
+  Initialized,
+  /// Terminate has been called.
+  Terminated
+};
+
+struct TestSubsystem {
+  static SystemState state;
+  static void Initialize() {
+    assert(state == SystemState::Start);
+    state = SystemState::Initialized;
+  }
+  static void Terminate() {
+    assert(state == SystemState::Initialized);
+    state = SystemState::Terminated;
+  }
+};
+} // namespace
+
+SystemState TestSubsystem::state = SystemState::Start;
+
+TEST(SubsystemRAIITest, NormalSubsystem) {
+  // Tests that SubsystemRAII handles Initialize functions that return void.
+  EXPECT_EQ(SystemState::Start, TestSubsystem::state);
+  {
+    SubsystemRAII<TestSubsystem> subsystem;
+    EXPECT_EQ(SystemState::Initialized, TestSubsystem::state);
+  }
+  EXPECT_EQ(SystemState::Terminated, TestSubsystem::state);
+}
+
+static const char *SubsystemErrorString = "Initialize failed";
+
+namespace {
+struct TestSubsystemWithError {
+  static SystemState state;
+  static bool will_fail;
+  static llvm::Error Initialize() {
+    assert(state == SystemState::Start);
+    state = SystemState::Initialized;
+    if (will_fail)
+      return llvm::make_error<llvm::StringError>(
+          SubsystemErrorString, llvm::inconvertibleErrorCode());
+    return llvm::Error::success();
+  }
+  static void Terminate() {
+    assert(state == SystemState::Initialized);
+    state = SystemState::Terminated;
+  }
+  /// Reset the subsystem to the default state for testing.
+  static void Reset() { state = SystemState::Start; }
+};
+} // namespace
+
+SystemState TestSubsystemWithError::state = SystemState::Start;
+bool TestSubsystemWithError::will_fail = false;
+
+TEST(SubsystemRAIITest, SubsystemWithErrorSuccess) {
+  // Tests that SubsystemRAII handles llvm::success() returned from
+  // Initialize.
+  TestSubsystemWithError::Reset();
+  EXPECT_EQ(SystemState::Start, TestSubsystemWithError::state);
+  {
+    TestSubsystemWithError::will_fail = false;
+    SubsystemRAII<TestSubsystemWithError> subsystem;
+    EXPECT_EQ(SystemState::Initialized, TestSubsystemWithError::state);
+  }
+  EXPECT_EQ(SystemState::Terminated, TestSubsystemWithError::state);
+}
+
+TEST(SubsystemRAIITest, SubsystemWithErrorFailure) {
+  // Tests that SubsystemRAII handles any errors returned from
+  // Initialize.
+  TestSubsystemWithError::Reset();
+  EXPECT_EQ(SystemState::Start, TestSubsystemWithError::state);
+  TestSubsystemWithError::will_fail = true;
+  EXPECT_FATAL_FAILURE(SubsystemRAII<TestSubsystemWithError> subsystem,
+                       SubsystemErrorString);
+}


        


More information about the lldb-commits mailing list