OLD | NEW |
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 // Asserts that the fixed-size array |expected_stack| matches the pseudo | 12 // Returns a pointer past the end of the fixed-size array |array| of |T| of |
13 // stack. Syntax note: |const StackFrame (&expected_stack)[N]| is the syntax | 13 // length |N|, identical to C++11 |std::end|. |
14 // for "expected_stack is a reference to a const fixed-size array of StackFrame | 14 template <typename T, int N> |
15 // of length N". | 15 const T* End(const T(&array)[N]) { |
| 16 return array + N; |
| 17 } |
| 18 |
| 19 // Asserts that the fixed-size array |expected_backtrace| matches the backtrace |
| 20 // in |AllocationContextTracker::GetContext|. |
16 template <size_t N> | 21 template <size_t N> |
17 void AssertPseudoStackEquals(const StackFrame (&expected_stack)[N]) { | 22 void AssertBacktraceEquals(const StackFrame(&expected_backtrace)[N]) { |
18 auto pseudo_stack = AllocationContextTracker::GetPseudoStackForTesting(); | 23 AllocationContext ctx = AllocationContextTracker::GetContext(); |
19 auto actual = pseudo_stack->top(); | 24 |
20 auto actual_bottom = pseudo_stack->bottom(); | 25 auto actual = ctx.backtrace; |
21 auto expected = expected_stack; | 26 auto actual_bottom = End(ctx.backtrace); |
22 auto expected_bottom = expected_stack + N; | 27 auto expected = expected_backtrace; |
| 28 auto expected_bottom = End(expected_backtrace); |
23 | 29 |
24 for (; actual != actual_bottom && expected != expected_bottom; | 30 for (; actual != actual_bottom && expected != expected_bottom; |
25 actual++, expected++) { | 31 actual++, expected++) { |
26 ASSERT_STREQ(*expected, *actual); | 32 ASSERT_STREQ(*expected, *actual); |
27 } | 33 } |
28 | 34 |
29 // Ensure that the height of the stacks is the same. | 35 // Ensure that the height of the stacks is the same. |
30 ASSERT_EQ(actual, actual_bottom); | 36 ASSERT_EQ(actual, actual_bottom); |
31 ASSERT_EQ(expected, expected_bottom); | 37 ASSERT_EQ(expected, expected_bottom); |
32 } | 38 } |
33 | 39 |
34 void AssertPseudoStackEmpty() { | 40 void AssertBacktraceEmpty() { |
35 auto pseudo_stack = AllocationContextTracker::GetPseudoStackForTesting(); | 41 AllocationContext ctx = AllocationContextTracker::GetContext(); |
36 ASSERT_EQ(pseudo_stack->top(), pseudo_stack->bottom()); | 42 |
| 43 for (StackFrame frame : ctx.backtrace) |
| 44 ASSERT_EQ(nullptr, frame); |
37 } | 45 } |
38 | 46 |
39 class AllocationContextTest : public testing::Test { | 47 class AllocationContextTest : public testing::Test { |
40 public: | 48 public: |
41 void EnableTracing() { | 49 void SetUp() override { |
42 TraceConfig config(""); | 50 TraceConfig config(""); |
43 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE); | 51 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE); |
44 AllocationContextTracker::SetCaptureEnabled(true); | 52 AllocationContextTracker::SetCaptureEnabled(true); |
45 } | 53 } |
46 | 54 |
47 void DisableTracing() { | 55 void TearDown() override { |
48 AllocationContextTracker::SetCaptureEnabled(false); | 56 AllocationContextTracker::SetCaptureEnabled(false); |
49 TraceLog::GetInstance()->SetDisabled(); | 57 TraceLog::GetInstance()->SetDisabled(); |
50 } | 58 } |
51 }; | 59 }; |
52 | 60 |
| 61 // Check that |TRACE_EVENT| macros push and pop to the pseudo stack correctly. |
| 62 // Also check that |GetContext| fills the backtrace with null pointers when the |
| 63 // pseudo stack height is less than the capacity. |
53 TEST_F(AllocationContextTest, PseudoStackScopedTrace) { | 64 TEST_F(AllocationContextTest, PseudoStackScopedTrace) { |
54 StackFrame c = "Cupcake"; | 65 StackFrame c = "Cupcake"; |
55 StackFrame d = "Donut"; | 66 StackFrame d = "Donut"; |
56 StackFrame e = "Eclair"; | 67 StackFrame e = "Eclair"; |
57 StackFrame f = "Froyo"; | 68 StackFrame f = "Froyo"; |
58 | 69 |
59 EnableTracing(); | 70 AssertBacktraceEmpty(); |
60 AssertPseudoStackEmpty(); | |
61 | 71 |
62 { | 72 { |
63 TRACE_EVENT0("Testing", "Cupcake"); | 73 TRACE_EVENT0("Testing", "Cupcake"); |
64 StackFrame frame_c[] = {c}; | 74 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0}; |
65 AssertPseudoStackEquals(frame_c); | 75 AssertBacktraceEquals(frame_c); |
66 | 76 |
67 { | 77 { |
68 TRACE_EVENT0("Testing", "Donut"); | 78 TRACE_EVENT0("Testing", "Donut"); |
69 StackFrame frame_dc[] = {d, c}; | 79 StackFrame frame_dc[] = {d, c, 0, 0, 0, 0, 0, 0}; |
70 AssertPseudoStackEquals(frame_dc); | 80 AssertBacktraceEquals(frame_dc); |
71 } | 81 } |
72 | 82 |
73 AssertPseudoStackEquals(frame_c); | 83 AssertBacktraceEquals(frame_c); |
74 | 84 |
75 { | 85 { |
76 TRACE_EVENT0("Testing", "Eclair"); | 86 TRACE_EVENT0("Testing", "Eclair"); |
77 StackFrame frame_ec[] = {e, c}; | 87 StackFrame frame_ec[] = {e, c, 0, 0, 0, 0, 0, 0}; |
78 AssertPseudoStackEquals(frame_ec); | 88 AssertBacktraceEquals(frame_ec); |
79 } | 89 } |
80 | 90 |
81 AssertPseudoStackEquals(frame_c); | 91 AssertBacktraceEquals(frame_c); |
82 } | 92 } |
83 | 93 |
84 AssertPseudoStackEmpty(); | 94 AssertBacktraceEmpty(); |
85 | 95 |
86 { | 96 { |
87 TRACE_EVENT0("Testing", "Froyo"); | 97 TRACE_EVENT0("Testing", "Froyo"); |
88 StackFrame frame_f[] = {f}; | 98 StackFrame frame_f[] = {f, 0, 0, 0, 0, 0, 0, 0}; |
89 AssertPseudoStackEquals(frame_f); | 99 AssertBacktraceEquals(frame_f); |
90 } | 100 } |
91 | 101 |
92 AssertPseudoStackEmpty(); | 102 AssertBacktraceEmpty(); |
93 DisableTracing(); | |
94 } | 103 } |
95 | 104 |
| 105 // Same as |PseudoStackScopedTrace|, but now test the |TRACE_EVENT_BEGIN| and |
| 106 // |TRACE_EVENT_END| macros. |
96 TEST_F(AllocationContextTest, PseudoStackBeginEndTrace) { | 107 TEST_F(AllocationContextTest, PseudoStackBeginEndTrace) { |
97 StackFrame c = "Cupcake"; | 108 StackFrame c = "Cupcake"; |
98 StackFrame d = "Donut"; | 109 StackFrame d = "Donut"; |
99 StackFrame e = "Eclair"; | 110 StackFrame e = "Eclair"; |
100 StackFrame f = "Froyo"; | 111 StackFrame f = "Froyo"; |
101 | 112 |
102 StackFrame frame_c[] = {c}; | 113 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0}; |
103 StackFrame frame_dc[] = {d, c}; | 114 StackFrame frame_dc[] = {d, c, 0, 0, 0, 0, 0, 0}; |
104 StackFrame frame_ec[] = {e, c}; | 115 StackFrame frame_ec[] = {e, c, 0, 0, 0, 0, 0, 0}; |
105 StackFrame frame_f[] = {f}; | 116 StackFrame frame_f[] = {f, 0, 0, 0, 0, 0, 0, 0}; |
106 | 117 |
107 EnableTracing(); | 118 AssertBacktraceEmpty(); |
108 AssertPseudoStackEmpty(); | |
109 | 119 |
110 TRACE_EVENT_BEGIN0("Testing", "Cupcake"); | 120 TRACE_EVENT_BEGIN0("Testing", "Cupcake"); |
111 AssertPseudoStackEquals(frame_c); | 121 AssertBacktraceEquals(frame_c); |
112 | 122 |
113 TRACE_EVENT_BEGIN0("Testing", "Donut"); | 123 TRACE_EVENT_BEGIN0("Testing", "Donut"); |
114 AssertPseudoStackEquals(frame_dc); | 124 AssertBacktraceEquals(frame_dc); |
115 TRACE_EVENT_END0("Testing", "Donut"); | 125 TRACE_EVENT_END0("Testing", "Donut"); |
116 | 126 |
117 AssertPseudoStackEquals(frame_c); | 127 AssertBacktraceEquals(frame_c); |
118 | 128 |
119 TRACE_EVENT_BEGIN0("Testing", "Eclair"); | 129 TRACE_EVENT_BEGIN0("Testing", "Eclair"); |
120 AssertPseudoStackEquals(frame_ec); | 130 AssertBacktraceEquals(frame_ec); |
121 TRACE_EVENT_END0("Testing", "Eclair"); | 131 TRACE_EVENT_END0("Testing", "Eclair"); |
122 | 132 |
123 AssertPseudoStackEquals(frame_c); | 133 AssertBacktraceEquals(frame_c); |
124 TRACE_EVENT_END0("Testing", "Cupcake"); | 134 TRACE_EVENT_END0("Testing", "Cupcake"); |
125 | 135 |
126 AssertPseudoStackEmpty(); | 136 AssertBacktraceEmpty(); |
127 | 137 |
128 TRACE_EVENT_BEGIN0("Testing", "Froyo"); | 138 TRACE_EVENT_BEGIN0("Testing", "Froyo"); |
129 AssertPseudoStackEquals(frame_f); | 139 AssertBacktraceEquals(frame_f); |
130 TRACE_EVENT_END0("Testing", "Froyo"); | 140 TRACE_EVENT_END0("Testing", "Froyo"); |
131 | 141 |
132 AssertPseudoStackEmpty(); | 142 AssertBacktraceEmpty(); |
133 DisableTracing(); | |
134 } | 143 } |
135 | 144 |
136 TEST_F(AllocationContextTest, PseudoStackMixedTrace) { | 145 TEST_F(AllocationContextTest, PseudoStackMixedTrace) { |
137 StackFrame c = "Cupcake"; | 146 StackFrame c = "Cupcake"; |
138 StackFrame d = "Donut"; | 147 StackFrame d = "Donut"; |
139 StackFrame e = "Eclair"; | 148 StackFrame e = "Eclair"; |
140 StackFrame f = "Froyo"; | 149 StackFrame f = "Froyo"; |
141 | 150 |
142 StackFrame frame_c[] = {c}; | 151 StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0}; |
143 StackFrame frame_dc[] = {d, c}; | 152 StackFrame frame_dc[] = {d, c, 0, 0, 0, 0, 0, 0}; |
144 StackFrame frame_e[] = {e}; | 153 StackFrame frame_e[] = {e, 0, 0, 0, 0, 0, 0, 0}; |
145 StackFrame frame_fe[] = {f, e}; | 154 StackFrame frame_fe[] = {f, e, 0, 0, 0, 0, 0, 0}; |
146 | 155 |
147 EnableTracing(); | 156 AssertBacktraceEmpty(); |
148 AssertPseudoStackEmpty(); | |
149 | 157 |
150 TRACE_EVENT_BEGIN0("Testing", "Cupcake"); | 158 TRACE_EVENT_BEGIN0("Testing", "Cupcake"); |
151 AssertPseudoStackEquals(frame_c); | 159 AssertBacktraceEquals(frame_c); |
152 | 160 |
153 { | 161 { |
154 TRACE_EVENT0("Testing", "Donut"); | 162 TRACE_EVENT0("Testing", "Donut"); |
155 AssertPseudoStackEquals(frame_dc); | 163 AssertBacktraceEquals(frame_dc); |
156 } | 164 } |
157 | 165 |
158 AssertPseudoStackEquals(frame_c); | 166 AssertBacktraceEquals(frame_c); |
159 TRACE_EVENT_END0("Testing", "Cupcake"); | 167 TRACE_EVENT_END0("Testing", "Cupcake"); |
160 AssertPseudoStackEmpty(); | 168 AssertBacktraceEmpty(); |
161 | 169 |
162 { | 170 { |
163 TRACE_EVENT0("Testing", "Eclair"); | 171 TRACE_EVENT0("Testing", "Eclair"); |
164 AssertPseudoStackEquals(frame_e); | 172 AssertBacktraceEquals(frame_e); |
165 | 173 |
166 TRACE_EVENT_BEGIN0("Testing", "Froyo"); | 174 TRACE_EVENT_BEGIN0("Testing", "Froyo"); |
167 AssertPseudoStackEquals(frame_fe); | 175 AssertBacktraceEquals(frame_fe); |
168 TRACE_EVENT_END0("Testing", "Froyo"); | 176 TRACE_EVENT_END0("Testing", "Froyo"); |
169 AssertPseudoStackEquals(frame_e); | 177 AssertBacktraceEquals(frame_e); |
170 } | 178 } |
171 | 179 |
172 AssertPseudoStackEmpty(); | 180 AssertBacktraceEmpty(); |
173 DisableTracing(); | |
174 } | 181 } |
175 | 182 |
176 TEST_F(AllocationContextTest, PseudoStackEnableWithEventInScope) { | 183 TEST_F(AllocationContextTest, BacktraceTakesTop) { |
177 StackFrame h = "Honeycomb"; | 184 TRACE_EVENT0("Testing", "Cupcake"); |
| 185 TRACE_EVENT0("Testing", "Donut"); |
| 186 TRACE_EVENT0("Testing", "Eclair"); |
| 187 TRACE_EVENT0("Testing", "Froyo"); |
| 188 TRACE_EVENT0("Testing", "Gingerbread"); |
| 189 TRACE_EVENT0("Testing", "Honeycomb"); |
| 190 TRACE_EVENT0("Testing", "Ice Cream Sandwich"); |
| 191 TRACE_EVENT0("Testing", "Jelly Bean"); |
178 | 192 |
179 { | 193 { |
180 TRACE_EVENT0("Testing", "Gingerbread"); | 194 TRACE_EVENT0("Testing", "KitKat"); |
181 EnableTracing(); | 195 AllocationContext ctx = AllocationContextTracker::GetContext(); |
182 AssertPseudoStackEmpty(); | 196 ASSERT_STREQ("KitKat", ctx.backtrace[0]); |
| 197 ASSERT_STREQ("Donut", ctx.backtrace[7]); |
| 198 } |
183 | 199 |
184 { | 200 { |
185 TRACE_EVENT0("Testing", "Honeycomb"); | 201 AllocationContext ctx = AllocationContextTracker::GetContext(); |
186 StackFrame frame_h[] = {h}; | 202 ASSERT_STREQ("Jelly Bean", ctx.backtrace[0]); |
187 AssertPseudoStackEquals(frame_h); | 203 ASSERT_STREQ("Cupcake", ctx.backtrace[7]); |
188 } | |
189 | |
190 AssertPseudoStackEmpty(); | |
191 | |
192 // The pop at the end of this scope for the 'Gingerbread' frame must not | |
193 // cause a stack underflow. | |
194 } | 204 } |
195 AssertPseudoStackEmpty(); | |
196 DisableTracing(); | |
197 } | 205 } |
198 | 206 |
199 } // namespace trace_event | 207 } // namespace trace_event |
200 } // namespace base | 208 } // namespace base |
OLD | NEW |