Home | History | Annotate | Download | only in test
      1 // Copyright (c) 2012 The Chromium 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 
      5 #include "base/bind.h"
      6 #include "base/debug/trace_event_unittest.h"
      7 #include "base/synchronization/waitable_event.h"
      8 #include "base/test/trace_event_analyzer.h"
      9 #include "testing/gmock/include/gmock/gmock.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 namespace trace_analyzer {
     13 
     14 namespace {
     15 
     16 class TraceEventAnalyzerTest : public testing::Test {
     17  public:
     18   void ManualSetUp();
     19   void OnTraceDataCollected(
     20       base::WaitableEvent* flush_complete_event,
     21       const scoped_refptr<base::RefCountedString>& json_events_str,
     22       bool has_more_events);
     23   void BeginTracing();
     24   void EndTracing();
     25 
     26   base::debug::TraceResultBuffer::SimpleOutput output_;
     27   base::debug::TraceResultBuffer buffer_;
     28 };
     29 
     30 void TraceEventAnalyzerTest::ManualSetUp() {
     31   ASSERT_TRUE(base::debug::TraceLog::GetInstance());
     32   buffer_.SetOutputCallback(output_.GetCallback());
     33   output_.json_output.clear();
     34 }
     35 
     36 void TraceEventAnalyzerTest::OnTraceDataCollected(
     37     base::WaitableEvent* flush_complete_event,
     38     const scoped_refptr<base::RefCountedString>& json_events_str,
     39     bool has_more_events) {
     40   buffer_.AddFragment(json_events_str->data());
     41   if (!has_more_events)
     42     flush_complete_event->Signal();
     43 }
     44 
     45 void TraceEventAnalyzerTest::BeginTracing() {
     46   output_.json_output.clear();
     47   buffer_.Start();
     48   base::debug::TraceLog::GetInstance()->SetEnabled(
     49       base::debug::CategoryFilter("*"),
     50       base::debug::TraceLog::RECORD_UNTIL_FULL);
     51 }
     52 
     53 void TraceEventAnalyzerTest::EndTracing() {
     54   base::debug::TraceLog::GetInstance()->SetDisabled();
     55   base::WaitableEvent flush_complete_event(false, false);
     56   base::debug::TraceLog::GetInstance()->Flush(
     57       base::Bind(&TraceEventAnalyzerTest::OnTraceDataCollected,
     58                  base::Unretained(this),
     59                  base::Unretained(&flush_complete_event)));
     60   flush_complete_event.Wait();
     61   buffer_.Finish();
     62 }
     63 
     64 }  // namespace
     65 
     66 TEST_F(TraceEventAnalyzerTest, NoEvents) {
     67   ManualSetUp();
     68 
     69   // Create an empty JSON event string:
     70   buffer_.Start();
     71   buffer_.Finish();
     72 
     73   scoped_ptr<TraceAnalyzer>
     74       analyzer(TraceAnalyzer::Create(output_.json_output));
     75   ASSERT_TRUE(analyzer.get());
     76 
     77   // Search for all events and verify that nothing is returned.
     78   TraceEventVector found;
     79   analyzer->FindEvents(Query::Bool(true), &found);
     80   EXPECT_EQ(0u, found.size());
     81 }
     82 
     83 TEST_F(TraceEventAnalyzerTest, TraceEvent) {
     84   ManualSetUp();
     85 
     86   int int_num = 2;
     87   double double_num = 3.5;
     88   const char* str = "the string";
     89 
     90   TraceEvent event;
     91   event.arg_numbers["false"] = 0.0;
     92   event.arg_numbers["true"] = 1.0;
     93   event.arg_numbers["int"] = static_cast<double>(int_num);
     94   event.arg_numbers["double"] = double_num;
     95   event.arg_strings["string"] = str;
     96 
     97   ASSERT_TRUE(event.HasNumberArg("false"));
     98   ASSERT_TRUE(event.HasNumberArg("true"));
     99   ASSERT_TRUE(event.HasNumberArg("int"));
    100   ASSERT_TRUE(event.HasNumberArg("double"));
    101   ASSERT_TRUE(event.HasStringArg("string"));
    102   ASSERT_FALSE(event.HasNumberArg("notfound"));
    103   ASSERT_FALSE(event.HasStringArg("notfound"));
    104 
    105   EXPECT_FALSE(event.GetKnownArgAsBool("false"));
    106   EXPECT_TRUE(event.GetKnownArgAsBool("true"));
    107   EXPECT_EQ(int_num, event.GetKnownArgAsInt("int"));
    108   EXPECT_EQ(double_num, event.GetKnownArgAsDouble("double"));
    109   EXPECT_STREQ(str, event.GetKnownArgAsString("string").c_str());
    110 }
    111 
    112 TEST_F(TraceEventAnalyzerTest, QueryEventMember) {
    113   ManualSetUp();
    114 
    115   TraceEvent event;
    116   event.thread.process_id = 3;
    117   event.thread.thread_id = 4;
    118   event.timestamp = 1.5;
    119   event.phase = TRACE_EVENT_PHASE_BEGIN;
    120   event.category = "category";
    121   event.name = "name";
    122   event.id = "1";
    123   event.arg_numbers["num"] = 7.0;
    124   event.arg_strings["str"] = "the string";
    125 
    126   // Other event with all different members:
    127   TraceEvent other;
    128   other.thread.process_id = 5;
    129   other.thread.thread_id = 6;
    130   other.timestamp = 2.5;
    131   other.phase = TRACE_EVENT_PHASE_END;
    132   other.category = "category2";
    133   other.name = "name2";
    134   other.id = "2";
    135   other.arg_numbers["num2"] = 8.0;
    136   other.arg_strings["str2"] = "the string 2";
    137 
    138   event.other_event = &other;
    139   ASSERT_TRUE(event.has_other_event());
    140   double duration = event.GetAbsTimeToOtherEvent();
    141 
    142   Query event_pid = Query::EventPidIs(event.thread.process_id);
    143   Query event_tid = Query::EventTidIs(event.thread.thread_id);
    144   Query event_time = Query::EventTimeIs(event.timestamp);
    145   Query event_duration = Query::EventDurationIs(duration);
    146   Query event_phase = Query::EventPhaseIs(event.phase);
    147   Query event_category = Query::EventCategoryIs(event.category);
    148   Query event_name = Query::EventNameIs(event.name);
    149   Query event_id = Query::EventIdIs(event.id);
    150   Query event_has_arg1 = Query::EventHasNumberArg("num");
    151   Query event_has_arg2 = Query::EventHasStringArg("str");
    152   Query event_arg1 =
    153       (Query::EventArg("num") == Query::Double(event.arg_numbers["num"]));
    154   Query event_arg2 =
    155       (Query::EventArg("str") == Query::String(event.arg_strings["str"]));
    156   Query event_has_other = Query::EventHasOther();
    157   Query other_pid = Query::OtherPidIs(other.thread.process_id);
    158   Query other_tid = Query::OtherTidIs(other.thread.thread_id);
    159   Query other_time = Query::OtherTimeIs(other.timestamp);
    160   Query other_phase = Query::OtherPhaseIs(other.phase);
    161   Query other_category = Query::OtherCategoryIs(other.category);
    162   Query other_name = Query::OtherNameIs(other.name);
    163   Query other_id = Query::OtherIdIs(other.id);
    164   Query other_has_arg1 = Query::OtherHasNumberArg("num2");
    165   Query other_has_arg2 = Query::OtherHasStringArg("str2");
    166   Query other_arg1 =
    167       (Query::OtherArg("num2") == Query::Double(other.arg_numbers["num2"]));
    168   Query other_arg2 =
    169       (Query::OtherArg("str2") == Query::String(other.arg_strings["str2"]));
    170 
    171   EXPECT_TRUE(event_pid.Evaluate(event));
    172   EXPECT_TRUE(event_tid.Evaluate(event));
    173   EXPECT_TRUE(event_time.Evaluate(event));
    174   EXPECT_TRUE(event_duration.Evaluate(event));
    175   EXPECT_TRUE(event_phase.Evaluate(event));
    176   EXPECT_TRUE(event_category.Evaluate(event));
    177   EXPECT_TRUE(event_name.Evaluate(event));
    178   EXPECT_TRUE(event_id.Evaluate(event));
    179   EXPECT_TRUE(event_has_arg1.Evaluate(event));
    180   EXPECT_TRUE(event_has_arg2.Evaluate(event));
    181   EXPECT_TRUE(event_arg1.Evaluate(event));
    182   EXPECT_TRUE(event_arg2.Evaluate(event));
    183   EXPECT_TRUE(event_has_other.Evaluate(event));
    184   EXPECT_TRUE(other_pid.Evaluate(event));
    185   EXPECT_TRUE(other_tid.Evaluate(event));
    186   EXPECT_TRUE(other_time.Evaluate(event));
    187   EXPECT_TRUE(other_phase.Evaluate(event));
    188   EXPECT_TRUE(other_category.Evaluate(event));
    189   EXPECT_TRUE(other_name.Evaluate(event));
    190   EXPECT_TRUE(other_id.Evaluate(event));
    191   EXPECT_TRUE(other_has_arg1.Evaluate(event));
    192   EXPECT_TRUE(other_has_arg2.Evaluate(event));
    193   EXPECT_TRUE(other_arg1.Evaluate(event));
    194   EXPECT_TRUE(other_arg2.Evaluate(event));
    195 
    196   // Evaluate event queries against other to verify the queries fail when the
    197   // event members are wrong.
    198   EXPECT_FALSE(event_pid.Evaluate(other));
    199   EXPECT_FALSE(event_tid.Evaluate(other));
    200   EXPECT_FALSE(event_time.Evaluate(other));
    201   EXPECT_FALSE(event_duration.Evaluate(other));
    202   EXPECT_FALSE(event_phase.Evaluate(other));
    203   EXPECT_FALSE(event_category.Evaluate(other));
    204   EXPECT_FALSE(event_name.Evaluate(other));
    205   EXPECT_FALSE(event_id.Evaluate(other));
    206   EXPECT_FALSE(event_has_arg1.Evaluate(other));
    207   EXPECT_FALSE(event_has_arg2.Evaluate(other));
    208   EXPECT_FALSE(event_arg1.Evaluate(other));
    209   EXPECT_FALSE(event_arg2.Evaluate(other));
    210   EXPECT_FALSE(event_has_other.Evaluate(other));
    211 }
    212 
    213 TEST_F(TraceEventAnalyzerTest, BooleanOperators) {
    214   ManualSetUp();
    215 
    216   BeginTracing();
    217   {
    218     TRACE_EVENT_INSTANT1("cat1", "name1", TRACE_EVENT_SCOPE_THREAD, "num", 1);
    219     TRACE_EVENT_INSTANT1("cat1", "name2", TRACE_EVENT_SCOPE_THREAD, "num", 2);
    220     TRACE_EVENT_INSTANT1("cat2", "name3", TRACE_EVENT_SCOPE_THREAD, "num", 3);
    221     TRACE_EVENT_INSTANT1("cat2", "name4", TRACE_EVENT_SCOPE_THREAD, "num", 4);
    222   }
    223   EndTracing();
    224 
    225   scoped_ptr<TraceAnalyzer>
    226       analyzer(TraceAnalyzer::Create(output_.json_output));
    227   ASSERT_TRUE(!!analyzer.get());
    228 
    229   TraceEventVector found;
    230 
    231   // ==
    232 
    233   analyzer->FindEvents(Query::EventCategory() == Query::String("cat1"), &found);
    234   ASSERT_EQ(2u, found.size());
    235   EXPECT_STREQ("name1", found[0]->name.c_str());
    236   EXPECT_STREQ("name2", found[1]->name.c_str());
    237 
    238   analyzer->FindEvents(Query::EventArg("num") == Query::Int(2), &found);
    239   ASSERT_EQ(1u, found.size());
    240   EXPECT_STREQ("name2", found[0]->name.c_str());
    241 
    242   // !=
    243 
    244   analyzer->FindEvents(Query::EventCategory() != Query::String("cat1"), &found);
    245   ASSERT_EQ(2u, found.size());
    246   EXPECT_STREQ("name3", found[0]->name.c_str());
    247   EXPECT_STREQ("name4", found[1]->name.c_str());
    248 
    249   analyzer->FindEvents(Query::EventArg("num") != Query::Int(2), &found);
    250   ASSERT_EQ(3u, found.size());
    251   EXPECT_STREQ("name1", found[0]->name.c_str());
    252   EXPECT_STREQ("name3", found[1]->name.c_str());
    253   EXPECT_STREQ("name4", found[2]->name.c_str());
    254 
    255   // <
    256   analyzer->FindEvents(Query::EventArg("num") < Query::Int(2), &found);
    257   ASSERT_EQ(1u, found.size());
    258   EXPECT_STREQ("name1", found[0]->name.c_str());
    259 
    260   // <=
    261   analyzer->FindEvents(Query::EventArg("num") <= Query::Int(2), &found);
    262   ASSERT_EQ(2u, found.size());
    263   EXPECT_STREQ("name1", found[0]->name.c_str());
    264   EXPECT_STREQ("name2", found[1]->name.c_str());
    265 
    266   // >
    267   analyzer->FindEvents(Query::EventArg("num") > Query::Int(3), &found);
    268   ASSERT_EQ(1u, found.size());
    269   EXPECT_STREQ("name4", found[0]->name.c_str());
    270 
    271   // >=
    272   analyzer->FindEvents(Query::EventArg("num") >= Query::Int(4), &found);
    273   ASSERT_EQ(1u, found.size());
    274   EXPECT_STREQ("name4", found[0]->name.c_str());
    275 
    276   // &&
    277   analyzer->FindEvents(Query::EventName() != Query::String("name1") &&
    278                        Query::EventArg("num") < Query::Int(3), &found);
    279   ASSERT_EQ(1u, found.size());
    280   EXPECT_STREQ("name2", found[0]->name.c_str());
    281 
    282   // ||
    283   analyzer->FindEvents(Query::EventName() == Query::String("name1") ||
    284                        Query::EventArg("num") == Query::Int(3), &found);
    285   ASSERT_EQ(2u, found.size());
    286   EXPECT_STREQ("name1", found[0]->name.c_str());
    287   EXPECT_STREQ("name3", found[1]->name.c_str());
    288 
    289   // !
    290   analyzer->FindEvents(!(Query::EventName() == Query::String("name1") ||
    291                          Query::EventArg("num") == Query::Int(3)), &found);
    292   ASSERT_EQ(2u, found.size());
    293   EXPECT_STREQ("name2", found[0]->name.c_str());
    294   EXPECT_STREQ("name4", found[1]->name.c_str());
    295 }
    296 
    297 TEST_F(TraceEventAnalyzerTest, ArithmeticOperators) {
    298   ManualSetUp();
    299 
    300   BeginTracing();
    301   {
    302     // These events are searched for:
    303     TRACE_EVENT_INSTANT2("cat1", "math1", TRACE_EVENT_SCOPE_THREAD,
    304                          "a", 10, "b", 5);
    305     TRACE_EVENT_INSTANT2("cat1", "math2", TRACE_EVENT_SCOPE_THREAD,
    306                          "a", 10, "b", 10);
    307     // Extra events that never match, for noise:
    308     TRACE_EVENT_INSTANT2("noise", "math3", TRACE_EVENT_SCOPE_THREAD,
    309                          "a", 1,  "b", 3);
    310     TRACE_EVENT_INSTANT2("noise", "math4", TRACE_EVENT_SCOPE_THREAD,
    311                          "c", 10, "d", 5);
    312   }
    313   EndTracing();
    314 
    315   scoped_ptr<TraceAnalyzer>
    316       analyzer(TraceAnalyzer::Create(output_.json_output));
    317   ASSERT_TRUE(analyzer.get());
    318 
    319   TraceEventVector found;
    320 
    321   // Verify that arithmetic operators function:
    322 
    323   // +
    324   analyzer->FindEvents(Query::EventArg("a") + Query::EventArg("b") ==
    325                        Query::Int(20), &found);
    326   EXPECT_EQ(1u, found.size());
    327   EXPECT_STREQ("math2", found.front()->name.c_str());
    328 
    329   // -
    330   analyzer->FindEvents(Query::EventArg("a") - Query::EventArg("b") ==
    331                        Query::Int(5), &found);
    332   EXPECT_EQ(1u, found.size());
    333   EXPECT_STREQ("math1", found.front()->name.c_str());
    334 
    335   // *
    336   analyzer->FindEvents(Query::EventArg("a") * Query::EventArg("b") ==
    337                        Query::Int(50), &found);
    338   EXPECT_EQ(1u, found.size());
    339   EXPECT_STREQ("math1", found.front()->name.c_str());
    340 
    341   // /
    342   analyzer->FindEvents(Query::EventArg("a") / Query::EventArg("b") ==
    343                        Query::Int(2), &found);
    344   EXPECT_EQ(1u, found.size());
    345   EXPECT_STREQ("math1", found.front()->name.c_str());
    346 
    347   // %
    348   analyzer->FindEvents(Query::EventArg("a") % Query::EventArg("b") ==
    349                        Query::Int(0), &found);
    350   EXPECT_EQ(2u, found.size());
    351 
    352   // - (negate)
    353   analyzer->FindEvents(-Query::EventArg("b") == Query::Int(-10), &found);
    354   EXPECT_EQ(1u, found.size());
    355   EXPECT_STREQ("math2", found.front()->name.c_str());
    356 }
    357 
    358 TEST_F(TraceEventAnalyzerTest, StringPattern) {
    359   ManualSetUp();
    360 
    361   BeginTracing();
    362   {
    363     TRACE_EVENT_INSTANT0("cat1", "name1", TRACE_EVENT_SCOPE_THREAD);
    364     TRACE_EVENT_INSTANT0("cat1", "name2", TRACE_EVENT_SCOPE_THREAD);
    365     TRACE_EVENT_INSTANT0("cat1", "no match", TRACE_EVENT_SCOPE_THREAD);
    366     TRACE_EVENT_INSTANT0("cat1", "name3x", TRACE_EVENT_SCOPE_THREAD);
    367   }
    368   EndTracing();
    369 
    370   scoped_ptr<TraceAnalyzer>
    371       analyzer(TraceAnalyzer::Create(output_.json_output));
    372   ASSERT_TRUE(analyzer.get());
    373 
    374   TraceEventVector found;
    375 
    376   analyzer->FindEvents(Query::EventName() == Query::Pattern("name?"), &found);
    377   ASSERT_EQ(2u, found.size());
    378   EXPECT_STREQ("name1", found[0]->name.c_str());
    379   EXPECT_STREQ("name2", found[1]->name.c_str());
    380 
    381   analyzer->FindEvents(Query::EventName() == Query::Pattern("name*"), &found);
    382   ASSERT_EQ(3u, found.size());
    383   EXPECT_STREQ("name1", found[0]->name.c_str());
    384   EXPECT_STREQ("name2", found[1]->name.c_str());
    385   EXPECT_STREQ("name3x", found[2]->name.c_str());
    386 
    387   analyzer->FindEvents(Query::EventName() != Query::Pattern("name*"), &found);
    388   ASSERT_EQ(1u, found.size());
    389   EXPECT_STREQ("no match", found[0]->name.c_str());
    390 }
    391 
    392 // Test that duration queries work.
    393 TEST_F(TraceEventAnalyzerTest, BeginEndDuration) {
    394   ManualSetUp();
    395 
    396   const base::TimeDelta kSleepTime = base::TimeDelta::FromMilliseconds(200);
    397   // We will search for events that have a duration of greater than 90% of the
    398   // sleep time, so that there is no flakiness.
    399   int duration_cutoff_us = (kSleepTime.InMicroseconds() * 9) / 10;
    400 
    401   BeginTracing();
    402   {
    403     TRACE_EVENT_BEGIN0("cat1", "name1"); // found by duration query
    404     TRACE_EVENT_BEGIN0("noise", "name2"); // not searched for, just noise
    405     {
    406       TRACE_EVENT_BEGIN0("cat2", "name3"); // found by duration query
    407       // next event not searched for, just noise
    408       TRACE_EVENT_INSTANT0("noise", "name4", TRACE_EVENT_SCOPE_THREAD);
    409       base::debug::HighResSleepForTraceTest(kSleepTime);
    410       TRACE_EVENT_BEGIN0("cat2", "name5"); // not found (duration too short)
    411       TRACE_EVENT_END0("cat2", "name5"); // not found (duration too short)
    412       TRACE_EVENT_END0("cat2", "name3"); // found by duration query
    413     }
    414     TRACE_EVENT_END0("noise", "name2"); // not searched for, just noise
    415     TRACE_EVENT_END0("cat1", "name1"); // found by duration query
    416   }
    417   EndTracing();
    418 
    419   scoped_ptr<TraceAnalyzer>
    420       analyzer(TraceAnalyzer::Create(output_.json_output));
    421   ASSERT_TRUE(analyzer.get());
    422   analyzer->AssociateBeginEndEvents();
    423 
    424   TraceEventVector found;
    425   analyzer->FindEvents(
    426       Query::MatchBeginWithEnd() &&
    427       Query::EventDuration() > Query::Int(duration_cutoff_us) &&
    428       (Query::EventCategory() == Query::String("cat1") ||
    429        Query::EventCategory() == Query::String("cat2") ||
    430        Query::EventCategory() == Query::String("cat3")),
    431       &found);
    432   ASSERT_EQ(2u, found.size());
    433   EXPECT_STREQ("name1", found[0]->name.c_str());
    434   EXPECT_STREQ("name3", found[1]->name.c_str());
    435 }
    436 
    437 // Test that duration queries work.
    438 TEST_F(TraceEventAnalyzerTest, CompleteDuration) {
    439   ManualSetUp();
    440 
    441   const base::TimeDelta kSleepTime = base::TimeDelta::FromMilliseconds(200);
    442   // We will search for events that have a duration of greater than 90% of the
    443   // sleep time, so that there is no flakiness.
    444   int duration_cutoff_us = (kSleepTime.InMicroseconds() * 9) / 10;
    445 
    446   BeginTracing();
    447   {
    448     TRACE_EVENT0("cat1", "name1"); // found by duration query
    449     TRACE_EVENT0("noise", "name2"); // not searched for, just noise
    450     {
    451       TRACE_EVENT0("cat2", "name3"); // found by duration query
    452       // next event not searched for, just noise
    453       TRACE_EVENT_INSTANT0("noise", "name4", TRACE_EVENT_SCOPE_THREAD);
    454       base::debug::HighResSleepForTraceTest(kSleepTime);
    455       TRACE_EVENT0("cat2", "name5"); // not found (duration too short)
    456     }
    457   }
    458   EndTracing();
    459 
    460   scoped_ptr<TraceAnalyzer>
    461       analyzer(TraceAnalyzer::Create(output_.json_output));
    462   ASSERT_TRUE(analyzer.get());
    463   analyzer->AssociateBeginEndEvents();
    464 
    465   TraceEventVector found;
    466   analyzer->FindEvents(
    467       Query::EventCompleteDuration() > Query::Int(duration_cutoff_us) &&
    468       (Query::EventCategory() == Query::String("cat1") ||
    469        Query::EventCategory() == Query::String("cat2") ||
    470        Query::EventCategory() == Query::String("cat3")),
    471       &found);
    472   ASSERT_EQ(2u, found.size());
    473   EXPECT_STREQ("name1", found[0]->name.c_str());
    474   EXPECT_STREQ("name3", found[1]->name.c_str());
    475 }
    476 
    477 // Test AssociateBeginEndEvents
    478 TEST_F(TraceEventAnalyzerTest, BeginEndAssocations) {
    479   ManualSetUp();
    480 
    481   BeginTracing();
    482   {
    483     TRACE_EVENT_END0("cat1", "name1"); // does not match out of order begin
    484     TRACE_EVENT_BEGIN0("cat1", "name2");
    485     TRACE_EVENT_INSTANT0("cat1", "name3", TRACE_EVENT_SCOPE_THREAD);
    486     TRACE_EVENT_BEGIN0("cat1", "name1");
    487     TRACE_EVENT_END0("cat1", "name2");
    488   }
    489   EndTracing();
    490 
    491   scoped_ptr<TraceAnalyzer>
    492       analyzer(TraceAnalyzer::Create(output_.json_output));
    493   ASSERT_TRUE(analyzer.get());
    494   analyzer->AssociateBeginEndEvents();
    495 
    496   TraceEventVector found;
    497   analyzer->FindEvents(Query::MatchBeginWithEnd(), &found);
    498   ASSERT_EQ(1u, found.size());
    499   EXPECT_STREQ("name2", found[0]->name.c_str());
    500 }
    501 
    502 // Test MergeAssociatedEventArgs
    503 TEST_F(TraceEventAnalyzerTest, MergeAssociatedEventArgs) {
    504   ManualSetUp();
    505 
    506   const char* arg_string = "arg_string";
    507   BeginTracing();
    508   {
    509     TRACE_EVENT_BEGIN0("cat1", "name1");
    510     TRACE_EVENT_END1("cat1", "name1", "arg", arg_string);
    511   }
    512   EndTracing();
    513 
    514   scoped_ptr<TraceAnalyzer>
    515       analyzer(TraceAnalyzer::Create(output_.json_output));
    516   ASSERT_TRUE(analyzer.get());
    517   analyzer->AssociateBeginEndEvents();
    518 
    519   TraceEventVector found;
    520   analyzer->FindEvents(Query::MatchBeginName("name1"), &found);
    521   ASSERT_EQ(1u, found.size());
    522   std::string arg_actual;
    523   EXPECT_FALSE(found[0]->GetArgAsString("arg", &arg_actual));
    524 
    525   analyzer->MergeAssociatedEventArgs();
    526   EXPECT_TRUE(found[0]->GetArgAsString("arg", &arg_actual));
    527   EXPECT_STREQ(arg_string, arg_actual.c_str());
    528 }
    529 
    530 // Test AssociateAsyncBeginEndEvents
    531 TEST_F(TraceEventAnalyzerTest, AsyncBeginEndAssocations) {
    532   ManualSetUp();
    533 
    534   BeginTracing();
    535   {
    536     TRACE_EVENT_ASYNC_END0("cat1", "name1", 0xA); // no match / out of order
    537     TRACE_EVENT_ASYNC_BEGIN0("cat1", "name1", 0xB);
    538     TRACE_EVENT_ASYNC_BEGIN0("cat1", "name1", 0xC);
    539     TRACE_EVENT_INSTANT0("cat1", "name1", TRACE_EVENT_SCOPE_THREAD); // noise
    540     TRACE_EVENT0("cat1", "name1"); // noise
    541     TRACE_EVENT_ASYNC_END0("cat1", "name1", 0xB);
    542     TRACE_EVENT_ASYNC_END0("cat1", "name1", 0xC);
    543     TRACE_EVENT_ASYNC_BEGIN0("cat1", "name1", 0xA); // no match / out of order
    544   }
    545   EndTracing();
    546 
    547   scoped_ptr<TraceAnalyzer>
    548       analyzer(TraceAnalyzer::Create(output_.json_output));
    549   ASSERT_TRUE(analyzer.get());
    550   analyzer->AssociateAsyncBeginEndEvents();
    551 
    552   TraceEventVector found;
    553   analyzer->FindEvents(Query::MatchAsyncBeginWithNext(), &found);
    554   ASSERT_EQ(2u, found.size());
    555   EXPECT_STRCASEEQ("0xb", found[0]->id.c_str());
    556   EXPECT_STRCASEEQ("0xc", found[1]->id.c_str());
    557 }
    558 
    559 // Test AssociateAsyncBeginEndEvents
    560 TEST_F(TraceEventAnalyzerTest, AsyncBeginEndAssocationsWithSteps) {
    561   ManualSetUp();
    562 
    563   BeginTracing();
    564   {
    565     TRACE_EVENT_ASYNC_STEP_INTO0("c", "n", 0xA, "s1");
    566     TRACE_EVENT_ASYNC_END0("c", "n", 0xA);
    567     TRACE_EVENT_ASYNC_BEGIN0("c", "n", 0xB);
    568     TRACE_EVENT_ASYNC_BEGIN0("c", "n", 0xC);
    569     TRACE_EVENT_ASYNC_STEP_PAST0("c", "n", 0xB, "s1");
    570     TRACE_EVENT_ASYNC_STEP_INTO0("c", "n", 0xC, "s1");
    571     TRACE_EVENT_ASYNC_STEP_INTO1("c", "n", 0xC, "s2", "a", 1);
    572     TRACE_EVENT_ASYNC_END0("c", "n", 0xB);
    573     TRACE_EVENT_ASYNC_END0("c", "n", 0xC);
    574     TRACE_EVENT_ASYNC_BEGIN0("c", "n", 0xA);
    575     TRACE_EVENT_ASYNC_STEP_INTO0("c", "n", 0xA, "s2");
    576   }
    577   EndTracing();
    578 
    579   scoped_ptr<TraceAnalyzer>
    580       analyzer(TraceAnalyzer::Create(output_.json_output));
    581   ASSERT_TRUE(analyzer.get());
    582   analyzer->AssociateAsyncBeginEndEvents();
    583 
    584   TraceEventVector found;
    585   analyzer->FindEvents(Query::MatchAsyncBeginWithNext(), &found);
    586   ASSERT_EQ(3u, found.size());
    587 
    588   EXPECT_STRCASEEQ("0xb", found[0]->id.c_str());
    589   EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, found[0]->other_event->phase);
    590   EXPECT_TRUE(found[0]->other_event->other_event);
    591   EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_END,
    592             found[0]->other_event->other_event->phase);
    593 
    594   EXPECT_STRCASEEQ("0xc", found[1]->id.c_str());
    595   EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, found[1]->other_event->phase);
    596   EXPECT_TRUE(found[1]->other_event->other_event);
    597   EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_STEP_INTO,
    598             found[1]->other_event->other_event->phase);
    599   double arg_actual = 0;
    600   EXPECT_TRUE(found[1]->other_event->other_event->GetArgAsNumber(
    601                   "a", &arg_actual));
    602   EXPECT_EQ(1.0, arg_actual);
    603   EXPECT_TRUE(found[1]->other_event->other_event->other_event);
    604   EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_END,
    605             found[1]->other_event->other_event->other_event->phase);
    606 
    607   EXPECT_STRCASEEQ("0xa", found[2]->id.c_str());
    608   EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, found[2]->other_event->phase);
    609 }
    610 
    611 // Test that the TraceAnalyzer custom associations work.
    612 TEST_F(TraceEventAnalyzerTest, CustomAssociations) {
    613   ManualSetUp();
    614 
    615   // Add events that begin/end in pipelined ordering with unique ID parameter
    616   // to match up the begin/end pairs.
    617   BeginTracing();
    618   {
    619     // no begin match
    620     TRACE_EVENT_INSTANT1("cat1", "end", TRACE_EVENT_SCOPE_THREAD, "id", 1);
    621     // end is cat4
    622     TRACE_EVENT_INSTANT1("cat2", "begin", TRACE_EVENT_SCOPE_THREAD, "id", 2);
    623     // end is cat5
    624     TRACE_EVENT_INSTANT1("cat3", "begin", TRACE_EVENT_SCOPE_THREAD, "id", 3);
    625     TRACE_EVENT_INSTANT1("cat4", "end", TRACE_EVENT_SCOPE_THREAD, "id", 2);
    626     TRACE_EVENT_INSTANT1("cat5", "end", TRACE_EVENT_SCOPE_THREAD, "id", 3);
    627     // no end match
    628     TRACE_EVENT_INSTANT1("cat6", "begin", TRACE_EVENT_SCOPE_THREAD, "id", 1);
    629   }
    630   EndTracing();
    631 
    632   scoped_ptr<TraceAnalyzer>
    633       analyzer(TraceAnalyzer::Create(output_.json_output));
    634   ASSERT_TRUE(analyzer.get());
    635 
    636   // begin, end, and match queries to find proper begin/end pairs.
    637   Query begin(Query::EventName() == Query::String("begin"));
    638   Query end(Query::EventName() == Query::String("end"));
    639   Query match(Query::EventArg("id") == Query::OtherArg("id"));
    640   analyzer->AssociateEvents(begin, end, match);
    641 
    642   TraceEventVector found;
    643 
    644   // cat1 has no other_event.
    645   analyzer->FindEvents(Query::EventCategory() == Query::String("cat1") &&
    646                        Query::EventHasOther(), &found);
    647   EXPECT_EQ(0u, found.size());
    648 
    649   // cat1 has no other_event.
    650   analyzer->FindEvents(Query::EventCategory() == Query::String("cat1") &&
    651                        !Query::EventHasOther(), &found);
    652   EXPECT_EQ(1u, found.size());
    653 
    654   // cat6 has no other_event.
    655   analyzer->FindEvents(Query::EventCategory() == Query::String("cat6") &&
    656                        !Query::EventHasOther(), &found);
    657   EXPECT_EQ(1u, found.size());
    658 
    659   // cat2 and cat4 are associated.
    660   analyzer->FindEvents(Query::EventCategory() == Query::String("cat2") &&
    661                        Query::OtherCategory() == Query::String("cat4"), &found);
    662   EXPECT_EQ(1u, found.size());
    663 
    664   // cat4 and cat2 are not associated.
    665   analyzer->FindEvents(Query::EventCategory() == Query::String("cat4") &&
    666                        Query::OtherCategory() == Query::String("cat2"), &found);
    667   EXPECT_EQ(0u, found.size());
    668 
    669   // cat3 and cat5 are associated.
    670   analyzer->FindEvents(Query::EventCategory() == Query::String("cat3") &&
    671                        Query::OtherCategory() == Query::String("cat5"), &found);
    672   EXPECT_EQ(1u, found.size());
    673 
    674   // cat5 and cat3 are not associated.
    675   analyzer->FindEvents(Query::EventCategory() == Query::String("cat5") &&
    676                        Query::OtherCategory() == Query::String("cat3"), &found);
    677   EXPECT_EQ(0u, found.size());
    678 }
    679 
    680 // Verify that Query literals and types are properly casted.
    681 TEST_F(TraceEventAnalyzerTest, Literals) {
    682   ManualSetUp();
    683 
    684   // Since these queries don't refer to the event data, the dummy event below
    685   // will never be accessed.
    686   TraceEvent dummy;
    687   char char_num = 5;
    688   short short_num = -5;
    689   EXPECT_TRUE((Query::Double(5.0) == Query::Int(char_num)).Evaluate(dummy));
    690   EXPECT_TRUE((Query::Double(-5.0) == Query::Int(short_num)).Evaluate(dummy));
    691   EXPECT_TRUE((Query::Double(1.0) == Query::Uint(1u)).Evaluate(dummy));
    692   EXPECT_TRUE((Query::Double(1.0) == Query::Int(1)).Evaluate(dummy));
    693   EXPECT_TRUE((Query::Double(-1.0) == Query::Int(-1)).Evaluate(dummy));
    694   EXPECT_TRUE((Query::Double(1.0) == Query::Double(1.0f)).Evaluate(dummy));
    695   EXPECT_TRUE((Query::Bool(true) == Query::Int(1)).Evaluate(dummy));
    696   EXPECT_TRUE((Query::Bool(false) == Query::Int(0)).Evaluate(dummy));
    697   EXPECT_TRUE((Query::Bool(true) == Query::Double(1.0f)).Evaluate(dummy));
    698   EXPECT_TRUE((Query::Bool(false) == Query::Double(0.0f)).Evaluate(dummy));
    699 }
    700 
    701 // Test GetRateStats.
    702 TEST_F(TraceEventAnalyzerTest, RateStats) {
    703   std::vector<TraceEvent> events;
    704   events.reserve(100);
    705   TraceEventVector event_ptrs;
    706   TraceEvent event;
    707   event.timestamp = 0.0;
    708   double little_delta = 1.0;
    709   double big_delta = 10.0;
    710   double tiny_delta = 0.1;
    711   RateStats stats;
    712   RateStatsOptions options;
    713 
    714   // Insert 10 events, each apart by little_delta.
    715   for (int i = 0; i < 10; ++i) {
    716     event.timestamp += little_delta;
    717     events.push_back(event);
    718     event_ptrs.push_back(&events.back());
    719   }
    720 
    721   ASSERT_TRUE(GetRateStats(event_ptrs, &stats, NULL));
    722   EXPECT_EQ(little_delta, stats.mean_us);
    723   EXPECT_EQ(little_delta, stats.min_us);
    724   EXPECT_EQ(little_delta, stats.max_us);
    725   EXPECT_EQ(0.0, stats.standard_deviation_us);
    726 
    727   // Add an event apart by big_delta.
    728   event.timestamp += big_delta;
    729   events.push_back(event);
    730   event_ptrs.push_back(&events.back());
    731 
    732   ASSERT_TRUE(GetRateStats(event_ptrs, &stats, NULL));
    733   EXPECT_LT(little_delta, stats.mean_us);
    734   EXPECT_EQ(little_delta, stats.min_us);
    735   EXPECT_EQ(big_delta, stats.max_us);
    736   EXPECT_LT(0.0, stats.standard_deviation_us);
    737 
    738   // Trim off the biggest delta and verify stats.
    739   options.trim_min = 0;
    740   options.trim_max = 1;
    741   ASSERT_TRUE(GetRateStats(event_ptrs, &stats, &options));
    742   EXPECT_EQ(little_delta, stats.mean_us);
    743   EXPECT_EQ(little_delta, stats.min_us);
    744   EXPECT_EQ(little_delta, stats.max_us);
    745   EXPECT_EQ(0.0, stats.standard_deviation_us);
    746 
    747   // Add an event apart by tiny_delta.
    748   event.timestamp += tiny_delta;
    749   events.push_back(event);
    750   event_ptrs.push_back(&events.back());
    751 
    752   // Trim off both the biggest and tiniest delta and verify stats.
    753   options.trim_min = 1;
    754   options.trim_max = 1;
    755   ASSERT_TRUE(GetRateStats(event_ptrs, &stats, &options));
    756   EXPECT_EQ(little_delta, stats.mean_us);
    757   EXPECT_EQ(little_delta, stats.min_us);
    758   EXPECT_EQ(little_delta, stats.max_us);
    759   EXPECT_EQ(0.0, stats.standard_deviation_us);
    760 
    761   // Verify smallest allowed number of events.
    762   TraceEventVector few_event_ptrs;
    763   few_event_ptrs.push_back(&event);
    764   few_event_ptrs.push_back(&event);
    765   ASSERT_FALSE(GetRateStats(few_event_ptrs, &stats, NULL));
    766   few_event_ptrs.push_back(&event);
    767   ASSERT_TRUE(GetRateStats(few_event_ptrs, &stats, NULL));
    768 
    769   // Trim off more than allowed and verify failure.
    770   options.trim_min = 0;
    771   options.trim_max = 1;
    772   ASSERT_FALSE(GetRateStats(few_event_ptrs, &stats, &options));
    773 }
    774 
    775 // Test FindFirstOf and FindLastOf.
    776 TEST_F(TraceEventAnalyzerTest, FindOf) {
    777   size_t num_events = 100;
    778   size_t index = 0;
    779   TraceEventVector event_ptrs;
    780   EXPECT_FALSE(FindFirstOf(event_ptrs, Query::Bool(true), 0, &index));
    781   EXPECT_FALSE(FindFirstOf(event_ptrs, Query::Bool(true), 10, &index));
    782   EXPECT_FALSE(FindLastOf(event_ptrs, Query::Bool(true), 0, &index));
    783   EXPECT_FALSE(FindLastOf(event_ptrs, Query::Bool(true), 10, &index));
    784 
    785   std::vector<TraceEvent> events;
    786   events.resize(num_events);
    787   for (size_t i = 0; i < events.size(); ++i)
    788     event_ptrs.push_back(&events[i]);
    789   size_t bam_index = num_events/2;
    790   events[bam_index].name = "bam";
    791   Query query_bam = Query::EventName() == Query::String(events[bam_index].name);
    792 
    793   // FindFirstOf
    794   EXPECT_FALSE(FindFirstOf(event_ptrs, Query::Bool(false), 0, &index));
    795   EXPECT_TRUE(FindFirstOf(event_ptrs, Query::Bool(true), 0, &index));
    796   EXPECT_EQ(0u, index);
    797   EXPECT_TRUE(FindFirstOf(event_ptrs, Query::Bool(true), 5, &index));
    798   EXPECT_EQ(5u, index);
    799 
    800   EXPECT_FALSE(FindFirstOf(event_ptrs, query_bam, bam_index + 1, &index));
    801   EXPECT_TRUE(FindFirstOf(event_ptrs, query_bam, 0, &index));
    802   EXPECT_EQ(bam_index, index);
    803   EXPECT_TRUE(FindFirstOf(event_ptrs, query_bam, bam_index, &index));
    804   EXPECT_EQ(bam_index, index);
    805 
    806   // FindLastOf
    807   EXPECT_FALSE(FindLastOf(event_ptrs, Query::Bool(false), 1000, &index));
    808   EXPECT_TRUE(FindLastOf(event_ptrs, Query::Bool(true), 1000, &index));
    809   EXPECT_EQ(num_events - 1, index);
    810   EXPECT_TRUE(FindLastOf(event_ptrs, Query::Bool(true), num_events - 5,
    811                          &index));
    812   EXPECT_EQ(num_events - 5, index);
    813 
    814   EXPECT_FALSE(FindLastOf(event_ptrs, query_bam, bam_index - 1, &index));
    815   EXPECT_TRUE(FindLastOf(event_ptrs, query_bam, num_events, &index));
    816   EXPECT_EQ(bam_index, index);
    817   EXPECT_TRUE(FindLastOf(event_ptrs, query_bam, bam_index, &index));
    818   EXPECT_EQ(bam_index, index);
    819 }
    820 
    821 // Test FindClosest.
    822 TEST_F(TraceEventAnalyzerTest, FindClosest) {
    823   size_t index_1 = 0;
    824   size_t index_2 = 0;
    825   TraceEventVector event_ptrs;
    826   EXPECT_FALSE(FindClosest(event_ptrs, Query::Bool(true), 0,
    827                            &index_1, &index_2));
    828 
    829   size_t num_events = 5;
    830   std::vector<TraceEvent> events;
    831   events.resize(num_events);
    832   for (size_t i = 0; i < events.size(); ++i) {
    833     // timestamps go up exponentially so the lower index is always closer in
    834     // time than the higher index.
    835     events[i].timestamp = static_cast<double>(i) * static_cast<double>(i);
    836     event_ptrs.push_back(&events[i]);
    837   }
    838   events[0].name = "one";
    839   events[2].name = "two";
    840   events[4].name = "three";
    841   Query query_named = Query::EventName() != Query::String(std::string());
    842   Query query_one = Query::EventName() == Query::String("one");
    843 
    844   // Only one event matches query_one, so two closest can't be found.
    845   EXPECT_FALSE(FindClosest(event_ptrs, query_one, 0, &index_1, &index_2));
    846 
    847   EXPECT_TRUE(FindClosest(event_ptrs, query_one, 3, &index_1, NULL));
    848   EXPECT_EQ(0u, index_1);
    849 
    850   EXPECT_TRUE(FindClosest(event_ptrs, query_named, 1, &index_1, &index_2));
    851   EXPECT_EQ(0u, index_1);
    852   EXPECT_EQ(2u, index_2);
    853 
    854   EXPECT_TRUE(FindClosest(event_ptrs, query_named, 4, &index_1, &index_2));
    855   EXPECT_EQ(4u, index_1);
    856   EXPECT_EQ(2u, index_2);
    857 
    858   EXPECT_TRUE(FindClosest(event_ptrs, query_named, 3, &index_1, &index_2));
    859   EXPECT_EQ(2u, index_1);
    860   EXPECT_EQ(0u, index_2);
    861 }
    862 
    863 // Test CountMatches.
    864 TEST_F(TraceEventAnalyzerTest, CountMatches) {
    865   TraceEventVector event_ptrs;
    866   EXPECT_EQ(0u, CountMatches(event_ptrs, Query::Bool(true), 0, 10));
    867 
    868   size_t num_events = 5;
    869   size_t num_named = 3;
    870   std::vector<TraceEvent> events;
    871   events.resize(num_events);
    872   for (size_t i = 0; i < events.size(); ++i)
    873     event_ptrs.push_back(&events[i]);
    874   events[0].name = "one";
    875   events[2].name = "two";
    876   events[4].name = "three";
    877   Query query_named = Query::EventName() != Query::String(std::string());
    878   Query query_one = Query::EventName() == Query::String("one");
    879 
    880   EXPECT_EQ(0u, CountMatches(event_ptrs, Query::Bool(false)));
    881   EXPECT_EQ(num_events, CountMatches(event_ptrs, Query::Bool(true)));
    882   EXPECT_EQ(num_events - 1, CountMatches(event_ptrs, Query::Bool(true),
    883                                          1, num_events));
    884   EXPECT_EQ(1u, CountMatches(event_ptrs, query_one));
    885   EXPECT_EQ(num_events - 1, CountMatches(event_ptrs, !query_one));
    886   EXPECT_EQ(num_named, CountMatches(event_ptrs, query_named));
    887 }
    888 
    889 
    890 }  // namespace trace_analyzer
    891