blob: b5337e95c74afbd31b9f1f81c4a2e0059443b510 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/process_memory_dump.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
namespace base {
namespace trace_event {
class MemoryDumpManagerTest : public testing::Test {
public:
void SetUp() override {
MemoryDumpManager::GetInstance()->Initialize();
mdm_ = MemoryDumpManager::GetInstance();
}
void TearDown() override {
MemoryDumpManager::DeleteForTesting();
TraceLog::DeleteForTesting();
mdm_ = NULL;
}
protected:
const char* const kTraceCategory = MemoryDumpManager::kTraceCategory;
void EnableTracing(const char* category) {
TraceLog::GetInstance()->SetEnabled(
CategoryFilter(category), TraceLog::RECORDING_MODE, TraceOptions());
}
void DisableTracing() { TraceLog::GetInstance()->SetDisabled(); }
MemoryDumpManager* mdm_;
private:
// We want our singleton torn down after each test.
ShadowingAtExitManager at_exit_manager_;
};
class MockDumpProvider : public MemoryDumpProvider {
public:
MOCK_METHOD1(DumpInto, void(ProcessMemoryDump* pmd));
};
TEST_F(MemoryDumpManagerTest, SingleDumper) {
MockDumpProvider mdp;
mdm_->RegisterDumpProvider(&mdp);
// Check that the dumper is not called if the memory category is not enabled.
EnableTracing("foo-and-bar-but-not-memory");
EXPECT_CALL(mdp, DumpInto(_)).Times(0);
mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
DisableTracing();
// Now repeat enabling the memory category and check that the dumper is
// invoked this time.
EnableTracing(kTraceCategory);
EXPECT_CALL(mdp, DumpInto(_)).Times(3);
for (int i = 0; i < 3; ++i)
mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
DisableTracing();
mdm_->UnregisterDumpProvider(&mdp);
// Finally check the unregister logic (no calls to the mdp after unregister).
EnableTracing(kTraceCategory);
EXPECT_CALL(mdp, DumpInto(_)).Times(0);
mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
TraceLog::GetInstance()->SetDisabled();
}
TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileTracing) {
MockDumpProvider mdp;
mdm_->RegisterDumpProvider(&mdp);
EnableTracing(kTraceCategory);
EXPECT_CALL(mdp, DumpInto(_)).Times(1);
mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
mdm_->UnregisterDumpProvider(&mdp);
EXPECT_CALL(mdp, DumpInto(_)).Times(0);
mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
DisableTracing();
}
TEST_F(MemoryDumpManagerTest, MultipleDumpers) {
MockDumpProvider mdp1;
MockDumpProvider mdp2;
// Enable only mdp1.
mdm_->RegisterDumpProvider(&mdp1);
EnableTracing(kTraceCategory);
EXPECT_CALL(mdp1, DumpInto(_)).Times(1);
EXPECT_CALL(mdp2, DumpInto(_)).Times(0);
mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
DisableTracing();
// Invert: enable mdp1 and disable mdp2.
mdm_->UnregisterDumpProvider(&mdp1);
mdm_->RegisterDumpProvider(&mdp2);
EnableTracing(kTraceCategory);
EXPECT_CALL(mdp1, DumpInto(_)).Times(0);
EXPECT_CALL(mdp2, DumpInto(_)).Times(1);
mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
DisableTracing();
// Enable both mdp1 and mdp2.
mdm_->RegisterDumpProvider(&mdp1);
EnableTracing(kTraceCategory);
EXPECT_CALL(mdp1, DumpInto(_)).Times(1);
EXPECT_CALL(mdp2, DumpInto(_)).Times(1);
mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED);
DisableTracing();
}
} // namespace trace_Event
} // namespace base