1 //===-- DiagnosticEventTest.cpp -------------------------------------------===// 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 #include "gtest/gtest.h" 10 11 #include "Plugins/Platform/MacOSX/PlatformMacOSX.h" 12 #include "Plugins/Platform/MacOSX/PlatformRemoteMacOSX.h" 13 #include "TestingSupport/SubsystemRAII.h" 14 #include "lldb/Core/Debugger.h" 15 #include "lldb/Core/DebuggerEvents.h" 16 #include "lldb/Host/FileSystem.h" 17 #include "lldb/Host/HostInfo.h" 18 #include "lldb/Utility/Broadcaster.h" 19 #include "lldb/Utility/Event.h" 20 #include "lldb/Utility/Listener.h" 21 #include "lldb/Utility/Reproducer.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 using namespace lldb_private::repro; 26 27 static const constexpr std::chrono::seconds TIMEOUT(0); 28 static const constexpr size_t DEBUGGERS = 3; 29 30 static std::once_flag debugger_initialize_flag; 31 32 namespace { 33 class DiagnosticEventTest : public ::testing::Test { 34 public: 35 void SetUp() override { 36 llvm::cantFail(Reproducer::Initialize(ReproducerMode::Off, llvm::None)); 37 FileSystem::Initialize(); 38 HostInfo::Initialize(); 39 PlatformMacOSX::Initialize(); 40 std::call_once(debugger_initialize_flag, 41 []() { Debugger::Initialize(nullptr); }); 42 ArchSpec arch("x86_64-apple-macosx-"); 43 Platform::SetHostPlatform( 44 PlatformRemoteMacOSX::CreateInstance(true, &arch)); 45 } 46 void TearDown() override { 47 PlatformMacOSX::Terminate(); 48 HostInfo::Terminate(); 49 FileSystem::Terminate(); 50 Reproducer::Terminate(); 51 } 52 }; 53 } // namespace 54 55 TEST_F(DiagnosticEventTest, Warning) { 56 DebuggerSP debugger_sp = Debugger::CreateInstance(); 57 58 Broadcaster &broadcaster = debugger_sp->GetBroadcaster(); 59 ListenerSP listener_sp = Listener::MakeListener("test-listener"); 60 61 listener_sp->StartListeningForEvents(&broadcaster, 62 Debugger::eBroadcastBitWarning); 63 EXPECT_TRUE( 64 broadcaster.EventTypeHasListeners(Debugger::eBroadcastBitWarning)); 65 66 Debugger::ReportWarning("foo", debugger_sp->GetID()); 67 68 EventSP event_sp; 69 EXPECT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT)); 70 ASSERT_TRUE(event_sp); 71 72 const DiagnosticEventData *data = 73 DiagnosticEventData::GetEventDataFromEvent(event_sp.get()); 74 ASSERT_NE(data, nullptr); 75 EXPECT_EQ(data->GetPrefix(), "warning"); 76 EXPECT_EQ(data->GetMessage(), "foo"); 77 78 Debugger::Destroy(debugger_sp); 79 } 80 81 TEST_F(DiagnosticEventTest, Error) { 82 DebuggerSP debugger_sp = Debugger::CreateInstance(); 83 84 Broadcaster &broadcaster = debugger_sp->GetBroadcaster(); 85 ListenerSP listener_sp = Listener::MakeListener("test-listener"); 86 87 listener_sp->StartListeningForEvents(&broadcaster, 88 Debugger::eBroadcastBitError); 89 EXPECT_TRUE(broadcaster.EventTypeHasListeners(Debugger::eBroadcastBitError)); 90 91 Debugger::ReportError("bar", debugger_sp->GetID()); 92 93 EventSP event_sp; 94 EXPECT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT)); 95 ASSERT_TRUE(event_sp); 96 97 const DiagnosticEventData *data = 98 DiagnosticEventData::GetEventDataFromEvent(event_sp.get()); 99 ASSERT_NE(data, nullptr); 100 EXPECT_EQ(data->GetPrefix(), "error"); 101 EXPECT_EQ(data->GetMessage(), "bar"); 102 103 Debugger::Destroy(debugger_sp); 104 } 105 106 TEST_F(DiagnosticEventTest, MultipleDebuggers) { 107 std::vector<DebuggerSP> debuggers; 108 std::vector<ListenerSP> listeners; 109 110 for (size_t i = 0; i < DEBUGGERS; ++i) { 111 DebuggerSP debugger = Debugger::CreateInstance(); 112 ListenerSP listener = Listener::MakeListener("listener"); 113 114 debuggers.push_back(debugger); 115 listeners.push_back(listener); 116 117 listener->StartListeningForEvents(&debugger->GetBroadcaster(), 118 Debugger::eBroadcastBitError); 119 } 120 121 Debugger::ReportError("baz"); 122 123 for (size_t i = 0; i < DEBUGGERS; ++i) { 124 EventSP event_sp; 125 EXPECT_TRUE(listeners[i]->GetEvent(event_sp, TIMEOUT)); 126 ASSERT_TRUE(event_sp); 127 128 const DiagnosticEventData *data = 129 DiagnosticEventData::GetEventDataFromEvent(event_sp.get()); 130 ASSERT_NE(data, nullptr); 131 EXPECT_EQ(data->GetPrefix(), "error"); 132 EXPECT_EQ(data->GetMessage(), "baz"); 133 } 134 135 for (size_t i = 0; i < DEBUGGERS; ++i) { 136 Debugger::Destroy(debuggers[i]); 137 } 138 } 139 140 TEST_F(DiagnosticEventTest, WarningOnce) { 141 DebuggerSP debugger_sp = Debugger::CreateInstance(); 142 143 Broadcaster &broadcaster = debugger_sp->GetBroadcaster(); 144 ListenerSP listener_sp = Listener::MakeListener("test-listener"); 145 146 listener_sp->StartListeningForEvents(&broadcaster, 147 Debugger::eBroadcastBitWarning); 148 EXPECT_TRUE( 149 broadcaster.EventTypeHasListeners(Debugger::eBroadcastBitWarning)); 150 151 std::once_flag once; 152 Debugger::ReportWarning("foo", debugger_sp->GetID(), &once); 153 154 { 155 EventSP event_sp; 156 EXPECT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT)); 157 ASSERT_TRUE(event_sp); 158 159 const DiagnosticEventData *data = 160 DiagnosticEventData::GetEventDataFromEvent(event_sp.get()); 161 ASSERT_NE(data, nullptr); 162 EXPECT_EQ(data->GetPrefix(), "warning"); 163 EXPECT_EQ(data->GetMessage(), "foo"); 164 } 165 166 EventSP second_event_sp; 167 EXPECT_FALSE(listener_sp->GetEvent(second_event_sp, TIMEOUT)); 168 169 Debugger::ReportWarning("foo", debugger_sp->GetID(), &once); 170 EXPECT_FALSE(listener_sp->GetEvent(second_event_sp, TIMEOUT)); 171 172 Debugger::ReportWarning("foo", debugger_sp->GetID()); 173 EXPECT_TRUE(listener_sp->GetEvent(second_event_sp, TIMEOUT)); 174 175 Debugger::Destroy(debugger_sp); 176 } 177