| // 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 |