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
23using namespace lldb;
24using namespace lldb_private;
25using namespace lldb_private::repro;
26
27static const constexpr std::chrono::seconds TIMEOUT(0);
28static const constexpr size_t DEBUGGERS = 3;
29
30namespace {
31class DiagnosticEventTest : public ::testing::Test {
32public:
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
51TEST_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
77TEST_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
102TEST_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
136TEST_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

source code of lldb/unittests/Core/DiagnosticEventTest.cpp