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