[NFC][Coroutines] Use structured binding with llvm::enumerate in CoroSplit (#116879)
[llvm-project.git] / lldb / unittests / Core / ProgressReportTest.cpp
blob0149b1de77add70cc206a97cc6851b88f7e1d6a8
1 //===-- ProgressReportTest.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 //===----------------------------------------------------------------------===//
9 #include "Plugins/Platform/MacOSX/PlatformMacOSX.h"
10 #include "Plugins/Platform/MacOSX/PlatformRemoteMacOSX.h"
11 #include "TestingSupport/SubsystemRAII.h"
12 #include "TestingSupport/TestUtilities.h"
13 #include "lldb/Core/Debugger.h"
14 #include "lldb/Core/Progress.h"
15 #include "lldb/Host/FileSystem.h"
16 #include "lldb/Host/HostInfo.h"
17 #include "lldb/Utility/Listener.h"
18 #include "gtest/gtest.h"
19 #include <memory>
20 #include <mutex>
22 using namespace lldb;
23 using namespace lldb_private;
25 static std::chrono::milliseconds TIMEOUT(500);
27 class ProgressReportTest : public ::testing::Test {
28 public:
29 ListenerSP CreateListenerFor(uint32_t bit) {
30 // Set up the debugger, make sure that was done properly.
31 ArchSpec arch("x86_64-apple-macosx-");
32 Platform::SetHostPlatform(
33 PlatformRemoteMacOSX::CreateInstance(true, &arch));
35 m_debugger_sp = Debugger::CreateInstance();
37 // Get the debugger's broadcaster.
38 Broadcaster &broadcaster = m_debugger_sp->GetBroadcaster();
40 // Create a listener, make sure it can receive events and that it's
41 // listening to the correct broadcast bit.
42 m_listener_sp = Listener::MakeListener("progress-listener");
43 m_listener_sp->StartListeningForEvents(&broadcaster, bit);
44 return m_listener_sp;
47 protected:
48 // The debugger's initialization function can't be called with no arguments
49 // so calling it using SubsystemRAII will cause the test build to fail as
50 // SubsystemRAII will call Initialize with no arguments. As such we set it up
51 // here the usual way.
52 void SetUp() override {
53 std::call_once(TestUtilities::g_debugger_initialize_flag,
54 []() { Debugger::Initialize(nullptr); });
57 DebuggerSP m_debugger_sp;
58 ListenerSP m_listener_sp;
59 SubsystemRAII<FileSystem, HostInfo, PlatformMacOSX, ProgressManager>
60 subsystems;
63 TEST_F(ProgressReportTest, TestReportCreation) {
64 ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);
65 EventSP event_sp;
66 const ProgressEventData *data;
68 // Scope this for RAII on the progress objects.
69 // Create progress reports and check that their respective events for having
70 // started and ended are broadcasted.
72 Progress progress1("Progress report 1", "Starting report 1");
73 Progress progress2("Progress report 2", "Starting report 2");
74 Progress progress3("Progress report 3", "Starting report 3");
77 // Start popping events from the queue, they should have been recevied
78 // in this order:
79 // Starting progress: 1, 2, 3
80 // Ending progress: 3, 2, 1
81 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
82 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
84 EXPECT_EQ(data->GetDetails(), "Starting report 1");
85 EXPECT_FALSE(data->IsFinite());
86 EXPECT_FALSE(data->GetCompleted());
87 EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
88 EXPECT_EQ(data->GetMessage(), "Progress report 1: Starting report 1");
90 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
91 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
93 EXPECT_EQ(data->GetDetails(), "Starting report 2");
94 EXPECT_FALSE(data->IsFinite());
95 EXPECT_FALSE(data->GetCompleted());
96 EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
97 EXPECT_EQ(data->GetMessage(), "Progress report 2: Starting report 2");
99 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
100 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
102 EXPECT_EQ(data->GetDetails(), "Starting report 3");
103 EXPECT_FALSE(data->IsFinite());
104 EXPECT_FALSE(data->GetCompleted());
105 EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
106 EXPECT_EQ(data->GetMessage(), "Progress report 3: Starting report 3");
108 // Progress report objects should be destroyed at this point so
109 // get each report from the queue and check that they've been
110 // destroyed in reverse order.
111 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
112 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
114 EXPECT_EQ(data->GetTitle(), "Progress report 3");
115 EXPECT_TRUE(data->GetCompleted());
116 EXPECT_FALSE(data->IsFinite());
117 EXPECT_EQ(data->GetMessage(), "Progress report 3: Starting report 3");
119 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
120 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
122 EXPECT_EQ(data->GetTitle(), "Progress report 2");
123 EXPECT_TRUE(data->GetCompleted());
124 EXPECT_FALSE(data->IsFinite());
125 EXPECT_EQ(data->GetMessage(), "Progress report 2: Starting report 2");
127 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
128 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
130 EXPECT_EQ(data->GetTitle(), "Progress report 1");
131 EXPECT_TRUE(data->GetCompleted());
132 EXPECT_FALSE(data->IsFinite());
133 EXPECT_EQ(data->GetMessage(), "Progress report 1: Starting report 1");
136 TEST_F(ProgressReportTest, TestReportDestructionWithPartialProgress) {
137 ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);
138 EventSP event_sp;
139 const ProgressEventData *data;
141 // Create a finite progress report and only increment to a non-completed
142 // state before destruction.
144 Progress progress("Finite progress", "Report 1", 100);
145 progress.Increment(3);
148 // Verify that the progress in the events are:
149 // 1. At construction: 0 out of 100
150 // 2. At increment: 3 out of 100
151 // 3. At destruction: 100 out of 100
152 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
153 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
154 EXPECT_EQ(data->GetDetails(), "Report 1");
155 EXPECT_TRUE(data->IsFinite());
156 EXPECT_EQ(data->GetCompleted(), (uint64_t)0);
157 EXPECT_EQ(data->GetTotal(), (uint64_t)100);
158 EXPECT_EQ(data->GetMessage(), "Finite progress: Report 1");
160 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
161 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
162 EXPECT_EQ(data->GetDetails(), "Report 1");
163 EXPECT_TRUE(data->IsFinite());
164 EXPECT_EQ(data->GetCompleted(), (uint64_t)3);
165 EXPECT_EQ(data->GetTotal(), (uint64_t)100);
166 EXPECT_EQ(data->GetMessage(), "Finite progress: Report 1");
168 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
169 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
170 EXPECT_EQ(data->GetDetails(), "Report 1");
171 EXPECT_TRUE(data->IsFinite());
172 EXPECT_EQ(data->GetCompleted(), (uint64_t)100);
173 EXPECT_EQ(data->GetTotal(), (uint64_t)100);
174 EXPECT_EQ(data->GetMessage(), "Finite progress: Report 1");
176 // Create an infinite progress report and increment by some amount.
178 Progress progress("Infinite progress", "Report 2");
179 progress.Increment(3);
182 // Verify that the progress in the events are:
183 // 1. At construction: 0
184 // 2. At increment: 3
185 // 3. At destruction: Progress::kNonDeterministicTotal
186 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
187 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
188 EXPECT_EQ(data->GetDetails(), "Report 2");
189 EXPECT_FALSE(data->IsFinite());
190 EXPECT_EQ(data->GetCompleted(), (uint64_t)0);
191 EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
192 EXPECT_EQ(data->GetMessage(), "Infinite progress: Report 2");
194 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
195 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
196 EXPECT_EQ(data->GetDetails(), "Report 2");
197 EXPECT_FALSE(data->IsFinite());
198 EXPECT_EQ(data->GetCompleted(), (uint64_t)3);
199 EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
200 EXPECT_EQ(data->GetMessage(), "Infinite progress: Report 2");
202 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
203 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
204 EXPECT_EQ(data->GetDetails(), "Report 2");
205 EXPECT_FALSE(data->IsFinite());
206 EXPECT_EQ(data->GetCompleted(), Progress::kNonDeterministicTotal);
207 EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
208 EXPECT_EQ(data->GetMessage(), "Infinite progress: Report 2");
211 TEST_F(ProgressReportTest, TestProgressManager) {
212 ListenerSP listener_sp =
213 CreateListenerFor(lldb::eBroadcastBitProgressCategory);
214 EventSP event_sp;
215 const ProgressEventData *data;
217 // Create three progress events with the same category then try to pop 2
218 // events from the queue in a row before the progress reports are destroyed.
219 // Since only 1 event should've been broadcast for this category, the second
220 // GetEvent() call should return false.
222 Progress progress1("Progress report 1", "Starting report 1");
223 Progress progress2("Progress report 1", "Starting report 2");
224 Progress progress3("Progress report 1", "Starting report 3");
225 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
226 ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT));
229 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
231 EXPECT_EQ(data->GetDetails(), "");
232 EXPECT_FALSE(data->IsFinite());
233 EXPECT_FALSE(data->GetCompleted());
234 EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
235 EXPECT_EQ(data->GetMessage(), "Progress report 1");
237 // Pop another event from the queue, this should be the event for the final
238 // report for this category.
239 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
240 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
242 EXPECT_EQ(data->GetDetails(), "");
243 EXPECT_FALSE(data->IsFinite());
244 EXPECT_TRUE(data->GetCompleted());
245 EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
246 EXPECT_EQ(data->GetMessage(), "Progress report 1");
249 TEST_F(ProgressReportTest, TestOverlappingEvents) {
250 ListenerSP listener_sp =
251 CreateListenerFor(lldb::eBroadcastBitProgressCategory);
252 EventSP event_sp;
253 const ProgressEventData *data;
255 // Create two progress reports of the same category that overlap with each
256 // other. Here we want to ensure that the ID broadcasted for the initial and
257 // final reports for this category are the same.
258 std::unique_ptr<Progress> overlap_progress1 =
259 std::make_unique<Progress>("Overlapping report 1", "Starting report 1");
260 std::unique_ptr<Progress> overlap_progress2 =
261 std::make_unique<Progress>("Overlapping report 1", "Starting report 2");
262 overlap_progress1.reset();
264 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
265 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
266 // Get the ID used in the first report for this category.
267 uint64_t expected_progress_id = data->GetID();
269 EXPECT_EQ(data->GetDetails(), "");
270 EXPECT_FALSE(data->IsFinite());
271 EXPECT_FALSE(data->GetCompleted());
272 EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
273 EXPECT_EQ(data->GetMessage(), "Overlapping report 1");
275 overlap_progress2.reset();
277 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
278 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
280 EXPECT_EQ(data->GetDetails(), "");
281 EXPECT_FALSE(data->IsFinite());
282 EXPECT_TRUE(data->GetCompleted());
283 EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
284 EXPECT_EQ(data->GetMessage(), "Overlapping report 1");
285 // The progress ID for the final report should be the same as that for the
286 // initial report.
287 EXPECT_EQ(data->GetID(), expected_progress_id);
290 TEST_F(ProgressReportTest, TestProgressManagerDisjointReports) {
291 ListenerSP listener_sp =
292 CreateListenerFor(lldb::eBroadcastBitProgressCategory);
293 EventSP event_sp;
294 const ProgressEventData *data;
295 uint64_t expected_progress_id;
297 { Progress progress("Coalesced report 1", "Starting report 1"); }
298 { Progress progress("Coalesced report 1", "Starting report 2"); }
299 { Progress progress("Coalesced report 1", "Starting report 3"); }
301 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
302 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
303 expected_progress_id = data->GetID();
305 EXPECT_EQ(data->GetDetails(), "");
306 EXPECT_FALSE(data->IsFinite());
307 EXPECT_FALSE(data->GetCompleted());
308 EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
309 EXPECT_EQ(data->GetMessage(), "Coalesced report 1");
311 ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
312 data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
314 EXPECT_EQ(data->GetID(), expected_progress_id);
315 EXPECT_EQ(data->GetDetails(), "");
316 EXPECT_FALSE(data->IsFinite());
317 EXPECT_TRUE(data->GetCompleted());
318 EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
319 EXPECT_EQ(data->GetMessage(), "Coalesced report 1");
321 ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT));