1// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include <cstring>
6
7#include "platform/assert.h"
8
9#include "vm/dart_api_impl.h"
10#include "vm/dart_api_state.h"
11#include "vm/globals.h"
12#include "vm/timeline.h"
13#include "vm/timeline_analysis.h"
14#include "vm/unit_test.h"
15
16namespace dart {
17
18#ifndef PRODUCT
19
20class TimelineRecorderOverride : public ValueObject {
21 public:
22 explicit TimelineRecorderOverride(TimelineEventRecorder* new_recorder)
23 : recorder_(Timeline::recorder()) {
24 Timeline::recorder_ = new_recorder;
25 }
26
27 ~TimelineRecorderOverride() { Timeline::recorder_ = recorder_; }
28
29 private:
30 TimelineEventRecorder* recorder_;
31};
32
33class TimelineTestHelper : public AllStatic {
34 public:
35 static void SetStream(TimelineEvent* event, TimelineStream* stream) {
36 event->StreamInit(stream);
37 }
38
39 static void FakeThreadEvent(TimelineEventBlock* block,
40 intptr_t ftid,
41 const char* label = "fake",
42 TimelineStream* stream = NULL) {
43 TimelineEvent* event = block->StartEvent();
44 ASSERT(event != NULL);
45 event->DurationBegin(label);
46 event->thread_ = OSThread::ThreadIdFromIntPtr(ftid);
47 if (stream != NULL) {
48 event->StreamInit(stream);
49 }
50 }
51
52 static void SetBlockThread(TimelineEventBlock* block, intptr_t ftid) {
53 block->thread_id_ = OSThread::ThreadIdFromIntPtr(ftid);
54 }
55
56 static void FakeDuration(TimelineEventRecorder* recorder,
57 const char* label,
58 int64_t start,
59 int64_t end) {
60 ASSERT(recorder != NULL);
61 ASSERT(start < end);
62 ASSERT(label != NULL);
63 TimelineEvent* event = recorder->StartEvent();
64 ASSERT(event != NULL);
65 event->Duration(label, start, end);
66 event->Complete();
67 }
68
69 static void FakeBegin(TimelineEventRecorder* recorder,
70 const char* label,
71 int64_t start) {
72 ASSERT(recorder != NULL);
73 ASSERT(label != NULL);
74 ASSERT(start >= 0);
75 TimelineEvent* event = recorder->StartEvent();
76 ASSERT(event != NULL);
77 event->Begin(label, start);
78 event->Complete();
79 }
80
81 static void FakeEnd(TimelineEventRecorder* recorder,
82 const char* label,
83 int64_t end) {
84 ASSERT(recorder != NULL);
85 ASSERT(label != NULL);
86 ASSERT(end >= 0);
87 TimelineEvent* event = recorder->StartEvent();
88 ASSERT(event != NULL);
89 event->End(label, end);
90 event->Complete();
91 }
92
93 static void Clear(TimelineEventRecorder* recorder) {
94 ASSERT(recorder != NULL);
95 recorder->Clear();
96 }
97
98 static void FinishBlock(TimelineEventBlock* block) { block->Finish(); }
99};
100
101TEST_CASE(TimelineEventIsValid) {
102 // Create a test stream.
103 TimelineStream stream("testStream", "testStream", true);
104
105 TimelineEvent event;
106 TimelineTestHelper::SetStream(&event, &stream);
107
108 // Starts invalid.
109 EXPECT(!event.IsValid());
110
111 // Becomes valid.
112 event.Instant("hello");
113 EXPECT(event.IsValid());
114
115 // Becomes invalid.
116 event.Reset();
117 EXPECT(!event.IsValid());
118}
119
120TEST_CASE(TimelineEventDuration) {
121 // Create a test stream.
122 TimelineStream stream("testStream", "testStream", true);
123
124 // Create a test event.
125 TimelineEvent event;
126 TimelineTestHelper::SetStream(&event, &stream);
127 event.DurationBegin("apple");
128 // Measure the duration.
129 int64_t current_duration = event.TimeDuration();
130 event.DurationEnd();
131 // Verify that duration is larger.
132 EXPECT_GE(event.TimeDuration(), current_duration);
133}
134
135TEST_CASE(TimelineEventDurationPrintJSON) {
136 // Create a test stream.
137 TimelineStream stream("testStream", "testStream", true);
138
139 // Create a test event.
140 TimelineEvent event;
141 TimelineTestHelper::SetStream(&event, &stream);
142 event.DurationBegin("apple");
143 {
144 // Test printing to JSON.
145 JSONStream js;
146 event.PrintJSON(&js);
147 // Check category
148 EXPECT_SUBSTRING("\"cat\":\"testStream\"", js.ToCString());
149 // Check name.
150 EXPECT_SUBSTRING("\"name\":\"apple\"", js.ToCString());
151 // Check phase.
152 EXPECT_SUBSTRING("\"ph\":\"X\"", js.ToCString());
153 // Check that ts key is present.
154 EXPECT_SUBSTRING("\"ts\":", js.ToCString());
155 // Check that dur key is present.
156 EXPECT_SUBSTRING("\"dur\":", js.ToCString());
157 }
158 event.DurationEnd();
159}
160
161#if defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX)
162TEST_CASE(TimelineEventPrintSystrace) {
163 const intptr_t kBufferLength = 1024;
164 char buffer[kBufferLength];
165
166 // Create a test stream.
167 TimelineStream stream("testStream", "testStream", true);
168
169 // Create a test event.
170 TimelineEvent event;
171 TimelineTestHelper::SetStream(&event, &stream);
172
173 // Test a Begin event.
174 event.Begin("apple", 1, 2);
175 TimelineEventSystraceRecorder::PrintSystrace(&event, &buffer[0],
176 kBufferLength);
177 EXPECT_SUBSTRING("|apple", buffer);
178 EXPECT_SUBSTRING("B|", buffer);
179
180 // Test an End event.
181 event.End("apple", 2, 3);
182 TimelineEventSystraceRecorder::PrintSystrace(&event, &buffer[0],
183 kBufferLength);
184 EXPECT_STREQ("E", buffer);
185
186 // Test a Counter event. We only report the first counter value (in this case
187 // "4").
188 event.Counter("CTR", 1);
189 // We have two counters.
190 event.SetNumArguments(2);
191 // Set the first counter value.
192 event.CopyArgument(0, "cats", "4");
193 // Set the second counter value.
194 event.CopyArgument(1, "dogs", "1");
195 TimelineEventSystraceRecorder::PrintSystrace(&event, &buffer[0],
196 kBufferLength);
197 EXPECT_SUBSTRING("C|", buffer);
198 EXPECT_SUBSTRING("|CTR|4", buffer);
199
200 // Test a duration event. This event kind is not supported so we should
201 // serialize it to an empty string.
202 event.Duration("DUR", 0, 1, 2, 3);
203 TimelineEventSystraceRecorder::PrintSystrace(&event, &buffer[0],
204 kBufferLength);
205 EXPECT_STREQ("", buffer);
206}
207#endif // defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX)
208
209TEST_CASE(TimelineEventArguments) {
210 // Create a test stream.
211 TimelineStream stream("testStream", "testStream", true);
212
213 // Create a test event.
214 TimelineEvent event;
215 TimelineTestHelper::SetStream(&event, &stream);
216
217 // Allocate room for four arguments.
218 event.SetNumArguments(4);
219 // Reset.
220 event.Reset();
221
222 event.DurationBegin("apple");
223 event.SetNumArguments(2);
224 event.CopyArgument(0, "arg1", "value1");
225 event.CopyArgument(1, "arg2", "value2");
226 event.DurationEnd();
227}
228
229TEST_CASE(TimelineEventArgumentsPrintJSON) {
230 // Create a test stream.
231 TimelineStream stream("testStream", "testStream", true);
232
233 // Create a test event.
234 TimelineEvent event;
235 TimelineTestHelper::SetStream(&event, &stream);
236
237 event.DurationBegin("apple");
238 event.SetNumArguments(2);
239 event.CopyArgument(0, "arg1", "value1");
240 event.CopyArgument(1, "arg2", "value2");
241 event.DurationEnd();
242
243 {
244 // Test printing to JSON.
245 JSONStream js;
246 event.PrintJSON(&js);
247
248 // Check both arguments.
249 EXPECT_SUBSTRING("\"arg1\":\"value1\"", js.ToCString());
250 EXPECT_SUBSTRING("\"arg2\":\"value2\"", js.ToCString());
251 }
252}
253
254TEST_CASE(TimelineEventBufferPrintJSON) {
255 TimelineEventRecorder* recorder = Timeline::recorder();
256 JSONStream js;
257 TimelineEventFilter filter;
258 recorder->PrintJSON(&js, &filter);
259 // Check the type.
260 EXPECT_SUBSTRING("\"type\":\"Timeline\"", js.ToCString());
261 // Check that there is a traceEvents array.
262 EXPECT_SUBSTRING("\"traceEvents\":[", js.ToCString());
263}
264
265// Count the number of each event type seen.
266class EventCounterRecorder : public TimelineEventCallbackRecorder {
267 public:
268 EventCounterRecorder() {
269 for (intptr_t i = 0; i < TimelineEvent::kNumEventTypes; i++) {
270 counts_[i] = 0;
271 }
272 }
273
274 void OnEvent(TimelineEvent* event) { counts_[event->event_type()]++; }
275
276 intptr_t CountFor(TimelineEvent::EventType type) { return counts_[type]; }
277
278 intptr_t Size() { return -1; }
279
280 private:
281 intptr_t counts_[TimelineEvent::kNumEventTypes];
282};
283
284TEST_CASE(TimelineEventCallbackRecorderBasic) {
285 EventCounterRecorder* recorder = new EventCounterRecorder();
286 TimelineRecorderOverride override(recorder);
287
288 // Initial counts are all zero.
289 for (intptr_t i = TimelineEvent::kNone + 1; i < TimelineEvent::kNumEventTypes;
290 i++) {
291 EXPECT_EQ(0, recorder->CountFor(static_cast<TimelineEvent::EventType>(i)));
292 }
293
294 // Create a test stream.
295 TimelineStream stream("testStream", "testStream", true);
296
297 TimelineEvent* event = NULL;
298
299 event = stream.StartEvent();
300 EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kDuration));
301 event->DurationBegin("cabbage");
302 EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kDuration));
303 event->DurationEnd();
304 EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kDuration));
305 event->Complete();
306 EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kDuration));
307
308 event = stream.StartEvent();
309 EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kInstant));
310 event->Instant("instantCabbage");
311 EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kInstant));
312 event->Complete();
313 EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kInstant));
314
315 event = stream.StartEvent();
316 EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncBegin));
317 int64_t async_id = recorder->GetNextAsyncId();
318 EXPECT(async_id >= 0);
319 event->AsyncBegin("asyncBeginCabbage", async_id);
320 EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncBegin));
321 event->Complete();
322 EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kAsyncBegin));
323
324 event = stream.StartEvent();
325 EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncInstant));
326 event->AsyncInstant("asyncInstantCabbage", async_id);
327 EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncInstant));
328 event->Complete();
329 EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kAsyncInstant));
330
331 event = stream.StartEvent();
332 EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncEnd));
333 event->AsyncEnd("asyncEndCabbage", async_id);
334 EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncEnd));
335 event->Complete();
336 EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kAsyncEnd));
337
338 delete recorder;
339}
340
341static bool LabelMatch(TimelineEvent* event, const char* label) {
342 ASSERT(event != NULL);
343 return strcmp(event->label(), label) == 0;
344}
345
346TEST_CASE(TimelineAnalysis_ThreadBlockCount) {
347 TimelineEventEndlessRecorder* recorder = new TimelineEventEndlessRecorder();
348 ASSERT(recorder != NULL);
349 // Blocks owned by thread "1".
350 TimelineEventBlock* block_1_0 = recorder->GetNewBlock();
351 TimelineTestHelper::SetBlockThread(block_1_0, 1);
352 TimelineEventBlock* block_1_1 = recorder->GetNewBlock();
353 TimelineTestHelper::SetBlockThread(block_1_1, 1);
354 TimelineEventBlock* block_1_2 = recorder->GetNewBlock();
355 TimelineTestHelper::SetBlockThread(block_1_2, 1);
356 // Blocks owned by thread "2".
357 TimelineEventBlock* block_2_0 = recorder->GetNewBlock();
358 TimelineTestHelper::SetBlockThread(block_2_0, 2);
359 // Blocks owned by thread "3".
360 TimelineEventBlock* block_3_0 = recorder->GetNewBlock();
361 TimelineTestHelper::SetBlockThread(block_3_0, 3);
362 USE(block_3_0);
363
364 // Add events to each block for thread 1.
365 TimelineTestHelper::FakeThreadEvent(block_1_2, 1, "B1");
366 TimelineTestHelper::FakeThreadEvent(block_1_2, 1, "B2");
367 TimelineTestHelper::FakeThreadEvent(block_1_2, 1, "B3");
368 // Sleep to ensure timestamps differ.
369 OS::Sleep(32);
370 TimelineTestHelper::FakeThreadEvent(block_1_0, 1, "A1");
371 OS::Sleep(32);
372 TimelineTestHelper::FakeThreadEvent(block_1_1, 1, "C1");
373 TimelineTestHelper::FakeThreadEvent(block_1_1, 1, "C2");
374 OS::Sleep(32);
375
376 // Add events to each block for thread 2.
377 TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "A");
378 TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "B");
379 TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "C");
380 TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "D");
381 TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "E");
382 TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "F");
383
384 Zone* zone = thread->zone();
385 Isolate* isolate = thread->isolate();
386
387 // Discover threads in recorder.
388 TimelineAnalysis ta(zone, isolate, recorder);
389 ta.BuildThreads();
390 EXPECT(!ta.has_error());
391 // block_3_0 is never used by a thread, so we only have two threads.
392 EXPECT_EQ(2, ta.NumThreads());
393
394 // Extract both threads.
395 TimelineAnalysisThread* thread_1 =
396 ta.GetThread(OSThread::ThreadIdFromIntPtr(1));
397 TimelineAnalysisThread* thread_2 =
398 ta.GetThread(OSThread::ThreadIdFromIntPtr(2));
399 EXPECT_EQ(OSThread::ThreadIdFromIntPtr(1), thread_1->id());
400 EXPECT_EQ(OSThread::ThreadIdFromIntPtr(2), thread_2->id());
401
402 // Thread "1" should have three blocks.
403 EXPECT_EQ(3, thread_1->NumBlocks());
404
405 // Verify that blocks for thread "1" are sorted based on start time.
406 EXPECT_EQ(thread_1->At(0), block_1_2);
407 EXPECT_EQ(thread_1->At(1), block_1_0);
408 EXPECT_EQ(thread_1->At(2), block_1_1);
409
410 // Verify that block_1_2 has three events.
411 EXPECT_EQ(3, block_1_2->length());
412
413 // Verify that block_1_0 has one events.
414 EXPECT_EQ(1, block_1_0->length());
415
416 // Verify that block_1_1 has two events.
417 EXPECT_EQ(2, block_1_1->length());
418
419 // Thread '2" should have one block.'
420 EXPECT_EQ(1, thread_2->NumBlocks());
421 EXPECT_EQ(thread_2->At(0), block_2_0);
422 // Verify that block_2_0 has six events.
423 EXPECT_EQ(6, block_2_0->length());
424
425 {
426 TimelineAnalysisThreadEventIterator it(thread_1);
427 // Six events spread across three blocks.
428 EXPECT(it.HasNext());
429 EXPECT(LabelMatch(it.Next(), "B1"));
430 EXPECT(it.HasNext());
431 EXPECT(LabelMatch(it.Next(), "B2"));
432 EXPECT(it.HasNext());
433 EXPECT(LabelMatch(it.Next(), "B3"));
434 EXPECT(it.HasNext());
435 EXPECT(LabelMatch(it.Next(), "A1"));
436 EXPECT(it.HasNext());
437 EXPECT(LabelMatch(it.Next(), "C1"));
438 EXPECT(it.HasNext());
439 EXPECT(LabelMatch(it.Next(), "C2"));
440 EXPECT(!it.HasNext());
441 }
442
443 {
444 TimelineAnalysisThreadEventIterator it(thread_2);
445 // Six events spread across three blocks.
446 EXPECT(it.HasNext());
447 EXPECT(LabelMatch(it.Next(), "A"));
448 EXPECT(it.HasNext());
449 EXPECT(LabelMatch(it.Next(), "B"));
450 EXPECT(it.HasNext());
451 EXPECT(LabelMatch(it.Next(), "C"));
452 EXPECT(it.HasNext());
453 EXPECT(LabelMatch(it.Next(), "D"));
454 EXPECT(it.HasNext());
455 EXPECT(LabelMatch(it.Next(), "E"));
456 EXPECT(it.HasNext());
457 EXPECT(LabelMatch(it.Next(), "F"));
458 EXPECT(!it.HasNext());
459 }
460
461 TimelineTestHelper::Clear(recorder);
462 delete recorder;
463}
464
465TEST_CASE(TimelineRingRecorderJSONOrder) {
466 TimelineStream stream("testStream", "testStream", true);
467
468 TimelineEventRingRecorder* recorder =
469 new TimelineEventRingRecorder(TimelineEventBlock::kBlockSize * 2);
470
471 TimelineEventBlock* block_0 = recorder->GetNewBlock();
472 EXPECT(block_0 != NULL);
473 TimelineEventBlock* block_1 = recorder->GetNewBlock();
474 EXPECT(block_1 != NULL);
475 // Test that we wrapped.
476 EXPECT(block_0 == recorder->GetNewBlock());
477
478 // Emit the earlier event into block_1.
479 TimelineTestHelper::FakeThreadEvent(block_1, 2, "Alpha", &stream);
480 OS::Sleep(32);
481 // Emit the later event into block_0.
482 TimelineTestHelper::FakeThreadEvent(block_0, 2, "Beta", &stream);
483
484 TimelineTestHelper::FinishBlock(block_0);
485 TimelineTestHelper::FinishBlock(block_1);
486
487 JSONStream js;
488 TimelineEventFilter filter;
489 recorder->PrintJSON(&js, &filter);
490 // trace-event has a requirement that events for a thread must have
491 // monotonically increasing timestamps.
492 // Verify that "Alpha" comes before "Beta" even though "Beta" is in the first
493 // block.
494 const char* alpha = strstr(js.ToCString(), "Alpha");
495 const char* beta = strstr(js.ToCString(), "Beta");
496 EXPECT(alpha < beta);
497
498 TimelineTestHelper::Clear(recorder);
499 delete recorder;
500}
501
502TEST_CASE(TimelinePauses_Basic) {
503 TimelineEventEndlessRecorder* recorder = new TimelineEventEndlessRecorder();
504 ASSERT(recorder != NULL);
505 Zone* zone = thread->zone();
506 Isolate* isolate = thread->isolate();
507 OSThread* os_thread = thread->os_thread();
508 ASSERT(os_thread != NULL);
509 ThreadId tid = os_thread->trace_id();
510
511 // Test case.
512 TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
513 {
514 TimelinePauses pauses(zone, isolate, recorder);
515 pauses.Setup();
516 pauses.CalculatePauseTimesForThread(tid);
517 EXPECT(!pauses.has_error());
518 EXPECT_EQ(10, pauses.InclusiveTime("a"));
519 EXPECT_EQ(10, pauses.ExclusiveTime("a"));
520 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
521 EXPECT_EQ(10, pauses.MaxExclusiveTime("a"));
522 }
523 TimelineTestHelper::Clear(recorder);
524
525 // Test case.
526 TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
527 TimelineTestHelper::FakeDuration(recorder, "b", 0, 10);
528 {
529 TimelinePauses pauses(zone, isolate, recorder);
530 pauses.Setup();
531 pauses.CalculatePauseTimesForThread(tid);
532 EXPECT(!pauses.has_error());
533 EXPECT_EQ(10, pauses.InclusiveTime("a"));
534 EXPECT_EQ(0, pauses.ExclusiveTime("a"));
535 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
536 EXPECT_EQ(0, pauses.MaxExclusiveTime("a"));
537 EXPECT_EQ(10, pauses.InclusiveTime("b"));
538 EXPECT_EQ(10, pauses.ExclusiveTime("b"));
539 EXPECT_EQ(10, pauses.MaxInclusiveTime("b"));
540 EXPECT_EQ(10, pauses.MaxExclusiveTime("b"));
541 }
542 TimelineTestHelper::Clear(recorder);
543
544 // Test case.
545 TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
546 TimelineTestHelper::FakeDuration(recorder, "b", 1, 8);
547 {
548 TimelinePauses pauses(zone, isolate, recorder);
549 pauses.Setup();
550 pauses.CalculatePauseTimesForThread(tid);
551 EXPECT(!pauses.has_error());
552 EXPECT_EQ(10, pauses.InclusiveTime("a"));
553 EXPECT_EQ(3, pauses.ExclusiveTime("a"));
554 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
555 EXPECT_EQ(3, pauses.MaxExclusiveTime("a"));
556 EXPECT_EQ(7, pauses.InclusiveTime("b"));
557 EXPECT_EQ(7, pauses.ExclusiveTime("b"));
558 EXPECT_EQ(7, pauses.MaxInclusiveTime("b"));
559 EXPECT_EQ(7, pauses.MaxExclusiveTime("b"));
560 }
561 TimelineTestHelper::Clear(recorder);
562
563 // Test case.
564 TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
565 TimelineTestHelper::FakeDuration(recorder, "b", 0, 1);
566 TimelineTestHelper::FakeDuration(recorder, "b", 1, 2);
567 TimelineTestHelper::FakeDuration(recorder, "b", 2, 3);
568 TimelineTestHelper::FakeDuration(recorder, "b", 3, 4);
569 TimelineTestHelper::FakeDuration(recorder, "b", 4, 5);
570 TimelineTestHelper::FakeDuration(recorder, "b", 5, 6);
571 TimelineTestHelper::FakeDuration(recorder, "b", 6, 7);
572 TimelineTestHelper::FakeDuration(recorder, "b", 7, 8);
573 TimelineTestHelper::FakeDuration(recorder, "b", 8, 9);
574 TimelineTestHelper::FakeDuration(recorder, "b", 9, 10);
575 {
576 TimelinePauses pauses(zone, isolate, recorder);
577 pauses.Setup();
578 pauses.CalculatePauseTimesForThread(tid);
579 EXPECT(!pauses.has_error());
580 EXPECT_EQ(10, pauses.InclusiveTime("a"));
581 EXPECT_EQ(0, pauses.ExclusiveTime("a"));
582 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
583 EXPECT_EQ(0, pauses.MaxExclusiveTime("a"));
584 EXPECT_EQ(10, pauses.InclusiveTime("b"));
585 EXPECT_EQ(10, pauses.ExclusiveTime("b"));
586 EXPECT_EQ(1, pauses.MaxInclusiveTime("b"));
587 EXPECT_EQ(1, pauses.MaxExclusiveTime("b"));
588 }
589 TimelineTestHelper::Clear(recorder);
590
591 // Test case.
592 TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
593 TimelineTestHelper::FakeDuration(recorder, "b", 0, 5);
594 TimelineTestHelper::FakeDuration(recorder, "c", 1, 4);
595 TimelineTestHelper::FakeDuration(recorder, "d", 5, 10);
596
597 {
598 TimelinePauses pauses(zone, isolate, recorder);
599 pauses.Setup();
600 pauses.CalculatePauseTimesForThread(tid);
601 EXPECT(!pauses.has_error());
602 EXPECT_EQ(10, pauses.InclusiveTime("a"));
603 EXPECT_EQ(0, pauses.ExclusiveTime("a"));
604 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
605 EXPECT_EQ(0, pauses.MaxExclusiveTime("a"));
606 EXPECT_EQ(5, pauses.InclusiveTime("b"));
607 EXPECT_EQ(2, pauses.ExclusiveTime("b"));
608 EXPECT_EQ(5, pauses.MaxInclusiveTime("b"));
609 EXPECT_EQ(2, pauses.MaxExclusiveTime("b"));
610 EXPECT_EQ(3, pauses.InclusiveTime("c"));
611 EXPECT_EQ(3, pauses.ExclusiveTime("c"));
612 EXPECT_EQ(3, pauses.MaxInclusiveTime("c"));
613 EXPECT_EQ(3, pauses.MaxExclusiveTime("c"));
614 EXPECT_EQ(5, pauses.InclusiveTime("d"));
615 EXPECT_EQ(5, pauses.ExclusiveTime("d"));
616 EXPECT_EQ(5, pauses.MaxInclusiveTime("d"));
617 EXPECT_EQ(5, pauses.MaxExclusiveTime("d"));
618 }
619 TimelineTestHelper::Clear(recorder);
620
621 // Test case.
622 TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
623 TimelineTestHelper::FakeDuration(recorder, "b", 1, 9);
624 TimelineTestHelper::FakeDuration(recorder, "c", 2, 8);
625 TimelineTestHelper::FakeDuration(recorder, "d", 3, 7);
626 TimelineTestHelper::FakeDuration(recorder, "e", 4, 6);
627
628 {
629 TimelinePauses pauses(zone, isolate, recorder);
630 pauses.Setup();
631 pauses.CalculatePauseTimesForThread(tid);
632 EXPECT(!pauses.has_error());
633 EXPECT_EQ(10, pauses.InclusiveTime("a"));
634 EXPECT_EQ(2, pauses.ExclusiveTime("a"));
635 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
636 EXPECT_EQ(2, pauses.MaxExclusiveTime("a"));
637 EXPECT_EQ(8, pauses.InclusiveTime("b"));
638 EXPECT_EQ(2, pauses.ExclusiveTime("b"));
639 EXPECT_EQ(8, pauses.MaxInclusiveTime("b"));
640 EXPECT_EQ(2, pauses.MaxExclusiveTime("b"));
641 EXPECT_EQ(6, pauses.InclusiveTime("c"));
642 EXPECT_EQ(2, pauses.ExclusiveTime("c"));
643 EXPECT_EQ(6, pauses.MaxInclusiveTime("c"));
644 EXPECT_EQ(2, pauses.MaxExclusiveTime("c"));
645 EXPECT_EQ(4, pauses.InclusiveTime("d"));
646 EXPECT_EQ(2, pauses.ExclusiveTime("d"));
647 EXPECT_EQ(4, pauses.MaxInclusiveTime("d"));
648 EXPECT_EQ(2, pauses.MaxExclusiveTime("d"));
649 EXPECT_EQ(2, pauses.InclusiveTime("e"));
650 EXPECT_EQ(2, pauses.ExclusiveTime("e"));
651 EXPECT_EQ(2, pauses.MaxInclusiveTime("e"));
652 EXPECT_EQ(2, pauses.MaxExclusiveTime("e"));
653 }
654 TimelineTestHelper::Clear(recorder);
655
656 // Test case.
657 TimelineTestHelper::FakeDuration(recorder, "a", 0, 10);
658 TimelineTestHelper::FakeDuration(recorder, "a", 1, 9);
659
660 {
661 TimelinePauses pauses(zone, isolate, recorder);
662 pauses.Setup();
663 pauses.CalculatePauseTimesForThread(tid);
664 EXPECT(!pauses.has_error());
665 EXPECT_EQ(10, pauses.InclusiveTime("a"));
666 EXPECT_EQ(10, pauses.ExclusiveTime("a"));
667 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
668 EXPECT_EQ(8, pauses.MaxExclusiveTime("a"));
669 }
670 TimelineTestHelper::Clear(recorder);
671
672 delete recorder;
673}
674
675TEST_CASE(TimelinePauses_BeginEnd) {
676 TimelineEventEndlessRecorder* recorder = new TimelineEventEndlessRecorder();
677 ASSERT(recorder != NULL);
678 Zone* zone = thread->zone();
679 Isolate* isolate = thread->isolate();
680 OSThread* os_thread = thread->os_thread();
681 ASSERT(os_thread != NULL);
682 ThreadId tid = os_thread->trace_id();
683
684 // Test case.
685 TimelineTestHelper::FakeBegin(recorder, "a", 0);
686 TimelineTestHelper::FakeEnd(recorder, "a", 10);
687
688 {
689 TimelinePauses pauses(zone, isolate, recorder);
690 pauses.Setup();
691 pauses.CalculatePauseTimesForThread(tid);
692 EXPECT(!pauses.has_error());
693 EXPECT_EQ(10, pauses.InclusiveTime("a"));
694 EXPECT_EQ(10, pauses.ExclusiveTime("a"));
695 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
696 EXPECT_EQ(10, pauses.MaxExclusiveTime("a"));
697 }
698 TimelineTestHelper::Clear(recorder);
699
700 // Test case.
701 TimelineTestHelper::FakeBegin(recorder, "a", 0);
702 TimelineTestHelper::FakeBegin(recorder, "b", 0);
703 TimelineTestHelper::FakeEnd(recorder, "b", 10);
704 TimelineTestHelper::FakeEnd(recorder, "a", 10);
705
706 {
707 TimelinePauses pauses(zone, isolate, recorder);
708 pauses.Setup();
709 pauses.CalculatePauseTimesForThread(tid);
710 EXPECT(!pauses.has_error());
711 EXPECT_EQ(10, pauses.InclusiveTime("a"));
712 EXPECT_EQ(0, pauses.ExclusiveTime("a"));
713 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
714 EXPECT_EQ(0, pauses.MaxExclusiveTime("a"));
715 EXPECT_EQ(10, pauses.InclusiveTime("b"));
716 EXPECT_EQ(10, pauses.ExclusiveTime("b"));
717 EXPECT_EQ(10, pauses.MaxInclusiveTime("b"));
718 EXPECT_EQ(10, pauses.MaxExclusiveTime("b"));
719 }
720 TimelineTestHelper::Clear(recorder);
721
722 // Test case.
723 TimelineTestHelper::FakeBegin(recorder, "a", 0);
724 TimelineTestHelper::FakeBegin(recorder, "b", 1);
725 TimelineTestHelper::FakeEnd(recorder, "b", 8);
726 TimelineTestHelper::FakeEnd(recorder, "a", 10);
727
728 {
729 TimelinePauses pauses(zone, isolate, recorder);
730 pauses.Setup();
731 pauses.CalculatePauseTimesForThread(tid);
732 EXPECT(!pauses.has_error());
733 EXPECT_EQ(10, pauses.InclusiveTime("a"));
734 EXPECT_EQ(3, pauses.ExclusiveTime("a"));
735 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
736 EXPECT_EQ(3, pauses.MaxExclusiveTime("a"));
737 EXPECT_EQ(7, pauses.InclusiveTime("b"));
738 EXPECT_EQ(7, pauses.ExclusiveTime("b"));
739 EXPECT_EQ(7, pauses.MaxInclusiveTime("b"));
740 EXPECT_EQ(7, pauses.MaxExclusiveTime("b"));
741 }
742 TimelineTestHelper::Clear(recorder);
743
744 // Test case.
745 TimelineTestHelper::FakeBegin(recorder, "a", 0);
746 TimelineTestHelper::FakeDuration(recorder, "b", 0, 1);
747 TimelineTestHelper::FakeDuration(recorder, "b", 1, 2);
748 TimelineTestHelper::FakeDuration(recorder, "b", 2, 3);
749 TimelineTestHelper::FakeBegin(recorder, "b", 3);
750 TimelineTestHelper::FakeEnd(recorder, "b", 4);
751 TimelineTestHelper::FakeDuration(recorder, "b", 4, 5);
752 TimelineTestHelper::FakeDuration(recorder, "b", 5, 6);
753 TimelineTestHelper::FakeDuration(recorder, "b", 6, 7);
754 TimelineTestHelper::FakeBegin(recorder, "b", 7);
755 TimelineTestHelper::FakeEnd(recorder, "b", 8);
756 TimelineTestHelper::FakeBegin(recorder, "b", 8);
757 TimelineTestHelper::FakeEnd(recorder, "b", 9);
758 TimelineTestHelper::FakeDuration(recorder, "b", 9, 10);
759 TimelineTestHelper::FakeEnd(recorder, "a", 10);
760
761 {
762 TimelinePauses pauses(zone, isolate, recorder);
763 pauses.Setup();
764 pauses.CalculatePauseTimesForThread(tid);
765 EXPECT(!pauses.has_error());
766 EXPECT_EQ(10, pauses.InclusiveTime("a"));
767 EXPECT_EQ(0, pauses.ExclusiveTime("a"));
768 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
769 EXPECT_EQ(0, pauses.MaxExclusiveTime("a"));
770 EXPECT_EQ(10, pauses.InclusiveTime("b"));
771 EXPECT_EQ(10, pauses.ExclusiveTime("b"));
772 EXPECT_EQ(1, pauses.MaxInclusiveTime("b"));
773 EXPECT_EQ(1, pauses.MaxExclusiveTime("b"));
774 }
775 TimelineTestHelper::Clear(recorder);
776
777 // Test case.
778 TimelineTestHelper::FakeBegin(recorder, "a", 0);
779 TimelineTestHelper::FakeBegin(recorder, "b", 0);
780 TimelineTestHelper::FakeBegin(recorder, "c", 1);
781 TimelineTestHelper::FakeEnd(recorder, "c", 4);
782 TimelineTestHelper::FakeEnd(recorder, "b", 5);
783 TimelineTestHelper::FakeBegin(recorder, "d", 5);
784 TimelineTestHelper::FakeEnd(recorder, "d", 10);
785 TimelineTestHelper::FakeEnd(recorder, "a", 10);
786
787 {
788 TimelinePauses pauses(zone, isolate, recorder);
789 pauses.Setup();
790 pauses.CalculatePauseTimesForThread(tid);
791 EXPECT(!pauses.has_error());
792 EXPECT_EQ(10, pauses.InclusiveTime("a"));
793 EXPECT_EQ(0, pauses.ExclusiveTime("a"));
794 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
795 EXPECT_EQ(0, pauses.MaxExclusiveTime("a"));
796 EXPECT_EQ(5, pauses.InclusiveTime("b"));
797 EXPECT_EQ(2, pauses.ExclusiveTime("b"));
798 EXPECT_EQ(5, pauses.MaxInclusiveTime("b"));
799 EXPECT_EQ(2, pauses.MaxExclusiveTime("b"));
800 EXPECT_EQ(3, pauses.InclusiveTime("c"));
801 EXPECT_EQ(3, pauses.ExclusiveTime("c"));
802 EXPECT_EQ(3, pauses.MaxInclusiveTime("c"));
803 EXPECT_EQ(3, pauses.MaxExclusiveTime("c"));
804 EXPECT_EQ(5, pauses.InclusiveTime("d"));
805 EXPECT_EQ(5, pauses.ExclusiveTime("d"));
806 EXPECT_EQ(5, pauses.MaxInclusiveTime("d"));
807 EXPECT_EQ(5, pauses.MaxExclusiveTime("d"));
808 }
809 TimelineTestHelper::Clear(recorder);
810
811 // Test case.
812 TimelineTestHelper::FakeBegin(recorder, "a", 0);
813 TimelineTestHelper::FakeBegin(recorder, "b", 1);
814 TimelineTestHelper::FakeBegin(recorder, "c", 2);
815 TimelineTestHelper::FakeBegin(recorder, "d", 3);
816 TimelineTestHelper::FakeBegin(recorder, "e", 4);
817 TimelineTestHelper::FakeEnd(recorder, "e", 6);
818 TimelineTestHelper::FakeEnd(recorder, "d", 7);
819 TimelineTestHelper::FakeEnd(recorder, "c", 8);
820 TimelineTestHelper::FakeEnd(recorder, "b", 9);
821 TimelineTestHelper::FakeEnd(recorder, "a", 10);
822
823 {
824 TimelinePauses pauses(zone, isolate, recorder);
825 pauses.Setup();
826 pauses.CalculatePauseTimesForThread(tid);
827 EXPECT(!pauses.has_error());
828 EXPECT_EQ(10, pauses.InclusiveTime("a"));
829 EXPECT_EQ(2, pauses.ExclusiveTime("a"));
830 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
831 EXPECT_EQ(2, pauses.MaxExclusiveTime("a"));
832 EXPECT_EQ(8, pauses.InclusiveTime("b"));
833 EXPECT_EQ(2, pauses.ExclusiveTime("b"));
834 EXPECT_EQ(8, pauses.MaxInclusiveTime("b"));
835 EXPECT_EQ(2, pauses.MaxExclusiveTime("b"));
836 EXPECT_EQ(6, pauses.InclusiveTime("c"));
837 EXPECT_EQ(2, pauses.ExclusiveTime("c"));
838 EXPECT_EQ(6, pauses.MaxInclusiveTime("c"));
839 EXPECT_EQ(2, pauses.MaxExclusiveTime("c"));
840 EXPECT_EQ(4, pauses.InclusiveTime("d"));
841 EXPECT_EQ(2, pauses.ExclusiveTime("d"));
842 EXPECT_EQ(4, pauses.MaxInclusiveTime("d"));
843 EXPECT_EQ(2, pauses.MaxExclusiveTime("d"));
844 EXPECT_EQ(2, pauses.InclusiveTime("e"));
845 EXPECT_EQ(2, pauses.ExclusiveTime("e"));
846 EXPECT_EQ(2, pauses.MaxInclusiveTime("e"));
847 EXPECT_EQ(2, pauses.MaxExclusiveTime("e"));
848 }
849 TimelineTestHelper::Clear(recorder);
850
851 // Test case.
852 TimelineTestHelper::FakeBegin(recorder, "a", 0);
853 TimelineTestHelper::FakeBegin(recorder, "a", 1);
854 TimelineTestHelper::FakeEnd(recorder, "a", 9);
855 TimelineTestHelper::FakeEnd(recorder, "a", 10);
856
857 {
858 TimelinePauses pauses(zone, isolate, recorder);
859 pauses.Setup();
860 pauses.CalculatePauseTimesForThread(tid);
861 EXPECT(!pauses.has_error());
862 EXPECT_EQ(10, pauses.InclusiveTime("a"));
863 EXPECT_EQ(10, pauses.ExclusiveTime("a"));
864 EXPECT_EQ(10, pauses.MaxInclusiveTime("a"));
865 EXPECT_EQ(8, pauses.MaxExclusiveTime("a"));
866 }
867 TimelineTestHelper::Clear(recorder);
868
869 // Test case.
870 TimelineTestHelper::FakeBegin(recorder, "a", 0);
871 TimelineTestHelper::FakeBegin(recorder, "b", 1);
872 // Pop "a" without popping "b" first.
873 TimelineTestHelper::FakeEnd(recorder, "a", 10);
874
875 {
876 TimelinePauses pauses(zone, isolate, recorder);
877 pauses.Setup();
878 pauses.CalculatePauseTimesForThread(tid);
879 EXPECT(pauses.has_error());
880 }
881 TimelineTestHelper::Clear(recorder);
882
883 delete recorder;
884}
885
886#endif // !PRODUCT
887
888} // namespace dart
889