| Index: base/trace_event/heap_profiler_heap_dump_writer_unittest.cc
|
| diff --git a/base/trace_event/heap_profiler_heap_dump_writer_unittest.cc b/base/trace_event/heap_profiler_heap_dump_writer_unittest.cc
|
| deleted file mode 100644
|
| index 800b6235ea6d1e2e648b27ebb843acd4d4e70548..0000000000000000000000000000000000000000
|
| --- a/base/trace_event/heap_profiler_heap_dump_writer_unittest.cc
|
| +++ /dev/null
|
| @@ -1,333 +0,0 @@
|
| -// 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/heap_profiler_heap_dump_writer.h"
|
| -
|
| -#include <stddef.h>
|
| -
|
| -#include <memory>
|
| -#include <set>
|
| -#include <string>
|
| -
|
| -#include "base/json/json_reader.h"
|
| -#include "base/macros.h"
|
| -#include "base/memory/ptr_util.h"
|
| -#include "base/trace_event/heap_profiler_allocation_context.h"
|
| -#include "base/trace_event/heap_profiler_stack_frame_deduplicator.h"
|
| -#include "base/trace_event/heap_profiler_type_name_deduplicator.h"
|
| -#include "base/trace_event/memory_dump_session_state.h"
|
| -#include "base/trace_event/trace_event_argument.h"
|
| -#include "base/values.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -namespace {
|
| -
|
| -using base::trace_event::StackFrame;
|
| -
|
| -// Define all strings once, because the deduplicator requires pointer equality,
|
| -// and string interning is unreliable.
|
| -StackFrame kBrowserMain = StackFrame::FromTraceEventName("BrowserMain");
|
| -StackFrame kRendererMain = StackFrame::FromTraceEventName("RendererMain");
|
| -StackFrame kCreateWidget = StackFrame::FromTraceEventName("CreateWidget");
|
| -StackFrame kInitialize = StackFrame::FromTraceEventName("Initialize");
|
| -StackFrame kGetBitmap = StackFrame::FromTraceEventName("GetBitmap");
|
| -
|
| -const char kInt[] = "int";
|
| -const char kBool[] = "bool";
|
| -const char kString[] = "string";
|
| -
|
| -} // namespace
|
| -
|
| -namespace base {
|
| -namespace trace_event {
|
| -namespace internal {
|
| -
|
| -std::unique_ptr<const Value> WriteAndReadBack(const std::set<Entry>& entries) {
|
| - std::unique_ptr<TracedValue> traced_value = Serialize(entries);
|
| - std::string json;
|
| - traced_value->AppendAsTraceFormat(&json);
|
| - return JSONReader::Read(json);
|
| -}
|
| -
|
| -std::unique_ptr<const DictionaryValue> WriteAndReadBackEntry(Entry entry) {
|
| - std::set<Entry> input_entries;
|
| - input_entries.insert(entry);
|
| -
|
| - std::unique_ptr<const Value> json_dict = WriteAndReadBack(input_entries);
|
| -
|
| - // Note: Ideally these should use |ASSERT_TRUE| instead of |EXPECT_TRUE|, but
|
| - // |ASSERT_TRUE| can only be used in void functions.
|
| - const DictionaryValue* dictionary;
|
| - EXPECT_TRUE(json_dict->GetAsDictionary(&dictionary));
|
| -
|
| - const ListValue* json_entries;
|
| - EXPECT_TRUE(dictionary->GetList("entries", &json_entries));
|
| -
|
| - const DictionaryValue* json_entry;
|
| - EXPECT_TRUE(json_entries->GetDictionary(0, &json_entry));
|
| -
|
| - return json_entry->CreateDeepCopy();
|
| -}
|
| -
|
| -// Given a desired stack frame ID and type ID, looks up the entry in the set and
|
| -// asserts that it is present and has the expected size and count.
|
| -void AssertSizeAndCountEq(const std::set<Entry>& entries,
|
| - int stack_frame_id,
|
| - int type_id,
|
| - const AllocationMetrics& expected) {
|
| - // The comparison operator for |Entry| does not take size into account, so by
|
| - // setting only stack frame ID and type ID, the real entry can be found.
|
| - Entry entry;
|
| - entry.stack_frame_id = stack_frame_id;
|
| - entry.type_id = type_id;
|
| - auto it = entries.find(entry);
|
| -
|
| - ASSERT_NE(entries.end(), it) << "No entry found for sf = " << stack_frame_id
|
| - << ", type = " << type_id << ".";
|
| - ASSERT_EQ(expected.size, it->size) << "Wrong size for sf = " << stack_frame_id
|
| - << ", type = " << type_id << ".";
|
| - ASSERT_EQ(expected.count, it->count)
|
| - << "Wrong count for sf = " << stack_frame_id << ", type = " << type_id
|
| - << ".";
|
| -}
|
| -
|
| -// Given a desired stack frame ID and type ID, asserts that no entry was dumped
|
| -// for that that particular combination of stack frame and type.
|
| -void AssertNotDumped(const std::set<Entry>& entries,
|
| - int stack_frame_id,
|
| - int type_id) {
|
| - // The comparison operator for |Entry| does not take size into account, so by
|
| - // setting only stack frame ID and type ID, the real entry can be found.
|
| - Entry entry;
|
| - entry.stack_frame_id = stack_frame_id;
|
| - entry.type_id = type_id;
|
| - auto it = entries.find(entry);
|
| - ASSERT_EQ(entries.end(), it)
|
| - << "Entry should not be present for sf = " << stack_frame_id
|
| - << ", type = " << type_id << ".";
|
| -}
|
| -
|
| -TEST(HeapDumpWriterTest, BacktraceIndex) {
|
| - Entry entry;
|
| - entry.stack_frame_id = -1; // -1 means empty backtrace.
|
| - entry.type_id = 0;
|
| - entry.size = 1;
|
| - entry.count = 1;
|
| -
|
| - std::unique_ptr<const DictionaryValue> json_entry =
|
| - WriteAndReadBackEntry(entry);
|
| -
|
| - // For an empty backtrace, the "bt" key cannot reference a stack frame.
|
| - // Instead it should be set to the empty string.
|
| - std::string backtrace_index;
|
| - ASSERT_TRUE(json_entry->GetString("bt", &backtrace_index));
|
| - ASSERT_EQ("", backtrace_index);
|
| -
|
| - // Also verify that a non-negative backtrace index is dumped properly.
|
| - entry.stack_frame_id = 2;
|
| - json_entry = WriteAndReadBackEntry(entry);
|
| - ASSERT_TRUE(json_entry->GetString("bt", &backtrace_index));
|
| - ASSERT_EQ("2", backtrace_index);
|
| -}
|
| -
|
| -TEST(HeapDumpWriterTest, TypeId) {
|
| - Entry entry;
|
| - entry.type_id = -1; // -1 means sum over all types.
|
| - entry.stack_frame_id = 0;
|
| - entry.size = 1;
|
| - entry.count = 1;
|
| -
|
| - std::unique_ptr<const DictionaryValue> json_entry =
|
| - WriteAndReadBackEntry(entry);
|
| -
|
| - // Entries for the cumulative size of all types should not have the "type"
|
| - // key set.
|
| - ASSERT_FALSE(json_entry->HasKey("type"));
|
| -
|
| - // Also verify that a non-negative type ID is dumped properly.
|
| - entry.type_id = 2;
|
| - json_entry = WriteAndReadBackEntry(entry);
|
| - std::string type_id;
|
| - ASSERT_TRUE(json_entry->GetString("type", &type_id));
|
| - ASSERT_EQ("2", type_id);
|
| -}
|
| -
|
| -TEST(HeapDumpWriterTest, SizeAndCountAreHexadecimal) {
|
| - // Take a number between 2^63 and 2^64 (or between 2^31 and 2^32 if |size_t|
|
| - // is not 64 bits).
|
| - const size_t large_value =
|
| - sizeof(size_t) == 8 ? 0xffffffffffffffc5 : 0xffffff9d;
|
| - const char* large_value_str =
|
| - sizeof(size_t) == 8 ? "ffffffffffffffc5" : "ffffff9d";
|
| - Entry entry;
|
| - entry.type_id = 0;
|
| - entry.stack_frame_id = 0;
|
| - entry.size = large_value;
|
| - entry.count = large_value;
|
| -
|
| - std::unique_ptr<const DictionaryValue> json_entry =
|
| - WriteAndReadBackEntry(entry);
|
| -
|
| - std::string size;
|
| - ASSERT_TRUE(json_entry->GetString("size", &size));
|
| - ASSERT_EQ(large_value_str, size);
|
| -
|
| - std::string count;
|
| - ASSERT_TRUE(json_entry->GetString("count", &count));
|
| - ASSERT_EQ(large_value_str, count);
|
| -}
|
| -
|
| -TEST(HeapDumpWriterTest, BacktraceTypeNameTable) {
|
| - hash_map<AllocationContext, AllocationMetrics> metrics_by_context;
|
| -
|
| - AllocationContext ctx;
|
| - ctx.backtrace.frames[0] = kBrowserMain;
|
| - ctx.backtrace.frames[1] = kCreateWidget;
|
| - ctx.backtrace.frame_count = 2;
|
| - ctx.type_name = kInt;
|
| -
|
| - // 10 bytes with context { type: int, bt: [BrowserMain, CreateWidget] }.
|
| - metrics_by_context[ctx] = {10, 5};
|
| -
|
| - ctx.type_name = kBool;
|
| -
|
| - // 18 bytes with context { type: bool, bt: [BrowserMain, CreateWidget] }.
|
| - metrics_by_context[ctx] = {18, 18};
|
| -
|
| - ctx.backtrace.frames[0] = kRendererMain;
|
| - ctx.backtrace.frames[1] = kInitialize;
|
| - ctx.backtrace.frame_count = 2;
|
| -
|
| - // 30 bytes with context { type: bool, bt: [RendererMain, Initialize] }.
|
| - metrics_by_context[ctx] = {30, 30};
|
| -
|
| - ctx.type_name = kString;
|
| -
|
| - // 19 bytes with context { type: string, bt: [RendererMain, Initialize] }.
|
| - metrics_by_context[ctx] = {19, 4};
|
| -
|
| - // At this point the heap looks like this:
|
| - //
|
| - // | | CrWidget <- BrMain | Init <- RenMain | Sum |
|
| - // +--------+--------------------+-----------------+-------------+
|
| - // | | size count | size count | size count |
|
| - // | int | 10 5 | 0 0 | 10 5 |
|
| - // | bool | 18 18 | 30 30 | 48 48 |
|
| - // | string | 0 0 | 19 4 | 19 4 |
|
| - // +--------+--------------------+-----------------+-------------+
|
| - // | Sum | 28 23 | 49 34 | 77 57 |
|
| -
|
| - auto stack_frame_deduplicator = WrapUnique(new StackFrameDeduplicator);
|
| - auto type_name_deduplicator = WrapUnique(new TypeNameDeduplicator);
|
| - HeapDumpWriter writer(stack_frame_deduplicator.get(),
|
| - type_name_deduplicator.get(),
|
| - 10u);
|
| - const std::set<Entry>& dump = writer.Summarize(metrics_by_context);
|
| -
|
| - // Get the indices of the backtraces and types by adding them again to the
|
| - // deduplicator. Because they were added before, the same number is returned.
|
| - StackFrame bt0[] = {kRendererMain, kInitialize};
|
| - StackFrame bt1[] = {kBrowserMain, kCreateWidget};
|
| - int bt_renderer_main = stack_frame_deduplicator->Insert(bt0, bt0 + 1);
|
| - int bt_browser_main = stack_frame_deduplicator->Insert(bt1, bt1 + 1);
|
| - int bt_renderer_main_initialize =
|
| - stack_frame_deduplicator->Insert(bt0, bt0 + 2);
|
| - int bt_browser_main_create_widget =
|
| - stack_frame_deduplicator->Insert(bt1, bt1 + 2);
|
| - int type_id_int = type_name_deduplicator->Insert(kInt);
|
| - int type_id_bool = type_name_deduplicator->Insert(kBool);
|
| - int type_id_string = type_name_deduplicator->Insert(kString);
|
| -
|
| - // Full heap should have size 77.
|
| - AssertSizeAndCountEq(dump, -1, -1, {77, 57});
|
| -
|
| - // 49 bytes in 34 chunks were allocated in RendererMain and children. Also
|
| - // check the type breakdown.
|
| - AssertSizeAndCountEq(dump, bt_renderer_main, -1, {49, 34});
|
| - AssertSizeAndCountEq(dump, bt_renderer_main, type_id_bool, {30, 30});
|
| - AssertSizeAndCountEq(dump, bt_renderer_main, type_id_string, {19, 4});
|
| -
|
| - // 28 bytes in 23 chunks were allocated in BrowserMain and children. Also
|
| - // check the type breakdown.
|
| - AssertSizeAndCountEq(dump, bt_browser_main, -1, {28, 23});
|
| - AssertSizeAndCountEq(dump, bt_browser_main, type_id_int, {10, 5});
|
| - AssertSizeAndCountEq(dump, bt_browser_main, type_id_bool, {18, 18});
|
| -
|
| - // In this test all bytes are allocated in leaf nodes, so check again one
|
| - // level deeper.
|
| - AssertSizeAndCountEq(dump, bt_renderer_main_initialize, -1, {49, 34});
|
| - AssertSizeAndCountEq(dump, bt_renderer_main_initialize, type_id_bool,
|
| - {30, 30});
|
| - AssertSizeAndCountEq(dump, bt_renderer_main_initialize, type_id_string,
|
| - {19, 4});
|
| - AssertSizeAndCountEq(dump, bt_browser_main_create_widget, -1, {28, 23});
|
| - AssertSizeAndCountEq(dump, bt_browser_main_create_widget, type_id_int,
|
| - {10, 5});
|
| - AssertSizeAndCountEq(dump, bt_browser_main_create_widget, type_id_bool,
|
| - {18, 18});
|
| -
|
| - // The type breakdown of the entrie heap should have been dumped as well.
|
| - AssertSizeAndCountEq(dump, -1, type_id_int, {10, 5});
|
| - AssertSizeAndCountEq(dump, -1, type_id_bool, {48, 48});
|
| - AssertSizeAndCountEq(dump, -1, type_id_string, {19, 4});
|
| -}
|
| -
|
| -TEST(HeapDumpWriterTest, InsignificantValuesNotDumped) {
|
| - hash_map<AllocationContext, AllocationMetrics> metrics_by_context;
|
| -
|
| - AllocationContext ctx;
|
| - ctx.backtrace.frames[0] = kBrowserMain;
|
| - ctx.backtrace.frames[1] = kCreateWidget;
|
| - ctx.backtrace.frame_count = 2;
|
| -
|
| - // 0.5 KiB and 1 chunk in BrowserMain -> CreateWidget itself.
|
| - metrics_by_context[ctx] = {512, 1};
|
| -
|
| - // 1 MiB and 1 chunk in BrowserMain -> CreateWidget -> GetBitmap.
|
| - ctx.backtrace.frames[2] = kGetBitmap;
|
| - ctx.backtrace.frame_count = 3;
|
| - metrics_by_context[ctx] = {1024 * 1024, 1};
|
| -
|
| - // 400B and 1 chunk in BrowserMain -> CreateWidget -> Initialize.
|
| - ctx.backtrace.frames[2] = kInitialize;
|
| - ctx.backtrace.frame_count = 3;
|
| - metrics_by_context[ctx] = {400, 1};
|
| -
|
| - auto stack_frame_deduplicator = WrapUnique(new StackFrameDeduplicator);
|
| - auto type_name_deduplicator = WrapUnique(new TypeNameDeduplicator);
|
| - HeapDumpWriter writer(stack_frame_deduplicator.get(),
|
| - type_name_deduplicator.get(),
|
| - 512u);
|
| - const std::set<Entry>& dump = writer.Summarize(metrics_by_context);
|
| -
|
| - // Get the indices of the backtraces and types by adding them again to the
|
| - // deduplicator. Because they were added before, the same number is returned.
|
| - StackFrame bt0[] = {kBrowserMain, kCreateWidget, kGetBitmap};
|
| - StackFrame bt1[] = {kBrowserMain, kCreateWidget, kInitialize};
|
| - int bt_browser_main = stack_frame_deduplicator->Insert(bt0, bt0 + 1);
|
| - int bt_create_widget = stack_frame_deduplicator->Insert(bt0, bt0 + 2);
|
| - int bt_get_bitmap = stack_frame_deduplicator->Insert(bt0, bt0 + 3);
|
| - int bt_initialize = stack_frame_deduplicator->Insert(bt1, bt1 + 3);
|
| -
|
| - // Full heap should have size of 1 MiB + .9 KiB and 3 chunks.
|
| - AssertSizeAndCountEq(dump, -1, -1 /* No type specified */,
|
| - {1024 * 1024 + 512 + 400, 3});
|
| -
|
| - // |GetBitmap| allocated 1 MiB and 1 chunk.
|
| - AssertSizeAndCountEq(dump, bt_get_bitmap, -1, {1024 * 1024, 1});
|
| -
|
| - // Because |GetBitmap| was dumped, all of its parent nodes should have been
|
| - // dumped too. |CreateWidget| has 1 MiB in |GetBitmap|, 400 bytes in
|
| - // |Initialize|, and 512 bytes of its own and each in 1 chunk.
|
| - AssertSizeAndCountEq(dump, bt_create_widget, -1,
|
| - {1024 * 1024 + 400 + 512, 3});
|
| - AssertSizeAndCountEq(dump, bt_browser_main, -1, {1024 * 1024 + 400 + 512, 3});
|
| -
|
| - // Initialize was not significant, it should not have been dumped.
|
| - AssertNotDumped(dump, bt_initialize, -1);
|
| -}
|
| -
|
| -} // namespace internal
|
| -} // namespace trace_event
|
| -} // namespace base
|
|
|