1 //===- SubsystemRAII.h ------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_UNITTESTS_TESTINGSUPPORT_SUBSYSTEMRAII_H 10 #define LLDB_UNITTESTS_TESTINGSUPPORT_SUBSYSTEMRAII_H 11 12 #include "llvm/Support/Error.h" 13 #include "llvm/Testing/Support/Error.h" 14 #include "gtest/gtest.h" 15 #include <type_traits> 16 17 namespace lldb_private { 18 19 namespace detail { 20 /// Initializes and deinitializes a single subsystem. 21 /// @see SubsystemRAII 22 template <typename T> struct SubsystemRAIICase { 23 24 /// Calls ::Initialize if it has a void return type. 25 template <typename U = T> 26 typename std::enable_if< 27 std::is_same<decltype(U::Initialize()), void>::value>::type CallInitializeSubsystemRAIICase28 CallInitialize() { 29 T::Initialize(); 30 } 31 32 /// Calls ::Initialize if it has a llvm::Error return type and checks 33 /// the Error instance for success. 34 template <typename U = T> 35 typename std::enable_if< 36 std::is_same<decltype(U::Initialize()), llvm::Error>::value>::type CallInitializeSubsystemRAIICase37 CallInitialize() { 38 ASSERT_THAT_ERROR(T::Initialize(), llvm::Succeeded()); 39 } 40 SubsystemRAIICaseSubsystemRAIICase41 SubsystemRAIICase() { CallInitialize(); } ~SubsystemRAIICaseSubsystemRAIICase42 ~SubsystemRAIICase() { T::Terminate(); } 43 }; 44 } // namespace detail 45 46 template <typename... T> class SubsystemRAII {}; 47 48 /// RAII for initializing and deinitializing LLDB subsystems. 49 /// 50 /// This RAII takes care of calling the Initialize and Terminate functions for 51 /// the subsystems specified by its template arguments. The ::Initialize 52 /// functions are called on construction for each subsystem template parameter 53 /// in the order in which they are passed as template parameters. 54 /// The ::Terminate functions are called in the reverse order at destruction 55 /// time. 56 /// 57 /// If the ::Initialize function returns an llvm::Error this function handles 58 /// the Error instance (by checking that there is no error). 59 /// 60 /// Constructing this RAII in a scope like this: 61 /// 62 /// @code{.cpp} 63 /// { 64 /// SubsystemRAII<FileSystem, HostInfo, Socket> Subsystems; 65 /// DoingTestWork(); 66 /// } 67 /// @endcode 68 /// 69 /// is equivalent to the following code: 70 /// 71 /// @code{.cpp} 72 /// { 73 /// FileSystem::Initialize(); 74 /// HostInfo::Initialize(); 75 /// ASSERT_THAT_ERROR(Socket::Initialize(), llvm::Succeeded()); 76 /// 77 /// DoingTestWork(); 78 /// 79 /// Socket::Terminate(); 80 /// FileSystem::Terminate(); 81 /// HostInfo::Terminate(); 82 /// } 83 /// @endcode 84 template <typename T, typename... Ts> class SubsystemRAII<T, Ts...> { 85 detail::SubsystemRAIICase<T> CurrentSubsystem; 86 SubsystemRAII<Ts...> RemainingSubsystems; 87 }; 88 } // namespace lldb_private 89 90 #endif // LLDB_UNITTESTS_TESTINGSUPPORT_SUBSYSTEMRAII_H 91