Index: base/trace_event/memory_profiler_allocation_context_unittest.cc |
diff --git a/base/trace_event/memory_profiler_allocation_context_unittest.cc b/base/trace_event/memory_profiler_allocation_context_unittest.cc |
index a5b7244717ad772d32ed07d85059c1939bf67ce2..6ee6b6120ff5ac24f67055d7ec24d8afecb9ccf4 100644 |
--- a/base/trace_event/memory_profiler_allocation_context_unittest.cc |
+++ b/base/trace_event/memory_profiler_allocation_context_unittest.cc |
@@ -16,19 +16,24 @@ const char kDonut[] = "Donut"; |
const char kEclair[] = "Eclair"; |
const char kFroyo[] = "Froyo"; |
const char kGingerbread[] = "Gingerbread"; |
-const char kHoneycomb[] = "Honeycomb"; |
-// Asserts that the fixed-size array |expected_stack| matches the pseudo |
-// stack. Syntax note: |const StackFrame (&expected_stack)[N]| is the syntax |
-// for "expected_stack is a reference to a const fixed-size array of StackFrame |
-// of length N". |
+// Returns a pointer past the end of the fixed-size array |array| of |T| of |
+// length |N|, identical to C++11 |std::end|. |
+template <typename T, int N> |
+const T* End(const T(&array)[N]) { |
+ return array + N; |
+} |
+ |
+// Asserts that the fixed-size array |expected_backtrace| matches the backtrace |
+// in |AllocationContextTracker::GetContextSnapshot|. |
template <size_t N> |
-void AssertPseudoStackEquals(const StackFrame(&expected_stack)[N]) { |
- auto pseudo_stack = AllocationContextTracker::GetPseudoStackForTesting(); |
- auto actual = pseudo_stack->top(); |
- auto actual_bottom = pseudo_stack->bottom(); |
- auto expected = expected_stack; |
- auto expected_bottom = expected_stack + N; |
+void AssertBacktraceEquals(const StackFrame(&expected_backtrace)[N]) { |
+ AllocationContext ctx = AllocationContextTracker::GetContextSnapshot(); |
+ |
+ auto actual = ctx.backtrace.frames; |
+ auto actual_bottom = End(ctx.backtrace.frames); |
+ auto expected = expected_backtrace; |
+ auto expected_bottom = End(expected_backtrace); |
// Note that this requires the pointers to be equal, this is not doing a deep |
// string comparison. |
@@ -41,106 +46,109 @@ void AssertPseudoStackEquals(const StackFrame(&expected_stack)[N]) { |
ASSERT_EQ(expected, expected_bottom); |
} |
-void AssertPseudoStackEmpty() { |
- auto pseudo_stack = AllocationContextTracker::GetPseudoStackForTesting(); |
- ASSERT_EQ(pseudo_stack->top(), pseudo_stack->bottom()); |
+void AssertBacktraceEmpty() { |
+ AllocationContext ctx = AllocationContextTracker::GetContextSnapshot(); |
+ |
+ for (StackFrame frame : ctx.backtrace.frames) |
+ ASSERT_EQ(nullptr, frame); |
} |
class AllocationContextTest : public testing::Test { |
public: |
- void EnableTracing() { |
+ void SetUp() override { |
TraceConfig config(""); |
TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE); |
AllocationContextTracker::SetCaptureEnabled(true); |
} |
- void DisableTracing() { |
+ void TearDown() override { |
AllocationContextTracker::SetCaptureEnabled(false); |
TraceLog::GetInstance()->SetDisabled(); |
} |
}; |
+// Check that |TRACE_EVENT| macros push and pop to the pseudo stack correctly. |
+// Also check that |GetContextSnapshot| fills the backtrace with null pointers |
+// when the pseudo stack height is less than the capacity. |
TEST_F(AllocationContextTest, PseudoStackScopedTrace) { |
StackFrame c = kCupcake; |
StackFrame d = kDonut; |
StackFrame e = kEclair; |
StackFrame f = kFroyo; |
- EnableTracing(); |
- AssertPseudoStackEmpty(); |
+ AssertBacktraceEmpty(); |
{ |
TRACE_EVENT0("Testing", kCupcake); |
- StackFrame frame_c[] = {c}; |
- AssertPseudoStackEquals(frame_c); |
+ StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+ AssertBacktraceEquals(frame_c); |
{ |
TRACE_EVENT0("Testing", kDonut); |
- StackFrame frame_dc[] = {d, c}; |
- AssertPseudoStackEquals(frame_dc); |
+ StackFrame frame_cd[] = {c, d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+ AssertBacktraceEquals(frame_cd); |
} |
- AssertPseudoStackEquals(frame_c); |
+ AssertBacktraceEquals(frame_c); |
{ |
TRACE_EVENT0("Testing", kEclair); |
- StackFrame frame_ec[] = {e, c}; |
- AssertPseudoStackEquals(frame_ec); |
+ StackFrame frame_ce[] = {c, e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+ AssertBacktraceEquals(frame_ce); |
} |
- AssertPseudoStackEquals(frame_c); |
+ AssertBacktraceEquals(frame_c); |
} |
- AssertPseudoStackEmpty(); |
+ AssertBacktraceEmpty(); |
{ |
TRACE_EVENT0("Testing", kFroyo); |
- StackFrame frame_f[] = {f}; |
- AssertPseudoStackEquals(frame_f); |
+ StackFrame frame_f[] = {f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+ AssertBacktraceEquals(frame_f); |
} |
- AssertPseudoStackEmpty(); |
- DisableTracing(); |
+ AssertBacktraceEmpty(); |
} |
+// Same as |PseudoStackScopedTrace|, but now test the |TRACE_EVENT_BEGIN| and |
+// |TRACE_EVENT_END| macros. |
TEST_F(AllocationContextTest, PseudoStackBeginEndTrace) { |
StackFrame c = kCupcake; |
StackFrame d = kDonut; |
StackFrame e = kEclair; |
StackFrame f = kFroyo; |
- StackFrame frame_c[] = {c}; |
- StackFrame frame_dc[] = {d, c}; |
- StackFrame frame_ec[] = {e, c}; |
- StackFrame frame_f[] = {f}; |
+ StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+ StackFrame frame_cd[] = {c, d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+ StackFrame frame_ce[] = {c, e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+ StackFrame frame_f[] = {f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
- EnableTracing(); |
- AssertPseudoStackEmpty(); |
+ AssertBacktraceEmpty(); |
TRACE_EVENT_BEGIN0("Testing", kCupcake); |
- AssertPseudoStackEquals(frame_c); |
+ AssertBacktraceEquals(frame_c); |
TRACE_EVENT_BEGIN0("Testing", kDonut); |
- AssertPseudoStackEquals(frame_dc); |
+ AssertBacktraceEquals(frame_cd); |
TRACE_EVENT_END0("Testing", kDonut); |
- AssertPseudoStackEquals(frame_c); |
+ AssertBacktraceEquals(frame_c); |
TRACE_EVENT_BEGIN0("Testing", kEclair); |
- AssertPseudoStackEquals(frame_ec); |
+ AssertBacktraceEquals(frame_ce); |
TRACE_EVENT_END0("Testing", kEclair); |
- AssertPseudoStackEquals(frame_c); |
+ AssertBacktraceEquals(frame_c); |
TRACE_EVENT_END0("Testing", kCupcake); |
- AssertPseudoStackEmpty(); |
+ AssertBacktraceEmpty(); |
TRACE_EVENT_BEGIN0("Testing", kFroyo); |
- AssertPseudoStackEquals(frame_f); |
+ AssertBacktraceEquals(frame_f); |
TRACE_EVENT_END0("Testing", kFroyo); |
- AssertPseudoStackEmpty(); |
- DisableTracing(); |
+ AssertBacktraceEmpty(); |
} |
TEST_F(AllocationContextTest, PseudoStackMixedTrace) { |
@@ -149,61 +157,69 @@ TEST_F(AllocationContextTest, PseudoStackMixedTrace) { |
StackFrame e = kEclair; |
StackFrame f = kFroyo; |
- StackFrame frame_c[] = {c}; |
- StackFrame frame_dc[] = {d, c}; |
- StackFrame frame_e[] = {e}; |
- StackFrame frame_fe[] = {f, e}; |
+ StackFrame frame_c[] = {c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+ StackFrame frame_cd[] = {c, d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+ StackFrame frame_e[] = {e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+ StackFrame frame_ef[] = {e, f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
- EnableTracing(); |
- AssertPseudoStackEmpty(); |
+ AssertBacktraceEmpty(); |
TRACE_EVENT_BEGIN0("Testing", kCupcake); |
- AssertPseudoStackEquals(frame_c); |
+ AssertBacktraceEquals(frame_c); |
{ |
TRACE_EVENT0("Testing", kDonut); |
- AssertPseudoStackEquals(frame_dc); |
+ AssertBacktraceEquals(frame_cd); |
} |
- AssertPseudoStackEquals(frame_c); |
+ AssertBacktraceEquals(frame_c); |
TRACE_EVENT_END0("Testing", kCupcake); |
- AssertPseudoStackEmpty(); |
+ AssertBacktraceEmpty(); |
{ |
TRACE_EVENT0("Testing", kEclair); |
- AssertPseudoStackEquals(frame_e); |
+ AssertBacktraceEquals(frame_e); |
TRACE_EVENT_BEGIN0("Testing", kFroyo); |
- AssertPseudoStackEquals(frame_fe); |
+ AssertBacktraceEquals(frame_ef); |
TRACE_EVENT_END0("Testing", kFroyo); |
- AssertPseudoStackEquals(frame_e); |
+ AssertBacktraceEquals(frame_e); |
} |
- AssertPseudoStackEmpty(); |
- DisableTracing(); |
+ AssertBacktraceEmpty(); |
} |
-TEST_F(AllocationContextTest, PseudoStackEnableWithEventInScope) { |
- StackFrame h = kHoneycomb; |
+TEST_F(AllocationContextTest, BacktraceTakesTop) { |
+ // Push 12 events onto the pseudo stack. |
+ TRACE_EVENT0("Testing", kCupcake); |
+ TRACE_EVENT0("Testing", kCupcake); |
+ TRACE_EVENT0("Testing", kCupcake); |
+ TRACE_EVENT0("Testing", kCupcake); |
+ |
+ TRACE_EVENT0("Testing", kCupcake); |
+ TRACE_EVENT0("Testing", kCupcake); |
+ TRACE_EVENT0("Testing", kCupcake); |
+ TRACE_EVENT0("Testing", kCupcake); |
+ |
+ TRACE_EVENT0("Testing", kCupcake); |
+ TRACE_EVENT0("Testing", kDonut); |
+ TRACE_EVENT0("Testing", kEclair); |
+ TRACE_EVENT0("Testing", kFroyo); |
{ |
TRACE_EVENT0("Testing", kGingerbread); |
- EnableTracing(); |
- AssertPseudoStackEmpty(); |
+ AllocationContext ctx = AllocationContextTracker::GetContextSnapshot(); |
- { |
- TRACE_EVENT0("Testing", kHoneycomb); |
- StackFrame frame_h[] = {h}; |
- AssertPseudoStackEquals(frame_h); |
- } |
- |
- AssertPseudoStackEmpty(); |
+ // The pseudo stack relies on pointer equality, not deep string comparisons. |
+ ASSERT_EQ(kCupcake, ctx.backtrace.frames[0]); |
+ ASSERT_EQ(kFroyo, ctx.backtrace.frames[11]); |
+ } |
- // The pop at the end of this scope for the 'Gingerbread' frame must not |
- // cause a stack underflow. |
+ { |
+ AllocationContext ctx = AllocationContextTracker::GetContextSnapshot(); |
+ ASSERT_EQ(kCupcake, ctx.backtrace.frames[0]); |
+ ASSERT_EQ(kFroyo, ctx.backtrace.frames[11]); |
} |
- AssertPseudoStackEmpty(); |
- DisableTracing(); |
} |
} // namespace trace_event |