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.
4
5 #include "base/trace_event/memory_allocator_dump.h"
6
7 #include <stdint.h>
8
9 #include "base/format_macros.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/trace_event/memory_allocator_dump_guid.h"
12 #include "base/trace_event/memory_dump_provider.h"
13 #include "base/trace_event/process_memory_dump.h"
14 #include "base/trace_event/traced_value.h"
15 #include "base/values.h"
16 #include "build/build_config.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 using testing::ElementsAre;
21 using testing::Eq;
22 using testing::ByRef;
23 using testing::IsEmpty;
24
25 namespace base {
26 namespace trace_event {
27
28 namespace {
29
30 class FakeMemoryAllocatorDumpProvider : public MemoryDumpProvider {
31 public:
OnMemoryDump(const MemoryDumpArgs & args,ProcessMemoryDump * pmd)32 bool OnMemoryDump(const MemoryDumpArgs& args,
33 ProcessMemoryDump* pmd) override {
34 MemoryAllocatorDump* root_heap =
35 pmd->CreateAllocatorDump("foobar_allocator");
36
37 root_heap->AddScalar(MemoryAllocatorDump::kNameSize,
38 MemoryAllocatorDump::kUnitsBytes, 4096);
39 root_heap->AddScalar(MemoryAllocatorDump::kNameObjectCount,
40 MemoryAllocatorDump::kUnitsObjects, 42);
41 root_heap->AddScalar("attr1", "units1", 1234);
42 root_heap->AddString("attr2", "units2", "string_value");
43
44 MemoryAllocatorDump* sub_heap =
45 pmd->CreateAllocatorDump("foobar_allocator/sub_heap");
46 sub_heap->AddScalar(MemoryAllocatorDump::kNameSize,
47 MemoryAllocatorDump::kUnitsBytes, 1);
48 sub_heap->AddScalar(MemoryAllocatorDump::kNameObjectCount,
49 MemoryAllocatorDump::kUnitsObjects, 3);
50
51 pmd->CreateAllocatorDump("foobar_allocator/sub_heap/empty");
52 // Leave the rest of sub heap deliberately uninitialized, to check that
53 // CreateAllocatorDump returns a properly zero-initialized object.
54
55 return true;
56 }
57 };
58
CheckString(const MemoryAllocatorDump * dump,const std::string & name,const char * expected_units,const std::string & expected_value)59 void CheckString(const MemoryAllocatorDump* dump,
60 const std::string& name,
61 const char* expected_units,
62 const std::string& expected_value) {
63 MemoryAllocatorDump::Entry expected(name, expected_units, expected_value);
64 EXPECT_THAT(dump->entries(), testing::Contains(Eq(ByRef(expected))));
65 }
66
CheckScalar(const MemoryAllocatorDump * dump,const std::string & name,const char * expected_units,uint64_t expected_value)67 void CheckScalar(const MemoryAllocatorDump* dump,
68 const std::string& name,
69 const char* expected_units,
70 uint64_t expected_value) {
71 MemoryAllocatorDump::Entry expected(name, expected_units, expected_value);
72 EXPECT_THAT(dump->entries(), testing::Contains(Eq(ByRef(expected))));
73 }
74
75 } // namespace
76
TEST(MemoryAllocatorDumpTest,GuidGeneration)77 TEST(MemoryAllocatorDumpTest, GuidGeneration) {
78 std::unique_ptr<MemoryAllocatorDump> mad(new MemoryAllocatorDump(
79 "foo", MemoryDumpLevelOfDetail::FIRST, MemoryAllocatorDumpGuid(0x42u)));
80 ASSERT_EQ("42", mad->guid().ToString());
81 }
82
TEST(MemoryAllocatorDumpTest,DumpIntoProcessMemoryDump)83 TEST(MemoryAllocatorDumpTest, DumpIntoProcessMemoryDump) {
84 FakeMemoryAllocatorDumpProvider fmadp;
85 MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
86 ProcessMemoryDump pmd(dump_args);
87
88 fmadp.OnMemoryDump(dump_args, &pmd);
89
90 ASSERT_EQ(3u, pmd.allocator_dumps().size());
91
92 const MemoryAllocatorDump* root_heap =
93 pmd.GetAllocatorDump("foobar_allocator");
94 ASSERT_NE(nullptr, root_heap);
95 EXPECT_EQ("foobar_allocator", root_heap->absolute_name());
96 CheckScalar(root_heap, MemoryAllocatorDump::kNameSize,
97 MemoryAllocatorDump::kUnitsBytes, 4096);
98 CheckScalar(root_heap, MemoryAllocatorDump::kNameObjectCount,
99 MemoryAllocatorDump::kUnitsObjects, 42);
100 CheckScalar(root_heap, "attr1", "units1", 1234);
101 CheckString(root_heap, "attr2", "units2", "string_value");
102
103 const MemoryAllocatorDump* sub_heap =
104 pmd.GetAllocatorDump("foobar_allocator/sub_heap");
105 ASSERT_NE(nullptr, sub_heap);
106 EXPECT_EQ("foobar_allocator/sub_heap", sub_heap->absolute_name());
107 CheckScalar(sub_heap, MemoryAllocatorDump::kNameSize,
108 MemoryAllocatorDump::kUnitsBytes, 1);
109 CheckScalar(sub_heap, MemoryAllocatorDump::kNameObjectCount,
110 MemoryAllocatorDump::kUnitsObjects, 3);
111 const MemoryAllocatorDump* empty_sub_heap =
112 pmd.GetAllocatorDump("foobar_allocator/sub_heap/empty");
113 ASSERT_NE(nullptr, empty_sub_heap);
114 EXPECT_EQ("foobar_allocator/sub_heap/empty", empty_sub_heap->absolute_name());
115
116 EXPECT_THAT(empty_sub_heap->entries(), IsEmpty());
117
118 // Check that calling serialization routines doesn't cause a crash.
119 std::unique_ptr<TracedValue> traced_value(new TracedValue);
120 pmd.SerializeAllocatorDumpsInto(traced_value.get());
121 }
122
TEST(MemoryAllocatorDumpTest,GetSize)123 TEST(MemoryAllocatorDumpTest, GetSize) {
124 MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
125 ProcessMemoryDump pmd(dump_args);
126 MemoryAllocatorDump* dump = pmd.CreateAllocatorDump("allocator_for_size");
127 dump->AddScalar(MemoryAllocatorDump::kNameSize,
128 MemoryAllocatorDump::kUnitsBytes, 1);
129 dump->AddScalar("foo", MemoryAllocatorDump::kUnitsBytes, 2);
130 EXPECT_EQ(1u, dump->GetSizeInternal());
131 }
132
TEST(MemoryAllocatorDumpTest,ReadValues)133 TEST(MemoryAllocatorDumpTest, ReadValues) {
134 MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
135 ProcessMemoryDump pmd(dump_args);
136 MemoryAllocatorDump* dump = pmd.CreateAllocatorDump("allocator_for_size");
137 dump->AddScalar("one", "byte", 1);
138 dump->AddString("one", "object", "one");
139
140 MemoryAllocatorDump::Entry expected_scalar("one", "byte", 1);
141 MemoryAllocatorDump::Entry expected_string("one", "object", "one");
142 EXPECT_THAT(dump->entries(), ElementsAre(Eq(ByRef(expected_scalar)),
143 Eq(ByRef(expected_string))));
144 }
145
TEST(MemoryAllocatorDumpTest,MovingAnEntry)146 TEST(MemoryAllocatorDumpTest, MovingAnEntry) {
147 MemoryAllocatorDump::Entry expected_entry("one", "byte", 1);
148 MemoryAllocatorDump::Entry from_entry("one", "byte", 1);
149 MemoryAllocatorDump::Entry to_entry = std::move(from_entry);
150 EXPECT_EQ(expected_entry, to_entry);
151 }
152
153 // DEATH tests are not supported in Android/iOS/Fuchsia.
154 #if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_IOS) && \
155 !defined(OS_FUCHSIA)
TEST(MemoryAllocatorDumpTest,ForbidDuplicatesDeathTest)156 TEST(MemoryAllocatorDumpTest, ForbidDuplicatesDeathTest) {
157 FakeMemoryAllocatorDumpProvider fmadp;
158 MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
159 ProcessMemoryDump pmd(dump_args);
160 pmd.CreateAllocatorDump("foo_allocator");
161 pmd.CreateAllocatorDump("bar_allocator/heap");
162 ASSERT_DEATH(pmd.CreateAllocatorDump("foo_allocator"), "");
163 ASSERT_DEATH(pmd.CreateAllocatorDump("bar_allocator/heap"), "");
164 ASSERT_DEATH(pmd.CreateAllocatorDump(""), "");
165 }
166
TEST(MemoryAllocatorDumpTest,ForbidStringsInBackgroundModeDeathTest)167 TEST(MemoryAllocatorDumpTest, ForbidStringsInBackgroundModeDeathTest) {
168 MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::BACKGROUND};
169 ProcessMemoryDump pmd(dump_args);
170 MemoryAllocatorDump* dump = pmd.CreateAllocatorDump("malloc");
171 ASSERT_DEATH(dump->AddString("foo", "bar", "baz"), "");
172 }
173 #endif
174
175 } // namespace trace_event
176 } // namespace base
177