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 | |
16 | namespace dart { |
17 | |
18 | #ifndef PRODUCT |
19 | |
20 | class 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 | |
33 | class 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 | |
101 | TEST_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 | |
120 | TEST_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 | |
135 | TEST_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) |
162 | TEST_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 | |
209 | TEST_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 | |
229 | TEST_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 | |
254 | TEST_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. |
266 | class 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 | |
284 | TEST_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 | |
341 | static bool LabelMatch(TimelineEvent* event, const char* label) { |
342 | ASSERT(event != NULL); |
343 | return strcmp(event->label(), label) == 0; |
344 | } |
345 | |
346 | TEST_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 | |
465 | TEST_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 | |
502 | TEST_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 | |
675 | TEST_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 | |