Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(352)

Side by Side Diff: base/trace_event/memory_profiler_allocation_context_unittest.cc

Issue 1372523002: [tracing] Implement trace_event::AllocationContext (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@alloccontext
Patch Set: Rebase + clarify comment Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/trace_event/memory_profiler_allocation_context.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/trace_event/memory_profiler_allocation_context.h" 5 #include "base/trace_event/memory_profiler_allocation_context.h"
6 #include "base/trace_event/trace_event.h" 6 #include "base/trace_event/trace_event.h"
7 #include "testing/gtest/include/gtest/gtest.h" 7 #include "testing/gtest/include/gtest/gtest.h"
8 8
9 namespace base { 9 namespace base {
10 namespace trace_event { 10 namespace trace_event {
11 11
12 // Define all strings once, because the pseudo stack requires pointer equality, 12 // Define all strings once, because the pseudo stack requires pointer equality,
13 // and string interning is unreliable. 13 // and string interning is unreliable.
14 const char kCupcake[] = "Cupcake"; 14 const char kCupcake[] = "Cupcake";
15 const char kDonut[] = "Donut"; 15 const char kDonut[] = "Donut";
16 const char kEclair[] = "Eclair"; 16 const char kEclair[] = "Eclair";
17 const char kFroyo[] = "Froyo"; 17 const char kFroyo[] = "Froyo";
18 const char kGingerbread[] = "Gingerbread"; 18 const char kGingerbread[] = "Gingerbread";
19 const char kHoneycomb[] = "Honeycomb";
20 19
21 // Asserts that the fixed-size array |expected_stack| matches the pseudo 20 // Returns a pointer past the end of the fixed-size array |array| of |T| of
22 // stack. Syntax note: |const StackFrame (&expected_stack)[N]| is the syntax 21 // length |N|, identical to C++11 |std::end|.
23 // for "expected_stack is a reference to a const fixed-size array of StackFrame 22 template <typename T, int N>
24 // of length N". 23 const T* End(const T(&array)[N]) {
24 return array + N;
25 }
26
27 // Asserts that the fixed-size array |expected_backtrace| matches the backtrace
28 // in |AllocationContextTracker::GetContextSnapshot|.
25 template <size_t N> 29 template <size_t N>
26 void AssertPseudoStackEquals(const StackFrame(&expected_stack)[N]) { 30 void AssertBacktraceEquals(const StackFrame(&expected_backtrace)[N]) {
27 auto pseudo_stack = AllocationContextTracker::GetPseudoStackForTesting(); 31 AllocationContext ctx = AllocationContextTracker::GetContextSnapshot();
28 auto actual = pseudo_stack->top(); 32
29 auto actual_bottom = pseudo_stack->bottom(); 33 auto actual = ctx.backtrace.frames;
30 auto expected = expected_stack; 34 auto actual_bottom = End(ctx.backtrace.frames);
31 auto expected_bottom = expected_stack + N; 35 auto expected = expected_backtrace;
36 auto expected_bottom = End(expected_backtrace);
32 37
33 // Note that this requires the pointers to be equal, this is not doing a deep 38 // Note that this requires the pointers to be equal, this is not doing a deep
34 // string comparison. 39 // string comparison.
35 for (; actual != actual_bottom && expected != expected_bottom; 40 for (; actual != actual_bottom && expected != expected_bottom;
36 actual++, expected++) 41 actual++, expected++)
37 ASSERT_EQ(*expected, *actual); 42 ASSERT_EQ(*expected, *actual);
38 43
39 // Ensure that the height of the stacks is the same. 44 // Ensure that the height of the stacks is the same.
40 ASSERT_EQ(actual, actual_bottom); 45 ASSERT_EQ(actual, actual_bottom);
41 ASSERT_EQ(expected, expected_bottom); 46 ASSERT_EQ(expected, expected_bottom);
42 } 47 }
43 48
44 void AssertPseudoStackEmpty() { 49 void AssertBacktraceEmpty() {
45 auto pseudo_stack = AllocationContextTracker::GetPseudoStackForTesting(); 50 AllocationContext ctx = AllocationContextTracker::GetContextSnapshot();
46 ASSERT_EQ(pseudo_stack->top(), pseudo_stack->bottom()); 51
52 for (StackFrame frame : ctx.backtrace.frames)
53 ASSERT_EQ(nullptr, frame);
47 } 54 }
48 55
49 class AllocationContextTest : public testing::Test { 56 class AllocationContextTest : public testing::Test {
50 public: 57 public:
51 void EnableTracing() { 58 void SetUp() override {
52 TraceConfig config(""); 59 TraceConfig config("");
53 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE); 60 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE);
54 AllocationContextTracker::SetCaptureEnabled(true); 61 AllocationContextTracker::SetCaptureEnabled(true);
55 } 62 }
56 63
57 void DisableTracing() { 64 void TearDown() override {
58 AllocationContextTracker::SetCaptureEnabled(false); 65 AllocationContextTracker::SetCaptureEnabled(false);
59 TraceLog::GetInstance()->SetDisabled(); 66 TraceLog::GetInstance()->SetDisabled();
60 } 67 }
61 }; 68 };
62 69
70 // Check that |TRACE_EVENT| macros push and pop to the pseudo stack correctly.
71 // Also check that |GetContextSnapshot| fills the backtrace with null pointers
72 // when the pseudo stack height is less than the capacity.
63 TEST_F(AllocationContextTest, PseudoStackScopedTrace) { 73 TEST_F(AllocationContextTest, PseudoStackScopedTrace) {
64 StackFrame c = kCupcake; 74 StackFrame c = kCupcake;
65 StackFrame d = kDonut; 75 StackFrame d = kDonut;
66 StackFrame e = kEclair; 76 StackFrame e = kEclair;
67 StackFrame f = kFroyo; 77 StackFrame f = kFroyo;
68 78
69 EnableTracing(); 79 AssertBacktraceEmpty();
70 AssertPseudoStackEmpty();
71 80
72 { 81 {
73 TRACE_EVENT0("Testing", kCupcake); 82 TRACE_EVENT0("Testing", kCupcake);
74 StackFrame frame_c[] = {c}; 83 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
75 AssertPseudoStackEquals(frame_c); 84 AssertBacktraceEquals(frame_c);
76 85
77 { 86 {
78 TRACE_EVENT0("Testing", kDonut); 87 TRACE_EVENT0("Testing", kDonut);
79 StackFrame frame_dc[] = {d, c}; 88 StackFrame frame_cd[] = {c, d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
80 AssertPseudoStackEquals(frame_dc); 89 AssertBacktraceEquals(frame_cd);
81 } 90 }
82 91
83 AssertPseudoStackEquals(frame_c); 92 AssertBacktraceEquals(frame_c);
84 93
85 { 94 {
86 TRACE_EVENT0("Testing", kEclair); 95 TRACE_EVENT0("Testing", kEclair);
87 StackFrame frame_ec[] = {e, c}; 96 StackFrame frame_ce[] = {c, e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
88 AssertPseudoStackEquals(frame_ec); 97 AssertBacktraceEquals(frame_ce);
89 } 98 }
90 99
91 AssertPseudoStackEquals(frame_c); 100 AssertBacktraceEquals(frame_c);
92 } 101 }
93 102
94 AssertPseudoStackEmpty(); 103 AssertBacktraceEmpty();
95 104
96 { 105 {
97 TRACE_EVENT0("Testing", kFroyo); 106 TRACE_EVENT0("Testing", kFroyo);
98 StackFrame frame_f[] = {f}; 107 StackFrame frame_f[] = {f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
99 AssertPseudoStackEquals(frame_f); 108 AssertBacktraceEquals(frame_f);
100 } 109 }
101 110
102 AssertPseudoStackEmpty(); 111 AssertBacktraceEmpty();
103 DisableTracing();
104 } 112 }
105 113
114 // Same as |PseudoStackScopedTrace|, but now test the |TRACE_EVENT_BEGIN| and
115 // |TRACE_EVENT_END| macros.
106 TEST_F(AllocationContextTest, PseudoStackBeginEndTrace) { 116 TEST_F(AllocationContextTest, PseudoStackBeginEndTrace) {
107 StackFrame c = kCupcake; 117 StackFrame c = kCupcake;
108 StackFrame d = kDonut; 118 StackFrame d = kDonut;
109 StackFrame e = kEclair; 119 StackFrame e = kEclair;
110 StackFrame f = kFroyo; 120 StackFrame f = kFroyo;
111 121
112 StackFrame frame_c[] = {c}; 122 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
113 StackFrame frame_dc[] = {d, c}; 123 StackFrame frame_cd[] = {c, d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
114 StackFrame frame_ec[] = {e, c}; 124 StackFrame frame_ce[] = {c, e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
115 StackFrame frame_f[] = {f}; 125 StackFrame frame_f[] = {f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
116 126
117 EnableTracing(); 127 AssertBacktraceEmpty();
118 AssertPseudoStackEmpty();
119 128
120 TRACE_EVENT_BEGIN0("Testing", kCupcake); 129 TRACE_EVENT_BEGIN0("Testing", kCupcake);
121 AssertPseudoStackEquals(frame_c); 130 AssertBacktraceEquals(frame_c);
122 131
123 TRACE_EVENT_BEGIN0("Testing", kDonut); 132 TRACE_EVENT_BEGIN0("Testing", kDonut);
124 AssertPseudoStackEquals(frame_dc); 133 AssertBacktraceEquals(frame_cd);
125 TRACE_EVENT_END0("Testing", kDonut); 134 TRACE_EVENT_END0("Testing", kDonut);
126 135
127 AssertPseudoStackEquals(frame_c); 136 AssertBacktraceEquals(frame_c);
128 137
129 TRACE_EVENT_BEGIN0("Testing", kEclair); 138 TRACE_EVENT_BEGIN0("Testing", kEclair);
130 AssertPseudoStackEquals(frame_ec); 139 AssertBacktraceEquals(frame_ce);
131 TRACE_EVENT_END0("Testing", kEclair); 140 TRACE_EVENT_END0("Testing", kEclair);
132 141
133 AssertPseudoStackEquals(frame_c); 142 AssertBacktraceEquals(frame_c);
134 TRACE_EVENT_END0("Testing", kCupcake); 143 TRACE_EVENT_END0("Testing", kCupcake);
135 144
136 AssertPseudoStackEmpty(); 145 AssertBacktraceEmpty();
137 146
138 TRACE_EVENT_BEGIN0("Testing", kFroyo); 147 TRACE_EVENT_BEGIN0("Testing", kFroyo);
139 AssertPseudoStackEquals(frame_f); 148 AssertBacktraceEquals(frame_f);
140 TRACE_EVENT_END0("Testing", kFroyo); 149 TRACE_EVENT_END0("Testing", kFroyo);
141 150
142 AssertPseudoStackEmpty(); 151 AssertBacktraceEmpty();
143 DisableTracing();
144 } 152 }
145 153
146 TEST_F(AllocationContextTest, PseudoStackMixedTrace) { 154 TEST_F(AllocationContextTest, PseudoStackMixedTrace) {
147 StackFrame c = kCupcake; 155 StackFrame c = kCupcake;
148 StackFrame d = kDonut; 156 StackFrame d = kDonut;
149 StackFrame e = kEclair; 157 StackFrame e = kEclair;
150 StackFrame f = kFroyo; 158 StackFrame f = kFroyo;
151 159
152 StackFrame frame_c[] = {c}; 160 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
153 StackFrame frame_dc[] = {d, c}; 161 StackFrame frame_cd[] = {c, d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
154 StackFrame frame_e[] = {e}; 162 StackFrame frame_e[] = {e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
155 StackFrame frame_fe[] = {f, e}; 163 StackFrame frame_ef[] = {e, f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
156 164
157 EnableTracing(); 165 AssertBacktraceEmpty();
158 AssertPseudoStackEmpty();
159 166
160 TRACE_EVENT_BEGIN0("Testing", kCupcake); 167 TRACE_EVENT_BEGIN0("Testing", kCupcake);
161 AssertPseudoStackEquals(frame_c); 168 AssertBacktraceEquals(frame_c);
162 169
163 { 170 {
164 TRACE_EVENT0("Testing", kDonut); 171 TRACE_EVENT0("Testing", kDonut);
165 AssertPseudoStackEquals(frame_dc); 172 AssertBacktraceEquals(frame_cd);
166 } 173 }
167 174
168 AssertPseudoStackEquals(frame_c); 175 AssertBacktraceEquals(frame_c);
169 TRACE_EVENT_END0("Testing", kCupcake); 176 TRACE_EVENT_END0("Testing", kCupcake);
170 AssertPseudoStackEmpty(); 177 AssertBacktraceEmpty();
171 178
172 { 179 {
173 TRACE_EVENT0("Testing", kEclair); 180 TRACE_EVENT0("Testing", kEclair);
174 AssertPseudoStackEquals(frame_e); 181 AssertBacktraceEquals(frame_e);
175 182
176 TRACE_EVENT_BEGIN0("Testing", kFroyo); 183 TRACE_EVENT_BEGIN0("Testing", kFroyo);
177 AssertPseudoStackEquals(frame_fe); 184 AssertBacktraceEquals(frame_ef);
178 TRACE_EVENT_END0("Testing", kFroyo); 185 TRACE_EVENT_END0("Testing", kFroyo);
179 AssertPseudoStackEquals(frame_e); 186 AssertBacktraceEquals(frame_e);
180 } 187 }
181 188
182 AssertPseudoStackEmpty(); 189 AssertBacktraceEmpty();
183 DisableTracing();
184 } 190 }
185 191
186 TEST_F(AllocationContextTest, PseudoStackEnableWithEventInScope) { 192 TEST_F(AllocationContextTest, BacktraceTakesTop) {
187 StackFrame h = kHoneycomb; 193 // Push 12 events onto the pseudo stack.
194 TRACE_EVENT0("Testing", kCupcake);
195 TRACE_EVENT0("Testing", kCupcake);
196 TRACE_EVENT0("Testing", kCupcake);
197 TRACE_EVENT0("Testing", kCupcake);
198
199 TRACE_EVENT0("Testing", kCupcake);
200 TRACE_EVENT0("Testing", kCupcake);
201 TRACE_EVENT0("Testing", kCupcake);
202 TRACE_EVENT0("Testing", kCupcake);
203
204 TRACE_EVENT0("Testing", kCupcake);
205 TRACE_EVENT0("Testing", kDonut);
206 TRACE_EVENT0("Testing", kEclair);
207 TRACE_EVENT0("Testing", kFroyo);
188 208
189 { 209 {
190 TRACE_EVENT0("Testing", kGingerbread); 210 TRACE_EVENT0("Testing", kGingerbread);
191 EnableTracing(); 211 AllocationContext ctx = AllocationContextTracker::GetContextSnapshot();
192 AssertPseudoStackEmpty();
193 212
194 { 213 // The pseudo stack relies on pointer equality, not deep string comparisons.
195 TRACE_EVENT0("Testing", kHoneycomb); 214 ASSERT_EQ(kCupcake, ctx.backtrace.frames[0]);
196 StackFrame frame_h[] = {h}; 215 ASSERT_EQ(kFroyo, ctx.backtrace.frames[11]);
197 AssertPseudoStackEquals(frame_h); 216 }
198 }
199 217
200 AssertPseudoStackEmpty(); 218 {
201 219 AllocationContext ctx = AllocationContextTracker::GetContextSnapshot();
202 // The pop at the end of this scope for the 'Gingerbread' frame must not 220 ASSERT_EQ(kCupcake, ctx.backtrace.frames[0]);
203 // cause a stack underflow. 221 ASSERT_EQ(kFroyo, ctx.backtrace.frames[11]);
204 } 222 }
205 AssertPseudoStackEmpty();
206 DisableTracing();
207 } 223 }
208 224
209 } // namespace trace_event 225 } // namespace trace_event
210 } // namespace base 226 } // namespace base
OLDNEW
« no previous file with comments | « base/trace_event/memory_profiler_allocation_context.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698