1bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// found in the LICENSE file.
4bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
5bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/debug/trace_event_memory.h"
6bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
7bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include <sstream>
8bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include <string>
9bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
10bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/debug/trace_event_impl.h"
11bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/message_loop/message_loop.h"
12bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "testing/gtest/include/gtest/gtest.h"
13bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
14bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
15bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
16bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#endif
17bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
18bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochnamespace base {
19bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochnamespace debug {
20bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
21bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// Tests for the trace event memory tracking system. Exists as a class so it
22bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch// can be a friend of TraceMemoryController.
23bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochclass TraceMemoryTest : public testing::Test {
24bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch public:
25bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  TraceMemoryTest() {}
26bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  virtual ~TraceMemoryTest() {}
27bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
28bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch private:
29bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(TraceMemoryTest);
30bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch};
31bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
32bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch//////////////////////////////////////////////////////////////////////////////
33bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
34bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
35bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
36bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_F(TraceMemoryTest, TraceMemoryController) {
37bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  MessageLoop message_loop;
38bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
39bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Start with no observers of the TraceLog.
40bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest());
41bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
42bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Creating a controller adds it to the TraceLog observer list.
43bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<TraceMemoryController> controller(
44bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      new TraceMemoryController(
45bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          message_loop.message_loop_proxy(),
46bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          ::HeapProfilerWithPseudoStackStart,
47bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          ::HeapProfilerStop,
48bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          ::GetHeapProfile));
49bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(1u, TraceLog::GetInstance()->GetObserverCountForTest());
50bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(
51bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      TraceLog::GetInstance()->HasEnabledStateObserver(controller.get()));
52bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
53bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // By default the observer isn't dumping memory profiles.
54bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_FALSE(controller->IsTimerRunningForTest());
55bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
56bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Simulate enabling tracing.
57bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  controller->StartProfiling();
58bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop.RunUntilIdle();
59bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(controller->IsTimerRunningForTest());
60bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
61bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Simulate disabling tracing.
62bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  controller->StopProfiling();
63bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  message_loop.RunUntilIdle();
64bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_FALSE(controller->IsTimerRunningForTest());
65bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
66bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Deleting the observer removes it from the TraceLog observer list.
67bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  controller.reset();
68bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest());
69bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
70bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
71bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_F(TraceMemoryTest, ScopedTraceMemory) {
72bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  ScopedTraceMemory::InitForTest();
73bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
74bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Start with an empty stack.
75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, ScopedTraceMemory::GetStackDepthForTest());
76bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
77bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  {
78bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    // Push an item.
79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ScopedTraceMemory scope1("cat1", "name1");
80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    EXPECT_EQ(1, ScopedTraceMemory::GetStackDepthForTest());
81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    EXPECT_EQ("cat1", ScopedTraceMemory::GetScopeDataForTest(0).category);
82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    EXPECT_EQ("name1", ScopedTraceMemory::GetScopeDataForTest(0).name);
83bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
84bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    {
85bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      // One more item.
86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      ScopedTraceMemory scope2("cat2", "name2");
87424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      EXPECT_EQ(2, ScopedTraceMemory::GetStackDepthForTest());
88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      EXPECT_EQ("cat2", ScopedTraceMemory::GetScopeDataForTest(1).category);
89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      EXPECT_EQ("name2", ScopedTraceMemory::GetScopeDataForTest(1).name);
90bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    }
91bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
92bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    // Ended scope 2.
93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    EXPECT_EQ(1, ScopedTraceMemory::GetStackDepthForTest());
94bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  }
95bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
96bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Ended scope 1.
97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(0, ScopedTraceMemory::GetStackDepthForTest());
98bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
99bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  ScopedTraceMemory::CleanupForTest();
100bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
101bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
102bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid TestDeepScopeNesting(int current, int depth) {
103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(current, ScopedTraceMemory::GetStackDepthForTest());
104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ScopedTraceMemory scope("category", "name");
105bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (current < depth)
106bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    TestDeepScopeNesting(current + 1, depth);
107424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(current + 1, ScopedTraceMemory::GetStackDepthForTest());
108bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
109bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
110bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_F(TraceMemoryTest, DeepScopeNesting) {
111bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  ScopedTraceMemory::InitForTest();
112bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
113bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Ensure really deep scopes don't crash.
114bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  TestDeepScopeNesting(0, 100);
115bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
116bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  ScopedTraceMemory::CleanupForTest();
117bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
118bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
119bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#endif  // defined(TRACE_MEMORY_SUPPORTED)
120bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
121bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch/////////////////////////////////////////////////////////////////////////////
122bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
123bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_F(TraceMemoryTest, AppendHeapProfileTotalsAsTraceFormat) {
124bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Empty input gives empty output.
125bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  std::string empty_output;
126bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  AppendHeapProfileTotalsAsTraceFormat("", &empty_output);
127bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ("", empty_output);
128bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
129bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Typical case.
130bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  const char input[] =
131bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "heap profile:    357:    55227 [ 14653:  2624014] @ heapprofile";
132bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  const std::string kExpectedOutput =
133bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "{\"current_allocs\": 357, \"current_bytes\": 55227, \"trace\": \"\"}";
134bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  std::string output;
135bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  AppendHeapProfileTotalsAsTraceFormat(input, &output);
136bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(kExpectedOutput, output);
137bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
138bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
139bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_F(TraceMemoryTest, AppendHeapProfileLineAsTraceFormat) {
140bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Empty input gives empty output.
141bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  std::string empty_output;
142bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat("", &empty_output));
143bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ("", empty_output);
144bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
145bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Invalid input returns false.
146bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  std::string junk_output;
147bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat("junk", &junk_output));
148bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
149424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Input with normal category and name entries.
150424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const char kCategory[] = "category";
151424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const char kName[] = "name";
152bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  std::ostringstream input;
153424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  input << "   68:     4195 [  1087:    98009] @ " << &kCategory << " "
154424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        << &kName;
155bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  const std::string kExpectedOutput =
156bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      ",\n"
157bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "{"
158bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "\"current_allocs\": 68, "
159bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "\"current_bytes\": 4195, "
160424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      "\"trace\": \"name \""
161bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "}";
162bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  std::string output;
163bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_TRUE(
164bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      AppendHeapProfileLineAsTraceFormat(input.str().c_str(), &output));
165bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(kExpectedOutput, output);
166bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Input with with the category "toplevel".
168424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(jamescook): Eliminate this special case and move the logic to the
169424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // trace viewer code.
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const char kTaskCategory[] = "toplevel";
171424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const char kTaskName[] = "TaskName";
172424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  std::ostringstream input2;
173424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  input2 << "   68:     4195 [  1087:    98009] @ " << &kTaskCategory << " "
174424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        << &kTaskName;
175424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const std::string kExpectedOutput2 =
176424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      ",\n"
177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      "{"
178424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      "\"current_allocs\": 68, "
179424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      "\"current_bytes\": 4195, "
180424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      "\"trace\": \"TaskName->PostTask \""
181424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      "}";
182424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  std::string output2;
183424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_TRUE(
184424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      AppendHeapProfileLineAsTraceFormat(input2.str().c_str(), &output2));
185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_EQ(kExpectedOutput2, output2);
186424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
187bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Zero current allocations is skipped.
188bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  std::ostringstream zero_input;
189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  zero_input << "   0:     0 [  1087:    98009] @ " << &kCategory << " "
190424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)             << &kName;
191bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  std::string zero_output;
192bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_FALSE(AppendHeapProfileLineAsTraceFormat(zero_input.str().c_str(),
193bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                                  &zero_output));
194bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ("", zero_output);
195bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
196bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
197bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben MurdochTEST_F(TraceMemoryTest, AppendHeapProfileAsTraceFormat) {
198bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Empty input gives empty output.
199bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  std::string empty_output;
200bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  AppendHeapProfileAsTraceFormat("", &empty_output);
201bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ("", empty_output);
202bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
203bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  // Typical case.
204bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  const char input[] =
205bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "heap profile:    357:    55227 [ 14653:  2624014] @ heapprofile\n"
206bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "   95:    40940 [   649:   114260] @\n"
207bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "   77:    32546 [   742:   106234] @ 0x0 0x0\n"
208bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "    0:        0 [   132:     4236] @ 0x0\n"
209bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "\n"
210bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "MAPPED_LIBRARIES:\n"
211bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "1be411fc1000-1be4139e4000 rw-p 00000000 00:00 0\n"
212bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "1be4139e4000-1be4139e5000 ---p 00000000 00:00 0\n";
213bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  const std::string kExpectedOutput =
214bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "[{"
215bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "\"current_allocs\": 357, "
216bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "\"current_bytes\": 55227, "
217bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "\"trace\": \"\"},\n"
218bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "{\"current_allocs\": 95, "
219bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "\"current_bytes\": 40940, "
220bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "\"trace\": \"\"},\n"
221bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "{\"current_allocs\": 77, "
222bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "\"current_bytes\": 32546, "
223424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      "\"trace\": \"null \""
224bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      "}]\n";
225bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  std::string output;
226bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  AppendHeapProfileAsTraceFormat(input, &output);
227bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  EXPECT_EQ(kExpectedOutput, output);
228bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
229bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
230424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)TEST_F(TraceMemoryTest, StringFromHexAddress) {
231424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_STREQ("null", StringFromHexAddress("0x0"));
232424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_STREQ("error", StringFromHexAddress("not an address"));
233424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const char kHello[] = "hello";
234424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  std::ostringstream hex_address;
235424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  hex_address << &kHello;
236424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  EXPECT_STREQ(kHello, StringFromHexAddress(hex_address.str()));
237424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
238424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
239bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}  // namespace debug
240bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}  // namespace base
241