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