// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/trace_event/trace_event_synthetic_delay.h" #include <stdint.h> #include "base/macros.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { namespace trace_event { namespace { const int kTargetDurationMs = 100; // Allow some leeway in timings to make it possible to run these tests with a // wall clock time source too. const int kShortDurationMs = 10; } // namespace class TraceEventSyntheticDelayTest : public testing::Test, public TraceEventSyntheticDelayClock { public: TraceEventSyntheticDelayTest() {} ~TraceEventSyntheticDelayTest() override { ResetTraceEventSyntheticDelays(); } // TraceEventSyntheticDelayClock implementation. base::TimeTicks Now() override { AdvanceTime(base::TimeDelta::FromMilliseconds(kShortDurationMs / 10)); return now_; } TraceEventSyntheticDelay* ConfigureDelay(const char* name) { TraceEventSyntheticDelay* delay = TraceEventSyntheticDelay::Lookup(name); delay->SetClock(this); delay->SetTargetDuration( base::TimeDelta::FromMilliseconds(kTargetDurationMs)); return delay; } void AdvanceTime(base::TimeDelta delta) { now_ += delta; } int64_t TestFunction() { base::TimeTicks start = Now(); { TRACE_EVENT_SYNTHETIC_DELAY("test.Delay"); } return (Now() - start).InMilliseconds(); } int64_t AsyncTestFunctionBegin() { base::TimeTicks start = Now(); { TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("test.AsyncDelay"); } return (Now() - start).InMilliseconds(); } int64_t AsyncTestFunctionEnd() { base::TimeTicks start = Now(); { TRACE_EVENT_SYNTHETIC_DELAY_END("test.AsyncDelay"); } return (Now() - start).InMilliseconds(); } private: base::TimeTicks now_; DISALLOW_COPY_AND_ASSIGN(TraceEventSyntheticDelayTest); }; TEST_F(TraceEventSyntheticDelayTest, StaticDelay) { TraceEventSyntheticDelay* delay = ConfigureDelay("test.Delay"); delay->SetMode(TraceEventSyntheticDelay::STATIC); EXPECT_GE(TestFunction(), kTargetDurationMs); } TEST_F(TraceEventSyntheticDelayTest, OneShotDelay) { TraceEventSyntheticDelay* delay = ConfigureDelay("test.Delay"); delay->SetMode(TraceEventSyntheticDelay::ONE_SHOT); EXPECT_GE(TestFunction(), kTargetDurationMs); EXPECT_LT(TestFunction(), kShortDurationMs); delay->SetTargetDuration( base::TimeDelta::FromMilliseconds(kTargetDurationMs)); EXPECT_GE(TestFunction(), kTargetDurationMs); } TEST_F(TraceEventSyntheticDelayTest, AlternatingDelay) { TraceEventSyntheticDelay* delay = ConfigureDelay("test.Delay"); delay->SetMode(TraceEventSyntheticDelay::ALTERNATING); EXPECT_GE(TestFunction(), kTargetDurationMs); EXPECT_LT(TestFunction(), kShortDurationMs); EXPECT_GE(TestFunction(), kTargetDurationMs); EXPECT_LT(TestFunction(), kShortDurationMs); } TEST_F(TraceEventSyntheticDelayTest, AsyncDelay) { ConfigureDelay("test.AsyncDelay"); EXPECT_LT(AsyncTestFunctionBegin(), kShortDurationMs); EXPECT_GE(AsyncTestFunctionEnd(), kTargetDurationMs / 2); } TEST_F(TraceEventSyntheticDelayTest, AsyncDelayExceeded) { ConfigureDelay("test.AsyncDelay"); EXPECT_LT(AsyncTestFunctionBegin(), kShortDurationMs); AdvanceTime(base::TimeDelta::FromMilliseconds(kTargetDurationMs)); EXPECT_LT(AsyncTestFunctionEnd(), kShortDurationMs); } TEST_F(TraceEventSyntheticDelayTest, AsyncDelayNoActivation) { ConfigureDelay("test.AsyncDelay"); EXPECT_LT(AsyncTestFunctionEnd(), kShortDurationMs); } TEST_F(TraceEventSyntheticDelayTest, AsyncDelayNested) { ConfigureDelay("test.AsyncDelay"); EXPECT_LT(AsyncTestFunctionBegin(), kShortDurationMs); EXPECT_LT(AsyncTestFunctionBegin(), kShortDurationMs); EXPECT_LT(AsyncTestFunctionEnd(), kShortDurationMs); EXPECT_GE(AsyncTestFunctionEnd(), kTargetDurationMs / 2); } TEST_F(TraceEventSyntheticDelayTest, AsyncDelayUnbalanced) { ConfigureDelay("test.AsyncDelay"); EXPECT_LT(AsyncTestFunctionBegin(), kShortDurationMs); EXPECT_GE(AsyncTestFunctionEnd(), kTargetDurationMs / 2); EXPECT_LT(AsyncTestFunctionEnd(), kShortDurationMs); EXPECT_LT(AsyncTestFunctionBegin(), kShortDurationMs); EXPECT_GE(AsyncTestFunctionEnd(), kTargetDurationMs / 2); } TEST_F(TraceEventSyntheticDelayTest, ResetDelays) { ConfigureDelay("test.Delay"); ResetTraceEventSyntheticDelays(); EXPECT_LT(TestFunction(), kShortDurationMs); } TEST_F(TraceEventSyntheticDelayTest, BeginParallel) { TraceEventSyntheticDelay* delay = ConfigureDelay("test.AsyncDelay"); base::TimeTicks end_times[2]; base::TimeTicks start_time = Now(); delay->BeginParallel(&end_times[0]); EXPECT_FALSE(end_times[0].is_null()); delay->BeginParallel(&end_times[1]); EXPECT_FALSE(end_times[1].is_null()); delay->EndParallel(end_times[0]); EXPECT_GE((Now() - start_time).InMilliseconds(), kTargetDurationMs); start_time = Now(); delay->EndParallel(end_times[1]); EXPECT_LT((Now() - start_time).InMilliseconds(), kShortDurationMs); } } // namespace trace_event } // namespace base