[tracing] Extend memory dump API with graphs
[chromium-blink-merge.git] / base / trace_event / memory_allocator_dump_unittest.cc
blobb6ca482afae7d62330d0e19e952550c84b62aca2
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/trace_event/memory_allocator_dump.h"
7 #include "base/format_macros.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/trace_event/memory_allocator_dump_guid.h"
10 #include "base/trace_event/memory_dump_provider.h"
11 #include "base/trace_event/memory_dump_session_state.h"
12 #include "base/trace_event/process_memory_dump.h"
13 #include "base/trace_event/trace_event_argument.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 namespace base {
17 namespace trace_event {
19 namespace {
21 class FakeMemoryAllocatorDumpProvider : public MemoryDumpProvider {
22 public:
23 bool OnMemoryDump(ProcessMemoryDump* pmd) override {
24 MemoryAllocatorDump* root_heap =
25 pmd->CreateAllocatorDump("foobar_allocator");
27 root_heap->AddScalar(MemoryAllocatorDump::kNameOuterSize,
28 MemoryAllocatorDump::kUnitsBytes, 4096);
29 root_heap->AddScalar(MemoryAllocatorDump::kNameInnerSize,
30 MemoryAllocatorDump::kUnitsBytes, 1000);
31 root_heap->AddScalar(MemoryAllocatorDump::kNameObjectsCount,
32 MemoryAllocatorDump::kUnitsObjects, 42);
33 root_heap->AddScalar("attr1", "units1", 1234);
34 root_heap->AddString("attr2", "units2", "string_value");
36 MemoryAllocatorDump* sub_heap =
37 pmd->CreateAllocatorDump("foobar_allocator/sub_heap");
38 sub_heap->AddScalar(MemoryAllocatorDump::kNameOuterSize,
39 MemoryAllocatorDump::kUnitsBytes, 1);
40 sub_heap->AddScalar(MemoryAllocatorDump::kNameInnerSize,
41 MemoryAllocatorDump::kUnitsBytes, 2);
42 sub_heap->AddScalar(MemoryAllocatorDump::kNameObjectsCount,
43 MemoryAllocatorDump::kUnitsObjects, 3);
45 pmd->CreateAllocatorDump("foobar_allocator/sub_heap/empty");
46 // Leave the rest of sub heap deliberately uninitialized, to check that
47 // CreateAllocatorDump returns a properly zero-initialized object.
49 return true;
53 void CheckAttribute(const MemoryAllocatorDump* dump,
54 const std::string& name,
55 const char* expected_type,
56 const char* expected_units,
57 const std::string& expected_value) {
58 const char* attr_type;
59 const char* attr_units;
60 const Value* attr_value;
61 std::string attr_str_value;
62 bool res = dump->Get(name, &attr_type, &attr_units, &attr_value);
63 EXPECT_TRUE(res);
64 if (!res)
65 return;
66 EXPECT_EQ(expected_type, std::string(attr_type));
67 EXPECT_EQ(expected_units, std::string(attr_units));
68 EXPECT_TRUE(attr_value->GetAsString(&attr_str_value));
69 EXPECT_EQ(expected_value, attr_str_value);
72 void CheckAttribute(const MemoryAllocatorDump* dump,
73 const std::string& name,
74 const char* expected_type,
75 const char* expected_units,
76 uint64 expected_value) {
77 CheckAttribute(dump, name, expected_type, expected_units,
78 StringPrintf("%" PRIx64, expected_value));
80 } // namespace
82 TEST(MemoryAllocatorDumpTest, GuidGeneration) {
83 scoped_ptr<MemoryAllocatorDump> mad(
84 new MemoryAllocatorDump("foo", nullptr, MemoryAllocatorDumpGuid(0x42u)));
85 ASSERT_EQ("42", mad->guid().ToString());
87 // If the dumper does not provide a Guid, the MAD will make one up on the
88 // flight. Furthermore that Guid will stay stable across across multiple
89 // snapshots if the |absolute_name| of the dump doesn't change
90 mad.reset(new MemoryAllocatorDump("bar", nullptr));
91 const MemoryAllocatorDumpGuid guid_bar = mad->guid();
92 ASSERT_FALSE(guid_bar.empty());
93 ASSERT_FALSE(guid_bar.ToString().empty());
94 ASSERT_EQ(guid_bar, mad->guid());
96 mad.reset(new MemoryAllocatorDump("bar", nullptr));
97 const MemoryAllocatorDumpGuid guid_bar_2 = mad->guid();
98 ASSERT_EQ(guid_bar, guid_bar_2);
100 mad.reset(new MemoryAllocatorDump("baz", nullptr));
101 const MemoryAllocatorDumpGuid guid_baz = mad->guid();
102 ASSERT_NE(guid_bar, guid_baz);
105 TEST(MemoryAllocatorDumpTest, DumpIntoProcessMemoryDump) {
106 FakeMemoryAllocatorDumpProvider fmadp;
107 ProcessMemoryDump pmd(make_scoped_refptr(new MemoryDumpSessionState()));
109 fmadp.OnMemoryDump(&pmd);
111 ASSERT_EQ(3u, pmd.allocator_dumps().size());
113 const MemoryAllocatorDump* root_heap =
114 pmd.GetAllocatorDump("foobar_allocator");
115 ASSERT_NE(nullptr, root_heap);
116 EXPECT_EQ("foobar_allocator", root_heap->absolute_name());
117 CheckAttribute(root_heap, MemoryAllocatorDump::kNameOuterSize,
118 MemoryAllocatorDump::kTypeScalar,
119 MemoryAllocatorDump::kUnitsBytes, 4096);
120 CheckAttribute(root_heap, MemoryAllocatorDump::kNameInnerSize,
121 MemoryAllocatorDump::kTypeScalar,
122 MemoryAllocatorDump::kUnitsBytes, 1000);
123 CheckAttribute(root_heap, MemoryAllocatorDump::kNameObjectsCount,
124 MemoryAllocatorDump::kTypeScalar,
125 MemoryAllocatorDump::kUnitsObjects, 42);
126 CheckAttribute(root_heap, "attr1", MemoryAllocatorDump::kTypeScalar, "units1",
127 1234);
128 CheckAttribute(root_heap, "attr2", MemoryAllocatorDump::kTypeString, "units2",
129 "string_value");
131 const MemoryAllocatorDump* sub_heap =
132 pmd.GetAllocatorDump("foobar_allocator/sub_heap");
133 ASSERT_NE(nullptr, sub_heap);
134 EXPECT_EQ("foobar_allocator/sub_heap", sub_heap->absolute_name());
135 CheckAttribute(sub_heap, MemoryAllocatorDump::kNameOuterSize,
136 MemoryAllocatorDump::kTypeScalar,
137 MemoryAllocatorDump::kUnitsBytes, 1);
138 CheckAttribute(sub_heap, MemoryAllocatorDump::kNameInnerSize,
139 MemoryAllocatorDump::kTypeScalar,
140 MemoryAllocatorDump::kUnitsBytes, 2);
141 CheckAttribute(sub_heap, MemoryAllocatorDump::kNameObjectsCount,
142 MemoryAllocatorDump::kTypeScalar,
143 MemoryAllocatorDump::kUnitsObjects, 3);
145 const MemoryAllocatorDump* empty_sub_heap =
146 pmd.GetAllocatorDump("foobar_allocator/sub_heap/empty");
147 ASSERT_NE(nullptr, empty_sub_heap);
148 EXPECT_EQ("foobar_allocator/sub_heap/empty", empty_sub_heap->absolute_name());
149 ASSERT_FALSE(empty_sub_heap->Get(MemoryAllocatorDump::kNameOuterSize, nullptr,
150 nullptr, nullptr));
151 ASSERT_FALSE(empty_sub_heap->Get(MemoryAllocatorDump::kNameInnerSize, nullptr,
152 nullptr, nullptr));
153 ASSERT_FALSE(empty_sub_heap->Get(MemoryAllocatorDump::kNameObjectsCount,
154 nullptr, nullptr, nullptr));
156 // Check that the AsValueInfo doesn't hit any DCHECK.
157 scoped_refptr<TracedValue> traced_value(new TracedValue());
158 pmd.AsValueInto(traced_value.get());
161 // DEATH tests are not supported in Android / iOS.
162 #if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_IOS)
163 TEST(MemoryAllocatorDumpTest, ForbidDuplicatesDeathTest) {
164 FakeMemoryAllocatorDumpProvider fmadp;
165 ProcessMemoryDump pmd(make_scoped_refptr(new MemoryDumpSessionState()));
166 pmd.CreateAllocatorDump("foo_allocator");
167 pmd.CreateAllocatorDump("bar_allocator/heap");
168 ASSERT_DEATH(pmd.CreateAllocatorDump("foo_allocator"), "");
169 ASSERT_DEATH(pmd.CreateAllocatorDump("bar_allocator/heap"), "");
170 ASSERT_DEATH(pmd.CreateAllocatorDump(""), "");
172 #endif
174 } // namespace trace_event
175 } // namespace base