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.
6 #include "base/synchronization/waitable_event.h"
7 #include "base/test/trace_event_analyzer.h"
8 #include "base/threading/platform_thread.h"
9 #include "testing/gmock/include/gmock/gmock.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 namespace trace_analyzer
{
16 class TraceEventAnalyzerTest
: public testing::Test
{
19 void OnTraceDataCollected(
20 base::WaitableEvent
* flush_complete_event
,
21 const scoped_refptr
<base::RefCountedString
>& json_events_str
,
22 bool has_more_events
);
26 base::trace_event::TraceResultBuffer::SimpleOutput output_
;
27 base::trace_event::TraceResultBuffer buffer_
;
30 void TraceEventAnalyzerTest::ManualSetUp() {
31 ASSERT_TRUE(base::trace_event::TraceLog::GetInstance());
32 buffer_
.SetOutputCallback(output_
.GetCallback());
33 output_
.json_output
.clear();
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());
42 flush_complete_event
->Signal();
45 void TraceEventAnalyzerTest::BeginTracing() {
46 output_
.json_output
.clear();
48 base::trace_event::TraceLog::GetInstance()->SetEnabled(
49 base::trace_event::TraceConfig("*", ""),
50 base::trace_event::TraceLog::RECORDING_MODE
);
53 void TraceEventAnalyzerTest::EndTracing() {
54 base::trace_event::TraceLog::GetInstance()->SetDisabled();
55 base::WaitableEvent
flush_complete_event(false, false);
56 base::trace_event::TraceLog::GetInstance()->Flush(
57 base::Bind(&TraceEventAnalyzerTest::OnTraceDataCollected
,
58 base::Unretained(this),
59 base::Unretained(&flush_complete_event
)));
60 flush_complete_event
.Wait();
66 TEST_F(TraceEventAnalyzerTest
, NoEvents
) {
69 // Create an empty JSON event string:
73 scoped_ptr
<TraceAnalyzer
>
74 analyzer(TraceAnalyzer::Create(output_
.json_output
));
75 ASSERT_TRUE(analyzer
.get());
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());
83 TEST_F(TraceEventAnalyzerTest
, TraceEvent
) {
87 double double_num
= 3.5;
88 const char str
[] = "the string";
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
;
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"));
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());
112 TEST_F(TraceEventAnalyzerTest
, QueryEventMember
) {
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";
123 event
.arg_numbers
["num"] = 7.0;
124 event
.arg_strings
["str"] = "the string";
126 // Other event with all different members:
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";
135 other
.arg_numbers
["num2"] = 8.0;
136 other
.arg_strings
["str2"] = "the string 2";
138 event
.other_event
= &other
;
139 ASSERT_TRUE(event
.has_other_event());
140 double duration
= event
.GetAbsTimeToOtherEvent();
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");
153 (Query::EventArg("num") == Query::Double(event
.arg_numbers
["num"]));
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");
167 (Query::OtherArg("num2") == Query::Double(other
.arg_numbers
["num2"]));
169 (Query::OtherArg("str2") == Query::String(other
.arg_strings
["str2"]));
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
));
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
));
213 TEST_F(TraceEventAnalyzerTest
, BooleanOperators
) {
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);
225 scoped_ptr
<TraceAnalyzer
>
226 analyzer(TraceAnalyzer::Create(output_
.json_output
));
227 ASSERT_TRUE(analyzer
);
228 analyzer
->SetIgnoreMetadataEvents(true);
230 TraceEventVector found
;
234 analyzer
->FindEvents(Query::EventCategory() == Query::String("cat1"), &found
);
235 ASSERT_EQ(2u, found
.size());
236 EXPECT_STREQ("name1", found
[0]->name
.c_str());
237 EXPECT_STREQ("name2", found
[1]->name
.c_str());
239 analyzer
->FindEvents(Query::EventArg("num") == Query::Int(2), &found
);
240 ASSERT_EQ(1u, found
.size());
241 EXPECT_STREQ("name2", found
[0]->name
.c_str());
245 analyzer
->FindEvents(Query::EventCategory() != Query::String("cat1"), &found
);
246 ASSERT_EQ(2u, found
.size());
247 EXPECT_STREQ("name3", found
[0]->name
.c_str());
248 EXPECT_STREQ("name4", found
[1]->name
.c_str());
250 analyzer
->FindEvents(Query::EventArg("num") != Query::Int(2), &found
);
251 ASSERT_EQ(3u, found
.size());
252 EXPECT_STREQ("name1", found
[0]->name
.c_str());
253 EXPECT_STREQ("name3", found
[1]->name
.c_str());
254 EXPECT_STREQ("name4", found
[2]->name
.c_str());
257 analyzer
->FindEvents(Query::EventArg("num") < Query::Int(2), &found
);
258 ASSERT_EQ(1u, found
.size());
259 EXPECT_STREQ("name1", found
[0]->name
.c_str());
262 analyzer
->FindEvents(Query::EventArg("num") <= Query::Int(2), &found
);
263 ASSERT_EQ(2u, found
.size());
264 EXPECT_STREQ("name1", found
[0]->name
.c_str());
265 EXPECT_STREQ("name2", found
[1]->name
.c_str());
268 analyzer
->FindEvents(Query::EventArg("num") > Query::Int(3), &found
);
269 ASSERT_EQ(1u, found
.size());
270 EXPECT_STREQ("name4", found
[0]->name
.c_str());
273 analyzer
->FindEvents(Query::EventArg("num") >= Query::Int(4), &found
);
274 ASSERT_EQ(1u, found
.size());
275 EXPECT_STREQ("name4", found
[0]->name
.c_str());
278 analyzer
->FindEvents(Query::EventName() != Query::String("name1") &&
279 Query::EventArg("num") < Query::Int(3), &found
);
280 ASSERT_EQ(1u, found
.size());
281 EXPECT_STREQ("name2", found
[0]->name
.c_str());
284 analyzer
->FindEvents(Query::EventName() == Query::String("name1") ||
285 Query::EventArg("num") == Query::Int(3), &found
);
286 ASSERT_EQ(2u, found
.size());
287 EXPECT_STREQ("name1", found
[0]->name
.c_str());
288 EXPECT_STREQ("name3", found
[1]->name
.c_str());
291 analyzer
->FindEvents(!(Query::EventName() == Query::String("name1") ||
292 Query::EventArg("num") == Query::Int(3)), &found
);
293 ASSERT_EQ(2u, found
.size());
294 EXPECT_STREQ("name2", found
[0]->name
.c_str());
295 EXPECT_STREQ("name4", found
[1]->name
.c_str());
298 TEST_F(TraceEventAnalyzerTest
, ArithmeticOperators
) {
303 // These events are searched for:
304 TRACE_EVENT_INSTANT2("cat1", "math1", TRACE_EVENT_SCOPE_THREAD
,
306 TRACE_EVENT_INSTANT2("cat1", "math2", TRACE_EVENT_SCOPE_THREAD
,
308 // Extra events that never match, for noise:
309 TRACE_EVENT_INSTANT2("noise", "math3", TRACE_EVENT_SCOPE_THREAD
,
311 TRACE_EVENT_INSTANT2("noise", "math4", TRACE_EVENT_SCOPE_THREAD
,
316 scoped_ptr
<TraceAnalyzer
>
317 analyzer(TraceAnalyzer::Create(output_
.json_output
));
318 ASSERT_TRUE(analyzer
.get());
320 TraceEventVector found
;
322 // Verify that arithmetic operators function:
325 analyzer
->FindEvents(Query::EventArg("a") + Query::EventArg("b") ==
326 Query::Int(20), &found
);
327 EXPECT_EQ(1u, found
.size());
328 EXPECT_STREQ("math2", found
.front()->name
.c_str());
331 analyzer
->FindEvents(Query::EventArg("a") - Query::EventArg("b") ==
332 Query::Int(5), &found
);
333 EXPECT_EQ(1u, found
.size());
334 EXPECT_STREQ("math1", found
.front()->name
.c_str());
337 analyzer
->FindEvents(Query::EventArg("a") * Query::EventArg("b") ==
338 Query::Int(50), &found
);
339 EXPECT_EQ(1u, found
.size());
340 EXPECT_STREQ("math1", found
.front()->name
.c_str());
343 analyzer
->FindEvents(Query::EventArg("a") / Query::EventArg("b") ==
344 Query::Int(2), &found
);
345 EXPECT_EQ(1u, found
.size());
346 EXPECT_STREQ("math1", found
.front()->name
.c_str());
349 analyzer
->FindEvents(Query::EventArg("a") % Query::EventArg("b") ==
350 Query::Int(0), &found
);
351 EXPECT_EQ(2u, found
.size());
354 analyzer
->FindEvents(-Query::EventArg("b") == Query::Int(-10), &found
);
355 EXPECT_EQ(1u, found
.size());
356 EXPECT_STREQ("math2", found
.front()->name
.c_str());
359 TEST_F(TraceEventAnalyzerTest
, StringPattern
) {
364 TRACE_EVENT_INSTANT0("cat1", "name1", TRACE_EVENT_SCOPE_THREAD
);
365 TRACE_EVENT_INSTANT0("cat1", "name2", TRACE_EVENT_SCOPE_THREAD
);
366 TRACE_EVENT_INSTANT0("cat1", "no match", TRACE_EVENT_SCOPE_THREAD
);
367 TRACE_EVENT_INSTANT0("cat1", "name3x", TRACE_EVENT_SCOPE_THREAD
);
371 scoped_ptr
<TraceAnalyzer
>
372 analyzer(TraceAnalyzer::Create(output_
.json_output
));
373 ASSERT_TRUE(analyzer
.get());
374 analyzer
->SetIgnoreMetadataEvents(true);
376 TraceEventVector found
;
378 analyzer
->FindEvents(Query::EventName() == Query::Pattern("name?"), &found
);
379 ASSERT_EQ(2u, found
.size());
380 EXPECT_STREQ("name1", found
[0]->name
.c_str());
381 EXPECT_STREQ("name2", found
[1]->name
.c_str());
383 analyzer
->FindEvents(Query::EventName() == Query::Pattern("name*"), &found
);
384 ASSERT_EQ(3u, found
.size());
385 EXPECT_STREQ("name1", found
[0]->name
.c_str());
386 EXPECT_STREQ("name2", found
[1]->name
.c_str());
387 EXPECT_STREQ("name3x", found
[2]->name
.c_str());
389 analyzer
->FindEvents(Query::EventName() != Query::Pattern("name*"), &found
);
390 ASSERT_EQ(1u, found
.size());
391 EXPECT_STREQ("no match", found
[0]->name
.c_str());
394 // Test that duration queries work.
395 TEST_F(TraceEventAnalyzerTest
, BeginEndDuration
) {
398 const base::TimeDelta kSleepTime
= base::TimeDelta::FromMilliseconds(200);
399 // We will search for events that have a duration of greater than 90% of the
400 // sleep time, so that there is no flakiness.
401 int64 duration_cutoff_us
= (kSleepTime
.InMicroseconds() * 9) / 10;
405 TRACE_EVENT_BEGIN0("cat1", "name1"); // found by duration query
406 TRACE_EVENT_BEGIN0("noise", "name2"); // not searched for, just noise
408 TRACE_EVENT_BEGIN0("cat2", "name3"); // found by duration query
409 // next event not searched for, just noise
410 TRACE_EVENT_INSTANT0("noise", "name4", TRACE_EVENT_SCOPE_THREAD
);
411 base::PlatformThread::Sleep(kSleepTime
);
412 TRACE_EVENT_BEGIN0("cat2", "name5"); // not found (duration too short)
413 TRACE_EVENT_END0("cat2", "name5"); // not found (duration too short)
414 TRACE_EVENT_END0("cat2", "name3"); // found by duration query
416 TRACE_EVENT_END0("noise", "name2"); // not searched for, just noise
417 TRACE_EVENT_END0("cat1", "name1"); // found by duration query
421 scoped_ptr
<TraceAnalyzer
>
422 analyzer(TraceAnalyzer::Create(output_
.json_output
));
423 ASSERT_TRUE(analyzer
.get());
424 analyzer
->AssociateBeginEndEvents();
426 TraceEventVector found
;
427 analyzer
->FindEvents(
428 Query::MatchBeginWithEnd() &&
429 Query::EventDuration() >
430 Query::Int(static_cast<int>(duration_cutoff_us
)) &&
431 (Query::EventCategory() == Query::String("cat1") ||
432 Query::EventCategory() == Query::String("cat2") ||
433 Query::EventCategory() == Query::String("cat3")),
435 ASSERT_EQ(2u, found
.size());
436 EXPECT_STREQ("name1", found
[0]->name
.c_str());
437 EXPECT_STREQ("name3", found
[1]->name
.c_str());
440 // Test that duration queries work.
441 TEST_F(TraceEventAnalyzerTest
, CompleteDuration
) {
444 const base::TimeDelta kSleepTime
= base::TimeDelta::FromMilliseconds(200);
445 // We will search for events that have a duration of greater than 90% of the
446 // sleep time, so that there is no flakiness.
447 int64 duration_cutoff_us
= (kSleepTime
.InMicroseconds() * 9) / 10;
451 TRACE_EVENT0("cat1", "name1"); // found by duration query
452 TRACE_EVENT0("noise", "name2"); // not searched for, just noise
454 TRACE_EVENT0("cat2", "name3"); // found by duration query
455 // next event not searched for, just noise
456 TRACE_EVENT_INSTANT0("noise", "name4", TRACE_EVENT_SCOPE_THREAD
);
457 base::PlatformThread::Sleep(kSleepTime
);
458 TRACE_EVENT0("cat2", "name5"); // not found (duration too short)
463 scoped_ptr
<TraceAnalyzer
>
464 analyzer(TraceAnalyzer::Create(output_
.json_output
));
465 ASSERT_TRUE(analyzer
.get());
466 analyzer
->AssociateBeginEndEvents();
468 TraceEventVector found
;
469 analyzer
->FindEvents(
470 Query::EventCompleteDuration() >
471 Query::Int(static_cast<int>(duration_cutoff_us
)) &&
472 (Query::EventCategory() == Query::String("cat1") ||
473 Query::EventCategory() == Query::String("cat2") ||
474 Query::EventCategory() == Query::String("cat3")),
476 ASSERT_EQ(2u, found
.size());
477 EXPECT_STREQ("name1", found
[0]->name
.c_str());
478 EXPECT_STREQ("name3", found
[1]->name
.c_str());
481 // Test AssociateBeginEndEvents
482 TEST_F(TraceEventAnalyzerTest
, BeginEndAssocations
) {
487 TRACE_EVENT_END0("cat1", "name1"); // does not match out of order begin
488 TRACE_EVENT_BEGIN0("cat1", "name2");
489 TRACE_EVENT_INSTANT0("cat1", "name3", TRACE_EVENT_SCOPE_THREAD
);
490 TRACE_EVENT_BEGIN0("cat1", "name1");
491 TRACE_EVENT_END0("cat1", "name2");
495 scoped_ptr
<TraceAnalyzer
>
496 analyzer(TraceAnalyzer::Create(output_
.json_output
));
497 ASSERT_TRUE(analyzer
.get());
498 analyzer
->AssociateBeginEndEvents();
500 TraceEventVector found
;
501 analyzer
->FindEvents(Query::MatchBeginWithEnd(), &found
);
502 ASSERT_EQ(1u, found
.size());
503 EXPECT_STREQ("name2", found
[0]->name
.c_str());
506 // Test MergeAssociatedEventArgs
507 TEST_F(TraceEventAnalyzerTest
, MergeAssociatedEventArgs
) {
510 const char arg_string
[] = "arg_string";
513 TRACE_EVENT_BEGIN0("cat1", "name1");
514 TRACE_EVENT_END1("cat1", "name1", "arg", arg_string
);
518 scoped_ptr
<TraceAnalyzer
>
519 analyzer(TraceAnalyzer::Create(output_
.json_output
));
520 ASSERT_TRUE(analyzer
.get());
521 analyzer
->AssociateBeginEndEvents();
523 TraceEventVector found
;
524 analyzer
->FindEvents(Query::MatchBeginName("name1"), &found
);
525 ASSERT_EQ(1u, found
.size());
526 std::string arg_actual
;
527 EXPECT_FALSE(found
[0]->GetArgAsString("arg", &arg_actual
));
529 analyzer
->MergeAssociatedEventArgs();
530 EXPECT_TRUE(found
[0]->GetArgAsString("arg", &arg_actual
));
531 EXPECT_STREQ(arg_string
, arg_actual
.c_str());
534 // Test AssociateAsyncBeginEndEvents
535 TEST_F(TraceEventAnalyzerTest
, AsyncBeginEndAssocations
) {
540 TRACE_EVENT_ASYNC_END0("cat1", "name1", 0xA); // no match / out of order
541 TRACE_EVENT_ASYNC_BEGIN0("cat1", "name1", 0xB);
542 TRACE_EVENT_ASYNC_BEGIN0("cat1", "name1", 0xC);
543 TRACE_EVENT_INSTANT0("cat1", "name1", TRACE_EVENT_SCOPE_THREAD
); // noise
544 TRACE_EVENT0("cat1", "name1"); // noise
545 TRACE_EVENT_ASYNC_END0("cat1", "name1", 0xB);
546 TRACE_EVENT_ASYNC_END0("cat1", "name1", 0xC);
547 TRACE_EVENT_ASYNC_BEGIN0("cat1", "name1", 0xA); // no match / out of order
551 scoped_ptr
<TraceAnalyzer
>
552 analyzer(TraceAnalyzer::Create(output_
.json_output
));
553 ASSERT_TRUE(analyzer
.get());
554 analyzer
->AssociateAsyncBeginEndEvents();
556 TraceEventVector found
;
557 analyzer
->FindEvents(Query::MatchAsyncBeginWithNext(), &found
);
558 ASSERT_EQ(2u, found
.size());
559 EXPECT_STRCASEEQ("0xb", found
[0]->id
.c_str());
560 EXPECT_STRCASEEQ("0xc", found
[1]->id
.c_str());
563 // Test AssociateAsyncBeginEndEvents
564 TEST_F(TraceEventAnalyzerTest
, AsyncBeginEndAssocationsWithSteps
) {
569 TRACE_EVENT_ASYNC_STEP_INTO0("c", "n", 0xA, "s1");
570 TRACE_EVENT_ASYNC_END0("c", "n", 0xA);
571 TRACE_EVENT_ASYNC_BEGIN0("c", "n", 0xB);
572 TRACE_EVENT_ASYNC_BEGIN0("c", "n", 0xC);
573 TRACE_EVENT_ASYNC_STEP_PAST0("c", "n", 0xB, "s1");
574 TRACE_EVENT_ASYNC_STEP_INTO0("c", "n", 0xC, "s1");
575 TRACE_EVENT_ASYNC_STEP_INTO1("c", "n", 0xC, "s2", "a", 1);
576 TRACE_EVENT_ASYNC_END0("c", "n", 0xB);
577 TRACE_EVENT_ASYNC_END0("c", "n", 0xC);
578 TRACE_EVENT_ASYNC_BEGIN0("c", "n", 0xA);
579 TRACE_EVENT_ASYNC_STEP_INTO0("c", "n", 0xA, "s2");
583 scoped_ptr
<TraceAnalyzer
>
584 analyzer(TraceAnalyzer::Create(output_
.json_output
));
585 ASSERT_TRUE(analyzer
.get());
586 analyzer
->AssociateAsyncBeginEndEvents();
588 TraceEventVector found
;
589 analyzer
->FindEvents(Query::MatchAsyncBeginWithNext(), &found
);
590 ASSERT_EQ(3u, found
.size());
592 EXPECT_STRCASEEQ("0xb", found
[0]->id
.c_str());
593 EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_STEP_PAST
, found
[0]->other_event
->phase
);
594 EXPECT_TRUE(found
[0]->other_event
->other_event
);
595 EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_END
,
596 found
[0]->other_event
->other_event
->phase
);
598 EXPECT_STRCASEEQ("0xc", found
[1]->id
.c_str());
599 EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_STEP_INTO
, found
[1]->other_event
->phase
);
600 EXPECT_TRUE(found
[1]->other_event
->other_event
);
601 EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_STEP_INTO
,
602 found
[1]->other_event
->other_event
->phase
);
603 double arg_actual
= 0;
604 EXPECT_TRUE(found
[1]->other_event
->other_event
->GetArgAsNumber(
606 EXPECT_EQ(1.0, arg_actual
);
607 EXPECT_TRUE(found
[1]->other_event
->other_event
->other_event
);
608 EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_END
,
609 found
[1]->other_event
->other_event
->other_event
->phase
);
611 EXPECT_STRCASEEQ("0xa", found
[2]->id
.c_str());
612 EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_STEP_INTO
, found
[2]->other_event
->phase
);
615 // Test that the TraceAnalyzer custom associations work.
616 TEST_F(TraceEventAnalyzerTest
, CustomAssociations
) {
619 // Add events that begin/end in pipelined ordering with unique ID parameter
620 // to match up the begin/end pairs.
624 TRACE_EVENT_INSTANT1("cat1", "end", TRACE_EVENT_SCOPE_THREAD
, "id", 1);
626 TRACE_EVENT_INSTANT1("cat2", "begin", TRACE_EVENT_SCOPE_THREAD
, "id", 2);
628 TRACE_EVENT_INSTANT1("cat3", "begin", TRACE_EVENT_SCOPE_THREAD
, "id", 3);
629 TRACE_EVENT_INSTANT1("cat4", "end", TRACE_EVENT_SCOPE_THREAD
, "id", 2);
630 TRACE_EVENT_INSTANT1("cat5", "end", TRACE_EVENT_SCOPE_THREAD
, "id", 3);
632 TRACE_EVENT_INSTANT1("cat6", "begin", TRACE_EVENT_SCOPE_THREAD
, "id", 1);
636 scoped_ptr
<TraceAnalyzer
>
637 analyzer(TraceAnalyzer::Create(output_
.json_output
));
638 ASSERT_TRUE(analyzer
.get());
640 // begin, end, and match queries to find proper begin/end pairs.
641 Query
begin(Query::EventName() == Query::String("begin"));
642 Query
end(Query::EventName() == Query::String("end"));
643 Query
match(Query::EventArg("id") == Query::OtherArg("id"));
644 analyzer
->AssociateEvents(begin
, end
, match
);
646 TraceEventVector found
;
648 // cat1 has no other_event.
649 analyzer
->FindEvents(Query::EventCategory() == Query::String("cat1") &&
650 Query::EventHasOther(), &found
);
651 EXPECT_EQ(0u, found
.size());
653 // cat1 has no other_event.
654 analyzer
->FindEvents(Query::EventCategory() == Query::String("cat1") &&
655 !Query::EventHasOther(), &found
);
656 EXPECT_EQ(1u, found
.size());
658 // cat6 has no other_event.
659 analyzer
->FindEvents(Query::EventCategory() == Query::String("cat6") &&
660 !Query::EventHasOther(), &found
);
661 EXPECT_EQ(1u, found
.size());
663 // cat2 and cat4 are associated.
664 analyzer
->FindEvents(Query::EventCategory() == Query::String("cat2") &&
665 Query::OtherCategory() == Query::String("cat4"), &found
);
666 EXPECT_EQ(1u, found
.size());
668 // cat4 and cat2 are not associated.
669 analyzer
->FindEvents(Query::EventCategory() == Query::String("cat4") &&
670 Query::OtherCategory() == Query::String("cat2"), &found
);
671 EXPECT_EQ(0u, found
.size());
673 // cat3 and cat5 are associated.
674 analyzer
->FindEvents(Query::EventCategory() == Query::String("cat3") &&
675 Query::OtherCategory() == Query::String("cat5"), &found
);
676 EXPECT_EQ(1u, found
.size());
678 // cat5 and cat3 are not associated.
679 analyzer
->FindEvents(Query::EventCategory() == Query::String("cat5") &&
680 Query::OtherCategory() == Query::String("cat3"), &found
);
681 EXPECT_EQ(0u, found
.size());
684 // Verify that Query literals and types are properly casted.
685 TEST_F(TraceEventAnalyzerTest
, Literals
) {
688 // Since these queries don't refer to the event data, the dummy event below
689 // will never be accessed.
692 short short_num
= -5;
693 EXPECT_TRUE((Query::Double(5.0) == Query::Int(char_num
)).Evaluate(dummy
));
694 EXPECT_TRUE((Query::Double(-5.0) == Query::Int(short_num
)).Evaluate(dummy
));
695 EXPECT_TRUE((Query::Double(1.0) == Query::Uint(1u)).Evaluate(dummy
));
696 EXPECT_TRUE((Query::Double(1.0) == Query::Int(1)).Evaluate(dummy
));
697 EXPECT_TRUE((Query::Double(-1.0) == Query::Int(-1)).Evaluate(dummy
));
698 EXPECT_TRUE((Query::Double(1.0) == Query::Double(1.0f
)).Evaluate(dummy
));
699 EXPECT_TRUE((Query::Bool(true) == Query::Int(1)).Evaluate(dummy
));
700 EXPECT_TRUE((Query::Bool(false) == Query::Int(0)).Evaluate(dummy
));
701 EXPECT_TRUE((Query::Bool(true) == Query::Double(1.0f
)).Evaluate(dummy
));
702 EXPECT_TRUE((Query::Bool(false) == Query::Double(0.0f
)).Evaluate(dummy
));
705 // Test GetRateStats.
706 TEST_F(TraceEventAnalyzerTest
, RateStats
) {
707 std::vector
<TraceEvent
> events
;
709 TraceEventVector event_ptrs
;
711 event
.timestamp
= 0.0;
712 double little_delta
= 1.0;
713 double big_delta
= 10.0;
714 double tiny_delta
= 0.1;
716 RateStatsOptions options
;
718 // Insert 10 events, each apart by little_delta.
719 for (int i
= 0; i
< 10; ++i
) {
720 event
.timestamp
+= little_delta
;
721 events
.push_back(event
);
722 event_ptrs
.push_back(&events
.back());
725 ASSERT_TRUE(GetRateStats(event_ptrs
, &stats
, NULL
));
726 EXPECT_EQ(little_delta
, stats
.mean_us
);
727 EXPECT_EQ(little_delta
, stats
.min_us
);
728 EXPECT_EQ(little_delta
, stats
.max_us
);
729 EXPECT_EQ(0.0, stats
.standard_deviation_us
);
731 // Add an event apart by big_delta.
732 event
.timestamp
+= big_delta
;
733 events
.push_back(event
);
734 event_ptrs
.push_back(&events
.back());
736 ASSERT_TRUE(GetRateStats(event_ptrs
, &stats
, NULL
));
737 EXPECT_LT(little_delta
, stats
.mean_us
);
738 EXPECT_EQ(little_delta
, stats
.min_us
);
739 EXPECT_EQ(big_delta
, stats
.max_us
);
740 EXPECT_LT(0.0, stats
.standard_deviation_us
);
742 // Trim off the biggest delta and verify stats.
743 options
.trim_min
= 0;
744 options
.trim_max
= 1;
745 ASSERT_TRUE(GetRateStats(event_ptrs
, &stats
, &options
));
746 EXPECT_EQ(little_delta
, stats
.mean_us
);
747 EXPECT_EQ(little_delta
, stats
.min_us
);
748 EXPECT_EQ(little_delta
, stats
.max_us
);
749 EXPECT_EQ(0.0, stats
.standard_deviation_us
);
751 // Add an event apart by tiny_delta.
752 event
.timestamp
+= tiny_delta
;
753 events
.push_back(event
);
754 event_ptrs
.push_back(&events
.back());
756 // Trim off both the biggest and tiniest delta and verify stats.
757 options
.trim_min
= 1;
758 options
.trim_max
= 1;
759 ASSERT_TRUE(GetRateStats(event_ptrs
, &stats
, &options
));
760 EXPECT_EQ(little_delta
, stats
.mean_us
);
761 EXPECT_EQ(little_delta
, stats
.min_us
);
762 EXPECT_EQ(little_delta
, stats
.max_us
);
763 EXPECT_EQ(0.0, stats
.standard_deviation_us
);
765 // Verify smallest allowed number of events.
766 TraceEventVector few_event_ptrs
;
767 few_event_ptrs
.push_back(&event
);
768 few_event_ptrs
.push_back(&event
);
769 ASSERT_FALSE(GetRateStats(few_event_ptrs
, &stats
, NULL
));
770 few_event_ptrs
.push_back(&event
);
771 ASSERT_TRUE(GetRateStats(few_event_ptrs
, &stats
, NULL
));
773 // Trim off more than allowed and verify failure.
774 options
.trim_min
= 0;
775 options
.trim_max
= 1;
776 ASSERT_FALSE(GetRateStats(few_event_ptrs
, &stats
, &options
));
779 // Test FindFirstOf and FindLastOf.
780 TEST_F(TraceEventAnalyzerTest
, FindOf
) {
781 size_t num_events
= 100;
783 TraceEventVector event_ptrs
;
784 EXPECT_FALSE(FindFirstOf(event_ptrs
, Query::Bool(true), 0, &index
));
785 EXPECT_FALSE(FindFirstOf(event_ptrs
, Query::Bool(true), 10, &index
));
786 EXPECT_FALSE(FindLastOf(event_ptrs
, Query::Bool(true), 0, &index
));
787 EXPECT_FALSE(FindLastOf(event_ptrs
, Query::Bool(true), 10, &index
));
789 std::vector
<TraceEvent
> events
;
790 events
.resize(num_events
);
791 for (size_t i
= 0; i
< events
.size(); ++i
)
792 event_ptrs
.push_back(&events
[i
]);
793 size_t bam_index
= num_events
/2;
794 events
[bam_index
].name
= "bam";
795 Query query_bam
= Query::EventName() == Query::String(events
[bam_index
].name
);
798 EXPECT_FALSE(FindFirstOf(event_ptrs
, Query::Bool(false), 0, &index
));
799 EXPECT_TRUE(FindFirstOf(event_ptrs
, Query::Bool(true), 0, &index
));
800 EXPECT_EQ(0u, index
);
801 EXPECT_TRUE(FindFirstOf(event_ptrs
, Query::Bool(true), 5, &index
));
802 EXPECT_EQ(5u, index
);
804 EXPECT_FALSE(FindFirstOf(event_ptrs
, query_bam
, bam_index
+ 1, &index
));
805 EXPECT_TRUE(FindFirstOf(event_ptrs
, query_bam
, 0, &index
));
806 EXPECT_EQ(bam_index
, index
);
807 EXPECT_TRUE(FindFirstOf(event_ptrs
, query_bam
, bam_index
, &index
));
808 EXPECT_EQ(bam_index
, index
);
811 EXPECT_FALSE(FindLastOf(event_ptrs
, Query::Bool(false), 1000, &index
));
812 EXPECT_TRUE(FindLastOf(event_ptrs
, Query::Bool(true), 1000, &index
));
813 EXPECT_EQ(num_events
- 1, index
);
814 EXPECT_TRUE(FindLastOf(event_ptrs
, Query::Bool(true), num_events
- 5,
816 EXPECT_EQ(num_events
- 5, index
);
818 EXPECT_FALSE(FindLastOf(event_ptrs
, query_bam
, bam_index
- 1, &index
));
819 EXPECT_TRUE(FindLastOf(event_ptrs
, query_bam
, num_events
, &index
));
820 EXPECT_EQ(bam_index
, index
);
821 EXPECT_TRUE(FindLastOf(event_ptrs
, query_bam
, bam_index
, &index
));
822 EXPECT_EQ(bam_index
, index
);
826 TEST_F(TraceEventAnalyzerTest
, FindClosest
) {
829 TraceEventVector event_ptrs
;
830 EXPECT_FALSE(FindClosest(event_ptrs
, Query::Bool(true), 0,
831 &index_1
, &index_2
));
833 size_t num_events
= 5;
834 std::vector
<TraceEvent
> events
;
835 events
.resize(num_events
);
836 for (size_t i
= 0; i
< events
.size(); ++i
) {
837 // timestamps go up exponentially so the lower index is always closer in
838 // time than the higher index.
839 events
[i
].timestamp
= static_cast<double>(i
) * static_cast<double>(i
);
840 event_ptrs
.push_back(&events
[i
]);
842 events
[0].name
= "one";
843 events
[2].name
= "two";
844 events
[4].name
= "three";
845 Query query_named
= Query::EventName() != Query::String(std::string());
846 Query query_one
= Query::EventName() == Query::String("one");
848 // Only one event matches query_one, so two closest can't be found.
849 EXPECT_FALSE(FindClosest(event_ptrs
, query_one
, 0, &index_1
, &index_2
));
851 EXPECT_TRUE(FindClosest(event_ptrs
, query_one
, 3, &index_1
, NULL
));
852 EXPECT_EQ(0u, index_1
);
854 EXPECT_TRUE(FindClosest(event_ptrs
, query_named
, 1, &index_1
, &index_2
));
855 EXPECT_EQ(0u, index_1
);
856 EXPECT_EQ(2u, index_2
);
858 EXPECT_TRUE(FindClosest(event_ptrs
, query_named
, 4, &index_1
, &index_2
));
859 EXPECT_EQ(4u, index_1
);
860 EXPECT_EQ(2u, index_2
);
862 EXPECT_TRUE(FindClosest(event_ptrs
, query_named
, 3, &index_1
, &index_2
));
863 EXPECT_EQ(2u, index_1
);
864 EXPECT_EQ(0u, index_2
);
867 // Test CountMatches.
868 TEST_F(TraceEventAnalyzerTest
, CountMatches
) {
869 TraceEventVector event_ptrs
;
870 EXPECT_EQ(0u, CountMatches(event_ptrs
, Query::Bool(true), 0, 10));
872 size_t num_events
= 5;
873 size_t num_named
= 3;
874 std::vector
<TraceEvent
> events
;
875 events
.resize(num_events
);
876 for (size_t i
= 0; i
< events
.size(); ++i
)
877 event_ptrs
.push_back(&events
[i
]);
878 events
[0].name
= "one";
879 events
[2].name
= "two";
880 events
[4].name
= "three";
881 Query query_named
= Query::EventName() != Query::String(std::string());
882 Query query_one
= Query::EventName() == Query::String("one");
884 EXPECT_EQ(0u, CountMatches(event_ptrs
, Query::Bool(false)));
885 EXPECT_EQ(num_events
, CountMatches(event_ptrs
, Query::Bool(true)));
886 EXPECT_EQ(num_events
- 1, CountMatches(event_ptrs
, Query::Bool(true),
888 EXPECT_EQ(1u, CountMatches(event_ptrs
, query_one
));
889 EXPECT_EQ(num_events
- 1, CountMatches(event_ptrs
, !query_one
));
890 EXPECT_EQ(num_named
, CountMatches(event_ptrs
, query_named
));
894 } // namespace trace_analyzer