mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 06:20:13 +00:00
894 lines
30 KiB
C++
894 lines
30 KiB
C++
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include <cstring>
|
|
|
|
#include "platform/assert.h"
|
|
|
|
#include "vm/dart_api_impl.h"
|
|
#include "vm/dart_api_state.h"
|
|
#include "vm/globals.h"
|
|
#include "vm/timeline.h"
|
|
#include "vm/timeline_analysis.h"
|
|
#include "vm/unit_test.h"
|
|
|
|
namespace dart {
|
|
|
|
#ifndef PRODUCT
|
|
|
|
class TimelineRecorderOverride : public ValueObject {
|
|
public:
|
|
explicit TimelineRecorderOverride(TimelineEventRecorder* new_recorder)
|
|
: recorder_(Timeline::recorder()) {
|
|
Timeline::recorder_ = new_recorder;
|
|
}
|
|
|
|
~TimelineRecorderOverride() { Timeline::recorder_ = recorder_; }
|
|
|
|
private:
|
|
TimelineEventRecorder* recorder_;
|
|
};
|
|
|
|
class TimelineTestHelper : public AllStatic {
|
|
public:
|
|
static void SetStream(TimelineEvent* event, TimelineStream* stream) {
|
|
event->StreamInit(stream);
|
|
}
|
|
|
|
static void FakeThreadEvent(TimelineEventBlock* block,
|
|
intptr_t ftid,
|
|
const char* label = "fake",
|
|
TimelineStream* stream = NULL) {
|
|
TimelineEvent* event = block->StartEvent();
|
|
ASSERT(event != NULL);
|
|
event->DurationBegin(label);
|
|
event->thread_ = OSThread::ThreadIdFromIntPtr(ftid);
|
|
if (stream != NULL) {
|
|
event->StreamInit(stream);
|
|
}
|
|
}
|
|
|
|
static void SetBlockThread(TimelineEventBlock* block, intptr_t ftid) {
|
|
block->thread_id_ = OSThread::ThreadIdFromIntPtr(ftid);
|
|
}
|
|
|
|
static void FakeDuration(TimelineEventRecorder* recorder,
|
|
const char* label,
|
|
int64_t start,
|
|
int64_t end) {
|
|
ASSERT(recorder != NULL);
|
|
ASSERT(start < end);
|
|
ASSERT(label != NULL);
|
|
TimelineEvent* event = recorder->StartEvent();
|
|
ASSERT(event != NULL);
|
|
event->Duration(label, start, end);
|
|
event->Complete();
|
|
}
|
|
|
|
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);
|
|
event->Complete();
|
|
}
|
|
|
|
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);
|
|
event->Complete();
|
|
}
|
|
|
|
static void Clear(TimelineEventRecorder* recorder) {
|
|
ASSERT(recorder != NULL);
|
|
recorder->Clear();
|
|
}
|
|
|
|
static void FinishBlock(TimelineEventBlock* block) { block->Finish(); }
|
|
};
|
|
|
|
TEST_CASE(TimelineEventIsValid) {
|
|
// Create a test stream.
|
|
TimelineStream stream;
|
|
stream.Init("testStream", true);
|
|
|
|
TimelineEvent event;
|
|
TimelineTestHelper::SetStream(&event, &stream);
|
|
|
|
// Starts invalid.
|
|
EXPECT(!event.IsValid());
|
|
|
|
// Becomes valid.
|
|
event.Instant("hello");
|
|
EXPECT(event.IsValid());
|
|
|
|
// Becomes invalid.
|
|
event.Reset();
|
|
EXPECT(!event.IsValid());
|
|
}
|
|
|
|
TEST_CASE(TimelineEventDuration) {
|
|
// Create a test stream.
|
|
TimelineStream stream;
|
|
stream.Init("testStream", true);
|
|
|
|
// Create a test event.
|
|
TimelineEvent event;
|
|
TimelineTestHelper::SetStream(&event, &stream);
|
|
event.DurationBegin("apple");
|
|
// Measure the duration.
|
|
int64_t current_duration = event.TimeDuration();
|
|
event.DurationEnd();
|
|
// Verify that duration is larger.
|
|
EXPECT_GE(event.TimeDuration(), current_duration);
|
|
}
|
|
|
|
TEST_CASE(TimelineEventDurationPrintJSON) {
|
|
// Create a test stream.
|
|
TimelineStream stream;
|
|
stream.Init("testStream", true);
|
|
|
|
// Create a test event.
|
|
TimelineEvent event;
|
|
TimelineTestHelper::SetStream(&event, &stream);
|
|
event.DurationBegin("apple");
|
|
{
|
|
// Test printing to JSON.
|
|
JSONStream js;
|
|
event.PrintJSON(&js);
|
|
// Check category
|
|
EXPECT_SUBSTRING("\"cat\":\"testStream\"", js.ToCString());
|
|
// Check name.
|
|
EXPECT_SUBSTRING("\"name\":\"apple\"", js.ToCString());
|
|
// Check phase.
|
|
EXPECT_SUBSTRING("\"ph\":\"X\"", js.ToCString());
|
|
// Check that ts key is present.
|
|
EXPECT_SUBSTRING("\"ts\":", js.ToCString());
|
|
// Check that dur key is present.
|
|
EXPECT_SUBSTRING("\"dur\":", js.ToCString());
|
|
}
|
|
event.DurationEnd();
|
|
}
|
|
|
|
#if defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX)
|
|
TEST_CASE(TimelineEventPrintSystrace) {
|
|
const intptr_t kBufferLength = 1024;
|
|
char buffer[kBufferLength];
|
|
|
|
// Create a test stream.
|
|
TimelineStream stream;
|
|
stream.Init("testStream", true);
|
|
|
|
// Create a test event.
|
|
TimelineEvent event;
|
|
TimelineTestHelper::SetStream(&event, &stream);
|
|
|
|
// Test a Begin event.
|
|
event.Begin("apple", 1, 2);
|
|
TimelineEventSystraceRecorder::PrintSystrace(&event, &buffer[0],
|
|
kBufferLength);
|
|
EXPECT_SUBSTRING("|apple", buffer);
|
|
EXPECT_SUBSTRING("B|", buffer);
|
|
|
|
// Test an End event.
|
|
event.End("apple", 2, 3);
|
|
TimelineEventSystraceRecorder::PrintSystrace(&event, &buffer[0],
|
|
kBufferLength);
|
|
EXPECT_STREQ("E", buffer);
|
|
|
|
// Test a Counter event. We only report the first counter value (in this case
|
|
// "4").
|
|
event.Counter("CTR", 1);
|
|
// We have two counters.
|
|
event.SetNumArguments(2);
|
|
// Set the first counter value.
|
|
event.CopyArgument(0, "cats", "4");
|
|
// Set the second counter value.
|
|
event.CopyArgument(1, "dogs", "1");
|
|
TimelineEventSystraceRecorder::PrintSystrace(&event, &buffer[0],
|
|
kBufferLength);
|
|
EXPECT_SUBSTRING("C|", buffer);
|
|
EXPECT_SUBSTRING("|CTR|4", buffer);
|
|
|
|
// Test a duration event. This event kind is not supported so we should
|
|
// serialize it to an empty string.
|
|
event.Duration("DUR", 0, 1, 2, 3);
|
|
TimelineEventSystraceRecorder::PrintSystrace(&event, &buffer[0],
|
|
kBufferLength);
|
|
EXPECT_STREQ("", buffer);
|
|
}
|
|
#endif // defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX)
|
|
|
|
TEST_CASE(TimelineEventArguments) {
|
|
// Create a test stream.
|
|
TimelineStream stream;
|
|
stream.Init("testStream", true);
|
|
|
|
// Create a test event.
|
|
TimelineEvent event;
|
|
TimelineTestHelper::SetStream(&event, &stream);
|
|
|
|
// Allocate room for four arguments.
|
|
event.SetNumArguments(4);
|
|
// Reset.
|
|
event.Reset();
|
|
|
|
event.DurationBegin("apple");
|
|
event.SetNumArguments(2);
|
|
event.CopyArgument(0, "arg1", "value1");
|
|
event.CopyArgument(1, "arg2", "value2");
|
|
event.DurationEnd();
|
|
}
|
|
|
|
TEST_CASE(TimelineEventArgumentsPrintJSON) {
|
|
// Create a test stream.
|
|
TimelineStream stream;
|
|
stream.Init("testStream", true);
|
|
|
|
// Create a test event.
|
|
TimelineEvent event;
|
|
TimelineTestHelper::SetStream(&event, &stream);
|
|
|
|
event.DurationBegin("apple");
|
|
event.SetNumArguments(2);
|
|
event.CopyArgument(0, "arg1", "value1");
|
|
event.CopyArgument(1, "arg2", "value2");
|
|
event.DurationEnd();
|
|
|
|
{
|
|
// Test printing to JSON.
|
|
JSONStream js;
|
|
event.PrintJSON(&js);
|
|
|
|
// Check both arguments.
|
|
EXPECT_SUBSTRING("\"arg1\":\"value1\"", js.ToCString());
|
|
EXPECT_SUBSTRING("\"arg2\":\"value2\"", js.ToCString());
|
|
}
|
|
}
|
|
|
|
TEST_CASE(TimelineEventBufferPrintJSON) {
|
|
TimelineEventRecorder* recorder = Timeline::recorder();
|
|
JSONStream js;
|
|
TimelineEventFilter filter;
|
|
recorder->PrintJSON(&js, &filter);
|
|
// Check the type. This test will fail if we ever make Timeline public.
|
|
EXPECT_SUBSTRING("\"type\":\"_Timeline\"", js.ToCString());
|
|
// Check that there is a traceEvents array.
|
|
EXPECT_SUBSTRING("\"traceEvents\":[", js.ToCString());
|
|
}
|
|
|
|
// Count the number of each event type seen.
|
|
class EventCounterRecorder : public TimelineEventCallbackRecorder {
|
|
public:
|
|
EventCounterRecorder() {
|
|
for (intptr_t i = 0; i < TimelineEvent::kNumEventTypes; i++) {
|
|
counts_[i] = 0;
|
|
}
|
|
}
|
|
|
|
void OnEvent(TimelineEvent* event) { counts_[event->event_type()]++; }
|
|
|
|
intptr_t CountFor(TimelineEvent::EventType type) { return counts_[type]; }
|
|
|
|
private:
|
|
intptr_t counts_[TimelineEvent::kNumEventTypes];
|
|
};
|
|
|
|
TEST_CASE(TimelineEventCallbackRecorderBasic) {
|
|
EventCounterRecorder* recorder = new EventCounterRecorder();
|
|
TimelineRecorderOverride override(recorder);
|
|
|
|
// Initial counts are all zero.
|
|
for (intptr_t i = TimelineEvent::kNone + 1; i < TimelineEvent::kNumEventTypes;
|
|
i++) {
|
|
EXPECT_EQ(0, recorder->CountFor(static_cast<TimelineEvent::EventType>(i)));
|
|
}
|
|
|
|
// Create a test stream.
|
|
TimelineStream stream;
|
|
stream.Init("testStream", true);
|
|
|
|
TimelineEvent* event = NULL;
|
|
|
|
event = stream.StartEvent();
|
|
EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kDuration));
|
|
event->DurationBegin("cabbage");
|
|
EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kDuration));
|
|
event->DurationEnd();
|
|
EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kDuration));
|
|
event->Complete();
|
|
EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kDuration));
|
|
|
|
event = stream.StartEvent();
|
|
EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kInstant));
|
|
event->Instant("instantCabbage");
|
|
EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kInstant));
|
|
event->Complete();
|
|
EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kInstant));
|
|
|
|
event = stream.StartEvent();
|
|
EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncBegin));
|
|
int64_t async_id = recorder->GetNextAsyncId();
|
|
EXPECT(async_id >= 0);
|
|
event->AsyncBegin("asyncBeginCabbage", async_id);
|
|
EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncBegin));
|
|
event->Complete();
|
|
EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kAsyncBegin));
|
|
|
|
event = stream.StartEvent();
|
|
EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncInstant));
|
|
event->AsyncInstant("asyncInstantCabbage", async_id);
|
|
EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncInstant));
|
|
event->Complete();
|
|
EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kAsyncInstant));
|
|
|
|
event = stream.StartEvent();
|
|
EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncEnd));
|
|
event->AsyncEnd("asyncEndCabbage", async_id);
|
|
EXPECT_EQ(0, recorder->CountFor(TimelineEvent::kAsyncEnd));
|
|
event->Complete();
|
|
EXPECT_EQ(1, recorder->CountFor(TimelineEvent::kAsyncEnd));
|
|
|
|
delete recorder;
|
|
}
|
|
|
|
static bool LabelMatch(TimelineEvent* event, const char* label) {
|
|
ASSERT(event != NULL);
|
|
return strcmp(event->label(), label) == 0;
|
|
}
|
|
|
|
TEST_CASE(TimelineAnalysis_ThreadBlockCount) {
|
|
TimelineEventEndlessRecorder* recorder = new TimelineEventEndlessRecorder();
|
|
ASSERT(recorder != NULL);
|
|
// Blocks owned by thread "1".
|
|
TimelineEventBlock* block_1_0 = recorder->GetNewBlock();
|
|
TimelineTestHelper::SetBlockThread(block_1_0, 1);
|
|
TimelineEventBlock* block_1_1 = recorder->GetNewBlock();
|
|
TimelineTestHelper::SetBlockThread(block_1_1, 1);
|
|
TimelineEventBlock* block_1_2 = recorder->GetNewBlock();
|
|
TimelineTestHelper::SetBlockThread(block_1_2, 1);
|
|
// Blocks owned by thread "2".
|
|
TimelineEventBlock* block_2_0 = recorder->GetNewBlock();
|
|
TimelineTestHelper::SetBlockThread(block_2_0, 2);
|
|
// Blocks owned by thread "3".
|
|
TimelineEventBlock* block_3_0 = recorder->GetNewBlock();
|
|
TimelineTestHelper::SetBlockThread(block_3_0, 3);
|
|
USE(block_3_0);
|
|
|
|
// Add events to each block for thread 1.
|
|
TimelineTestHelper::FakeThreadEvent(block_1_2, 1, "B1");
|
|
TimelineTestHelper::FakeThreadEvent(block_1_2, 1, "B2");
|
|
TimelineTestHelper::FakeThreadEvent(block_1_2, 1, "B3");
|
|
// Sleep to ensure timestamps differ.
|
|
OS::Sleep(32);
|
|
TimelineTestHelper::FakeThreadEvent(block_1_0, 1, "A1");
|
|
OS::Sleep(32);
|
|
TimelineTestHelper::FakeThreadEvent(block_1_1, 1, "C1");
|
|
TimelineTestHelper::FakeThreadEvent(block_1_1, 1, "C2");
|
|
OS::Sleep(32);
|
|
|
|
// Add events to each block for thread 2.
|
|
TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "A");
|
|
TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "B");
|
|
TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "C");
|
|
TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "D");
|
|
TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "E");
|
|
TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "F");
|
|
|
|
Zone* zone = thread->zone();
|
|
Isolate* isolate = thread->isolate();
|
|
|
|
// Discover threads in recorder.
|
|
TimelineAnalysis ta(zone, isolate, recorder);
|
|
ta.BuildThreads();
|
|
EXPECT(!ta.has_error());
|
|
// block_3_0 is never used by a thread, so we only have two threads.
|
|
EXPECT_EQ(2, ta.NumThreads());
|
|
|
|
// Extract both threads.
|
|
TimelineAnalysisThread* thread_1 =
|
|
ta.GetThread(OSThread::ThreadIdFromIntPtr(1));
|
|
TimelineAnalysisThread* thread_2 =
|
|
ta.GetThread(OSThread::ThreadIdFromIntPtr(2));
|
|
EXPECT_EQ(OSThread::ThreadIdFromIntPtr(1), thread_1->id());
|
|
EXPECT_EQ(OSThread::ThreadIdFromIntPtr(2), thread_2->id());
|
|
|
|
// Thread "1" should have three blocks.
|
|
EXPECT_EQ(3, thread_1->NumBlocks());
|
|
|
|
// Verify that blocks for thread "1" are sorted based on start time.
|
|
EXPECT_EQ(thread_1->At(0), block_1_2);
|
|
EXPECT_EQ(thread_1->At(1), block_1_0);
|
|
EXPECT_EQ(thread_1->At(2), block_1_1);
|
|
|
|
// Verify that block_1_2 has three events.
|
|
EXPECT_EQ(3, block_1_2->length());
|
|
|
|
// Verify that block_1_0 has one events.
|
|
EXPECT_EQ(1, block_1_0->length());
|
|
|
|
// Verify that block_1_1 has two events.
|
|
EXPECT_EQ(2, block_1_1->length());
|
|
|
|
// Thread '2" should have one block.'
|
|
EXPECT_EQ(1, thread_2->NumBlocks());
|
|
EXPECT_EQ(thread_2->At(0), block_2_0);
|
|
// Verify that block_2_0 has six events.
|
|
EXPECT_EQ(6, block_2_0->length());
|
|
|
|
{
|
|
TimelineAnalysisThreadEventIterator it(thread_1);
|
|
// Six events spread across three blocks.
|
|
EXPECT(it.HasNext());
|
|
EXPECT(LabelMatch(it.Next(), "B1"));
|
|
EXPECT(it.HasNext());
|
|
EXPECT(LabelMatch(it.Next(), "B2"));
|
|
EXPECT(it.HasNext());
|
|
EXPECT(LabelMatch(it.Next(), "B3"));
|
|
EXPECT(it.HasNext());
|
|
EXPECT(LabelMatch(it.Next(), "A1"));
|
|
EXPECT(it.HasNext());
|
|
EXPECT(LabelMatch(it.Next(), "C1"));
|
|
EXPECT(it.HasNext());
|
|
EXPECT(LabelMatch(it.Next(), "C2"));
|
|
EXPECT(!it.HasNext());
|
|
}
|
|
|
|
{
|
|
TimelineAnalysisThreadEventIterator it(thread_2);
|
|
// Six events spread across three blocks.
|
|
EXPECT(it.HasNext());
|
|
EXPECT(LabelMatch(it.Next(), "A"));
|
|
EXPECT(it.HasNext());
|
|
EXPECT(LabelMatch(it.Next(), "B"));
|
|
EXPECT(it.HasNext());
|
|
EXPECT(LabelMatch(it.Next(), "C"));
|
|
EXPECT(it.HasNext());
|
|
EXPECT(LabelMatch(it.Next(), "D"));
|
|
EXPECT(it.HasNext());
|
|
EXPECT(LabelMatch(it.Next(), "E"));
|
|
EXPECT(it.HasNext());
|
|
EXPECT(LabelMatch(it.Next(), "F"));
|
|
EXPECT(!it.HasNext());
|
|
}
|
|
|
|
TimelineTestHelper::Clear(recorder);
|
|
delete recorder;
|
|
}
|
|
|
|
TEST_CASE(TimelineRingRecorderJSONOrder) {
|
|
TimelineStream stream;
|
|
stream.Init("testStream", true);
|
|
|
|
TimelineEventRingRecorder* recorder =
|
|
new TimelineEventRingRecorder(TimelineEventBlock::kBlockSize * 2);
|
|
|
|
TimelineEventBlock* block_0 = recorder->GetNewBlock();
|
|
EXPECT(block_0 != NULL);
|
|
TimelineEventBlock* block_1 = recorder->GetNewBlock();
|
|
EXPECT(block_1 != NULL);
|
|
// Test that we wrapped.
|
|
EXPECT(block_0 == recorder->GetNewBlock());
|
|
|
|
// Emit the earlier event into block_1.
|
|
TimelineTestHelper::FakeThreadEvent(block_1, 2, "Alpha", &stream);
|
|
OS::Sleep(32);
|
|
// Emit the later event into block_0.
|
|
TimelineTestHelper::FakeThreadEvent(block_0, 2, "Beta", &stream);
|
|
|
|
TimelineTestHelper::FinishBlock(block_0);
|
|
TimelineTestHelper::FinishBlock(block_1);
|
|
|
|
JSONStream js;
|
|
TimelineEventFilter filter;
|
|
recorder->PrintJSON(&js, &filter);
|
|
// trace-event has a requirement that events for a thread must have
|
|
// monotonically increasing timestamps.
|
|
// Verify that "Alpha" comes before "Beta" even though "Beta" is in the first
|
|
// block.
|
|
const char* alpha = strstr(js.ToCString(), "Alpha");
|
|
const char* beta = strstr(js.ToCString(), "Beta");
|
|
EXPECT(alpha < beta);
|
|
|
|
TimelineTestHelper::Clear(recorder);
|
|
delete recorder;
|
|
}
|
|
|
|
TEST_CASE(TimelinePauses_Basic) {
|
|
TimelineEventEndlessRecorder* recorder = new TimelineEventEndlessRecorder();
|
|
ASSERT(recorder != NULL);
|
|
Zone* zone = thread->zone();
|
|
Isolate* isolate = thread->isolate();
|
|
OSThread* os_thread = thread->os_thread();
|
|
ASSERT(os_thread != NULL);
|
|
ThreadId tid = os_thread->trace_id();
|
|
|
|
// Test case.
|
|
TimelineTestHelper::FakeDuration(recorder, "a", 0, 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::FakeDuration(recorder, "a", 0, 10);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 0, 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::FakeDuration(recorder, "a", 0, 10);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 1, 8);
|
|
{
|
|
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::FakeDuration(recorder, "a", 0, 10);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 0, 1);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 1, 2);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 2, 3);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 3, 4);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 4, 5);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 5, 6);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 6, 7);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 7, 8);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 8, 9);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 9, 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::FakeDuration(recorder, "a", 0, 10);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 0, 5);
|
|
TimelineTestHelper::FakeDuration(recorder, "c", 1, 4);
|
|
TimelineTestHelper::FakeDuration(recorder, "d", 5, 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::FakeDuration(recorder, "a", 0, 10);
|
|
TimelineTestHelper::FakeDuration(recorder, "b", 1, 9);
|
|
TimelineTestHelper::FakeDuration(recorder, "c", 2, 8);
|
|
TimelineTestHelper::FakeDuration(recorder, "d", 3, 7);
|
|
TimelineTestHelper::FakeDuration(recorder, "e", 4, 6);
|
|
|
|
{
|
|
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::FakeDuration(recorder, "a", 0, 10);
|
|
TimelineTestHelper::FakeDuration(recorder, "a", 1, 9);
|
|
|
|
{
|
|
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);
|
|
|
|
delete recorder;
|
|
}
|
|
|
|
TEST_CASE(TimelinePauses_BeginEnd) {
|
|
TimelineEventEndlessRecorder* recorder = new TimelineEventEndlessRecorder();
|
|
ASSERT(recorder != NULL);
|
|
Zone* zone = thread->zone();
|
|
Isolate* isolate = thread->isolate();
|
|
OSThread* os_thread = thread->os_thread();
|
|
ASSERT(os_thread != NULL);
|
|
ThreadId tid = os_thread->trace_id();
|
|
|
|
// 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);
|
|
|
|
delete recorder;
|
|
}
|
|
|
|
#endif // !PRODUCT
|
|
|
|
} // namespace dart
|