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