OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "base/trace_event/trace_event_memory.h" | |
6 | |
7 #include <sstream> | |
8 #include <string> | |
9 | |
10 #include "base/trace_event/trace_event_impl.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 | |
13 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED) | |
14 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" | |
15 #endif | |
16 | |
17 namespace base { | |
18 namespace trace_event { | |
19 | |
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 { | |
23 public: | |
24 TraceMemoryTest() {} | |
25 ~TraceMemoryTest() override {} | |
26 | |
27 private: | |
28 DISALLOW_COPY_AND_ASSIGN(TraceMemoryTest); | |
29 }; | |
30 | |
31 ////////////////////////////////////////////////////////////////////////////// | |
32 | |
33 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED) | |
34 | |
35 TEST_F(TraceMemoryTest, TraceMemoryController) { | |
36 MessageLoop message_loop; | |
37 | |
38 // Start with no observers of the TraceLog. | |
39 EXPECT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest()); | |
40 | |
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()); | |
46 EXPECT_TRUE( | |
47 TraceLog::GetInstance()->HasEnabledStateObserver(controller.get())); | |
48 | |
49 // By default the observer isn't dumping memory profiles. | |
50 EXPECT_FALSE(controller->IsTimerRunningForTest()); | |
51 | |
52 // Simulate enabling tracing. | |
53 controller->StartProfiling(); | |
54 message_loop.RunUntilIdle(); | |
55 EXPECT_TRUE(controller->IsTimerRunningForTest()); | |
56 | |
57 // Simulate disabling tracing. | |
58 controller->StopProfiling(); | |
59 message_loop.RunUntilIdle(); | |
60 EXPECT_FALSE(controller->IsTimerRunningForTest()); | |
61 | |
62 // Deleting the observer removes it from the TraceLog observer list. | |
63 controller.reset(); | |
64 EXPECT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest()); | |
65 } | |
66 | |
67 TEST_F(TraceMemoryTest, ScopedTraceMemory) { | |
68 ScopedTraceMemory::InitForTest(); | |
69 | |
70 // Start with an empty stack. | |
71 EXPECT_EQ(0, ScopedTraceMemory::GetStackDepthForTest()); | |
72 | |
73 { | |
74 // Push an item. | |
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); | |
79 | |
80 { | |
81 // One more item. | |
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); | |
86 } | |
87 | |
88 // Ended scope 2. | |
89 EXPECT_EQ(1, ScopedTraceMemory::GetStackDepthForTest()); | |
90 } | |
91 | |
92 // Ended scope 1. | |
93 EXPECT_EQ(0, ScopedTraceMemory::GetStackDepthForTest()); | |
94 | |
95 ScopedTraceMemory::CleanupForTest(); | |
96 } | |
97 | |
98 void TestDeepScopeNesting(int current, int depth) { | |
99 EXPECT_EQ(current, ScopedTraceMemory::GetStackDepthForTest()); | |
100 ScopedTraceMemory scope("category", "name"); | |
101 if (current < depth) | |
102 TestDeepScopeNesting(current + 1, depth); | |
103 EXPECT_EQ(current + 1, ScopedTraceMemory::GetStackDepthForTest()); | |
104 } | |
105 | |
106 TEST_F(TraceMemoryTest, DeepScopeNesting) { | |
107 ScopedTraceMemory::InitForTest(); | |
108 | |
109 // Ensure really deep scopes don't crash. | |
110 TestDeepScopeNesting(0, 100); | |
111 | |
112 ScopedTraceMemory::CleanupForTest(); | |
113 } | |
114 | |
115 #endif // defined(TRACE_MEMORY_SUPPORTED) | |
116 | |
117 ///////////////////////////////////////////////////////////////////////////// | |
118 | |
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); | |
124 | |
125 // Typical case. | |
126 const char input[] = | |
127 "heap profile: 357: 55227 [ 14653: 2624014] @ heapprofile"; | |
128 const std::string kExpectedOutput = | |
129 "{\"current_allocs\": 357, \"current_bytes\": 55227, \"trace\": \"\"}"; | |
130 std::string output; | |
131 AppendHeapProfileTotalsAsTraceFormat(input, &output); | |
132 EXPECT_EQ(kExpectedOutput, output); | |
133 } | |
134 | |
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); | |
140 | |
141 // Invalid input returns false. | |
142 std::string junk_output; | |
143 EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat("junk", &junk_output)); | |
144 | |
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 << " " | |
150 << &kName; | |
151 const std::string kExpectedOutput = | |
152 ",\n" | |
153 "{" | |
154 "\"current_allocs\": 68, " | |
155 "\"current_bytes\": 4195, " | |
156 "\"trace\": \"name \"" | |
157 "}"; | |
158 std::string output; | |
159 EXPECT_TRUE( | |
160 AppendHeapProfileLineAsTraceFormat(input.str().c_str(), &output)); | |
161 EXPECT_EQ(kExpectedOutput, output); | |
162 | |
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 << " " | |
170 << &kTaskName; | |
171 const std::string kExpectedOutput2 = | |
172 ",\n" | |
173 "{" | |
174 "\"current_allocs\": 68, " | |
175 "\"current_bytes\": 4195, " | |
176 "\"trace\": \"TaskName->PostTask \"" | |
177 "}"; | |
178 std::string output2; | |
179 EXPECT_TRUE( | |
180 AppendHeapProfileLineAsTraceFormat(input2.str().c_str(), &output2)); | |
181 EXPECT_EQ(kExpectedOutput2, output2); | |
182 | |
183 // Zero current allocations is skipped. | |
184 std::ostringstream zero_input; | |
185 zero_input << " 0: 0 [ 1087: 98009] @ " << &kCategory << " " | |
186 << &kName; | |
187 std::string zero_output; | |
188 EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat(zero_input.str().c_str(), | |
189 &zero_output)); | |
190 EXPECT_EQ("", zero_output); | |
191 } | |
192 | |
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); | |
198 | |
199 // Typical case. | |
200 const char input[] = | |
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" | |
205 "\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 = | |
210 "[{" | |
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 \"" | |
220 "}]\n"; | |
221 std::string output; | |
222 AppendHeapProfileAsTraceFormat(input, &output); | |
223 EXPECT_EQ(kExpectedOutput, output); | |
224 } | |
225 | |
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())); | |
233 } | |
234 | |
235 } // namespace trace_event | |
236 } // namespace base | |
OLD | NEW |