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