xref: /llvm-project/lldb/unittests/Core/ProgressReportTest.cpp (revision 774c22686330f3ca43e48a1b8076eb30ae03dbd8)
1a8ab8306SChelsea Cassanova //===-- ProgressReportTest.cpp --------------------------------------------===//
2a8ab8306SChelsea Cassanova //
3a8ab8306SChelsea Cassanova // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a8ab8306SChelsea Cassanova // See https://llvm.org/LICENSE.txt for license information.
5a8ab8306SChelsea Cassanova // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a8ab8306SChelsea Cassanova //
7a8ab8306SChelsea Cassanova //===----------------------------------------------------------------------===//
8a8ab8306SChelsea Cassanova 
9a8ab8306SChelsea Cassanova #include "Plugins/Platform/MacOSX/PlatformMacOSX.h"
10a8ab8306SChelsea Cassanova #include "Plugins/Platform/MacOSX/PlatformRemoteMacOSX.h"
11a8ab8306SChelsea Cassanova #include "TestingSupport/SubsystemRAII.h"
12a8ab8306SChelsea Cassanova #include "TestingSupport/TestUtilities.h"
13a8ab8306SChelsea Cassanova #include "lldb/Core/Debugger.h"
14a8ab8306SChelsea Cassanova #include "lldb/Core/Progress.h"
15a8ab8306SChelsea Cassanova #include "lldb/Host/FileSystem.h"
16a8ab8306SChelsea Cassanova #include "lldb/Host/HostInfo.h"
17a8ab8306SChelsea Cassanova #include "lldb/Utility/Listener.h"
18a8ab8306SChelsea Cassanova #include "gtest/gtest.h"
19137ed170SChelsea Cassanova #include <memory>
20a8ab8306SChelsea Cassanova #include <mutex>
210dbdc23eSPavel Labath #include <thread>
22a8ab8306SChelsea Cassanova 
23a8ab8306SChelsea Cassanova using namespace lldb;
24a8ab8306SChelsea Cassanova using namespace lldb_private;
25a8ab8306SChelsea Cassanova 
26156c2907SJonas Devlieghere static std::chrono::milliseconds TIMEOUT(500);
27a8ab8306SChelsea Cassanova 
2845863669SJonas Devlieghere class ProgressReportTest : public ::testing::Test {
2945863669SJonas Devlieghere public:
3045863669SJonas Devlieghere   ListenerSP CreateListenerFor(uint32_t bit) {
3145863669SJonas Devlieghere     // Set up the debugger, make sure that was done properly.
3245863669SJonas Devlieghere     ArchSpec arch("x86_64-apple-macosx-");
3345863669SJonas Devlieghere     Platform::SetHostPlatform(
3445863669SJonas Devlieghere         PlatformRemoteMacOSX::CreateInstance(true, &arch));
3545863669SJonas Devlieghere 
3645863669SJonas Devlieghere     m_debugger_sp = Debugger::CreateInstance();
3745863669SJonas Devlieghere 
3845863669SJonas Devlieghere     // Get the debugger's broadcaster.
3945863669SJonas Devlieghere     Broadcaster &broadcaster = m_debugger_sp->GetBroadcaster();
4045863669SJonas Devlieghere 
4145863669SJonas Devlieghere     // Create a listener, make sure it can receive events and that it's
4245863669SJonas Devlieghere     // listening to the correct broadcast bit.
4345863669SJonas Devlieghere     m_listener_sp = Listener::MakeListener("progress-listener");
4445863669SJonas Devlieghere     m_listener_sp->StartListeningForEvents(&broadcaster, bit);
4545863669SJonas Devlieghere     return m_listener_sp;
4645863669SJonas Devlieghere   }
4745863669SJonas Devlieghere 
4845863669SJonas Devlieghere protected:
49a8ab8306SChelsea Cassanova   // The debugger's initialization function can't be called with no arguments
50a8ab8306SChelsea Cassanova   // so calling it using SubsystemRAII will cause the test build to fail as
51a8ab8306SChelsea Cassanova   // SubsystemRAII will call Initialize with no arguments. As such we set it up
52a8ab8306SChelsea Cassanova   // here the usual way.
53a8ab8306SChelsea Cassanova   void SetUp() override {
54a8ab8306SChelsea Cassanova     std::call_once(TestUtilities::g_debugger_initialize_flag,
55a8ab8306SChelsea Cassanova                    []() { Debugger::Initialize(nullptr); });
56a8ab8306SChelsea Cassanova   };
5745863669SJonas Devlieghere 
5845863669SJonas Devlieghere   DebuggerSP m_debugger_sp;
5945863669SJonas Devlieghere   ListenerSP m_listener_sp;
60156c2907SJonas Devlieghere   SubsystemRAII<FileSystem, HostInfo, PlatformMacOSX, ProgressManager>
61156c2907SJonas Devlieghere       subsystems;
62a8ab8306SChelsea Cassanova };
63a8ab8306SChelsea Cassanova 
64a8ab8306SChelsea Cassanova TEST_F(ProgressReportTest, TestReportCreation) {
65b9e3fa84SChelsea Cassanova   ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);
66a8ab8306SChelsea Cassanova   EventSP event_sp;
67a8ab8306SChelsea Cassanova   const ProgressEventData *data;
68a8ab8306SChelsea Cassanova 
69a8ab8306SChelsea Cassanova   // Scope this for RAII on the progress objects.
70a8ab8306SChelsea Cassanova   // Create progress reports and check that their respective events for having
71a8ab8306SChelsea Cassanova   // started and ended are broadcasted.
72a8ab8306SChelsea Cassanova   {
73a8ab8306SChelsea Cassanova     Progress progress1("Progress report 1", "Starting report 1");
74a8ab8306SChelsea Cassanova     Progress progress2("Progress report 2", "Starting report 2");
75a8ab8306SChelsea Cassanova     Progress progress3("Progress report 3", "Starting report 3");
76a8ab8306SChelsea Cassanova   }
77a8ab8306SChelsea Cassanova 
78a8ab8306SChelsea Cassanova   // Start popping events from the queue, they should have been recevied
79a8ab8306SChelsea Cassanova   // in this order:
80a8ab8306SChelsea Cassanova   // Starting progress: 1, 2, 3
81a8ab8306SChelsea Cassanova   // Ending progress: 3, 2, 1
8245863669SJonas Devlieghere   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
83a8ab8306SChelsea Cassanova   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
84a8ab8306SChelsea Cassanova 
8545863669SJonas Devlieghere   EXPECT_EQ(data->GetDetails(), "Starting report 1");
8645863669SJonas Devlieghere   EXPECT_FALSE(data->IsFinite());
8745863669SJonas Devlieghere   EXPECT_FALSE(data->GetCompleted());
8845863669SJonas Devlieghere   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
8945863669SJonas Devlieghere   EXPECT_EQ(data->GetMessage(), "Progress report 1: Starting report 1");
90a8ab8306SChelsea Cassanova 
9145863669SJonas Devlieghere   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
92a8ab8306SChelsea Cassanova   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
93a8ab8306SChelsea Cassanova 
9445863669SJonas Devlieghere   EXPECT_EQ(data->GetDetails(), "Starting report 2");
9545863669SJonas Devlieghere   EXPECT_FALSE(data->IsFinite());
9645863669SJonas Devlieghere   EXPECT_FALSE(data->GetCompleted());
9745863669SJonas Devlieghere   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
9845863669SJonas Devlieghere   EXPECT_EQ(data->GetMessage(), "Progress report 2: Starting report 2");
99a8ab8306SChelsea Cassanova 
10045863669SJonas Devlieghere   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
101a8ab8306SChelsea Cassanova   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
10245863669SJonas Devlieghere 
10345863669SJonas Devlieghere   EXPECT_EQ(data->GetDetails(), "Starting report 3");
10445863669SJonas Devlieghere   EXPECT_FALSE(data->IsFinite());
10545863669SJonas Devlieghere   EXPECT_FALSE(data->GetCompleted());
10645863669SJonas Devlieghere   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
10745863669SJonas Devlieghere   EXPECT_EQ(data->GetMessage(), "Progress report 3: Starting report 3");
108a8ab8306SChelsea Cassanova 
109a8ab8306SChelsea Cassanova   // Progress report objects should be destroyed at this point so
110a8ab8306SChelsea Cassanova   // get each report from the queue and check that they've been
111a8ab8306SChelsea Cassanova   // destroyed in reverse order.
11245863669SJonas Devlieghere   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
113a8ab8306SChelsea Cassanova   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
114a8ab8306SChelsea Cassanova 
11545863669SJonas Devlieghere   EXPECT_EQ(data->GetTitle(), "Progress report 3");
11645863669SJonas Devlieghere   EXPECT_TRUE(data->GetCompleted());
11745863669SJonas Devlieghere   EXPECT_FALSE(data->IsFinite());
11845863669SJonas Devlieghere   EXPECT_EQ(data->GetMessage(), "Progress report 3: Starting report 3");
119a8ab8306SChelsea Cassanova 
12045863669SJonas Devlieghere   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
121a8ab8306SChelsea Cassanova   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
122a8ab8306SChelsea Cassanova 
12345863669SJonas Devlieghere   EXPECT_EQ(data->GetTitle(), "Progress report 2");
12445863669SJonas Devlieghere   EXPECT_TRUE(data->GetCompleted());
12545863669SJonas Devlieghere   EXPECT_FALSE(data->IsFinite());
12645863669SJonas Devlieghere   EXPECT_EQ(data->GetMessage(), "Progress report 2: Starting report 2");
127a8ab8306SChelsea Cassanova 
12845863669SJonas Devlieghere   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
129a8ab8306SChelsea Cassanova   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
130a8ab8306SChelsea Cassanova 
13145863669SJonas Devlieghere   EXPECT_EQ(data->GetTitle(), "Progress report 1");
13245863669SJonas Devlieghere   EXPECT_TRUE(data->GetCompleted());
13345863669SJonas Devlieghere   EXPECT_FALSE(data->IsFinite());
13445863669SJonas Devlieghere   EXPECT_EQ(data->GetMessage(), "Progress report 1: Starting report 1");
135a8ab8306SChelsea Cassanova }
136137ed170SChelsea Cassanova 
13712fa4b17Sroyitaqi TEST_F(ProgressReportTest, TestReportDestructionWithPartialProgress) {
13812fa4b17Sroyitaqi   ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);
13912fa4b17Sroyitaqi   EventSP event_sp;
14012fa4b17Sroyitaqi   const ProgressEventData *data;
14112fa4b17Sroyitaqi 
14212fa4b17Sroyitaqi   // Create a finite progress report and only increment to a non-completed
14312fa4b17Sroyitaqi   // state before destruction.
14412fa4b17Sroyitaqi   {
14512fa4b17Sroyitaqi     Progress progress("Finite progress", "Report 1", 100);
14612fa4b17Sroyitaqi     progress.Increment(3);
14712fa4b17Sroyitaqi   }
14812fa4b17Sroyitaqi 
14912fa4b17Sroyitaqi   // Verify that the progress in the events are:
15012fa4b17Sroyitaqi   // 1. At construction: 0 out of 100
15112fa4b17Sroyitaqi   // 2. At increment: 3 out of 100
15212fa4b17Sroyitaqi   // 3. At destruction: 100 out of 100
15312fa4b17Sroyitaqi   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
15412fa4b17Sroyitaqi   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
15512fa4b17Sroyitaqi   EXPECT_EQ(data->GetDetails(), "Report 1");
15612fa4b17Sroyitaqi   EXPECT_TRUE(data->IsFinite());
15712fa4b17Sroyitaqi   EXPECT_EQ(data->GetCompleted(), (uint64_t)0);
15812fa4b17Sroyitaqi   EXPECT_EQ(data->GetTotal(), (uint64_t)100);
15912fa4b17Sroyitaqi   EXPECT_EQ(data->GetMessage(), "Finite progress: Report 1");
16012fa4b17Sroyitaqi 
16112fa4b17Sroyitaqi   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
16212fa4b17Sroyitaqi   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
16312fa4b17Sroyitaqi   EXPECT_EQ(data->GetDetails(), "Report 1");
16412fa4b17Sroyitaqi   EXPECT_TRUE(data->IsFinite());
16512fa4b17Sroyitaqi   EXPECT_EQ(data->GetCompleted(), (uint64_t)3);
16612fa4b17Sroyitaqi   EXPECT_EQ(data->GetTotal(), (uint64_t)100);
16712fa4b17Sroyitaqi   EXPECT_EQ(data->GetMessage(), "Finite progress: Report 1");
16812fa4b17Sroyitaqi 
16912fa4b17Sroyitaqi   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
17012fa4b17Sroyitaqi   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
17112fa4b17Sroyitaqi   EXPECT_EQ(data->GetDetails(), "Report 1");
17212fa4b17Sroyitaqi   EXPECT_TRUE(data->IsFinite());
17312fa4b17Sroyitaqi   EXPECT_EQ(data->GetCompleted(), (uint64_t)100);
17412fa4b17Sroyitaqi   EXPECT_EQ(data->GetTotal(), (uint64_t)100);
17512fa4b17Sroyitaqi   EXPECT_EQ(data->GetMessage(), "Finite progress: Report 1");
17612fa4b17Sroyitaqi 
17712fa4b17Sroyitaqi   // Create an infinite progress report and increment by some amount.
17812fa4b17Sroyitaqi   {
17912fa4b17Sroyitaqi     Progress progress("Infinite progress", "Report 2");
18012fa4b17Sroyitaqi     progress.Increment(3);
18112fa4b17Sroyitaqi   }
18212fa4b17Sroyitaqi 
18312fa4b17Sroyitaqi   // Verify that the progress in the events are:
18412fa4b17Sroyitaqi   // 1. At construction: 0
18512fa4b17Sroyitaqi   // 2. At increment: 3
18612fa4b17Sroyitaqi   // 3. At destruction: Progress::kNonDeterministicTotal
18712fa4b17Sroyitaqi   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
18812fa4b17Sroyitaqi   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
18912fa4b17Sroyitaqi   EXPECT_EQ(data->GetDetails(), "Report 2");
19012fa4b17Sroyitaqi   EXPECT_FALSE(data->IsFinite());
19112fa4b17Sroyitaqi   EXPECT_EQ(data->GetCompleted(), (uint64_t)0);
19212fa4b17Sroyitaqi   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
19312fa4b17Sroyitaqi   EXPECT_EQ(data->GetMessage(), "Infinite progress: Report 2");
19412fa4b17Sroyitaqi 
19512fa4b17Sroyitaqi   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
19612fa4b17Sroyitaqi   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
19712fa4b17Sroyitaqi   EXPECT_EQ(data->GetDetails(), "Report 2");
19812fa4b17Sroyitaqi   EXPECT_FALSE(data->IsFinite());
19912fa4b17Sroyitaqi   EXPECT_EQ(data->GetCompleted(), (uint64_t)3);
20012fa4b17Sroyitaqi   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
20112fa4b17Sroyitaqi   EXPECT_EQ(data->GetMessage(), "Infinite progress: Report 2");
20212fa4b17Sroyitaqi 
20312fa4b17Sroyitaqi   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
20412fa4b17Sroyitaqi   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
20512fa4b17Sroyitaqi   EXPECT_EQ(data->GetDetails(), "Report 2");
20612fa4b17Sroyitaqi   EXPECT_FALSE(data->IsFinite());
20712fa4b17Sroyitaqi   EXPECT_EQ(data->GetCompleted(), Progress::kNonDeterministicTotal);
20812fa4b17Sroyitaqi   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
20912fa4b17Sroyitaqi   EXPECT_EQ(data->GetMessage(), "Infinite progress: Report 2");
21012fa4b17Sroyitaqi }
21112fa4b17Sroyitaqi 
2120dbdc23eSPavel Labath TEST_F(ProgressReportTest, TestFiniteOverflow) {
2130dbdc23eSPavel Labath   ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);
2140dbdc23eSPavel Labath   EventSP event_sp;
2150dbdc23eSPavel Labath   const ProgressEventData *data;
2160dbdc23eSPavel Labath 
2170dbdc23eSPavel Labath   // Increment the report beyond its limit and make sure we only get one
2180dbdc23eSPavel Labath   // completed event.
2190dbdc23eSPavel Labath   {
2200dbdc23eSPavel Labath     Progress progress("Finite progress", "Report 1", 10);
2210dbdc23eSPavel Labath     progress.Increment(11);
2220dbdc23eSPavel Labath     progress.Increment(47);
2230dbdc23eSPavel Labath   }
2240dbdc23eSPavel Labath 
2250dbdc23eSPavel Labath   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
2260dbdc23eSPavel Labath   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
2270dbdc23eSPavel Labath   EXPECT_TRUE(data->IsFinite());
22811d2911eSKazu Hirata   EXPECT_EQ(data->GetCompleted(), 0U);
22911d2911eSKazu Hirata   EXPECT_EQ(data->GetTotal(), 10U);
2300dbdc23eSPavel Labath 
2310dbdc23eSPavel Labath   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
2320dbdc23eSPavel Labath   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
2330dbdc23eSPavel Labath   EXPECT_TRUE(data->IsFinite());
23411d2911eSKazu Hirata   EXPECT_EQ(data->GetCompleted(), 10U);
23511d2911eSKazu Hirata   EXPECT_EQ(data->GetTotal(), 10U);
2360dbdc23eSPavel Labath 
2370dbdc23eSPavel Labath   ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT));
2380dbdc23eSPavel Labath }
2390dbdc23eSPavel Labath 
2400dbdc23eSPavel Labath TEST_F(ProgressReportTest, TestNonDeterministicOverflow) {
2410dbdc23eSPavel Labath   ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);
2420dbdc23eSPavel Labath   EventSP event_sp;
2430dbdc23eSPavel Labath   const ProgressEventData *data;
2440dbdc23eSPavel Labath   constexpr uint64_t max_minus_1 = std::numeric_limits<uint64_t>::max() - 1;
2450dbdc23eSPavel Labath 
2460dbdc23eSPavel Labath   // Increment the report beyond its limit and make sure we only get one
2470dbdc23eSPavel Labath   // completed event. The event which overflows the counter should be ignored.
2480dbdc23eSPavel Labath   {
2490dbdc23eSPavel Labath     Progress progress("Non deterministic progress", "Report 1");
2500dbdc23eSPavel Labath     progress.Increment(max_minus_1);
2510dbdc23eSPavel Labath     progress.Increment(max_minus_1);
2520dbdc23eSPavel Labath   }
2530dbdc23eSPavel Labath 
2540dbdc23eSPavel Labath   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
2550dbdc23eSPavel Labath   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
2560dbdc23eSPavel Labath   EXPECT_FALSE(data->IsFinite());
25711d2911eSKazu Hirata   EXPECT_EQ(data->GetCompleted(), 0U);
2580dbdc23eSPavel Labath   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
2590dbdc23eSPavel Labath 
2600dbdc23eSPavel Labath   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
2610dbdc23eSPavel Labath   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
2620dbdc23eSPavel Labath   EXPECT_FALSE(data->IsFinite());
2630dbdc23eSPavel Labath   EXPECT_EQ(data->GetCompleted(), max_minus_1);
2640dbdc23eSPavel Labath   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
2650dbdc23eSPavel Labath 
2660dbdc23eSPavel Labath   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
2670dbdc23eSPavel Labath   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
2680dbdc23eSPavel Labath   EXPECT_FALSE(data->IsFinite());
2690dbdc23eSPavel Labath   EXPECT_EQ(data->GetCompleted(), Progress::kNonDeterministicTotal);
2700dbdc23eSPavel Labath   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
2710dbdc23eSPavel Labath 
2720dbdc23eSPavel Labath   ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT));
2730dbdc23eSPavel Labath }
2740dbdc23eSPavel Labath 
2750dbdc23eSPavel Labath TEST_F(ProgressReportTest, TestMinimumReportTime) {
2760dbdc23eSPavel Labath   ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);
2770dbdc23eSPavel Labath   EventSP event_sp;
2780dbdc23eSPavel Labath   const ProgressEventData *data;
2790dbdc23eSPavel Labath 
2800dbdc23eSPavel Labath   {
2810dbdc23eSPavel Labath     Progress progress("Finite progress", "Report 1", /*total=*/20,
2820dbdc23eSPavel Labath                       m_debugger_sp.get(),
2830dbdc23eSPavel Labath                       /*minimum_report_time=*/std::chrono::seconds(1));
2840dbdc23eSPavel Labath     // Send 10 events in quick succession. These should not generate any events.
2850dbdc23eSPavel Labath     for (int i = 0; i < 10; ++i)
2860dbdc23eSPavel Labath       progress.Increment();
2870dbdc23eSPavel Labath 
2880dbdc23eSPavel Labath     // Sleep, then send 10 more. This should generate one event for the first
2890dbdc23eSPavel Labath     // increment, and then another for completion.
2900dbdc23eSPavel Labath     std::this_thread::sleep_for(std::chrono::seconds(1));
2910dbdc23eSPavel Labath     for (int i = 0; i < 10; ++i)
2920dbdc23eSPavel Labath       progress.Increment();
2930dbdc23eSPavel Labath   }
2940dbdc23eSPavel Labath 
2950dbdc23eSPavel Labath   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
2960dbdc23eSPavel Labath   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
2970dbdc23eSPavel Labath   EXPECT_TRUE(data->IsFinite());
29811d2911eSKazu Hirata   EXPECT_EQ(data->GetCompleted(), 0U);
29911d2911eSKazu Hirata   EXPECT_EQ(data->GetTotal(), 20U);
3000dbdc23eSPavel Labath 
3010dbdc23eSPavel Labath   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
3020dbdc23eSPavel Labath   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
3030dbdc23eSPavel Labath   EXPECT_TRUE(data->IsFinite());
30411d2911eSKazu Hirata   EXPECT_EQ(data->GetCompleted(), 11U);
30511d2911eSKazu Hirata   EXPECT_EQ(data->GetTotal(), 20U);
3060dbdc23eSPavel Labath 
3070dbdc23eSPavel Labath   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
3080dbdc23eSPavel Labath   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
3090dbdc23eSPavel Labath   EXPECT_TRUE(data->IsFinite());
31011d2911eSKazu Hirata   EXPECT_EQ(data->GetCompleted(), 20U);
31111d2911eSKazu Hirata   EXPECT_EQ(data->GetTotal(), 20U);
3120dbdc23eSPavel Labath 
3130dbdc23eSPavel Labath   ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT));
3140dbdc23eSPavel Labath }
3150dbdc23eSPavel Labath 
316137ed170SChelsea Cassanova TEST_F(ProgressReportTest, TestProgressManager) {
31745863669SJonas Devlieghere   ListenerSP listener_sp =
318b9e3fa84SChelsea Cassanova       CreateListenerFor(lldb::eBroadcastBitProgressCategory);
319137ed170SChelsea Cassanova   EventSP event_sp;
320137ed170SChelsea Cassanova   const ProgressEventData *data;
321137ed170SChelsea Cassanova 
322137ed170SChelsea Cassanova   // Create three progress events with the same category then try to pop 2
323137ed170SChelsea Cassanova   // events from the queue in a row before the progress reports are destroyed.
324137ed170SChelsea Cassanova   // Since only 1 event should've been broadcast for this category, the second
325137ed170SChelsea Cassanova   // GetEvent() call should return false.
326137ed170SChelsea Cassanova   {
327137ed170SChelsea Cassanova     Progress progress1("Progress report 1", "Starting report 1");
328137ed170SChelsea Cassanova     Progress progress2("Progress report 1", "Starting report 2");
329137ed170SChelsea Cassanova     Progress progress3("Progress report 1", "Starting report 3");
33045863669SJonas Devlieghere     ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
33145863669SJonas Devlieghere     ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT));
332137ed170SChelsea Cassanova   }
333137ed170SChelsea Cassanova 
334137ed170SChelsea Cassanova   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
335137ed170SChelsea Cassanova 
33645863669SJonas Devlieghere   EXPECT_EQ(data->GetDetails(), "");
33745863669SJonas Devlieghere   EXPECT_FALSE(data->IsFinite());
33845863669SJonas Devlieghere   EXPECT_FALSE(data->GetCompleted());
33945863669SJonas Devlieghere   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
34045863669SJonas Devlieghere   EXPECT_EQ(data->GetMessage(), "Progress report 1");
341137ed170SChelsea Cassanova 
342137ed170SChelsea Cassanova   // Pop another event from the queue, this should be the event for the final
343137ed170SChelsea Cassanova   // report for this category.
34445863669SJonas Devlieghere   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
345137ed170SChelsea Cassanova   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
34645863669SJonas Devlieghere 
34745863669SJonas Devlieghere   EXPECT_EQ(data->GetDetails(), "");
34845863669SJonas Devlieghere   EXPECT_FALSE(data->IsFinite());
34945863669SJonas Devlieghere   EXPECT_TRUE(data->GetCompleted());
35045863669SJonas Devlieghere   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
35145863669SJonas Devlieghere   EXPECT_EQ(data->GetMessage(), "Progress report 1");
35245863669SJonas Devlieghere }
35345863669SJonas Devlieghere 
35445863669SJonas Devlieghere TEST_F(ProgressReportTest, TestOverlappingEvents) {
35545863669SJonas Devlieghere   ListenerSP listener_sp =
356b9e3fa84SChelsea Cassanova       CreateListenerFor(lldb::eBroadcastBitProgressCategory);
35745863669SJonas Devlieghere   EventSP event_sp;
35845863669SJonas Devlieghere   const ProgressEventData *data;
359137ed170SChelsea Cassanova 
360137ed170SChelsea Cassanova   // Create two progress reports of the same category that overlap with each
361137ed170SChelsea Cassanova   // other. Here we want to ensure that the ID broadcasted for the initial and
362137ed170SChelsea Cassanova   // final reports for this category are the same.
363137ed170SChelsea Cassanova   std::unique_ptr<Progress> overlap_progress1 =
364137ed170SChelsea Cassanova       std::make_unique<Progress>("Overlapping report 1", "Starting report 1");
365137ed170SChelsea Cassanova   std::unique_ptr<Progress> overlap_progress2 =
366137ed170SChelsea Cassanova       std::make_unique<Progress>("Overlapping report 1", "Starting report 2");
367137ed170SChelsea Cassanova   overlap_progress1.reset();
368137ed170SChelsea Cassanova 
36945863669SJonas Devlieghere   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
370137ed170SChelsea Cassanova   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
371137ed170SChelsea Cassanova   // Get the ID used in the first report for this category.
372137ed170SChelsea Cassanova   uint64_t expected_progress_id = data->GetID();
373137ed170SChelsea Cassanova 
37445863669SJonas Devlieghere   EXPECT_EQ(data->GetDetails(), "");
37545863669SJonas Devlieghere   EXPECT_FALSE(data->IsFinite());
37645863669SJonas Devlieghere   EXPECT_FALSE(data->GetCompleted());
37745863669SJonas Devlieghere   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
37845863669SJonas Devlieghere   EXPECT_EQ(data->GetMessage(), "Overlapping report 1");
379137ed170SChelsea Cassanova 
380137ed170SChelsea Cassanova   overlap_progress2.reset();
381137ed170SChelsea Cassanova 
38245863669SJonas Devlieghere   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
383137ed170SChelsea Cassanova   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
384137ed170SChelsea Cassanova 
38545863669SJonas Devlieghere   EXPECT_EQ(data->GetDetails(), "");
38645863669SJonas Devlieghere   EXPECT_FALSE(data->IsFinite());
38745863669SJonas Devlieghere   EXPECT_TRUE(data->GetCompleted());
38845863669SJonas Devlieghere   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
38945863669SJonas Devlieghere   EXPECT_EQ(data->GetMessage(), "Overlapping report 1");
390137ed170SChelsea Cassanova   // The progress ID for the final report should be the same as that for the
391137ed170SChelsea Cassanova   // initial report.
39245863669SJonas Devlieghere   EXPECT_EQ(data->GetID(), expected_progress_id);
393137ed170SChelsea Cassanova }
394156c2907SJonas Devlieghere 
395156c2907SJonas Devlieghere TEST_F(ProgressReportTest, TestProgressManagerDisjointReports) {
396156c2907SJonas Devlieghere   ListenerSP listener_sp =
397b9e3fa84SChelsea Cassanova       CreateListenerFor(lldb::eBroadcastBitProgressCategory);
398156c2907SJonas Devlieghere   EventSP event_sp;
399156c2907SJonas Devlieghere   const ProgressEventData *data;
400156c2907SJonas Devlieghere   uint64_t expected_progress_id;
401156c2907SJonas Devlieghere 
402156c2907SJonas Devlieghere   { Progress progress("Coalesced report 1", "Starting report 1"); }
403156c2907SJonas Devlieghere   { Progress progress("Coalesced report 1", "Starting report 2"); }
404156c2907SJonas Devlieghere   { Progress progress("Coalesced report 1", "Starting report 3"); }
405156c2907SJonas Devlieghere 
406156c2907SJonas Devlieghere   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
407156c2907SJonas Devlieghere   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
408156c2907SJonas Devlieghere   expected_progress_id = data->GetID();
409156c2907SJonas Devlieghere 
410156c2907SJonas Devlieghere   EXPECT_EQ(data->GetDetails(), "");
411156c2907SJonas Devlieghere   EXPECT_FALSE(data->IsFinite());
412156c2907SJonas Devlieghere   EXPECT_FALSE(data->GetCompleted());
413156c2907SJonas Devlieghere   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
414156c2907SJonas Devlieghere   EXPECT_EQ(data->GetMessage(), "Coalesced report 1");
415156c2907SJonas Devlieghere 
416156c2907SJonas Devlieghere   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
417156c2907SJonas Devlieghere   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
418156c2907SJonas Devlieghere 
419156c2907SJonas Devlieghere   EXPECT_EQ(data->GetID(), expected_progress_id);
420156c2907SJonas Devlieghere   EXPECT_EQ(data->GetDetails(), "");
421156c2907SJonas Devlieghere   EXPECT_FALSE(data->IsFinite());
422156c2907SJonas Devlieghere   EXPECT_TRUE(data->GetCompleted());
423156c2907SJonas Devlieghere   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
424156c2907SJonas Devlieghere   EXPECT_EQ(data->GetMessage(), "Coalesced report 1");
425156c2907SJonas Devlieghere 
426156c2907SJonas Devlieghere   ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT));
427156c2907SJonas Devlieghere }
428*774c2268SJacob Lalonde 
429*774c2268SJacob Lalonde TEST_F(ProgressReportTest, TestExternalReportCreation) {
430*774c2268SJacob Lalonde   ListenerSP listener_sp =
431*774c2268SJacob Lalonde       CreateListenerFor(lldb::eBroadcastBitExternalProgress);
432*774c2268SJacob Lalonde   EventSP event_sp;
433*774c2268SJacob Lalonde   const ProgressEventData *data;
434*774c2268SJacob Lalonde 
435*774c2268SJacob Lalonde   // Scope this for RAII on the progress objects.
436*774c2268SJacob Lalonde   // Create progress reports and check that their respective events for having
437*774c2268SJacob Lalonde   // started and ended are broadcasted.
438*774c2268SJacob Lalonde   {
439*774c2268SJacob Lalonde     Progress progress1("Progress report 1", "Starting report 1",
440*774c2268SJacob Lalonde                        /*total=*/std::nullopt, /*debugger=*/nullptr,
441*774c2268SJacob Lalonde                        /*minimum_report_time=*/std::chrono::seconds(0),
442*774c2268SJacob Lalonde                        Progress::Origin::eExternal);
443*774c2268SJacob Lalonde     Progress progress2("Progress report 2", "Starting report 2",
444*774c2268SJacob Lalonde                        /*total=*/std::nullopt, /*debugger=*/nullptr,
445*774c2268SJacob Lalonde                        /*minimum_report_time=*/std::chrono::seconds(0),
446*774c2268SJacob Lalonde                        Progress::Origin::eExternal);
447*774c2268SJacob Lalonde     Progress progress3("Progress report 3", "Starting report 3",
448*774c2268SJacob Lalonde                        /*total=*/std::nullopt, /*debugger=*/nullptr,
449*774c2268SJacob Lalonde                        /*minimum_report_time=*/std::chrono::seconds(0),
450*774c2268SJacob Lalonde                        Progress::Origin::eExternal);
451*774c2268SJacob Lalonde   }
452*774c2268SJacob Lalonde 
453*774c2268SJacob Lalonde   // Start popping events from the queue, they should have been recevied
454*774c2268SJacob Lalonde   // in this order:
455*774c2268SJacob Lalonde   // Starting progress: 1, 2, 3
456*774c2268SJacob Lalonde   // Ending progress: 3, 2, 1
457*774c2268SJacob Lalonde   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
458*774c2268SJacob Lalonde   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
459*774c2268SJacob Lalonde 
460*774c2268SJacob Lalonde   EXPECT_EQ(data->GetDetails(), "Starting report 1");
461*774c2268SJacob Lalonde   EXPECT_FALSE(data->IsFinite());
462*774c2268SJacob Lalonde   EXPECT_FALSE(data->GetCompleted());
463*774c2268SJacob Lalonde   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
464*774c2268SJacob Lalonde   EXPECT_EQ(data->GetMessage(), "Progress report 1: Starting report 1");
465*774c2268SJacob Lalonde 
466*774c2268SJacob Lalonde   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
467*774c2268SJacob Lalonde   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
468*774c2268SJacob Lalonde 
469*774c2268SJacob Lalonde   EXPECT_EQ(data->GetDetails(), "Starting report 2");
470*774c2268SJacob Lalonde   EXPECT_FALSE(data->IsFinite());
471*774c2268SJacob Lalonde   EXPECT_FALSE(data->GetCompleted());
472*774c2268SJacob Lalonde   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
473*774c2268SJacob Lalonde   EXPECT_EQ(data->GetMessage(), "Progress report 2: Starting report 2");
474*774c2268SJacob Lalonde 
475*774c2268SJacob Lalonde   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
476*774c2268SJacob Lalonde   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
477*774c2268SJacob Lalonde 
478*774c2268SJacob Lalonde   EXPECT_EQ(data->GetDetails(), "Starting report 3");
479*774c2268SJacob Lalonde   EXPECT_FALSE(data->IsFinite());
480*774c2268SJacob Lalonde   EXPECT_FALSE(data->GetCompleted());
481*774c2268SJacob Lalonde   EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);
482*774c2268SJacob Lalonde   EXPECT_EQ(data->GetMessage(), "Progress report 3: Starting report 3");
483*774c2268SJacob Lalonde 
484*774c2268SJacob Lalonde   // Progress report objects should be destroyed at this point so
485*774c2268SJacob Lalonde   // get each report from the queue and check that they've been
486*774c2268SJacob Lalonde   // destroyed in reverse order.
487*774c2268SJacob Lalonde   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
488*774c2268SJacob Lalonde   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
489*774c2268SJacob Lalonde 
490*774c2268SJacob Lalonde   EXPECT_EQ(data->GetTitle(), "Progress report 3");
491*774c2268SJacob Lalonde   EXPECT_TRUE(data->GetCompleted());
492*774c2268SJacob Lalonde   EXPECT_FALSE(data->IsFinite());
493*774c2268SJacob Lalonde   EXPECT_EQ(data->GetMessage(), "Progress report 3: Starting report 3");
494*774c2268SJacob Lalonde 
495*774c2268SJacob Lalonde   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
496*774c2268SJacob Lalonde   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
497*774c2268SJacob Lalonde 
498*774c2268SJacob Lalonde   EXPECT_EQ(data->GetTitle(), "Progress report 2");
499*774c2268SJacob Lalonde   EXPECT_TRUE(data->GetCompleted());
500*774c2268SJacob Lalonde   EXPECT_FALSE(data->IsFinite());
501*774c2268SJacob Lalonde   EXPECT_EQ(data->GetMessage(), "Progress report 2: Starting report 2");
502*774c2268SJacob Lalonde 
503*774c2268SJacob Lalonde   ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));
504*774c2268SJacob Lalonde   data = ProgressEventData::GetEventDataFromEvent(event_sp.get());
505*774c2268SJacob Lalonde 
506*774c2268SJacob Lalonde   EXPECT_EQ(data->GetTitle(), "Progress report 1");
507*774c2268SJacob Lalonde   EXPECT_TRUE(data->GetCompleted());
508*774c2268SJacob Lalonde   EXPECT_FALSE(data->IsFinite());
509*774c2268SJacob Lalonde   EXPECT_EQ(data->GetMessage(), "Progress report 1: Starting report 1");
510*774c2268SJacob Lalonde }
511*774c2268SJacob Lalonde 
512*774c2268SJacob Lalonde TEST_F(ProgressReportTest, TestExternalReportNotReceived) {
513*774c2268SJacob Lalonde   ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);
514*774c2268SJacob Lalonde   EventSP event_sp;
515*774c2268SJacob Lalonde 
516*774c2268SJacob Lalonde   // Scope this for RAII on the progress objects.
517*774c2268SJacob Lalonde   // Create progress reports and check that their respective events for having
518*774c2268SJacob Lalonde   // started and ended are broadcasted.
519*774c2268SJacob Lalonde   {
520*774c2268SJacob Lalonde     Progress progress1("External Progress report 1",
521*774c2268SJacob Lalonde                        "Starting external report 1",
522*774c2268SJacob Lalonde                        /*total=*/std::nullopt, /*debugger=*/nullptr,
523*774c2268SJacob Lalonde                        /*minimum_report_time=*/std::chrono::seconds(0),
524*774c2268SJacob Lalonde                        Progress::Origin::eExternal);
525*774c2268SJacob Lalonde   }
526*774c2268SJacob Lalonde 
527*774c2268SJacob Lalonde   ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT));
528*774c2268SJacob Lalonde }
529