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