Home | History | Annotate | Download | only in debug
      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   virtual ~TraceMemoryTest() {}
     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::GetStackIndexForTest());
     76 
     77   {
     78     // Push an item.
     79     const char kScope1[] = "scope1";
     80     ScopedTraceMemory scope1(kScope1);
     81     EXPECT_EQ(1, ScopedTraceMemory::GetStackIndexForTest());
     82     EXPECT_EQ(kScope1, ScopedTraceMemory::GetItemForTest(0));
     83 
     84     {
     85       // One more item.
     86       const char kScope2[] = "scope2";
     87       ScopedTraceMemory scope2(kScope2);
     88       EXPECT_EQ(2, ScopedTraceMemory::GetStackIndexForTest());
     89       EXPECT_EQ(kScope2, ScopedTraceMemory::GetItemForTest(1));
     90     }
     91 
     92     // Ended scope 2.
     93     EXPECT_EQ(1, ScopedTraceMemory::GetStackIndexForTest());
     94   }
     95 
     96   // Ended scope 1.
     97   EXPECT_EQ(0, ScopedTraceMemory::GetStackIndexForTest());
     98 
     99   ScopedTraceMemory::CleanupForTest();
    100 }
    101 
    102 void TestDeepScopeNesting(int current, int depth) {
    103   EXPECT_EQ(current, ScopedTraceMemory::GetStackIndexForTest());
    104   const char kCategory[] = "foo";
    105   ScopedTraceMemory scope(kCategory);
    106   if (current < depth)
    107     TestDeepScopeNesting(current + 1, depth);
    108   EXPECT_EQ(current + 1, ScopedTraceMemory::GetStackIndexForTest());
    109 }
    110 
    111 TEST_F(TraceMemoryTest, DeepScopeNesting) {
    112   ScopedTraceMemory::InitForTest();
    113 
    114   // Ensure really deep scopes don't crash.
    115   TestDeepScopeNesting(0, 100);
    116 
    117   ScopedTraceMemory::CleanupForTest();
    118 }
    119 
    120 #endif  // defined(TRACE_MEMORY_SUPPORTED)
    121 
    122 /////////////////////////////////////////////////////////////////////////////
    123 
    124 TEST_F(TraceMemoryTest, AppendHeapProfileTotalsAsTraceFormat) {
    125   // Empty input gives empty output.
    126   std::string empty_output;
    127   AppendHeapProfileTotalsAsTraceFormat("", &empty_output);
    128   EXPECT_EQ("", empty_output);
    129 
    130   // Typical case.
    131   const char input[] =
    132       "heap profile:    357:    55227 [ 14653:  2624014] @ heapprofile";
    133   const std::string kExpectedOutput =
    134       "{\"current_allocs\": 357, \"current_bytes\": 55227, \"trace\": \"\"}";
    135   std::string output;
    136   AppendHeapProfileTotalsAsTraceFormat(input, &output);
    137   EXPECT_EQ(kExpectedOutput, output);
    138 }
    139 
    140 TEST_F(TraceMemoryTest, AppendHeapProfileLineAsTraceFormat) {
    141   // Empty input gives empty output.
    142   std::string empty_output;
    143   EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat("", &empty_output));
    144   EXPECT_EQ("", empty_output);
    145 
    146   // Invalid input returns false.
    147   std::string junk_output;
    148   EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat("junk", &junk_output));
    149 
    150   // Input with the addresses of name1 and name2.
    151   const char kName1[] = "name1";
    152   const char kName2[] = "name2";
    153   std::ostringstream input;
    154   input << "   68:     4195 [  1087:    98009] @ " << &kName1 << " " << &kName2;
    155   const std::string kExpectedOutput =
    156       ",\n"
    157       "{"
    158       "\"current_allocs\": 68, "
    159       "\"current_bytes\": 4195, "
    160       "\"trace\": \"name1 name2 \""
    161       "}";
    162   std::string output;
    163   EXPECT_TRUE(
    164       AppendHeapProfileLineAsTraceFormat(input.str().c_str(), &output));
    165   EXPECT_EQ(kExpectedOutput, output);
    166 
    167   // Zero current allocations is skipped.
    168   std::ostringstream zero_input;
    169   zero_input << "   0:     0 [  1087:    98009] @ " << &kName1 << " "
    170              << &kName2;
    171   std::string zero_output;
    172   EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat(zero_input.str().c_str(),
    173                                                   &zero_output));
    174   EXPECT_EQ("", zero_output);
    175 }
    176 
    177 TEST_F(TraceMemoryTest, AppendHeapProfileAsTraceFormat) {
    178   // Empty input gives empty output.
    179   std::string empty_output;
    180   AppendHeapProfileAsTraceFormat("", &empty_output);
    181   EXPECT_EQ("", empty_output);
    182 
    183   // Typical case.
    184   const char input[] =
    185       "heap profile:    357:    55227 [ 14653:  2624014] @ heapprofile\n"
    186       "   95:    40940 [   649:   114260] @\n"
    187       "   77:    32546 [   742:   106234] @ 0x0 0x0\n"
    188       "    0:        0 [   132:     4236] @ 0x0\n"
    189       "\n"
    190       "MAPPED_LIBRARIES:\n"
    191       "1be411fc1000-1be4139e4000 rw-p 00000000 00:00 0\n"
    192       "1be4139e4000-1be4139e5000 ---p 00000000 00:00 0\n";
    193   const std::string kExpectedOutput =
    194       "[{"
    195       "\"current_allocs\": 357, "
    196       "\"current_bytes\": 55227, "
    197       "\"trace\": \"\"},\n"
    198       "{\"current_allocs\": 95, "
    199       "\"current_bytes\": 40940, "
    200       "\"trace\": \"\"},\n"
    201       "{\"current_allocs\": 77, "
    202       "\"current_bytes\": 32546, "
    203       "\"trace\": \"null null \""
    204       "}]\n";
    205   std::string output;
    206   AppendHeapProfileAsTraceFormat(input, &output);
    207   EXPECT_EQ(kExpectedOutput, output);
    208 }
    209 
    210 }  // namespace debug
    211 }  // namespace base
    212