Chromium Code Reviews| Index: base/trace_event/memory_dump_scheduler_unittest.cc |
| diff --git a/base/trace_event/memory_dump_scheduler_unittest.cc b/base/trace_event/memory_dump_scheduler_unittest.cc |
| index 9af2a3b4306bf1b6ecf08b3cf66a417b61659ee5..a7049a1c3ffc71ce32000118ea9a76cee1387c64 100644 |
| --- a/base/trace_event/memory_dump_scheduler_unittest.cc |
| +++ b/base/trace_event/memory_dump_scheduler_unittest.cc |
| @@ -6,96 +6,88 @@ |
| #include <memory> |
| +#include "base/bind.h" |
| #include "base/single_thread_task_runner.h" |
| +#include "base/synchronization/waitable_event.h" |
| +#include "base/threading/thread.h" |
| +#include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| +using ::testing::Invoke; |
| +using ::testing::_; |
| + |
| namespace base { |
| namespace trace_event { |
| -class MemoryDumpSchedulerPollingTest : public testing::Test { |
| +namespace { |
| + |
| +// Wrapper to use gmock on a callback. |
| +struct SchedulerCallbackWrapper { |
| + MOCK_METHOD1(OnTick, void(MemoryDumpLevelOfDetail)); |
| +}; |
| + |
| +} // namespace |
| + |
| +class MemoryDumpSchedulerTest : public testing::Test { |
| public: |
| - static const uint32_t kMinPollsToDump = 5; |
| + struct FriendDeleter { |
| + void operator()(MemoryDumpScheduler* inst) { delete inst; } |
| + }; |
| - MemoryDumpSchedulerPollingTest() |
| - : testing::Test(), |
| - num_samples_tracked_( |
| - MemoryDumpScheduler::PollingTriggerState::kMaxNumMemorySamples) {} |
| + MemoryDumpSchedulerTest() : testing::Test() {} |
| void SetUp() override { |
| - MemoryDumpScheduler::SetPollingIntervalForTesting(1); |
| - uint32_t kMinPollsToDump = 5; |
| - mds_ = MemoryDumpScheduler::GetInstance(); |
| - mds_->Setup(nullptr, nullptr); |
| - mds_->AddTrigger(MemoryDumpType::PEAK_MEMORY_USAGE, |
| - MemoryDumpLevelOfDetail::LIGHT, kMinPollsToDump); |
| - mds_->polling_state_->ResetTotals(); |
| - mds_->polling_state_->current_state = |
| - MemoryDumpScheduler::PollingTriggerState::ENABLED; |
| + bg_thread_.reset(new Thread("MemoryDumpSchedulerTest Thread")); |
| + bg_thread_->Start(); |
| + scheduler_.reset(new MemoryDumpScheduler()); |
| } |
| void TearDown() override { |
| - mds_->polling_state_->current_state = |
| - MemoryDumpScheduler::PollingTriggerState::DISABLED; |
| + bg_thread_.reset(); |
| + scheduler_.reset(); |
| } |
| protected: |
| - bool ShouldTriggerDump(uint64_t total) { |
| - return mds_->ShouldTriggerDump(total); |
| - } |
| - |
| - uint32_t num_samples_tracked_; |
| - MemoryDumpScheduler* mds_; |
| + std::unique_ptr<MemoryDumpScheduler, FriendDeleter> scheduler_; |
| + std::unique_ptr<Thread> bg_thread_; |
| + SchedulerCallbackWrapper on_tick_callback_; |
| }; |
| -TEST_F(MemoryDumpSchedulerPollingTest, PeakDetection) { |
| - for (uint32_t i = 0; i < num_samples_tracked_ * 6; ++i) { |
| - // Memory is increased in steps and dumps must be triggered at every step. |
| - uint64_t total = (2 + (i / (2 * num_samples_tracked_))) * 1024 * 1204; |
| - bool did_trigger = ShouldTriggerDump(total); |
| - // Dumps must be triggered only at specific iterations. |
| - bool should_have_triggered = i == 0; |
| - should_have_triggered |= |
| - (i > num_samples_tracked_) && (i % (2 * num_samples_tracked_) == 1); |
| - if (should_have_triggered) { |
| - ASSERT_TRUE(did_trigger) << "Dump wasn't triggered at " << i; |
| - } else { |
| - ASSERT_FALSE(did_trigger) << "Unexpected dump at " << i; |
| - } |
| - } |
| -} |
| +TEST_F(MemoryDumpSchedulerTest, SingleTrigger) { |
|
ssid
2017/04/05 22:04:22
We should remove some tests from MDM maybe, which
Primiano Tucci (use gerrit)
2017/04/10 19:16:41
I simplified a bit the TestPollingOnDumpThread lim
ssid
2017/04/10 21:35:51
You are right. They test trace config parsing.
|
| + const uint32_t kPeriodMs = 1; |
| + const auto kLevelOfDetail = MemoryDumpLevelOfDetail::DETAILED; |
| + const uint32_t kTicks = 10; |
| + WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL, |
| + WaitableEvent::InitialState::NOT_SIGNALED); |
| + MemoryDumpScheduler::Config config; |
| + config.triggers.push_back({kLevelOfDetail, kPeriodMs}); |
| + config.callback = |
| + Bind(&SchedulerCallbackWrapper::OnTick, Unretained(&on_tick_callback_)); |
| -TEST_F(MemoryDumpSchedulerPollingTest, SlowGrowthDetection) { |
| - for (uint32_t i = 0; i < 15; ++i) { |
| - // Record 1GiB of increase in each call. Dumps are triggered with 1% w.r.t |
| - // system's total memory. |
| - uint64_t total = static_cast<uint64_t>(i + 1) * 1024 * 1024 * 1024; |
| - bool did_trigger = ShouldTriggerDump(total); |
| - bool should_have_triggered = i % kMinPollsToDump == 0; |
| - if (should_have_triggered) { |
| - ASSERT_TRUE(did_trigger) << "Dump wasn't triggered at " << i; |
| - } else { |
| - ASSERT_FALSE(did_trigger) << "Unexpected dump at " << i; |
| - } |
| - } |
| -} |
| + uint32_t num_ticks = 0; |
| + EXPECT_CALL(on_tick_callback_, OnTick(_)) |
| + .WillRepeatedly(Invoke([&num_ticks, &evt, kTicks, kLevelOfDetail]( |
| + MemoryDumpLevelOfDetail level_of_detail) { |
| + EXPECT_EQ(kLevelOfDetail, level_of_detail); |
| + if (++num_ticks == kTicks) |
| + evt.Signal(); |
| + })); |
| + const TimeTicks tstart = TimeTicks::Now(); |
| -TEST_F(MemoryDumpSchedulerPollingTest, NotifyDumpTriggered) { |
| - for (uint32_t i = 0; i < num_samples_tracked_ * 6; ++i) { |
| - uint64_t total = (2 + (i / (2 * num_samples_tracked_))) * 1024 * 1204; |
| - if (i % num_samples_tracked_ == 0) |
| - mds_->NotifyDumpTriggered(); |
| - bool did_trigger = ShouldTriggerDump(total); |
| - // Dumps should never be triggered since NotifyDumpTriggered() is called |
| - // frequently. |
| - EXPECT_NE(0u, mds_->polling_state_->last_dump_memory_total); |
| - EXPECT_GT(num_samples_tracked_ - 1, |
| - mds_->polling_state_->last_memory_totals_kb_index); |
| - EXPECT_LT(static_cast<int64_t>( |
| - total - mds_->polling_state_->last_dump_memory_total), |
| - mds_->polling_state_->memory_increase_threshold); |
| - ASSERT_FALSE(did_trigger && i) << "Unexpected dump at " << i; |
| - } |
| + // Check that Stop() before Start() doesn't cause any error. |
| + scheduler_->Stop(); |
| + |
| + scheduler_->Start(config, bg_thread_->task_runner()); |
| + evt.Wait(); |
| + const double time_ms = (TimeTicks::Now() - tstart).InMillisecondsF(); |
| + EXPECT_GE(time_ms, kPeriodMs * kTicks); |
| + |
| + // Check that stopping twice doesn't cause any problems. |
| + scheduler_->Stop(); |
| + scheduler_->Stop(); |
| } |
| +// TODO add other tests to cover StartStopQuickly and multiple triggers. |
| + |
| } // namespace trace_event |
| } // namespace base |