• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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