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:
SetUp()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 }
TearDown()46 void TearDown() override {
47 PlatformMacOSX::Terminate();
48 HostInfo::Terminate();
49 FileSystem::Terminate();
50 Reproducer::Terminate();
51 }
52 };
53 } // namespace
54
TEST_F(DiagnosticEventTest,Warning)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
TEST_F(DiagnosticEventTest,Error)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
TEST_F(DiagnosticEventTest,MultipleDebuggers)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
TEST_F(DiagnosticEventTest,WarningOnce)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