brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.2 KiB · 592e13a Raw
415 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 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>21#include <thread>22 23using namespace lldb;24using namespace lldb_private;25 26static std::chrono::milliseconds TIMEOUT(500);27 28class ProgressReportTest : public ::testing::Test {29public:30  ListenerSP CreateListenerFor(uint32_t bit) {31    // Set up the debugger, make sure that was done properly.32    ArchSpec arch("x86_64-apple-macosx-");33    Platform::SetHostPlatform(34        PlatformRemoteMacOSX::CreateInstance(true, &arch));35 36    m_debugger_sp = Debugger::CreateInstance();37 38    // Get the debugger's broadcaster.39    Broadcaster &broadcaster = m_debugger_sp->GetBroadcaster();40 41    // Create a listener, make sure it can receive events and that it's42    // listening to the correct broadcast bit.43    m_listener_sp = Listener::MakeListener("progress-listener");44    m_listener_sp->StartListeningForEvents(&broadcaster, bit);45    return m_listener_sp;46  }47 48protected:49  // The debugger's initialization function can't be called with no arguments50  // so calling it using SubsystemRAII will cause the test build to fail as51  // SubsystemRAII will call Initialize with no arguments. As such we set it up52  // here the usual way.53  void SetUp() override {54    std::call_once(TestUtilities::g_debugger_initialize_flag,55                   []() { Debugger::Initialize(nullptr); });56  };57 58  DebuggerSP m_debugger_sp;59  ListenerSP m_listener_sp;60  SubsystemRAII<FileSystem, HostInfo, PlatformMacOSX> subsystems;61};62 63TEST_F(ProgressReportTest, TestReportCreation) {64  ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);65  EventSP event_sp;66  const ProgressEventData *data;67 68  // Scope this for RAII on the progress objects.69  // Create progress reports and check that their respective events for having70  // started and ended are broadcasted.71  {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");75  }76 77  // Start popping events from the queue, they should have been recevied78  // in this order:79  // Starting progress: 1, 2, 380  // Ending progress: 3, 2, 181  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));82  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());83 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");89 90  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));91  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());92 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");98 99  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));100  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());101 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");107 108  // Progress report objects should be destroyed at this point so109  // get each report from the queue and check that they've been110  // destroyed in reverse order.111  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));112  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());113 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");118 119  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));120  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());121 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");126 127  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));128  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());129 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");134}135 136TEST_F(ProgressReportTest, TestReportDestructionWithPartialProgress) {137  ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);138  EventSP event_sp;139  const ProgressEventData *data;140 141  // Create a finite progress report and only increment to a non-completed142  // state before destruction.143  {144    Progress progress("Finite progress", "Report 1", 100);145    progress.Increment(3);146  }147 148  // Verify that the progress in the events are:149  // 1. At construction: 0 out of 100150  // 2. At increment: 3 out of 100151  // 3. At destruction: 100 out of 100152  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");159 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");167 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");175 176  // Create an infinite progress report and increment by some amount.177  {178    Progress progress("Infinite progress", "Report 2");179    progress.Increment(3);180  }181 182  // Verify that the progress in the events are:183  // 1. At construction: 0184  // 2. At increment: 3185  // 3. At destruction: Progress::kNonDeterministicTotal186  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");193 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");201 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");209}210 211TEST_F(ProgressReportTest, TestFiniteOverflow) {212  ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);213  EventSP event_sp;214  const ProgressEventData *data;215 216  // Increment the report beyond its limit and make sure we only get one217  // completed event.218  {219    Progress progress("Finite progress", "Report 1", 10);220    progress.Increment(11);221    progress.Increment(47);222  }223 224  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));225  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());226  EXPECT_TRUE(data->IsFinite());227  EXPECT_EQ(data->GetCompleted(), 0U);228  EXPECT_EQ(data->GetTotal(), 10U);229 230  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));231  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());232  EXPECT_TRUE(data->IsFinite());233  EXPECT_EQ(data->GetCompleted(), 10U);234  EXPECT_EQ(data->GetTotal(), 10U);235 236  ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT));237}238 239TEST_F(ProgressReportTest, TestNonDeterministicOverflow) {240  ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);241  EventSP event_sp;242  const ProgressEventData *data;243  constexpr uint64_t max_minus_1 = std::numeric_limits<uint64_t>::max() - 1;244 245  // Increment the report beyond its limit and make sure we only get one246  // completed event. The event which overflows the counter should be ignored.247  {248    Progress progress("Non deterministic progress", "Report 1");249    progress.Increment(max_minus_1);250    progress.Increment(max_minus_1);251  }252 253  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));254  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());255  EXPECT_FALSE(data->IsFinite());256  EXPECT_EQ(data->GetCompleted(), 0U);257  EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);258 259  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));260  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());261  EXPECT_FALSE(data->IsFinite());262  EXPECT_EQ(data->GetCompleted(), max_minus_1);263  EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);264 265  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));266  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());267  EXPECT_FALSE(data->IsFinite());268  EXPECT_EQ(data->GetCompleted(), Progress::kNonDeterministicTotal);269  EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);270 271  ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT));272}273 274TEST_F(ProgressReportTest, TestMinimumReportTime) {275  ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);276  EventSP event_sp;277  const ProgressEventData *data;278 279  {280    Progress progress("Finite progress", "Report 1", /*total=*/20,281                      m_debugger_sp.get(),282                      /*minimum_report_time=*/std::chrono::seconds(1));283    // Send 10 events in quick succession. These should not generate any events.284    for (int i = 0; i < 10; ++i)285      progress.Increment();286 287    // Sleep, then send 10 more. This should generate one event for the first288    // increment, and then another for completion.289    std::this_thread::sleep_for(std::chrono::seconds(1));290    for (int i = 0; i < 10; ++i)291      progress.Increment();292  }293 294  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));295  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());296  EXPECT_TRUE(data->IsFinite());297  EXPECT_EQ(data->GetCompleted(), 0U);298  EXPECT_EQ(data->GetTotal(), 20U);299 300  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));301  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());302  EXPECT_TRUE(data->IsFinite());303  EXPECT_EQ(data->GetCompleted(), 11U);304  EXPECT_EQ(data->GetTotal(), 20U);305 306  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));307  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());308  EXPECT_TRUE(data->IsFinite());309  EXPECT_EQ(data->GetCompleted(), 20U);310  EXPECT_EQ(data->GetTotal(), 20U);311 312  ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT));313}314 315TEST_F(ProgressReportTest, TestExternalReportCreation) {316  ListenerSP listener_sp =317      CreateListenerFor(lldb::eBroadcastBitExternalProgress);318  EventSP event_sp;319  const ProgressEventData *data;320 321  // Scope this for RAII on the progress objects.322  // Create progress reports and check that their respective events for having323  // started and ended are broadcasted.324  {325    Progress progress1("Progress report 1", "Starting report 1",326                       /*total=*/std::nullopt, /*debugger=*/nullptr,327                       /*minimum_report_time=*/std::chrono::seconds(0),328                       Progress::Origin::eExternal);329    Progress progress2("Progress report 2", "Starting report 2",330                       /*total=*/std::nullopt, /*debugger=*/nullptr,331                       /*minimum_report_time=*/std::chrono::seconds(0),332                       Progress::Origin::eExternal);333    Progress progress3("Progress report 3", "Starting report 3",334                       /*total=*/std::nullopt, /*debugger=*/nullptr,335                       /*minimum_report_time=*/std::chrono::seconds(0),336                       Progress::Origin::eExternal);337  }338 339  // Start popping events from the queue, they should have been recevied340  // in this order:341  // Starting progress: 1, 2, 3342  // Ending progress: 3, 2, 1343  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));344  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());345 346  EXPECT_EQ(data->GetDetails(), "Starting report 1");347  EXPECT_FALSE(data->IsFinite());348  EXPECT_FALSE(data->GetCompleted());349  EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);350  EXPECT_EQ(data->GetMessage(), "Progress report 1: Starting report 1");351 352  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));353  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());354 355  EXPECT_EQ(data->GetDetails(), "Starting report 2");356  EXPECT_FALSE(data->IsFinite());357  EXPECT_FALSE(data->GetCompleted());358  EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);359  EXPECT_EQ(data->GetMessage(), "Progress report 2: Starting report 2");360 361  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));362  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());363 364  EXPECT_EQ(data->GetDetails(), "Starting report 3");365  EXPECT_FALSE(data->IsFinite());366  EXPECT_FALSE(data->GetCompleted());367  EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal);368  EXPECT_EQ(data->GetMessage(), "Progress report 3: Starting report 3");369 370  // Progress report objects should be destroyed at this point so371  // get each report from the queue and check that they've been372  // destroyed in reverse order.373  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));374  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());375 376  EXPECT_EQ(data->GetTitle(), "Progress report 3");377  EXPECT_TRUE(data->GetCompleted());378  EXPECT_FALSE(data->IsFinite());379  EXPECT_EQ(data->GetMessage(), "Progress report 3: Starting report 3");380 381  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));382  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());383 384  EXPECT_EQ(data->GetTitle(), "Progress report 2");385  EXPECT_TRUE(data->GetCompleted());386  EXPECT_FALSE(data->IsFinite());387  EXPECT_EQ(data->GetMessage(), "Progress report 2: Starting report 2");388 389  ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT));390  data = ProgressEventData::GetEventDataFromEvent(event_sp.get());391 392  EXPECT_EQ(data->GetTitle(), "Progress report 1");393  EXPECT_TRUE(data->GetCompleted());394  EXPECT_FALSE(data->IsFinite());395  EXPECT_EQ(data->GetMessage(), "Progress report 1: Starting report 1");396}397 398TEST_F(ProgressReportTest, TestExternalReportNotReceived) {399  ListenerSP listener_sp = CreateListenerFor(lldb::eBroadcastBitProgress);400  EventSP event_sp;401 402  // Scope this for RAII on the progress objects.403  // Create progress reports and check that their respective events for having404  // started and ended are broadcasted.405  {406    Progress progress1("External Progress report 1",407                       "Starting external report 1",408                       /*total=*/std::nullopt, /*debugger=*/nullptr,409                       /*minimum_report_time=*/std::chrono::seconds(0),410                       Progress::Origin::eExternal);411  }412 413  ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT));414}415