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