| 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/debug/trace_event_memory.h" | |
| 6 | |
| 7 #include <sstream> | |
| 8 #include <string> | |
| 9 | |
| 10 #include "base/debug/trace_event_impl.h" | |
| 11 #include "base/message_loop/message_loop.h" | |
| 12 #include "testing/gtest/include/gtest/gtest.h" | |
| 13 | |
| 14 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED) | |
| 15 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" | |
| 16 #endif | |
| 17 | |
| 18 namespace base { | |
| 19 namespace debug { | |
| 20 | |
| 21 // Tests for the trace event memory tracking system. Exists as a class so it | |
| 22 // can be a friend of TraceMemoryController. | |
| 23 class TraceMemoryTest : public testing::Test { | |
| 24 public: | |
| 25 TraceMemoryTest() {} | |
| 26 ~TraceMemoryTest() override {} | |
| 27 | |
| 28 private: | |
| 29 DISALLOW_COPY_AND_ASSIGN(TraceMemoryTest); | |
| 30 }; | |
| 31 | |
| 32 ////////////////////////////////////////////////////////////////////////////// | |
| 33 | |
| 34 #if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED) | |
| 35 | |
| 36 TEST_F(TraceMemoryTest, TraceMemoryController) { | |
| 37 MessageLoop message_loop; | |
| 38 | |
| 39 // Start with no observers of the TraceLog. | |
| 40 EXPECT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest()); | |
| 41 | |
| 42 // Creating a controller adds it to the TraceLog observer list. | |
| 43 scoped_ptr<TraceMemoryController> controller( | |
| 44 new TraceMemoryController( | |
| 45 message_loop.message_loop_proxy(), | |
| 46 ::HeapProfilerWithPseudoStackStart, | |
| 47 ::HeapProfilerStop, | |
| 48 ::GetHeapProfile)); | |
| 49 EXPECT_EQ(1u, TraceLog::GetInstance()->GetObserverCountForTest()); | |
| 50 EXPECT_TRUE( | |
| 51 TraceLog::GetInstance()->HasEnabledStateObserver(controller.get())); | |
| 52 | |
| 53 // By default the observer isn't dumping memory profiles. | |
| 54 EXPECT_FALSE(controller->IsTimerRunningForTest()); | |
| 55 | |
| 56 // Simulate enabling tracing. | |
| 57 controller->StartProfiling(); | |
| 58 message_loop.RunUntilIdle(); | |
| 59 EXPECT_TRUE(controller->IsTimerRunningForTest()); | |
| 60 | |
| 61 // Simulate disabling tracing. | |
| 62 controller->StopProfiling(); | |
| 63 message_loop.RunUntilIdle(); | |
| 64 EXPECT_FALSE(controller->IsTimerRunningForTest()); | |
| 65 | |
| 66 // Deleting the observer removes it from the TraceLog observer list. | |
| 67 controller.reset(); | |
| 68 EXPECT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest()); | |
| 69 } | |
| 70 | |
| 71 TEST_F(TraceMemoryTest, ScopedTraceMemory) { | |
| 72 ScopedTraceMemory::InitForTest(); | |
| 73 | |
| 74 // Start with an empty stack. | |
| 75 EXPECT_EQ(0, ScopedTraceMemory::GetStackDepthForTest()); | |
| 76 | |
| 77 { | |
| 78 // Push an item. | |
| 79 ScopedTraceMemory scope1("cat1", "name1"); | |
| 80 EXPECT_EQ(1, ScopedTraceMemory::GetStackDepthForTest()); | |
| 81 EXPECT_EQ("cat1", ScopedTraceMemory::GetScopeDataForTest(0).category); | |
| 82 EXPECT_EQ("name1", ScopedTraceMemory::GetScopeDataForTest(0).name); | |
| 83 | |
| 84 { | |
| 85 // One more item. | |
| 86 ScopedTraceMemory scope2("cat2", "name2"); | |
| 87 EXPECT_EQ(2, ScopedTraceMemory::GetStackDepthForTest()); | |
| 88 EXPECT_EQ("cat2", ScopedTraceMemory::GetScopeDataForTest(1).category); | |
| 89 EXPECT_EQ("name2", ScopedTraceMemory::GetScopeDataForTest(1).name); | |
| 90 } | |
| 91 | |
| 92 // Ended scope 2. | |
| 93 EXPECT_EQ(1, ScopedTraceMemory::GetStackDepthForTest()); | |
| 94 } | |
| 95 | |
| 96 // Ended scope 1. | |
| 97 EXPECT_EQ(0, ScopedTraceMemory::GetStackDepthForTest()); | |
| 98 | |
| 99 ScopedTraceMemory::CleanupForTest(); | |
| 100 } | |
| 101 | |
| 102 void TestDeepScopeNesting(int current, int depth) { | |
| 103 EXPECT_EQ(current, ScopedTraceMemory::GetStackDepthForTest()); | |
| 104 ScopedTraceMemory scope("category", "name"); | |
| 105 if (current < depth) | |
| 106 TestDeepScopeNesting(current + 1, depth); | |
| 107 EXPECT_EQ(current + 1, ScopedTraceMemory::GetStackDepthForTest()); | |
| 108 } | |
| 109 | |
| 110 TEST_F(TraceMemoryTest, DeepScopeNesting) { | |
| 111 ScopedTraceMemory::InitForTest(); | |
| 112 | |
| 113 // Ensure really deep scopes don't crash. | |
| 114 TestDeepScopeNesting(0, 100); | |
| 115 | |
| 116 ScopedTraceMemory::CleanupForTest(); | |
| 117 } | |
| 118 | |
| 119 #endif // defined(TRACE_MEMORY_SUPPORTED) | |
| 120 | |
| 121 ///////////////////////////////////////////////////////////////////////////// | |
| 122 | |
| 123 TEST_F(TraceMemoryTest, AppendHeapProfileTotalsAsTraceFormat) { | |
| 124 // Empty input gives empty output. | |
| 125 std::string empty_output; | |
| 126 AppendHeapProfileTotalsAsTraceFormat("", &empty_output); | |
| 127 EXPECT_EQ("", empty_output); | |
| 128 | |
| 129 // Typical case. | |
| 130 const char input[] = | |
| 131 "heap profile: 357: 55227 [ 14653: 2624014] @ heapprofile"; | |
| 132 const std::string kExpectedOutput = | |
| 133 "{\"current_allocs\": 357, \"current_bytes\": 55227, \"trace\": \"\"}"; | |
| 134 std::string output; | |
| 135 AppendHeapProfileTotalsAsTraceFormat(input, &output); | |
| 136 EXPECT_EQ(kExpectedOutput, output); | |
| 137 } | |
| 138 | |
| 139 TEST_F(TraceMemoryTest, AppendHeapProfileLineAsTraceFormat) { | |
| 140 // Empty input gives empty output. | |
| 141 std::string empty_output; | |
| 142 EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat("", &empty_output)); | |
| 143 EXPECT_EQ("", empty_output); | |
| 144 | |
| 145 // Invalid input returns false. | |
| 146 std::string junk_output; | |
| 147 EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat("junk", &junk_output)); | |
| 148 | |
| 149 // Input with normal category and name entries. | |
| 150 const char kCategory[] = "category"; | |
| 151 const char kName[] = "name"; | |
| 152 std::ostringstream input; | |
| 153 input << " 68: 4195 [ 1087: 98009] @ " << &kCategory << " " | |
| 154 << &kName; | |
| 155 const std::string kExpectedOutput = | |
| 156 ",\n" | |
| 157 "{" | |
| 158 "\"current_allocs\": 68, " | |
| 159 "\"current_bytes\": 4195, " | |
| 160 "\"trace\": \"name \"" | |
| 161 "}"; | |
| 162 std::string output; | |
| 163 EXPECT_TRUE( | |
| 164 AppendHeapProfileLineAsTraceFormat(input.str().c_str(), &output)); | |
| 165 EXPECT_EQ(kExpectedOutput, output); | |
| 166 | |
| 167 // Input with with the category "toplevel". | |
| 168 // TODO(jamescook): Eliminate this special case and move the logic to the | |
| 169 // trace viewer code. | |
| 170 const char kTaskCategory[] = "toplevel"; | |
| 171 const char kTaskName[] = "TaskName"; | |
| 172 std::ostringstream input2; | |
| 173 input2 << " 68: 4195 [ 1087: 98009] @ " << &kTaskCategory << " " | |
| 174 << &kTaskName; | |
| 175 const std::string kExpectedOutput2 = | |
| 176 ",\n" | |
| 177 "{" | |
| 178 "\"current_allocs\": 68, " | |
| 179 "\"current_bytes\": 4195, " | |
| 180 "\"trace\": \"TaskName->PostTask \"" | |
| 181 "}"; | |
| 182 std::string output2; | |
| 183 EXPECT_TRUE( | |
| 184 AppendHeapProfileLineAsTraceFormat(input2.str().c_str(), &output2)); | |
| 185 EXPECT_EQ(kExpectedOutput2, output2); | |
| 186 | |
| 187 // Zero current allocations is skipped. | |
| 188 std::ostringstream zero_input; | |
| 189 zero_input << " 0: 0 [ 1087: 98009] @ " << &kCategory << " " | |
| 190 << &kName; | |
| 191 std::string zero_output; | |
| 192 EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat(zero_input.str().c_str(), | |
| 193 &zero_output)); | |
| 194 EXPECT_EQ("", zero_output); | |
| 195 } | |
| 196 | |
| 197 TEST_F(TraceMemoryTest, AppendHeapProfileAsTraceFormat) { | |
| 198 // Empty input gives empty output. | |
| 199 std::string empty_output; | |
| 200 AppendHeapProfileAsTraceFormat("", &empty_output); | |
| 201 EXPECT_EQ("", empty_output); | |
| 202 | |
| 203 // Typical case. | |
| 204 const char input[] = | |
| 205 "heap profile: 357: 55227 [ 14653: 2624014] @ heapprofile\n" | |
| 206 " 95: 40940 [ 649: 114260] @\n" | |
| 207 " 77: 32546 [ 742: 106234] @ 0x0 0x0\n" | |
| 208 " 0: 0 [ 132: 4236] @ 0x0\n" | |
| 209 "\n" | |
| 210 "MAPPED_LIBRARIES:\n" | |
| 211 "1be411fc1000-1be4139e4000 rw-p 00000000 00:00 0\n" | |
| 212 "1be4139e4000-1be4139e5000 ---p 00000000 00:00 0\n"; | |
| 213 const std::string kExpectedOutput = | |
| 214 "[{" | |
| 215 "\"current_allocs\": 357, " | |
| 216 "\"current_bytes\": 55227, " | |
| 217 "\"trace\": \"\"},\n" | |
| 218 "{\"current_allocs\": 95, " | |
| 219 "\"current_bytes\": 40940, " | |
| 220 "\"trace\": \"\"},\n" | |
| 221 "{\"current_allocs\": 77, " | |
| 222 "\"current_bytes\": 32546, " | |
| 223 "\"trace\": \"null \"" | |
| 224 "}]\n"; | |
| 225 std::string output; | |
| 226 AppendHeapProfileAsTraceFormat(input, &output); | |
| 227 EXPECT_EQ(kExpectedOutput, output); | |
| 228 } | |
| 229 | |
| 230 TEST_F(TraceMemoryTest, StringFromHexAddress) { | |
| 231 EXPECT_STREQ("null", StringFromHexAddress("0x0")); | |
| 232 EXPECT_STREQ("error", StringFromHexAddress("not an address")); | |
| 233 const char kHello[] = "hello"; | |
| 234 std::ostringstream hex_address; | |
| 235 hex_address << &kHello; | |
| 236 EXPECT_STREQ(kHello, StringFromHexAddress(hex_address.str())); | |
| 237 } | |
| 238 | |
| 239 } // namespace debug | |
| 240 } // namespace base | |
| OLD | NEW |