blob: 68762c78c369382cd1a44f83567b449fec51e42e [file] [log] [blame]
// Copyright 2017 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 "content/browser/tracing/background_memory_tracing_observer.h"
#include "base/allocator/buildflags.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/message_loop/message_loop.h"
#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_manager_test_utils.h"
#include "base/trace_event/trace_log.h"
#include "build/build_config.h"
#include "content/browser/tracing/background_tracing_config_impl.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::trace_event::AllocationContextTracker;
using base::trace_event::MemoryDumpManager;
using base::trace_event::TraceConfig;
using base::trace_event::TraceLog;
using base::trace_event::InitializeMemoryDumpManagerForInProcessTesting;
namespace content {
namespace {
std::unique_ptr<BackgroundTracingConfigImpl> ReadFromJSONString(
const std::string& json_text) {
std::unique_ptr<base::Value> json_value(base::JSONReader::Read(json_text));
base::DictionaryValue* dict = nullptr;
if (json_value)
json_value->GetAsDictionary(&dict);
std::unique_ptr<BackgroundTracingConfigImpl> config(
static_cast<BackgroundTracingConfigImpl*>(
BackgroundTracingConfig::FromDict(dict).release()));
CHECK(config);
return config;
}
} // namespace
class BackgroundMemoryTracingObserverTest : public testing::Test {
public:
BackgroundMemoryTracingObserverTest()
: ui_thread_(BrowserThread::UI, &message_loop_) {}
void SetUp() override {
mdm_ = MemoryDumpManager::CreateInstanceForTesting();
InitializeMemoryDumpManagerForInProcessTesting(
/*is_coordinator_process=*/false);
}
void TearDown() override { mdm_ = nullptr; }
private:
std::unique_ptr<MemoryDumpManager> mdm_;
base::MessageLoop message_loop_;
TestBrowserThread ui_thread_;
};
TEST_F(BackgroundMemoryTracingObserverTest, NoOpOnNonMemoryConfig) {
auto* observer = BackgroundMemoryTracingObserver::GetInstance();
auto config = ReadFromJSONString(
"{\"mode\":\"REACTIVE_TRACING_MODE\", \"configs\": [{\"category\": "
"\"BENCHMARK\", \"rule\": "
"\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\", "
"\"histogram_name\":\"foo\", \"histogram_lower_value\": 1, "
"\"histogram_upper_value\": 2}]}");
observer->OnScenarioActivated(config.get());
EXPECT_FALSE(observer->heap_profiling_enabled_for_testing());
observer->OnTracingEnabled(BackgroundTracingConfigImpl::BENCHMARK);
EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
AllocationContextTracker::capture_mode());
observer->OnScenarioAborted();
EXPECT_FALSE(observer->heap_profiling_enabled_for_testing());
EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
AllocationContextTracker::capture_mode());
}
TEST_F(BackgroundMemoryTracingObserverTest, OnlyBackgroundDumpConfig) {
auto* observer = BackgroundMemoryTracingObserver::GetInstance();
auto config = ReadFromJSONString(
"{\"mode\":\"REACTIVE_TRACING_MODE\", \"configs\": [{\"category\": "
"\"BENCHMARK_MEMORY_LIGHT\", \"rule\": "
"\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\", "
"\"histogram_name\":\"foo\", \"histogram_lower_value\": 1, "
"\"histogram_upper_value\": 2}]}");
observer->OnScenarioActivated(config.get());
EXPECT_FALSE(observer->heap_profiling_enabled_for_testing());
observer->OnTracingEnabled(BackgroundTracingConfigImpl::BENCHMARK);
EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
AllocationContextTracker::capture_mode());
observer->OnScenarioAborted();
EXPECT_FALSE(observer->heap_profiling_enabled_for_testing());
EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
AllocationContextTracker::capture_mode());
}
TEST_F(BackgroundMemoryTracingObserverTest, DISABLED_HeapProfilingConfig) {
auto* observer = BackgroundMemoryTracingObserver::GetInstance();
auto config = ReadFromJSONString(
"{\"mode\":\"REACTIVE_TRACING_MODE\", \"configs\": [{\"category\": "
"\"BENCHMARK_MEMORY_LIGHT\", \"rule\": "
"\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\", "
"\"histogram_name\":\"foo\", \"histogram_lower_value\": 1, "
"\"histogram_upper_value\": 2, \"args\": {\"enable_heap_profiler_mode\": "
"\"background\"}}]}");
observer->OnScenarioActivated(config.get());
EXPECT_TRUE(observer->heap_profiling_enabled_for_testing());
observer->OnTracingEnabled(BackgroundTracingConfigImpl::BENCHMARK);
EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
#if BUILDFLAG(USE_ALLOCATOR_SHIM) && !defined(OS_NACL)
EXPECT_EQ(AllocationContextTracker::CaptureMode::PSEUDO_STACK,
AllocationContextTracker::capture_mode());
#else
EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
AllocationContextTracker::capture_mode());
#endif
observer->OnScenarioAborted();
EXPECT_FALSE(observer->heap_profiling_enabled_for_testing());
EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
AllocationContextTracker::capture_mode());
}
TEST_F(BackgroundMemoryTracingObserverTest, DISABLED_HeapProfilingWithFilters) {
auto* observer = BackgroundMemoryTracingObserver::GetInstance();
auto config = ReadFromJSONString(
"{\"mode\":\"REACTIVE_TRACING_MODE\", \"configs\": [{\"category\": "
"\"BENCHMARK_MEMORY_LIGHT\", \"rule\": "
"\"MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE\", "
"\"histogram_name\":\"foo\", \"histogram_lower_value\": 1, "
"\"histogram_upper_value\": 2, \"args\": {\"enable_heap_profiler_mode\": "
"\"background\", \"heap_profiler_category_filter\": \"cat,dog\"}}]}");
observer->OnScenarioActivated(config.get());
EXPECT_TRUE(observer->heap_profiling_enabled_for_testing());
observer->OnTracingEnabled(BackgroundTracingConfigImpl::BENCHMARK);
#if BUILDFLAG(USE_ALLOCATOR_SHIM) && !defined(OS_NACL)
EXPECT_EQ(AllocationContextTracker::CaptureMode::PSEUDO_STACK,
AllocationContextTracker::capture_mode());
EXPECT_EQ(TraceLog::FILTERING_MODE, TraceLog::GetInstance()->enabled_modes());
const char kExpectedConfig[] =
"{\"filter_predicate\":\"heap_profiler_predicate\","
"\"included_categories\":[\"cat\",\"dog\"]}";
auto trace_config = TraceLog::GetInstance()->GetCurrentTraceConfig();
ASSERT_EQ(1u, trace_config.event_filters().size());
base::DictionaryValue filter_dict;
trace_config.event_filters()[0].ToDict(&filter_dict);
std::string filter_str;
base::JSONWriter::Write(filter_dict, &filter_str);
EXPECT_EQ(kExpectedConfig, filter_str);
#else // BUILDFLAG(USE_ALLOCATOR_SHIM) && !defined(OS_NACL)
EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
AllocationContextTracker::capture_mode());
#endif // BUILDFLAG(USE_ALLOCATOR_SHIM) && !defined(OS_NACL)
observer->OnScenarioAborted();
EXPECT_FALSE(observer->heap_profiling_enabled_for_testing());
EXPECT_EQ(0u, TraceLog::GetInstance()->enabled_modes());
EXPECT_EQ(AllocationContextTracker::CaptureMode::DISABLED,
AllocationContextTracker::capture_mode());
}
} // namespace content