1 //===-- ProgressReportTest.cpp --------------------------------------------===//
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
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"
23 using namespace lldb_private
;
25 static std::chrono::milliseconds
TIMEOUT(500);
27 class ProgressReportTest
: public ::testing::Test
{
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
);
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
>
63 TEST_F(ProgressReportTest
, TestReportCreation
) {
64 ListenerSP listener_sp
= CreateListenerFor(lldb::eBroadcastBitProgress
);
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
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
);
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
);
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
);
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
287 EXPECT_EQ(data
->GetID(), expected_progress_id
);
290 TEST_F(ProgressReportTest
, TestProgressManagerDisjointReports
) {
291 ListenerSP listener_sp
=
292 CreateListenerFor(lldb::eBroadcastBitProgressCategory
);
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
));