| // Copyright 2015 the V8 project 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 <stdlib.h> |
| #include <string.h> |
| |
| #include "src/v8.h" |
| |
| #include "test/cctest/cctest.h" |
| |
| #include "src/tracing/trace-event.h" |
| |
| #define GET_TRACE_OBJECTS_LIST platform.GetMockTraceObjects() |
| |
| #define GET_TRACE_OBJECT(Index) GET_TRACE_OBJECTS_LIST->at(Index) |
| |
| |
| struct MockTraceObject { |
| char phase; |
| std::string name; |
| uint64_t id; |
| uint64_t bind_id; |
| int num_args; |
| unsigned int flags; |
| MockTraceObject(char phase, std::string name, uint64_t id, uint64_t bind_id, |
| int num_args, int flags) |
| : phase(phase), |
| name(name), |
| id(id), |
| bind_id(bind_id), |
| num_args(num_args), |
| flags(flags) {} |
| }; |
| |
| typedef std::vector<MockTraceObject*> MockTraceObjectList; |
| |
| class MockTracingController : public v8::TracingController { |
| public: |
| MockTracingController() = default; |
| ~MockTracingController() { |
| for (size_t i = 0; i < trace_object_list_.size(); ++i) { |
| delete trace_object_list_[i]; |
| } |
| trace_object_list_.clear(); |
| } |
| |
| uint64_t AddTraceEvent( |
| char phase, const uint8_t* category_enabled_flag, const char* name, |
| const char* scope, uint64_t id, uint64_t bind_id, int num_args, |
| const char** arg_names, const uint8_t* arg_types, |
| const uint64_t* arg_values, |
| std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, |
| unsigned int flags) override { |
| MockTraceObject* to = new MockTraceObject(phase, std::string(name), id, |
| bind_id, num_args, flags); |
| trace_object_list_.push_back(to); |
| return 0; |
| } |
| |
| void UpdateTraceEventDuration(const uint8_t* category_enabled_flag, |
| const char* name, uint64_t handle) override {} |
| |
| const uint8_t* GetCategoryGroupEnabled(const char* name) override { |
| if (strcmp(name, "v8-cat")) { |
| static uint8_t no = 0; |
| return &no; |
| } else { |
| static uint8_t yes = 0x7; |
| return &yes; |
| } |
| } |
| |
| MockTraceObjectList* GetMockTraceObjects() { return &trace_object_list_; } |
| |
| private: |
| MockTraceObjectList trace_object_list_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MockTracingController); |
| }; |
| |
| class MockTracingPlatform : public TestPlatform { |
| public: |
| MockTracingPlatform() { |
| // Now that it's completely constructed, make this the current platform. |
| i::V8::SetPlatformForTesting(this); |
| } |
| virtual ~MockTracingPlatform() {} |
| |
| v8::TracingController* GetTracingController() override { |
| return &tracing_controller_; |
| } |
| |
| MockTraceObjectList* GetMockTraceObjects() { |
| return tracing_controller_.GetMockTraceObjects(); |
| } |
| |
| private: |
| MockTracingController tracing_controller_; |
| }; |
| |
| |
| TEST(TraceEventDisabledCategory) { |
| MockTracingPlatform platform; |
| |
| // Disabled category, will not add events. |
| TRACE_EVENT_BEGIN0("cat", "e1"); |
| TRACE_EVENT_END0("cat", "e1"); |
| CHECK(GET_TRACE_OBJECTS_LIST->empty()); |
| } |
| |
| |
| TEST(TraceEventNoArgs) { |
| MockTracingPlatform platform; |
| |
| // Enabled category will add 2 events. |
| TRACE_EVENT_BEGIN0("v8-cat", "e1"); |
| TRACE_EVENT_END0("v8-cat", "e1"); |
| |
| CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->size()); |
| CHECK_EQ('B', GET_TRACE_OBJECT(0)->phase); |
| CHECK_EQ("e1", GET_TRACE_OBJECT(0)->name); |
| CHECK_EQ(0, GET_TRACE_OBJECT(0)->num_args); |
| |
| CHECK_EQ('E', GET_TRACE_OBJECT(1)->phase); |
| CHECK_EQ("e1", GET_TRACE_OBJECT(1)->name); |
| CHECK_EQ(0, GET_TRACE_OBJECT(1)->num_args); |
| } |
| |
| |
| TEST(TraceEventWithOneArg) { |
| MockTracingPlatform platform; |
| |
| TRACE_EVENT_BEGIN1("v8-cat", "e1", "arg1", 42); |
| TRACE_EVENT_END1("v8-cat", "e1", "arg1", 42); |
| TRACE_EVENT_BEGIN1("v8-cat", "e2", "arg1", "abc"); |
| TRACE_EVENT_END1("v8-cat", "e2", "arg1", "abc"); |
| |
| CHECK_EQ(4, GET_TRACE_OBJECTS_LIST->size()); |
| |
| CHECK_EQ(1, GET_TRACE_OBJECT(0)->num_args); |
| CHECK_EQ(1, GET_TRACE_OBJECT(1)->num_args); |
| CHECK_EQ(1, GET_TRACE_OBJECT(2)->num_args); |
| CHECK_EQ(1, GET_TRACE_OBJECT(3)->num_args); |
| } |
| |
| |
| TEST(TraceEventWithTwoArgs) { |
| MockTracingPlatform platform; |
| |
| TRACE_EVENT_BEGIN2("v8-cat", "e1", "arg1", 42, "arg2", "abc"); |
| TRACE_EVENT_END2("v8-cat", "e1", "arg1", 42, "arg2", "abc"); |
| TRACE_EVENT_BEGIN2("v8-cat", "e2", "arg1", "abc", "arg2", 43); |
| TRACE_EVENT_END2("v8-cat", "e2", "arg1", "abc", "arg2", 43); |
| |
| CHECK_EQ(4, GET_TRACE_OBJECTS_LIST->size()); |
| |
| CHECK_EQ(2, GET_TRACE_OBJECT(0)->num_args); |
| CHECK_EQ(2, GET_TRACE_OBJECT(1)->num_args); |
| CHECK_EQ(2, GET_TRACE_OBJECT(2)->num_args); |
| CHECK_EQ(2, GET_TRACE_OBJECT(3)->num_args); |
| } |
| |
| |
| TEST(ScopedTraceEvent) { |
| MockTracingPlatform platform; |
| |
| { TRACE_EVENT0("v8-cat", "e"); } |
| |
| CHECK_EQ(1, GET_TRACE_OBJECTS_LIST->size()); |
| CHECK_EQ(0, GET_TRACE_OBJECT(0)->num_args); |
| |
| { TRACE_EVENT1("v8-cat", "e1", "arg1", "abc"); } |
| |
| CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->size()); |
| CHECK_EQ(1, GET_TRACE_OBJECT(1)->num_args); |
| |
| { TRACE_EVENT2("v8-cat", "e1", "arg1", "abc", "arg2", 42); } |
| |
| CHECK_EQ(3, GET_TRACE_OBJECTS_LIST->size()); |
| CHECK_EQ(2, GET_TRACE_OBJECT(2)->num_args); |
| } |
| |
| |
| TEST(TestEventWithFlow) { |
| MockTracingPlatform platform; |
| |
| static uint64_t bind_id = 21; |
| { |
| TRACE_EVENT_WITH_FLOW0("v8-cat", "f1", bind_id, TRACE_EVENT_FLAG_FLOW_OUT); |
| } |
| { |
| TRACE_EVENT_WITH_FLOW0( |
| "v8-cat", "f2", bind_id, |
| TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
| } |
| { TRACE_EVENT_WITH_FLOW0("v8-cat", "f3", bind_id, TRACE_EVENT_FLAG_FLOW_IN); } |
| |
| CHECK_EQ(3, GET_TRACE_OBJECTS_LIST->size()); |
| CHECK_EQ(bind_id, GET_TRACE_OBJECT(0)->bind_id); |
| CHECK_EQ(TRACE_EVENT_FLAG_FLOW_OUT, GET_TRACE_OBJECT(0)->flags); |
| CHECK_EQ(bind_id, GET_TRACE_OBJECT(1)->bind_id); |
| CHECK_EQ(TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, |
| GET_TRACE_OBJECT(1)->flags); |
| CHECK_EQ(bind_id, GET_TRACE_OBJECT(2)->bind_id); |
| CHECK_EQ(TRACE_EVENT_FLAG_FLOW_IN, GET_TRACE_OBJECT(2)->flags); |
| } |
| |
| |
| TEST(TestEventWithId) { |
| MockTracingPlatform platform; |
| |
| static uint64_t event_id = 21; |
| TRACE_EVENT_ASYNC_BEGIN0("v8-cat", "a1", event_id); |
| TRACE_EVENT_ASYNC_END0("v8-cat", "a1", event_id); |
| |
| CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->size()); |
| CHECK_EQ(TRACE_EVENT_PHASE_ASYNC_BEGIN, GET_TRACE_OBJECT(0)->phase); |
| CHECK_EQ(event_id, GET_TRACE_OBJECT(0)->id); |
| CHECK_EQ(TRACE_EVENT_PHASE_ASYNC_END, GET_TRACE_OBJECT(1)->phase); |
| CHECK_EQ(event_id, GET_TRACE_OBJECT(1)->id); |
| } |
| |
| TEST(TestEventInContext) { |
| MockTracingPlatform platform; |
| |
| static uint64_t isolate_id = 0x20151021; |
| { |
| TRACE_EVENT_SCOPED_CONTEXT("v8-cat", "Isolate", isolate_id); |
| TRACE_EVENT0("v8-cat", "e"); |
| } |
| |
| CHECK_EQ(3, GET_TRACE_OBJECTS_LIST->size()); |
| CHECK_EQ(TRACE_EVENT_PHASE_ENTER_CONTEXT, GET_TRACE_OBJECT(0)->phase); |
| CHECK_EQ("Isolate", GET_TRACE_OBJECT(0)->name); |
| CHECK_EQ(isolate_id, GET_TRACE_OBJECT(0)->id); |
| CHECK_EQ(TRACE_EVENT_PHASE_COMPLETE, GET_TRACE_OBJECT(1)->phase); |
| CHECK_EQ("e", GET_TRACE_OBJECT(1)->name); |
| CHECK_EQ(TRACE_EVENT_PHASE_LEAVE_CONTEXT, GET_TRACE_OBJECT(2)->phase); |
| CHECK_EQ("Isolate", GET_TRACE_OBJECT(2)->name); |
| CHECK_EQ(isolate_id, GET_TRACE_OBJECT(2)->id); |
| } |