| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/trace_event/blame_context.h" |
| |
| #include "base/json/json_writer.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/test/trace_event_analyzer.h" |
| #include "base/trace_event/trace_event_argument.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace base { |
| namespace trace_event { |
| namespace { |
| |
| const char kTestBlameContextCategory[] = "test"; |
| const char kDisabledTestBlameContextCategory[] = "disabled-by-default-test"; |
| const char kTestBlameContextName[] = "TestBlameContext"; |
| const char kTestBlameContextType[] = "TestBlameContextType"; |
| const char kTestBlameContextScope[] = "TestBlameContextScope"; |
| |
| class TestBlameContext : public BlameContext { |
| public: |
| explicit TestBlameContext(int id) |
| : BlameContext(kTestBlameContextCategory, |
| kTestBlameContextName, |
| kTestBlameContextType, |
| kTestBlameContextScope, |
| id, |
| nullptr) {} |
| |
| TestBlameContext(int id, const TestBlameContext& parent) |
| : BlameContext(kTestBlameContextCategory, |
| kTestBlameContextName, |
| kTestBlameContextType, |
| kTestBlameContextScope, |
| id, |
| &parent) {} |
| |
| protected: |
| void AsValueInto(trace_event::TracedValue* state) override { |
| BlameContext::AsValueInto(state); |
| state->SetBoolean("crossStreams", false); |
| } |
| }; |
| |
| class DisabledTestBlameContext : public BlameContext { |
| public: |
| explicit DisabledTestBlameContext(int id) |
| : BlameContext(kDisabledTestBlameContextCategory, |
| kTestBlameContextName, |
| kTestBlameContextType, |
| kTestBlameContextScope, |
| id, |
| nullptr) {} |
| }; |
| |
| class BlameContextTest : public testing::Test { |
| protected: |
| MessageLoop loop_; |
| }; |
| |
| TEST_F(BlameContextTest, EnterAndLeave) { |
| using trace_analyzer::Query; |
| trace_analyzer::Start("*"); |
| { |
| TestBlameContext blame_context(0x1234); |
| blame_context.Initialize(); |
| blame_context.Enter(); |
| blame_context.Leave(); |
| } |
| auto analyzer = trace_analyzer::Stop(); |
| |
| trace_analyzer::TraceEventVector events; |
| Query q = Query::EventPhaseIs(TRACE_EVENT_PHASE_ENTER_CONTEXT) || |
| Query::EventPhaseIs(TRACE_EVENT_PHASE_LEAVE_CONTEXT); |
| analyzer->FindEvents(q, &events); |
| |
| EXPECT_EQ(2u, events.size()); |
| EXPECT_EQ(TRACE_EVENT_PHASE_ENTER_CONTEXT, events[0]->phase); |
| EXPECT_EQ(kTestBlameContextCategory, events[0]->category); |
| EXPECT_EQ(kTestBlameContextName, events[0]->name); |
| EXPECT_EQ("0x1234", events[0]->id); |
| EXPECT_EQ(TRACE_EVENT_PHASE_LEAVE_CONTEXT, events[1]->phase); |
| EXPECT_EQ(kTestBlameContextCategory, events[1]->category); |
| EXPECT_EQ(kTestBlameContextName, events[1]->name); |
| EXPECT_EQ("0x1234", events[1]->id); |
| } |
| |
| TEST_F(BlameContextTest, DifferentCategories) { |
| // Ensure there is no cross talk between blame contexts from different |
| // categories. |
| using trace_analyzer::Query; |
| trace_analyzer::Start("*"); |
| { |
| TestBlameContext blame_context(0x1234); |
| DisabledTestBlameContext disabled_blame_context(0x5678); |
| blame_context.Initialize(); |
| blame_context.Enter(); |
| blame_context.Leave(); |
| disabled_blame_context.Initialize(); |
| disabled_blame_context.Enter(); |
| disabled_blame_context.Leave(); |
| } |
| auto analyzer = trace_analyzer::Stop(); |
| |
| trace_analyzer::TraceEventVector events; |
| Query q = Query::EventPhaseIs(TRACE_EVENT_PHASE_ENTER_CONTEXT) || |
| Query::EventPhaseIs(TRACE_EVENT_PHASE_LEAVE_CONTEXT); |
| analyzer->FindEvents(q, &events); |
| |
| // None of the events from the disabled-by-default category should show up. |
| EXPECT_EQ(2u, events.size()); |
| EXPECT_EQ(TRACE_EVENT_PHASE_ENTER_CONTEXT, events[0]->phase); |
| EXPECT_EQ(kTestBlameContextCategory, events[0]->category); |
| EXPECT_EQ(kTestBlameContextName, events[0]->name); |
| EXPECT_EQ("0x1234", events[0]->id); |
| EXPECT_EQ(TRACE_EVENT_PHASE_LEAVE_CONTEXT, events[1]->phase); |
| EXPECT_EQ(kTestBlameContextCategory, events[1]->category); |
| EXPECT_EQ(kTestBlameContextName, events[1]->name); |
| EXPECT_EQ("0x1234", events[1]->id); |
| } |
| |
| TEST_F(BlameContextTest, TakeSnapshot) { |
| using trace_analyzer::Query; |
| trace_analyzer::Start("*"); |
| { |
| TestBlameContext parent_blame_context(0x5678); |
| TestBlameContext blame_context(0x1234, parent_blame_context); |
| parent_blame_context.Initialize(); |
| blame_context.Initialize(); |
| blame_context.TakeSnapshot(); |
| } |
| auto analyzer = trace_analyzer::Stop(); |
| |
| trace_analyzer::TraceEventVector events; |
| Query q = Query::EventPhaseIs(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT); |
| analyzer->FindEvents(q, &events); |
| |
| // We should have 3 snapshots: one for both calls to Initialize() and one from |
| // the explicit call to TakeSnapshot(). |
| EXPECT_EQ(3u, events.size()); |
| EXPECT_EQ(kTestBlameContextCategory, events[0]->category); |
| EXPECT_EQ(kTestBlameContextType, events[0]->name); |
| EXPECT_EQ("0x5678", events[0]->id); |
| EXPECT_TRUE(events[0]->HasArg("snapshot")); |
| |
| EXPECT_EQ(kTestBlameContextCategory, events[1]->category); |
| EXPECT_EQ(kTestBlameContextType, events[1]->name); |
| EXPECT_EQ("0x1234", events[1]->id); |
| EXPECT_TRUE(events[0]->HasArg("snapshot")); |
| |
| EXPECT_EQ(kTestBlameContextCategory, events[2]->category); |
| EXPECT_EQ(kTestBlameContextType, events[2]->name); |
| EXPECT_EQ("0x1234", events[2]->id); |
| EXPECT_TRUE(events[0]->HasArg("snapshot")); |
| |
| const char kExpectedSnapshotJson[] = |
| "{" |
| "\"crossStreams\":false," |
| "\"parent\":{" |
| "\"id_ref\":\"0x5678\"," |
| "\"scope\":\"TestBlameContextScope\"" |
| "}" |
| "}"; |
| |
| std::string snapshot_json; |
| JSONWriter::Write(*events[2]->GetKnownArgAsValue("snapshot"), &snapshot_json); |
| EXPECT_EQ(kExpectedSnapshotJson, snapshot_json); |
| } |
| |
| } // namepace |
| } // namespace trace_event |
| } // namespace base |