Home | History | Annotate | Download | only in cctest
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 #include "src/v8.h"
      8 
      9 #include "src/list.h"
     10 #include "src/list-inl.h"
     11 #include "test/cctest/cctest.h"
     12 
     13 using v8::IdleTask;
     14 using v8::Task;
     15 using v8::Isolate;
     16 
     17 #include "src/tracing/trace-event.h"
     18 
     19 #define GET_TRACE_OBJECTS_LIST platform.GetMockTraceObjects()
     20 
     21 #define GET_TRACE_OBJECT(Index) GET_TRACE_OBJECTS_LIST->at(Index)
     22 
     23 
     24 struct MockTraceObject {
     25   char phase;
     26   std::string name;
     27   uint64_t id;
     28   uint64_t bind_id;
     29   int num_args;
     30   unsigned int flags;
     31   MockTraceObject(char phase, std::string name, uint64_t id, uint64_t bind_id,
     32                   int num_args, int flags)
     33       : phase(phase),
     34         name(name),
     35         id(id),
     36         bind_id(bind_id),
     37         num_args(num_args),
     38         flags(flags) {}
     39 };
     40 
     41 typedef v8::internal::List<MockTraceObject*> MockTraceObjectList;
     42 
     43 class MockTracingPlatform : public v8::Platform {
     44  public:
     45   explicit MockTracingPlatform(v8::Platform* platform) {}
     46   virtual ~MockTracingPlatform() {
     47     for (int i = 0; i < trace_object_list_.length(); ++i) {
     48       delete trace_object_list_[i];
     49     }
     50     trace_object_list_.Clear();
     51   }
     52   void CallOnBackgroundThread(Task* task,
     53                               ExpectedRuntime expected_runtime) override {}
     54 
     55   void CallOnForegroundThread(Isolate* isolate, Task* task) override {}
     56 
     57   void CallDelayedOnForegroundThread(Isolate* isolate, Task* task,
     58                                      double delay_in_seconds) override {}
     59 
     60   double MonotonicallyIncreasingTime() override { return 0.0; }
     61 
     62   void CallIdleOnForegroundThread(Isolate* isolate, IdleTask* task) override {}
     63 
     64   bool IdleTasksEnabled(Isolate* isolate) override { return false; }
     65 
     66   bool PendingIdleTask() { return false; }
     67 
     68   void PerformIdleTask(double idle_time_in_seconds) {}
     69 
     70   bool PendingDelayedTask() { return false; }
     71 
     72   void PerformDelayedTask() {}
     73 
     74   uint64_t AddTraceEvent(char phase, const uint8_t* category_enabled_flag,
     75                          const char* name, const char* scope, uint64_t id,
     76                          uint64_t bind_id, int num_args, const char** arg_names,
     77                          const uint8_t* arg_types, const uint64_t* arg_values,
     78                          unsigned int flags) override {
     79     MockTraceObject* to = new MockTraceObject(phase, std::string(name), id,
     80                                               bind_id, num_args, flags);
     81     trace_object_list_.Add(to);
     82     return 0;
     83   }
     84 
     85   void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
     86                                 const char* name, uint64_t handle) override {}
     87 
     88   const uint8_t* GetCategoryGroupEnabled(const char* name) override {
     89     if (strcmp(name, "v8-cat")) {
     90       static uint8_t no = 0;
     91       return &no;
     92     } else {
     93       static uint8_t yes = 0x7;
     94       return &yes;
     95     }
     96   }
     97 
     98   const char* GetCategoryGroupName(
     99       const uint8_t* category_enabled_flag) override {
    100     static const char dummy[] = "dummy";
    101     return dummy;
    102   }
    103 
    104   MockTraceObjectList* GetMockTraceObjects() { return &trace_object_list_; }
    105 
    106  private:
    107   MockTraceObjectList trace_object_list_;
    108 };
    109 
    110 
    111 TEST(TraceEventDisabledCategory) {
    112   v8::Platform* old_platform = i::V8::GetCurrentPlatform();
    113   MockTracingPlatform platform(old_platform);
    114   i::V8::SetPlatformForTesting(&platform);
    115 
    116   // Disabled category, will not add events.
    117   TRACE_EVENT_BEGIN0("cat", "e1");
    118   TRACE_EVENT_END0("cat", "e1");
    119   CHECK_EQ(0, GET_TRACE_OBJECTS_LIST->length());
    120 
    121   i::V8::SetPlatformForTesting(old_platform);
    122 }
    123 
    124 
    125 TEST(TraceEventNoArgs) {
    126   v8::Platform* old_platform = i::V8::GetCurrentPlatform();
    127   MockTracingPlatform platform(old_platform);
    128   i::V8::SetPlatformForTesting(&platform);
    129 
    130   // Enabled category will add 2 events.
    131   TRACE_EVENT_BEGIN0("v8-cat", "e1");
    132   TRACE_EVENT_END0("v8-cat", "e1");
    133 
    134   CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->length());
    135   CHECK_EQ('B', GET_TRACE_OBJECT(0)->phase);
    136   CHECK_EQ("e1", GET_TRACE_OBJECT(0)->name);
    137   CHECK_EQ(0, GET_TRACE_OBJECT(0)->num_args);
    138 
    139   CHECK_EQ('E', GET_TRACE_OBJECT(1)->phase);
    140   CHECK_EQ("e1", GET_TRACE_OBJECT(1)->name);
    141   CHECK_EQ(0, GET_TRACE_OBJECT(1)->num_args);
    142 
    143   i::V8::SetPlatformForTesting(old_platform);
    144 }
    145 
    146 
    147 TEST(TraceEventWithOneArg) {
    148   v8::Platform* old_platform = i::V8::GetCurrentPlatform();
    149   MockTracingPlatform platform(old_platform);
    150   i::V8::SetPlatformForTesting(&platform);
    151 
    152   TRACE_EVENT_BEGIN1("v8-cat", "e1", "arg1", 42);
    153   TRACE_EVENT_END1("v8-cat", "e1", "arg1", 42);
    154   TRACE_EVENT_BEGIN1("v8-cat", "e2", "arg1", "abc");
    155   TRACE_EVENT_END1("v8-cat", "e2", "arg1", "abc");
    156 
    157   CHECK_EQ(4, GET_TRACE_OBJECTS_LIST->length());
    158 
    159   CHECK_EQ(1, GET_TRACE_OBJECT(0)->num_args);
    160   CHECK_EQ(1, GET_TRACE_OBJECT(1)->num_args);
    161   CHECK_EQ(1, GET_TRACE_OBJECT(2)->num_args);
    162   CHECK_EQ(1, GET_TRACE_OBJECT(3)->num_args);
    163 
    164   i::V8::SetPlatformForTesting(old_platform);
    165 }
    166 
    167 
    168 TEST(TraceEventWithTwoArgs) {
    169   v8::Platform* old_platform = i::V8::GetCurrentPlatform();
    170   MockTracingPlatform platform(old_platform);
    171   i::V8::SetPlatformForTesting(&platform);
    172 
    173   TRACE_EVENT_BEGIN2("v8-cat", "e1", "arg1", 42, "arg2", "abc");
    174   TRACE_EVENT_END2("v8-cat", "e1", "arg1", 42, "arg2", "abc");
    175   TRACE_EVENT_BEGIN2("v8-cat", "e2", "arg1", "abc", "arg2", 43);
    176   TRACE_EVENT_END2("v8-cat", "e2", "arg1", "abc", "arg2", 43);
    177 
    178   CHECK_EQ(4, GET_TRACE_OBJECTS_LIST->length());
    179 
    180   CHECK_EQ(2, GET_TRACE_OBJECT(0)->num_args);
    181   CHECK_EQ(2, GET_TRACE_OBJECT(1)->num_args);
    182   CHECK_EQ(2, GET_TRACE_OBJECT(2)->num_args);
    183   CHECK_EQ(2, GET_TRACE_OBJECT(3)->num_args);
    184 
    185   i::V8::SetPlatformForTesting(old_platform);
    186 }
    187 
    188 
    189 TEST(ScopedTraceEvent) {
    190   v8::Platform* old_platform = i::V8::GetCurrentPlatform();
    191   MockTracingPlatform platform(old_platform);
    192   i::V8::SetPlatformForTesting(&platform);
    193 
    194   { TRACE_EVENT0("v8-cat", "e"); }
    195 
    196   CHECK_EQ(1, GET_TRACE_OBJECTS_LIST->length());
    197   CHECK_EQ(0, GET_TRACE_OBJECT(0)->num_args);
    198 
    199   { TRACE_EVENT1("v8-cat", "e1", "arg1", "abc"); }
    200 
    201   CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->length());
    202   CHECK_EQ(1, GET_TRACE_OBJECT(1)->num_args);
    203 
    204   { TRACE_EVENT2("v8-cat", "e1", "arg1", "abc", "arg2", 42); }
    205 
    206   CHECK_EQ(3, GET_TRACE_OBJECTS_LIST->length());
    207   CHECK_EQ(2, GET_TRACE_OBJECT(2)->num_args);
    208 
    209   i::V8::SetPlatformForTesting(old_platform);
    210 }
    211 
    212 
    213 TEST(TestEventWithFlow) {
    214   v8::Platform* old_platform = i::V8::GetCurrentPlatform();
    215   MockTracingPlatform platform(old_platform);
    216   i::V8::SetPlatformForTesting(&platform);
    217 
    218   static uint64_t bind_id = 21;
    219   {
    220     TRACE_EVENT_WITH_FLOW0("v8-cat", "f1", bind_id, TRACE_EVENT_FLAG_FLOW_OUT);
    221   }
    222   {
    223     TRACE_EVENT_WITH_FLOW0(
    224         "v8-cat", "f2", bind_id,
    225         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
    226   }
    227   { TRACE_EVENT_WITH_FLOW0("v8-cat", "f3", bind_id, TRACE_EVENT_FLAG_FLOW_IN); }
    228 
    229   CHECK_EQ(3, GET_TRACE_OBJECTS_LIST->length());
    230   CHECK_EQ(bind_id, GET_TRACE_OBJECT(0)->bind_id);
    231   CHECK_EQ(TRACE_EVENT_FLAG_FLOW_OUT, GET_TRACE_OBJECT(0)->flags);
    232   CHECK_EQ(bind_id, GET_TRACE_OBJECT(1)->bind_id);
    233   CHECK_EQ(TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
    234            GET_TRACE_OBJECT(1)->flags);
    235   CHECK_EQ(bind_id, GET_TRACE_OBJECT(2)->bind_id);
    236   CHECK_EQ(TRACE_EVENT_FLAG_FLOW_IN, GET_TRACE_OBJECT(2)->flags);
    237 
    238   i::V8::SetPlatformForTesting(old_platform);
    239 }
    240 
    241 
    242 TEST(TestEventWithId) {
    243   v8::Platform* old_platform = i::V8::GetCurrentPlatform();
    244   MockTracingPlatform platform(old_platform);
    245   i::V8::SetPlatformForTesting(&platform);
    246 
    247   static uint64_t event_id = 21;
    248   TRACE_EVENT_ASYNC_BEGIN0("v8-cat", "a1", event_id);
    249   TRACE_EVENT_ASYNC_END0("v8-cat", "a1", event_id);
    250 
    251   CHECK_EQ(2, GET_TRACE_OBJECTS_LIST->length());
    252   CHECK_EQ(TRACE_EVENT_PHASE_ASYNC_BEGIN, GET_TRACE_OBJECT(0)->phase);
    253   CHECK_EQ(event_id, GET_TRACE_OBJECT(0)->id);
    254   CHECK_EQ(TRACE_EVENT_PHASE_ASYNC_END, GET_TRACE_OBJECT(1)->phase);
    255   CHECK_EQ(event_id, GET_TRACE_OBJECT(1)->id);
    256 
    257   i::V8::SetPlatformForTesting(old_platform);
    258 }
    259 
    260 TEST(TestEventInContext) {
    261   v8::Platform* old_platform = i::V8::GetCurrentPlatform();
    262   MockTracingPlatform platform(old_platform);
    263   i::V8::SetPlatformForTesting(&platform);
    264 
    265   static uint64_t isolate_id = 0x20151021;
    266   {
    267     TRACE_EVENT_SCOPED_CONTEXT("v8-cat", "Isolate", isolate_id);
    268     TRACE_EVENT0("v8-cat", "e");
    269   }
    270 
    271   CHECK_EQ(3, GET_TRACE_OBJECTS_LIST->length());
    272   CHECK_EQ(TRACE_EVENT_PHASE_ENTER_CONTEXT, GET_TRACE_OBJECT(0)->phase);
    273   CHECK_EQ("Isolate", GET_TRACE_OBJECT(0)->name);
    274   CHECK_EQ(isolate_id, GET_TRACE_OBJECT(0)->id);
    275   CHECK_EQ(TRACE_EVENT_PHASE_COMPLETE, GET_TRACE_OBJECT(1)->phase);
    276   CHECK_EQ("e", GET_TRACE_OBJECT(1)->name);
    277   CHECK_EQ(TRACE_EVENT_PHASE_LEAVE_CONTEXT, GET_TRACE_OBJECT(2)->phase);
    278   CHECK_EQ("Isolate", GET_TRACE_OBJECT(2)->name);
    279   CHECK_EQ(isolate_id, GET_TRACE_OBJECT(2)->id);
    280 
    281   i::V8::SetPlatformForTesting(old_platform);
    282 }
    283