1 // Copyright 2013 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/trace_event_memory.h"
10 #include "base/trace_event/trace_event_impl.h"
11 #include "testing/gtest/include/gtest/gtest.h"
13 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
14 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
18 namespace trace_event
{
20 // Tests for the trace event memory tracking system. Exists as a class so it
21 // can be a friend of TraceMemoryController.
22 class TraceMemoryTest
: public testing::Test
{
25 ~TraceMemoryTest() override
{}
28 DISALLOW_COPY_AND_ASSIGN(TraceMemoryTest
);
31 //////////////////////////////////////////////////////////////////////////////
33 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
35 TEST_F(TraceMemoryTest
, TraceMemoryController
) {
36 MessageLoop message_loop
;
38 // Start with no observers of the TraceLog.
39 EXPECT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest());
41 // Creating a controller adds it to the TraceLog observer list.
42 scoped_ptr
<TraceMemoryController
> controller(new TraceMemoryController(
43 message_loop
.task_runner(), ::HeapProfilerWithPseudoStackStart
,
44 ::HeapProfilerStop
, ::GetHeapProfile
));
45 EXPECT_EQ(1u, TraceLog::GetInstance()->GetObserverCountForTest());
47 TraceLog::GetInstance()->HasEnabledStateObserver(controller
.get()));
49 // By default the observer isn't dumping memory profiles.
50 EXPECT_FALSE(controller
->IsTimerRunningForTest());
52 // Simulate enabling tracing.
53 controller
->StartProfiling();
54 message_loop
.RunUntilIdle();
55 EXPECT_TRUE(controller
->IsTimerRunningForTest());
57 // Simulate disabling tracing.
58 controller
->StopProfiling();
59 message_loop
.RunUntilIdle();
60 EXPECT_FALSE(controller
->IsTimerRunningForTest());
62 // Deleting the observer removes it from the TraceLog observer list.
64 EXPECT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest());
67 TEST_F(TraceMemoryTest
, ScopedTraceMemory
) {
68 ScopedTraceMemory::InitForTest();
70 // Start with an empty stack.
71 EXPECT_EQ(0, ScopedTraceMemory::GetStackDepthForTest());
75 ScopedTraceMemory
scope1("cat1", "name1");
76 EXPECT_EQ(1, ScopedTraceMemory::GetStackDepthForTest());
77 EXPECT_EQ("cat1", ScopedTraceMemory::GetScopeDataForTest(0).category
);
78 EXPECT_EQ("name1", ScopedTraceMemory::GetScopeDataForTest(0).name
);
82 ScopedTraceMemory
scope2("cat2", "name2");
83 EXPECT_EQ(2, ScopedTraceMemory::GetStackDepthForTest());
84 EXPECT_EQ("cat2", ScopedTraceMemory::GetScopeDataForTest(1).category
);
85 EXPECT_EQ("name2", ScopedTraceMemory::GetScopeDataForTest(1).name
);
89 EXPECT_EQ(1, ScopedTraceMemory::GetStackDepthForTest());
93 EXPECT_EQ(0, ScopedTraceMemory::GetStackDepthForTest());
95 ScopedTraceMemory::CleanupForTest();
98 void TestDeepScopeNesting(int current
, int depth
) {
99 EXPECT_EQ(current
, ScopedTraceMemory::GetStackDepthForTest());
100 ScopedTraceMemory
scope("category", "name");
102 TestDeepScopeNesting(current
+ 1, depth
);
103 EXPECT_EQ(current
+ 1, ScopedTraceMemory::GetStackDepthForTest());
106 TEST_F(TraceMemoryTest
, DeepScopeNesting
) {
107 ScopedTraceMemory::InitForTest();
109 // Ensure really deep scopes don't crash.
110 TestDeepScopeNesting(0, 100);
112 ScopedTraceMemory::CleanupForTest();
115 #endif // defined(TRACE_MEMORY_SUPPORTED)
117 /////////////////////////////////////////////////////////////////////////////
119 TEST_F(TraceMemoryTest
, AppendHeapProfileTotalsAsTraceFormat
) {
120 // Empty input gives empty output.
121 std::string empty_output
;
122 AppendHeapProfileTotalsAsTraceFormat("", &empty_output
);
123 EXPECT_EQ("", empty_output
);
127 "heap profile: 357: 55227 [ 14653: 2624014] @ heapprofile";
128 const std::string kExpectedOutput
=
129 "{\"current_allocs\": 357, \"current_bytes\": 55227, \"trace\": \"\"}";
131 AppendHeapProfileTotalsAsTraceFormat(input
, &output
);
132 EXPECT_EQ(kExpectedOutput
, output
);
135 TEST_F(TraceMemoryTest
, AppendHeapProfileLineAsTraceFormat
) {
136 // Empty input gives empty output.
137 std::string empty_output
;
138 EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat("", &empty_output
));
139 EXPECT_EQ("", empty_output
);
141 // Invalid input returns false.
142 std::string junk_output
;
143 EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat("junk", &junk_output
));
145 // Input with normal category and name entries.
146 const char kCategory
[] = "category";
147 const char kName
[] = "name";
148 std::ostringstream input
;
149 input
<< " 68: 4195 [ 1087: 98009] @ " << &kCategory
<< " "
151 const std::string kExpectedOutput
=
154 "\"current_allocs\": 68, "
155 "\"current_bytes\": 4195, "
156 "\"trace\": \"name \""
160 AppendHeapProfileLineAsTraceFormat(input
.str().c_str(), &output
));
161 EXPECT_EQ(kExpectedOutput
, output
);
163 // Input with with the category "toplevel".
164 // TODO(jamescook): Eliminate this special case and move the logic to the
165 // trace viewer code.
166 const char kTaskCategory
[] = "toplevel";
167 const char kTaskName
[] = "TaskName";
168 std::ostringstream input2
;
169 input2
<< " 68: 4195 [ 1087: 98009] @ " << &kTaskCategory
<< " "
171 const std::string kExpectedOutput2
=
174 "\"current_allocs\": 68, "
175 "\"current_bytes\": 4195, "
176 "\"trace\": \"TaskName->PostTask \""
180 AppendHeapProfileLineAsTraceFormat(input2
.str().c_str(), &output2
));
181 EXPECT_EQ(kExpectedOutput2
, output2
);
183 // Zero current allocations is skipped.
184 std::ostringstream zero_input
;
185 zero_input
<< " 0: 0 [ 1087: 98009] @ " << &kCategory
<< " "
187 std::string zero_output
;
188 EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat(zero_input
.str().c_str(),
190 EXPECT_EQ("", zero_output
);
193 TEST_F(TraceMemoryTest
, AppendHeapProfileAsTraceFormat
) {
194 // Empty input gives empty output.
195 std::string empty_output
;
196 AppendHeapProfileAsTraceFormat("", &empty_output
);
197 EXPECT_EQ("", empty_output
);
201 "heap profile: 357: 55227 [ 14653: 2624014] @ heapprofile\n"
202 " 95: 40940 [ 649: 114260] @\n"
203 " 77: 32546 [ 742: 106234] @ 0x0 0x0\n"
204 " 0: 0 [ 132: 4236] @ 0x0\n"
206 "MAPPED_LIBRARIES:\n"
207 "1be411fc1000-1be4139e4000 rw-p 00000000 00:00 0\n"
208 "1be4139e4000-1be4139e5000 ---p 00000000 00:00 0\n";
209 const std::string kExpectedOutput
=
211 "\"current_allocs\": 357, "
212 "\"current_bytes\": 55227, "
213 "\"trace\": \"\"},\n"
214 "{\"current_allocs\": 95, "
215 "\"current_bytes\": 40940, "
216 "\"trace\": \"\"},\n"
217 "{\"current_allocs\": 77, "
218 "\"current_bytes\": 32546, "
219 "\"trace\": \"null \""
222 AppendHeapProfileAsTraceFormat(input
, &output
);
223 EXPECT_EQ(kExpectedOutput
, output
);
226 TEST_F(TraceMemoryTest
, StringFromHexAddress
) {
227 EXPECT_STREQ("null", StringFromHexAddress("0x0"));
228 EXPECT_STREQ("error", StringFromHexAddress("not an address"));
229 const char kHello
[] = "hello";
230 std::ostringstream hex_address
;
231 hex_address
<< &kHello
;
232 EXPECT_STREQ(kHello
, StringFromHexAddress(hex_address
.str()));
235 } // namespace trace_event