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