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