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