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_dump_provider.h"
10 #include "base/trace_event/memory_dump_session_state.h"
11 #include "base/trace_event/process_memory_dump.h"
12 #include "base/trace_event/trace_event_argument.h"
13 #include "testing/gtest/include/gtest/gtest.h"
16 namespace trace_event
{
20 class FakeMemoryAllocatorDumpProvider
: public MemoryDumpProvider
{
22 bool OnMemoryDump(ProcessMemoryDump
* pmd
) override
{
23 MemoryAllocatorDump
* root_heap
=
24 pmd
->CreateAllocatorDump("foobar_allocator");
26 root_heap
->AddScalar(MemoryAllocatorDump::kNameOuterSize
,
27 MemoryAllocatorDump::kUnitsBytes
, 4096);
28 root_heap
->AddScalar(MemoryAllocatorDump::kNameInnerSize
,
29 MemoryAllocatorDump::kUnitsBytes
, 1000);
30 root_heap
->AddScalar(MemoryAllocatorDump::kNameObjectsCount
,
31 MemoryAllocatorDump::kUnitsObjects
, 42);
32 root_heap
->AddScalar("attr1", "units1", 1234);
33 root_heap
->AddString("attr2", "units2", "string_value");
35 MemoryAllocatorDump
* sub_heap
=
36 pmd
->CreateAllocatorDump("foobar_allocator/sub_heap");
37 sub_heap
->AddScalar(MemoryAllocatorDump::kNameOuterSize
,
38 MemoryAllocatorDump::kUnitsBytes
, 1);
39 sub_heap
->AddScalar(MemoryAllocatorDump::kNameInnerSize
,
40 MemoryAllocatorDump::kUnitsBytes
, 2);
41 sub_heap
->AddScalar(MemoryAllocatorDump::kNameObjectsCount
,
42 MemoryAllocatorDump::kUnitsObjects
, 3);
44 pmd
->CreateAllocatorDump("foobar_allocator/sub_heap/empty");
45 // Leave the rest of sub heap deliberately uninitialized, to check that
46 // CreateAllocatorDump returns a properly zero-initialized object.
52 void CheckAttribute(const MemoryAllocatorDump
* dump
,
53 const std::string
& name
,
54 const char* expected_type
,
55 const char* expected_units
,
56 const std::string
& expected_value
) {
57 const char* attr_type
;
58 const char* attr_units
;
59 const Value
* attr_value
;
60 std::string attr_str_value
;
61 bool res
= dump
->Get(name
, &attr_type
, &attr_units
, &attr_value
);
65 EXPECT_EQ(expected_type
, std::string(attr_type
));
66 EXPECT_EQ(expected_units
, std::string(attr_units
));
67 EXPECT_TRUE(attr_value
->GetAsString(&attr_str_value
));
68 EXPECT_EQ(expected_value
, attr_str_value
);
71 void CheckAttribute(const MemoryAllocatorDump
* dump
,
72 const std::string
& name
,
73 const char* expected_type
,
74 const char* expected_units
,
75 uint64 expected_value
) {
76 CheckAttribute(dump
, name
, expected_type
, expected_units
,
77 StringPrintf("%" PRIx64
, expected_value
));
81 TEST(MemoryAllocatorDumpTest
, DumpIntoProcessMemoryDump
) {
82 FakeMemoryAllocatorDumpProvider fmadp
;
83 ProcessMemoryDump
pmd(make_scoped_refptr(new MemoryDumpSessionState()));
85 fmadp
.OnMemoryDump(&pmd
);
87 ASSERT_EQ(3u, pmd
.allocator_dumps().size());
89 const MemoryAllocatorDump
* root_heap
=
90 pmd
.GetAllocatorDump("foobar_allocator");
91 ASSERT_NE(nullptr, root_heap
);
92 EXPECT_EQ("foobar_allocator", root_heap
->absolute_name());
93 CheckAttribute(root_heap
, MemoryAllocatorDump::kNameOuterSize
,
94 MemoryAllocatorDump::kTypeScalar
,
95 MemoryAllocatorDump::kUnitsBytes
, 4096);
96 CheckAttribute(root_heap
, MemoryAllocatorDump::kNameInnerSize
,
97 MemoryAllocatorDump::kTypeScalar
,
98 MemoryAllocatorDump::kUnitsBytes
, 1000);
99 CheckAttribute(root_heap
, MemoryAllocatorDump::kNameObjectsCount
,
100 MemoryAllocatorDump::kTypeScalar
,
101 MemoryAllocatorDump::kUnitsObjects
, 42);
102 CheckAttribute(root_heap
, "attr1", MemoryAllocatorDump::kTypeScalar
, "units1",
104 CheckAttribute(root_heap
, "attr2", MemoryAllocatorDump::kTypeString
, "units2",
107 const MemoryAllocatorDump
* sub_heap
=
108 pmd
.GetAllocatorDump("foobar_allocator/sub_heap");
109 ASSERT_NE(nullptr, sub_heap
);
110 EXPECT_EQ("foobar_allocator/sub_heap", sub_heap
->absolute_name());
111 CheckAttribute(sub_heap
, MemoryAllocatorDump::kNameOuterSize
,
112 MemoryAllocatorDump::kTypeScalar
,
113 MemoryAllocatorDump::kUnitsBytes
, 1);
114 CheckAttribute(sub_heap
, MemoryAllocatorDump::kNameInnerSize
,
115 MemoryAllocatorDump::kTypeScalar
,
116 MemoryAllocatorDump::kUnitsBytes
, 2);
117 CheckAttribute(sub_heap
, MemoryAllocatorDump::kNameObjectsCount
,
118 MemoryAllocatorDump::kTypeScalar
,
119 MemoryAllocatorDump::kUnitsObjects
, 3);
121 const MemoryAllocatorDump
* empty_sub_heap
=
122 pmd
.GetAllocatorDump("foobar_allocator/sub_heap/empty");
123 ASSERT_NE(nullptr, empty_sub_heap
);
124 EXPECT_EQ("foobar_allocator/sub_heap/empty", empty_sub_heap
->absolute_name());
125 ASSERT_FALSE(empty_sub_heap
->Get(MemoryAllocatorDump::kNameOuterSize
, nullptr,
127 ASSERT_FALSE(empty_sub_heap
->Get(MemoryAllocatorDump::kNameInnerSize
, nullptr,
129 ASSERT_FALSE(empty_sub_heap
->Get(MemoryAllocatorDump::kNameObjectsCount
,
130 nullptr, nullptr, nullptr));
132 // Check that the AsValueInfo doesn't hit any DCHECK.
133 scoped_refptr
<TracedValue
> traced_value(new TracedValue());
134 pmd
.AsValueInto(traced_value
.get());
137 // DEATH tests are not supported in Android / iOS.
138 #if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_IOS)
139 TEST(MemoryAllocatorDumpTest
, ForbidDuplicatesDeathTest
) {
140 FakeMemoryAllocatorDumpProvider fmadp
;
141 ProcessMemoryDump
pmd(make_scoped_refptr(new MemoryDumpSessionState()));
142 pmd
.CreateAllocatorDump("foo_allocator");
143 pmd
.CreateAllocatorDump("bar_allocator/heap");
144 ASSERT_DEATH(pmd
.CreateAllocatorDump("foo_allocator"), "");
145 ASSERT_DEATH(pmd
.CreateAllocatorDump("bar_allocator/heap"), "");
146 ASSERT_DEATH(pmd
.CreateAllocatorDump(""), "");
150 } // namespace trace_event