Skip to content

Commit 3ff6fb6

Browse files
authored
[LLDB][SBProgress] Add a finalize method (#128966)
This patch adds a finalize method which destroys the underlying RAII SBProgress. My primary motivation for this is so I can write better tests that are non-flaky, but after discussing with @clayborg in my DAP message improvement patch (#124648) this is probably an essential API despite that I originally argued it wasn't.
1 parent 8179bcf commit 3ff6fb6

File tree

4 files changed

+58
-29
lines changed

4 files changed

+58
-29
lines changed

lldb/bindings/interface/SBProgressDocstrings.i

+11
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,14 @@ and will always send an initial progress update, updates when
1212
Progress::Increment() is called, and also will make sure that a progress
1313
completed update is reported even if the user doesn't explicitly cause one
1414
to be sent.") lldb::SBProgress;
15+
16+
%feature("docstring",
17+
"Finalize the SBProgress, which will cause a progress end event to be emitted. This
18+
happens automatically when the SBProcess object is destroyed, but can be done explicitly
19+
with Finalize to avoid having to rely on the language semantics for destruction.
20+
21+
Note once finalized, no further increments will be processed.") lldb::SBProgress::Finalize;
22+
23+
%feature("docstring",
24+
"Increment the progress by a given number of units, optionally with a message. Not all progress events are guaraunteed
25+
to be sent, but incrementing to the total will always guarauntee a progress end event being sent.") lldb::SBProcess::Increment;

lldb/include/lldb/API/SBProgress.h

+5
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ class LLDB_API SBProgress {
5959

6060
void Increment(uint64_t amount, const char *description = nullptr);
6161

62+
/// Explicitly finalize an SBProgress, this can be used to terminate a
63+
/// progress on command instead of waiting for a garbage collection or other
64+
/// RAII to destroy the contained progress object.
65+
void Finalize();
66+
6267
protected:
6368
lldb_private::Progress &ref() const;
6469

lldb/source/API/SBProgress.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,22 @@ SBProgress::~SBProgress() = default;
4040
void SBProgress::Increment(uint64_t amount, const char *description) {
4141
LLDB_INSTRUMENT_VA(amount, description);
4242

43+
if (!m_opaque_up)
44+
return;
45+
4346
std::optional<std::string> description_opt;
4447
if (description && description[0])
4548
description_opt = description;
4649
m_opaque_up->Increment(amount, std::move(description_opt));
4750
}
4851

52+
void SBProgress::Finalize() {
53+
// The lldb_private::Progress object is designed to be RAII and send the end
54+
// progress event when it gets destroyed. So force our contained object to be
55+
// destroyed and send the progress end event. Clearing this object also allows
56+
// all other methods to quickly return without doing any work if they are
57+
// called after this method.
58+
m_opaque_up.reset();
59+
}
60+
4961
lldb_private::Progress &SBProgress::ref() const { return *m_opaque_up; }

lldb/test/API/python_api/sbprogress/TestSBProgress.py

+30-29
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,6 @@
55

66

77
class SBProgressTestCase(TestBase):
8-
def test_with_external_bit_set(self):
9-
"""Test SBProgress events are listened to when the external bit is set."""
10-
11-
progress = lldb.SBProgress("Test SBProgress", "Test progress", self.dbg)
12-
listener = lldb.SBListener("Test listener")
13-
broadcaster = self.dbg.GetBroadcaster()
14-
broadcaster.AddListener(listener, lldb.eBroadcastBitExternalProgress)
15-
event = lldb.SBEvent()
16-
17-
expected_string = "Test progress first increment"
18-
progress.Increment(1, expected_string)
19-
self.assertTrue(listener.PeekAtNextEvent(event))
20-
stream = lldb.SBStream()
21-
event.GetDescription(stream)
22-
self.assertIn(expected_string, stream.GetData())
23-
24-
def test_without_external_bit_set(self):
25-
"""Test SBProgress events are not listened to on the internal progress bit."""
26-
27-
progress = lldb.SBProgress("Test SBProgress", "Test progress", self.dbg)
28-
listener = lldb.SBListener("Test listener")
29-
broadcaster = self.dbg.GetBroadcaster()
30-
broadcaster.AddListener(listener, lldb.eBroadcastBitProgress)
31-
event = lldb.SBEvent()
32-
33-
expected_string = "Test progress first increment"
34-
progress.Increment(1, expected_string)
35-
self.assertFalse(listener.PeekAtNextEvent(event))
36-
378
def test_with_external_bit_set(self):
389
"""Test SBProgress can handle null events."""
3910

@@ -65,3 +36,33 @@ def test_with_external_bit_set(self):
6536
stream = lldb.SBStream()
6637
event.GetDescription(stream)
6738
self.assertIn("Step 3", stream.GetData())
39+
40+
def test_progress_finalize_non_deterministic_progress(self):
41+
"""Test SBProgress finalize sends the progressEnd event"""
42+
43+
progress = lldb.SBProgress("Test SBProgress", "Test finalize", self.dbg)
44+
listener = lldb.SBListener("Test listener")
45+
broadcaster = self.dbg.GetBroadcaster()
46+
broadcaster.AddListener(listener, lldb.eBroadcastBitExternalProgressCategory)
47+
event = lldb.SBEvent()
48+
progress.Finalize()
49+
self.assertTrue(listener.WaitForEvent(5, event))
50+
stream = lldb.SBStream()
51+
event.GetDescription(stream)
52+
self.assertIn("type = end", stream.GetData())
53+
54+
def test_progress_finalize_deterministic_progress(self):
55+
"""Test SBProgress finalize sends the progressEnd event"""
56+
57+
progress = lldb.SBProgress("Test SBProgress", "Test finalize", 13, self.dbg)
58+
listener = lldb.SBListener("Test listener")
59+
broadcaster = self.dbg.GetBroadcaster()
60+
broadcaster.AddListener(listener, lldb.eBroadcastBitExternalProgressCategory)
61+
event = lldb.SBEvent()
62+
progress.Finalize()
63+
self.assertTrue(listener.WaitForEvent(5, event))
64+
stream = lldb.SBStream()
65+
event.GetDescription(stream)
66+
# Note even for progresses with a total, the total isn't
67+
# sent in the end message.
68+
self.assertIn("type = end", stream.GetData())

0 commit comments

Comments
 (0)