| Index: runtime/vm/timeline_test.cc | 
| diff --git a/runtime/vm/timeline_test.cc b/runtime/vm/timeline_test.cc | 
| index 617e8fe493d08a6a49ea586337291093fa91ed79..bdd2fddf7e4e988a71f93703fd418e137622a159 100644 | 
| --- a/runtime/vm/timeline_test.cc | 
| +++ b/runtime/vm/timeline_test.cc | 
| @@ -65,6 +65,30 @@ class TimelineTestHelper : public AllStatic { | 
| event->Duration(label, start, end); | 
| } | 
|  | 
| +  static void FakeBegin( | 
| +      TimelineEventRecorder* recorder, | 
| +      const char* label, | 
| +      int64_t start) { | 
| +    ASSERT(recorder != NULL); | 
| +    ASSERT(label != NULL); | 
| +    ASSERT(start >= 0); | 
| +    TimelineEvent* event = recorder->StartEvent(); | 
| +    ASSERT(event != NULL); | 
| +    event->Begin(label, start); | 
| +  } | 
| + | 
| +  static void FakeEnd( | 
| +      TimelineEventRecorder* recorder, | 
| +      const char* label, | 
| +      int64_t end) { | 
| +    ASSERT(recorder != NULL); | 
| +    ASSERT(label != NULL); | 
| +    ASSERT(end >= 0); | 
| +    TimelineEvent* event = recorder->StartEvent(); | 
| +    ASSERT(event != NULL); | 
| +    event->End(label, end); | 
| +  } | 
| + | 
| static void Clear(TimelineEventEndlessRecorder* recorder) { | 
| ASSERT(recorder != NULL); | 
| recorder->Clear(); | 
| @@ -609,4 +633,212 @@ TEST_CASE(TimelinePauses_Basic) { | 
| TimelineTestHelper::Clear(recorder); | 
| } | 
|  | 
| + | 
| +TEST_CASE(TimelinePauses_BeginEnd) { | 
| +  TimelineEventEndlessRecorder* recorder = new TimelineEventEndlessRecorder(); | 
| +  ASSERT(recorder != NULL); | 
| +  Zone* zone = thread->zone(); | 
| +  Isolate* isolate = thread->isolate(); | 
| +  ThreadId tid = OSThread::GetCurrentThreadTraceId(); | 
| + | 
| +  // Test case. | 
| +  TimelineTestHelper::FakeBegin(recorder, "a", 0); | 
| +  TimelineTestHelper::FakeEnd(recorder, "a", 10); | 
| + | 
| +  { | 
| +    TimelinePauses pauses(zone, isolate, recorder); | 
| +    pauses.Setup(); | 
| +    pauses.CalculatePauseTimesForThread(tid); | 
| +    EXPECT(!pauses.has_error()); | 
| +    EXPECT_EQ(10, pauses.InclusiveTime("a")); | 
| +    EXPECT_EQ(10, pauses.ExclusiveTime("a")); | 
| +    EXPECT_EQ(10, pauses.MaxInclusiveTime("a")); | 
| +    EXPECT_EQ(10, pauses.MaxExclusiveTime("a")); | 
| +  } | 
| +  TimelineTestHelper::Clear(recorder); | 
| + | 
| +  // Test case. | 
| +  TimelineTestHelper::FakeBegin(recorder, "a", 0); | 
| +  TimelineTestHelper::FakeBegin(recorder, "b", 0); | 
| +  TimelineTestHelper::FakeEnd(recorder, "b", 10); | 
| +  TimelineTestHelper::FakeEnd(recorder, "a", 10); | 
| + | 
| +  { | 
| +    TimelinePauses pauses(zone, isolate, recorder); | 
| +    pauses.Setup(); | 
| +    pauses.CalculatePauseTimesForThread(tid); | 
| +    EXPECT(!pauses.has_error()); | 
| +    EXPECT_EQ(10, pauses.InclusiveTime("a")); | 
| +    EXPECT_EQ(0, pauses.ExclusiveTime("a")); | 
| +    EXPECT_EQ(10, pauses.MaxInclusiveTime("a")); | 
| +    EXPECT_EQ(0, pauses.MaxExclusiveTime("a")); | 
| +    EXPECT_EQ(10, pauses.InclusiveTime("b")); | 
| +    EXPECT_EQ(10, pauses.ExclusiveTime("b")); | 
| +    EXPECT_EQ(10, pauses.MaxInclusiveTime("b")); | 
| +    EXPECT_EQ(10, pauses.MaxExclusiveTime("b")); | 
| +  } | 
| +  TimelineTestHelper::Clear(recorder); | 
| + | 
| +  // Test case. | 
| +  TimelineTestHelper::FakeBegin(recorder, "a", 0); | 
| +  TimelineTestHelper::FakeBegin(recorder, "b", 1); | 
| +  TimelineTestHelper::FakeEnd(recorder, "b", 8); | 
| +  TimelineTestHelper::FakeEnd(recorder, "a", 10); | 
| + | 
| +  { | 
| +    TimelinePauses pauses(zone, isolate, recorder); | 
| +    pauses.Setup(); | 
| +    pauses.CalculatePauseTimesForThread(tid); | 
| +    EXPECT(!pauses.has_error()); | 
| +    EXPECT_EQ(10, pauses.InclusiveTime("a")); | 
| +    EXPECT_EQ(3, pauses.ExclusiveTime("a")); | 
| +    EXPECT_EQ(10, pauses.MaxInclusiveTime("a")); | 
| +    EXPECT_EQ(3, pauses.MaxExclusiveTime("a")); | 
| +    EXPECT_EQ(7, pauses.InclusiveTime("b")); | 
| +    EXPECT_EQ(7, pauses.ExclusiveTime("b")); | 
| +    EXPECT_EQ(7, pauses.MaxInclusiveTime("b")); | 
| +    EXPECT_EQ(7, pauses.MaxExclusiveTime("b")); | 
| +  } | 
| +  TimelineTestHelper::Clear(recorder); | 
| + | 
| +  // Test case. | 
| +  TimelineTestHelper::FakeBegin(recorder, "a", 0); | 
| +  TimelineTestHelper::FakeDuration(recorder, "b", 0, 1); | 
| +  TimelineTestHelper::FakeDuration(recorder, "b", 1, 2); | 
| +  TimelineTestHelper::FakeDuration(recorder, "b", 2, 3); | 
| +  TimelineTestHelper::FakeBegin(recorder, "b", 3); | 
| +  TimelineTestHelper::FakeEnd(recorder, "b", 4); | 
| +  TimelineTestHelper::FakeDuration(recorder, "b", 4, 5); | 
| +  TimelineTestHelper::FakeDuration(recorder, "b", 5, 6); | 
| +  TimelineTestHelper::FakeDuration(recorder, "b", 6, 7); | 
| +  TimelineTestHelper::FakeBegin(recorder, "b", 7); | 
| +  TimelineTestHelper::FakeEnd(recorder, "b", 8); | 
| +  TimelineTestHelper::FakeBegin(recorder, "b", 8); | 
| +  TimelineTestHelper::FakeEnd(recorder, "b", 9); | 
| +  TimelineTestHelper::FakeDuration(recorder, "b", 9, 10); | 
| +  TimelineTestHelper::FakeEnd(recorder, "a", 10); | 
| + | 
| +  { | 
| +    TimelinePauses pauses(zone, isolate, recorder); | 
| +    pauses.Setup(); | 
| +    pauses.CalculatePauseTimesForThread(tid); | 
| +    EXPECT(!pauses.has_error()); | 
| +    EXPECT_EQ(10, pauses.InclusiveTime("a")); | 
| +    EXPECT_EQ(0, pauses.ExclusiveTime("a")); | 
| +    EXPECT_EQ(10, pauses.MaxInclusiveTime("a")); | 
| +    EXPECT_EQ(0, pauses.MaxExclusiveTime("a")); | 
| +    EXPECT_EQ(10, pauses.InclusiveTime("b")); | 
| +    EXPECT_EQ(10, pauses.ExclusiveTime("b")); | 
| +    EXPECT_EQ(1, pauses.MaxInclusiveTime("b")); | 
| +    EXPECT_EQ(1, pauses.MaxExclusiveTime("b")); | 
| +  } | 
| +  TimelineTestHelper::Clear(recorder); | 
| + | 
| +  // Test case. | 
| +  TimelineTestHelper::FakeBegin(recorder, "a", 0); | 
| +  TimelineTestHelper::FakeBegin(recorder, "b", 0); | 
| +  TimelineTestHelper::FakeBegin(recorder, "c", 1); | 
| +  TimelineTestHelper::FakeEnd(recorder, "c", 4); | 
| +  TimelineTestHelper::FakeEnd(recorder, "b", 5); | 
| +  TimelineTestHelper::FakeBegin(recorder, "d", 5); | 
| +  TimelineTestHelper::FakeEnd(recorder, "d", 10); | 
| +  TimelineTestHelper::FakeEnd(recorder, "a", 10); | 
| + | 
| +  { | 
| +    TimelinePauses pauses(zone, isolate, recorder); | 
| +    pauses.Setup(); | 
| +    pauses.CalculatePauseTimesForThread(tid); | 
| +    EXPECT(!pauses.has_error()); | 
| +    EXPECT_EQ(10, pauses.InclusiveTime("a")); | 
| +    EXPECT_EQ(0, pauses.ExclusiveTime("a")); | 
| +    EXPECT_EQ(10, pauses.MaxInclusiveTime("a")); | 
| +    EXPECT_EQ(0, pauses.MaxExclusiveTime("a")); | 
| +    EXPECT_EQ(5, pauses.InclusiveTime("b")); | 
| +    EXPECT_EQ(2, pauses.ExclusiveTime("b")); | 
| +    EXPECT_EQ(5, pauses.MaxInclusiveTime("b")); | 
| +    EXPECT_EQ(2, pauses.MaxExclusiveTime("b")); | 
| +    EXPECT_EQ(3, pauses.InclusiveTime("c")); | 
| +    EXPECT_EQ(3, pauses.ExclusiveTime("c")); | 
| +    EXPECT_EQ(3, pauses.MaxInclusiveTime("c")); | 
| +    EXPECT_EQ(3, pauses.MaxExclusiveTime("c")); | 
| +    EXPECT_EQ(5, pauses.InclusiveTime("d")); | 
| +    EXPECT_EQ(5, pauses.ExclusiveTime("d")); | 
| +    EXPECT_EQ(5, pauses.MaxInclusiveTime("d")); | 
| +    EXPECT_EQ(5, pauses.MaxExclusiveTime("d")); | 
| +  } | 
| +  TimelineTestHelper::Clear(recorder); | 
| + | 
| +  // Test case. | 
| +  TimelineTestHelper::FakeBegin(recorder, "a", 0); | 
| +  TimelineTestHelper::FakeBegin(recorder, "b", 1); | 
| +  TimelineTestHelper::FakeBegin(recorder, "c", 2); | 
| +  TimelineTestHelper::FakeBegin(recorder, "d", 3); | 
| +  TimelineTestHelper::FakeBegin(recorder, "e", 4); | 
| +  TimelineTestHelper::FakeEnd(recorder, "e", 6); | 
| +  TimelineTestHelper::FakeEnd(recorder, "d", 7); | 
| +  TimelineTestHelper::FakeEnd(recorder, "c", 8); | 
| +  TimelineTestHelper::FakeEnd(recorder, "b", 9); | 
| +  TimelineTestHelper::FakeEnd(recorder, "a", 10); | 
| + | 
| +  { | 
| +    TimelinePauses pauses(zone, isolate, recorder); | 
| +    pauses.Setup(); | 
| +    pauses.CalculatePauseTimesForThread(tid); | 
| +    EXPECT(!pauses.has_error()); | 
| +    EXPECT_EQ(10, pauses.InclusiveTime("a")); | 
| +    EXPECT_EQ(2, pauses.ExclusiveTime("a")); | 
| +    EXPECT_EQ(10, pauses.MaxInclusiveTime("a")); | 
| +    EXPECT_EQ(2, pauses.MaxExclusiveTime("a")); | 
| +    EXPECT_EQ(8, pauses.InclusiveTime("b")); | 
| +    EXPECT_EQ(2, pauses.ExclusiveTime("b")); | 
| +    EXPECT_EQ(8, pauses.MaxInclusiveTime("b")); | 
| +    EXPECT_EQ(2, pauses.MaxExclusiveTime("b")); | 
| +    EXPECT_EQ(6, pauses.InclusiveTime("c")); | 
| +    EXPECT_EQ(2, pauses.ExclusiveTime("c")); | 
| +    EXPECT_EQ(6, pauses.MaxInclusiveTime("c")); | 
| +    EXPECT_EQ(2, pauses.MaxExclusiveTime("c")); | 
| +    EXPECT_EQ(4, pauses.InclusiveTime("d")); | 
| +    EXPECT_EQ(2, pauses.ExclusiveTime("d")); | 
| +    EXPECT_EQ(4, pauses.MaxInclusiveTime("d")); | 
| +    EXPECT_EQ(2, pauses.MaxExclusiveTime("d")); | 
| +    EXPECT_EQ(2, pauses.InclusiveTime("e")); | 
| +    EXPECT_EQ(2, pauses.ExclusiveTime("e")); | 
| +    EXPECT_EQ(2, pauses.MaxInclusiveTime("e")); | 
| +    EXPECT_EQ(2, pauses.MaxExclusiveTime("e")); | 
| +  } | 
| +  TimelineTestHelper::Clear(recorder); | 
| + | 
| +  // Test case. | 
| +  TimelineTestHelper::FakeBegin(recorder, "a", 0); | 
| +  TimelineTestHelper::FakeBegin(recorder, "a", 1); | 
| +  TimelineTestHelper::FakeEnd(recorder, "a", 9); | 
| +  TimelineTestHelper::FakeEnd(recorder, "a", 10); | 
| + | 
| +  { | 
| +    TimelinePauses pauses(zone, isolate, recorder); | 
| +    pauses.Setup(); | 
| +    pauses.CalculatePauseTimesForThread(tid); | 
| +    EXPECT(!pauses.has_error()); | 
| +    EXPECT_EQ(10, pauses.InclusiveTime("a")); | 
| +    EXPECT_EQ(10, pauses.ExclusiveTime("a")); | 
| +    EXPECT_EQ(10, pauses.MaxInclusiveTime("a")); | 
| +    EXPECT_EQ(8, pauses.MaxExclusiveTime("a")); | 
| +  } | 
| +  TimelineTestHelper::Clear(recorder); | 
| + | 
| +  // Test case. | 
| +  TimelineTestHelper::FakeBegin(recorder, "a", 0); | 
| +  TimelineTestHelper::FakeBegin(recorder, "b", 1); | 
| +  // Pop "a" without popping "b" first. | 
| +  TimelineTestHelper::FakeEnd(recorder, "a", 10); | 
| + | 
| +  { | 
| +    TimelinePauses pauses(zone, isolate, recorder); | 
| +    pauses.Setup(); | 
| +    pauses.CalculatePauseTimesForThread(tid); | 
| +    EXPECT(pauses.has_error()); | 
| +  } | 
| +  TimelineTestHelper::Clear(recorder); | 
| +} | 
| + | 
| }  // namespace dart | 
|  |