Commit a9367935 authored by Eric Seckler's avatar Eric Seckler Committed by Commit Bot

base: Add override mechanism for Time/TimeTicks/ThreadTicks::Now.

Allows clients to provide functions to override the return values of
Time::Now(), TimeTicks::Now(), ThreadTicks::Now().

Also adds a way to bypass the override in places where real timestamps
should be used even if an override is set.

Bug: 802217, 751993
Change-Id: I76ce536caf9bf0ef5e580abcc23215ce9851ee34
Reviewed-on: https://chromium-review.googlesource.com/867911
Commit-Queue: Eric Seckler <eseckler@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Reviewed-by: default avatarYuri Wiitala <miu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#531923}
parent ff96a216
...@@ -937,6 +937,8 @@ jumbo_component("base") { ...@@ -937,6 +937,8 @@ jumbo_component("base") {
"time/tick_clock.h", "time/tick_clock.h",
"time/time.cc", "time/time.cc",
"time/time.h", "time/time.h",
"time/time_override.cc",
"time/time_override.h",
"timer/elapsed_timer.cc", "timer/elapsed_timer.cc",
"timer/elapsed_timer.h", "timer/elapsed_timer.h",
"timer/hi_res_timer_manager.h", "timer/hi_res_timer_manager.h",
......
...@@ -15,10 +15,26 @@ ...@@ -15,10 +15,26 @@
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/third_party/nspr/prtime.h" #include "base/third_party/nspr/prtime.h"
#include "base/time/time_override.h"
#include "build/build_config.h" #include "build/build_config.h"
namespace base { namespace base {
namespace internal {
TimeNowFunction g_time_now_function = &subtle::TimeNowIgnoringOverride;
TimeNowFunction g_time_now_from_system_time_function =
&subtle::TimeNowFromSystemTimeIgnoringOverride;
TimeTicksNowFunction g_time_ticks_now_function =
&subtle::TimeTicksNowIgnoringOverride;
ThreadTicksNowFunction g_thread_ticks_now_function =
&subtle::ThreadTicksNowIgnoringOverride;
} // namespace internal
// TimeDelta ------------------------------------------------------------------ // TimeDelta ------------------------------------------------------------------
int TimeDelta::InDays() const { int TimeDelta::InDays() const {
...@@ -134,6 +150,17 @@ std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) { ...@@ -134,6 +150,17 @@ std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) {
// Time ----------------------------------------------------------------------- // Time -----------------------------------------------------------------------
// static
Time Time::Now() {
return internal::g_time_now_function();
}
// static
Time Time::NowFromSystemTime() {
// Just use g_time_now_function because it returns the system time.
return internal::g_time_now_from_system_time_function();
}
// static // static
Time Time::FromDeltaSinceWindowsEpoch(TimeDelta delta) { Time Time::FromDeltaSinceWindowsEpoch(TimeDelta delta) {
return Time(delta.InMicroseconds()); return Time(delta.InMicroseconds());
...@@ -298,10 +325,19 @@ std::ostream& operator<<(std::ostream& os, Time time) { ...@@ -298,10 +325,19 @@ std::ostream& operator<<(std::ostream& os, Time time) {
exploded.millisecond); exploded.millisecond);
} }
// Static // TimeTicks ------------------------------------------------------------------
// static
TimeTicks TimeTicks::Now() {
return internal::g_time_ticks_now_function();
}
// static
TimeTicks TimeTicks::UnixEpoch() { TimeTicks TimeTicks::UnixEpoch() {
static const base::NoDestructor<base::TimeTicks> epoch( static const base::NoDestructor<base::TimeTicks> epoch([]() {
[]() { return TimeTicks::Now() - (Time::Now() - Time::UnixEpoch()); }()); return subtle::TimeTicksNowIgnoringOverride() -
(subtle::TimeNowIgnoringOverride() - Time::UnixEpoch());
}());
return *epoch; return *epoch;
} }
...@@ -328,6 +364,13 @@ std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) { ...@@ -328,6 +364,13 @@ std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
return os << as_time_delta.InMicroseconds() << " bogo-microseconds"; return os << as_time_delta.InMicroseconds() << " bogo-microseconds";
} }
// ThreadTicks ----------------------------------------------------------------
// static
ThreadTicks ThreadTicks::Now() {
return internal::g_thread_ticks_now_function();
}
std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) { std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) {
const TimeDelta as_time_delta = thread_ticks - ThreadTicks(); const TimeDelta as_time_delta = thread_ticks - ThreadTicks();
return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds"; return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds";
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/numerics/checked_math.h" #include "base/numerics/checked_math.h"
#include "base/time/time_override.h"
namespace base { namespace base {
...@@ -25,28 +26,32 @@ ALWAYS_INLINE int64_t ZxTimeToMicroseconds(zx_time_t nanos) { ...@@ -25,28 +26,32 @@ ALWAYS_INLINE int64_t ZxTimeToMicroseconds(zx_time_t nanos) {
// Time ----------------------------------------------------------------------- // Time -----------------------------------------------------------------------
// static namespace subtle {
Time Time::Now() { Time TimeNowIgnoringOverride() {
const zx_time_t nanos_since_unix_epoch = zx_time_get(ZX_CLOCK_UTC); const zx_time_t nanos_since_unix_epoch = zx_time_get(ZX_CLOCK_UTC);
CHECK(nanos_since_unix_epoch != 0); CHECK(nanos_since_unix_epoch != 0);
// The following expression will overflow in the year 289938 A.D.: // The following expression will overflow in the year 289938 A.D.:
return Time(ZxTimeToMicroseconds(nanos_since_unix_epoch) + return Time() + TimeDelta::FromMicroseconds(
kTimeTToMicrosecondsOffset); ZxTimeToMicroseconds(nanos_since_unix_epoch) +
Time::kTimeTToMicrosecondsOffset);
} }
// static Time TimeNowFromSystemTimeIgnoringOverride() {
Time Time::NowFromSystemTime() { // Just use TimeNowIgnoringOverride() because it returns the system time.
return Now(); return TimeNowIgnoringOverride();
} }
} // namespace subtle
// TimeTicks ------------------------------------------------------------------ // TimeTicks ------------------------------------------------------------------
// static namespace subtle {
TimeTicks TimeTicks::Now() { TimeTicks TimeTicksNowIgnoringOverride() {
const zx_time_t nanos_since_boot = zx_time_get(ZX_CLOCK_MONOTONIC); const zx_time_t nanos_since_boot = zx_time_get(ZX_CLOCK_MONOTONIC);
CHECK(nanos_since_boot != 0); CHECK(nanos_since_boot != 0);
return TimeTicks(ZxTimeToMicroseconds(nanos_since_boot)); return TimeTicks() +
TimeDelta::FromMicroseconds(ZxTimeToMicroseconds(nanos_since_boot));
} }
} // namespace subtle
// static // static
TimeTicks::Clock TimeTicks::GetClock() { TimeTicks::Clock TimeTicks::GetClock() {
...@@ -74,11 +79,15 @@ zx_time_t TimeTicks::ToZxTime() const { ...@@ -74,11 +79,15 @@ zx_time_t TimeTicks::ToZxTime() const {
return result.ValueOrDie(); return result.ValueOrDie();
} }
// static // ThreadTicks ----------------------------------------------------------------
ThreadTicks ThreadTicks::Now() {
namespace subtle {
ThreadTicks ThreadTicksNowIgnoringOverride() {
const zx_time_t nanos_since_thread_started = zx_time_get(ZX_CLOCK_THREAD); const zx_time_t nanos_since_thread_started = zx_time_get(ZX_CLOCK_THREAD);
CHECK(nanos_since_thread_started != 0); CHECK(nanos_since_thread_started != 0);
return ThreadTicks(ZxTimeToMicroseconds(nanos_since_thread_started)); return ThreadTicks() + TimeDelta::FromMicroseconds(
ZxTimeToMicroseconds(nanos_since_thread_started));
} }
} // namespace subtle
} // namespace base } // namespace base
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "base/mac/scoped_mach_port.h" #include "base/mac/scoped_mach_port.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_conversions.h"
#include "base/time/time_override.h"
#include "build/build_config.h" #include "build/build_config.h"
#if defined(OS_IOS) #if defined(OS_IOS)
...@@ -81,8 +82,9 @@ int64_t ComputeCurrentTicks() { ...@@ -81,8 +82,9 @@ int64_t ComputeCurrentTicks() {
int kr = sysctl(mib, arraysize(mib), &boottime, &size, nullptr, 0); int kr = sysctl(mib, arraysize(mib), &boottime, &size, nullptr, 0);
DCHECK_EQ(KERN_SUCCESS, kr); DCHECK_EQ(KERN_SUCCESS, kr);
base::TimeDelta time_difference = base::TimeDelta time_difference =
base::Time::Now() - (base::Time::FromTimeT(boottime.tv_sec) + base::subtle::TimeNowIgnoringOverride() -
base::TimeDelta::FromMicroseconds(boottime.tv_usec)); (base::Time::FromTimeT(boottime.tv_sec) +
base::TimeDelta::FromMicroseconds(boottime.tv_usec));
return time_difference.InMicroseconds(); return time_difference.InMicroseconds();
#else #else
// mach_absolute_time is it when it comes to ticks on the Mac. Other calls // mach_absolute_time is it when it comes to ticks on the Mac. Other calls
...@@ -135,10 +137,16 @@ namespace base { ...@@ -135,10 +137,16 @@ namespace base {
// Time ----------------------------------------------------------------------- // Time -----------------------------------------------------------------------
// static namespace subtle {
Time Time::Now() { Time TimeNowIgnoringOverride() {
return FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent()); return Time::FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent());
}
Time TimeNowFromSystemTimeIgnoringOverride() {
// Just use TimeNowIgnoringOverride() because it returns the system time.
return TimeNowIgnoringOverride();
} }
} // namespace subtle
// static // static
Time Time::FromCFAbsoluteTime(CFAbsoluteTime t) { Time Time::FromCFAbsoluteTime(CFAbsoluteTime t) {
...@@ -165,12 +173,6 @@ CFAbsoluteTime Time::ToCFAbsoluteTime() const { ...@@ -165,12 +173,6 @@ CFAbsoluteTime Time::ToCFAbsoluteTime() const {
kCFAbsoluteTimeIntervalSince1970; kCFAbsoluteTimeIntervalSince1970;
} }
// static
Time Time::NowFromSystemTime() {
// Just use Now() because Now() returns the system time.
return Now();
}
// Note: These implementations of Time::FromExploded() and Time::Explode() are // Note: These implementations of Time::FromExploded() and Time::Explode() are
// only used on iOS now. Since Mac is now always 64-bit, we can use the POSIX // only used on iOS now. Since Mac is now always 64-bit, we can use the POSIX
// versions of these functions as time_t is not capped at year 2038 on 64-bit // versions of these functions as time_t is not capped at year 2038 on 64-bit
...@@ -269,10 +271,11 @@ void Time::Explode(bool is_local, Exploded* exploded) const { ...@@ -269,10 +271,11 @@ void Time::Explode(bool is_local, Exploded* exploded) const {
// TimeTicks ------------------------------------------------------------------ // TimeTicks ------------------------------------------------------------------
// static namespace subtle {
TimeTicks TimeTicks::Now() { TimeTicks TimeTicksNowIgnoringOverride() {
return TimeTicks(ComputeCurrentTicks()); return TimeTicks() + TimeDelta::FromMicroseconds(ComputeCurrentTicks());
} }
} // namespace subtle
// static // static
bool TimeTicks::IsHighResolution() { bool TimeTicks::IsHighResolution() {
...@@ -300,9 +303,12 @@ TimeTicks::Clock TimeTicks::GetClock() { ...@@ -300,9 +303,12 @@ TimeTicks::Clock TimeTicks::GetClock() {
#endif // defined(OS_IOS) #endif // defined(OS_IOS)
} }
// static // ThreadTicks ----------------------------------------------------------------
ThreadTicks ThreadTicks::Now() {
return ThreadTicks(ComputeThreadTicks()); namespace subtle {
ThreadTicks ThreadTicksNowIgnoringOverride() {
return ThreadTicks() + TimeDelta::FromMicroseconds(ComputeThreadTicks());
} }
} // namespace subtle
} // namespace base } // namespace base
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/numerics/safe_math.h" #include "base/numerics/safe_math.h"
#include "base/time/time_override.h"
#include "build/build_config.h" #include "build/build_config.h"
// Ensure the Fuchsia and Mac builds do not include this module. Instead, // Ensure the Fuchsia and Mac builds do not include this module. Instead,
...@@ -62,30 +63,32 @@ namespace base { ...@@ -62,30 +63,32 @@ namespace base {
// Time ----------------------------------------------------------------------- // Time -----------------------------------------------------------------------
// static namespace subtle {
Time Time::Now() { Time TimeNowIgnoringOverride() {
struct timeval tv; struct timeval tv;
struct timezone tz = {0, 0}; // UTC struct timezone tz = {0, 0}; // UTC
CHECK(gettimeofday(&tv, &tz) == 0); CHECK(gettimeofday(&tv, &tz) == 0);
// Combine seconds and microseconds in a 64-bit field containing microseconds // Combine seconds and microseconds in a 64-bit field containing microseconds
// since the epoch. That's enough for nearly 600 centuries. Adjust from // since the epoch. That's enough for nearly 600 centuries. Adjust from
// Unix (1970) to Windows (1601) epoch. // Unix (1970) to Windows (1601) epoch.
return Time((tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec) + return Time() + TimeDelta::FromMicroseconds(
kTimeTToMicrosecondsOffset); (tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec) +
Time::kTimeTToMicrosecondsOffset);
} }
// static Time TimeNowFromSystemTimeIgnoringOverride() {
Time Time::NowFromSystemTime() { // Just use TimeNowIgnoringOverride() because it returns the system time.
// Just use Now() because Now() returns the system time. return TimeNowIgnoringOverride();
return Now();
} }
} // namespace subtle
// TimeTicks ------------------------------------------------------------------ // TimeTicks ------------------------------------------------------------------
// static namespace subtle {
TimeTicks TimeTicks::Now() { TimeTicks TimeTicksNowIgnoringOverride() {
return TimeTicks(ClockNow(CLOCK_MONOTONIC)); return TimeTicks() + TimeDelta::FromMicroseconds(ClockNow(CLOCK_MONOTONIC));
} }
} // namespace subtle
// static // static
TimeTicks::Clock TimeTicks::GetClock() { TimeTicks::Clock TimeTicks::GetClock() {
...@@ -102,15 +105,19 @@ bool TimeTicks::IsConsistentAcrossProcesses() { ...@@ -102,15 +105,19 @@ bool TimeTicks::IsConsistentAcrossProcesses() {
return true; return true;
} }
// static // ThreadTicks ----------------------------------------------------------------
ThreadTicks ThreadTicks::Now() {
namespace subtle {
ThreadTicks ThreadTicksNowIgnoringOverride() {
#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ #if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
defined(OS_ANDROID) defined(OS_ANDROID)
return ThreadTicks(ClockNow(CLOCK_THREAD_CPUTIME_ID)); return ThreadTicks() +
TimeDelta::FromMicroseconds(ClockNow(CLOCK_THREAD_CPUTIME_ID));
#else #else
NOTREACHED(); NOTREACHED();
return ThreadTicks(); return ThreadTicks();
#endif #endif
} }
} // namespace subtle
} // namespace base } // namespace base
// Copyright 2018 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/time/time_override.h"
namespace base {
namespace subtle {
#if DCHECK_IS_ON()
// static
bool ScopedTimeClockOverrides::overrides_active_ = false;
#endif
ScopedTimeClockOverrides::ScopedTimeClockOverrides(
TimeNowFunction time_override,
TimeTicksNowFunction time_ticks_override,
ThreadTicksNowFunction thread_ticks_override) {
#if DCHECK_IS_ON()
DCHECK(!overrides_active_);
overrides_active_ = true;
#endif
if (time_override) {
internal::g_time_now_function = time_override;
internal::g_time_now_from_system_time_function = time_override;
}
if (time_ticks_override)
internal::g_time_ticks_now_function = time_ticks_override;
if (thread_ticks_override)
internal::g_thread_ticks_now_function = thread_ticks_override;
}
ScopedTimeClockOverrides::~ScopedTimeClockOverrides() {
internal::g_time_now_function = &TimeNowIgnoringOverride;
internal::g_time_now_from_system_time_function =
&TimeNowFromSystemTimeIgnoringOverride;
internal::g_time_ticks_now_function = &TimeTicksNowIgnoringOverride;
internal::g_thread_ticks_now_function = &ThreadTicksNowIgnoringOverride;
#if DCHECK_IS_ON()
overrides_active_ = false;
#endif
}
} // namespace subtle
} // namespace base
// Copyright 2018 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.
#ifndef BASE_TIME_TIME_OVERRIDE_H_
#define BASE_TIME_TIME_OVERRIDE_H_
#include "base/base_export.h"
#include "base/time/time.h"
namespace base {
using TimeNowFunction = decltype(&Time::Now);
using TimeTicksNowFunction = decltype(&TimeTicks::Now);
using ThreadTicksNowFunction = decltype(&ThreadTicks::Now);
// Time overrides should be used with extreme caution. Discuss with //base/time
// OWNERS before adding a new one.
namespace subtle {
// Override the return value of Time::Now and Time::NowFromSystemTime /
// TimeTicks::Now / ThreadTicks::Now to emulate time, e.g. for tests or to
// modify progression of time. Note that the override should be set while
// single-threaded and before the first call to Now() to avoid threading issues
// and inconsistencies in returned values. Nested overrides are not allowed.
class BASE_EXPORT ScopedTimeClockOverrides {
public:
// Pass |nullptr| for any override if it shouldn't be overriden.
ScopedTimeClockOverrides(TimeNowFunction time_override,
TimeTicksNowFunction time_ticks_override,
ThreadTicksNowFunction thread_ticks_override);
// Restores the platform default Now() functions.
~ScopedTimeClockOverrides();
private:
#if DCHECK_IS_ON()
static bool overrides_active_;
#endif
DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedTimeClockOverrides);
};
// These methods return the platform default Time::Now / TimeTicks::Now /
// ThreadTicks::Now values even while an override is in place. These methods
// should only be used in places where emulated time should be disregarded. For
// example, they can be used to implement test timeouts for tests that may
// override time.
BASE_EXPORT Time TimeNowIgnoringOverride();
BASE_EXPORT Time TimeNowFromSystemTimeIgnoringOverride();
BASE_EXPORT TimeTicks TimeTicksNowIgnoringOverride();
BASE_EXPORT ThreadTicks ThreadTicksNowIgnoringOverride();
} // namespace subtle
namespace internal {
// These function pointers are used by platform-independent implementations of
// the Now() methods and ScopedTimeClockOverrides. They are set to point to the
// respective NowIgnoringOverride functions by default, but can also be set by
// platform-specific code to select a default implementation at runtime, thereby
// avoiding the indirection via the NowIgnoringOverride functions. Note that the
// pointers can be overridden and later reset to the NowIgnoringOverride
// functions by ScopedTimeClockOverrides.
extern TimeNowFunction g_time_now_function;
extern TimeNowFunction g_time_now_from_system_time_function;
extern TimeTicksNowFunction g_time_ticks_now_function;
extern ThreadTicksNowFunction g_thread_ticks_now_function;
} // namespace internal
} // namespace base
#endif // BASE_TIME_TIME_OVERRIDE_H_
...@@ -9,11 +9,13 @@ ...@@ -9,11 +9,13 @@
#include <limits> #include <limits>
#include <string> #include <string>
#include "base/build_time.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
#include "base/time/time_override.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -750,6 +752,73 @@ TEST_F(TimeTest, FromExploded_MinMax) { ...@@ -750,6 +752,73 @@ TEST_F(TimeTest, FromExploded_MinMax) {
} }
} }
class TimeOverride {
public:
static Time Now() {
now_time_ += TimeDelta::FromSeconds(1);
return now_time_;
}
static Time now_time_;
};
// static
Time TimeOverride::now_time_;
TEST_F(TimeTest, NowOverride) {
TimeOverride::now_time_ = Time::UnixEpoch();
// Choose a reference time that we know to be in the past but close to now.
Time build_time = GetBuildTime();
// Override is not active. All Now() methods should return a time greater than
// the build time.
EXPECT_LT(build_time, Time::Now());
EXPECT_GT(Time::Max(), Time::Now());
EXPECT_LT(build_time, subtle::TimeNowIgnoringOverride());
EXPECT_GT(Time::Max(), subtle::TimeNowIgnoringOverride());
EXPECT_LT(build_time, Time::NowFromSystemTime());
EXPECT_GT(Time::Max(), Time::NowFromSystemTime());
EXPECT_LT(build_time, subtle::TimeNowFromSystemTimeIgnoringOverride());
EXPECT_GT(Time::Max(), subtle::TimeNowFromSystemTimeIgnoringOverride());
{
// Set override.
subtle::ScopedTimeClockOverrides overrides(&TimeOverride::Now, nullptr,
nullptr);
// Overridden value is returned and incremented when Now() or
// NowFromSystemTime() is called.
EXPECT_EQ(Time::UnixEpoch() + TimeDelta::FromSeconds(1), Time::Now());
EXPECT_EQ(Time::UnixEpoch() + TimeDelta::FromSeconds(2), Time::Now());
EXPECT_EQ(Time::UnixEpoch() + TimeDelta::FromSeconds(3),
Time::NowFromSystemTime());
EXPECT_EQ(Time::UnixEpoch() + TimeDelta::FromSeconds(4),
Time::NowFromSystemTime());
// IgnoringOverride methods still return real time.
EXPECT_LT(build_time, subtle::TimeNowIgnoringOverride());
EXPECT_GT(Time::Max(), subtle::TimeNowIgnoringOverride());
EXPECT_LT(build_time, subtle::TimeNowFromSystemTimeIgnoringOverride());
EXPECT_GT(Time::Max(), subtle::TimeNowFromSystemTimeIgnoringOverride());
// IgnoringOverride methods didn't call NowOverrideClock::Now().
EXPECT_EQ(Time::UnixEpoch() + TimeDelta::FromSeconds(5), Time::Now());
EXPECT_EQ(Time::UnixEpoch() + TimeDelta::FromSeconds(6),
Time::NowFromSystemTime());
}
// All methods return real time again.
EXPECT_LT(build_time, Time::Now());
EXPECT_GT(Time::Max(), Time::Now());
EXPECT_LT(build_time, subtle::TimeNowIgnoringOverride());
EXPECT_GT(Time::Max(), subtle::TimeNowIgnoringOverride());
EXPECT_LT(build_time, Time::NowFromSystemTime());
EXPECT_GT(Time::Max(), Time::NowFromSystemTime());
EXPECT_LT(build_time, subtle::TimeNowFromSystemTimeIgnoringOverride());
EXPECT_GT(Time::Max(), subtle::TimeNowFromSystemTimeIgnoringOverride());
}
TEST(TimeTicks, Deltas) { TEST(TimeTicks, Deltas) {
for (int index = 0; index < 50; index++) { for (int index = 0; index < 50; index++) {
TimeTicks ticks_start = TimeTicks::Now(); TimeTicks ticks_start = TimeTicks::Now();
...@@ -818,6 +887,109 @@ TEST(TimeTicks, HighRes) { ...@@ -818,6 +887,109 @@ TEST(TimeTicks, HighRes) {
HighResClockTest(&TimeTicks::Now); HighResClockTest(&TimeTicks::Now);
} }
class TimeTicksOverride {
public:
static TimeTicks Now() {
now_ticks_ += TimeDelta::FromSeconds(1);
return now_ticks_;
}
static TimeTicks now_ticks_;
};
// static
TimeTicks TimeTicksOverride::now_ticks_;
TEST(TimeTicks, NowOverride) {
TimeTicksOverride::now_ticks_ = TimeTicks::Min();
// Override is not active. All Now() methods should return a sensible value.
EXPECT_LT(TimeTicks::Min(), TimeTicks::UnixEpoch());
EXPECT_LT(TimeTicks::UnixEpoch(), TimeTicks::Now());
EXPECT_GT(TimeTicks::Max(), TimeTicks::Now());
EXPECT_LT(TimeTicks::UnixEpoch(), subtle::TimeTicksNowIgnoringOverride());
EXPECT_GT(TimeTicks::Max(), subtle::TimeTicksNowIgnoringOverride());
{
// Set override.
subtle::ScopedTimeClockOverrides overrides(nullptr, &TimeTicksOverride::Now,
nullptr);
// Overridden value is returned and incremented when Now() is called.
EXPECT_EQ(TimeTicks::Min() + TimeDelta::FromSeconds(1), TimeTicks::Now());
EXPECT_EQ(TimeTicks::Min() + TimeDelta::FromSeconds(2), TimeTicks::Now());
// NowIgnoringOverride() still returns real ticks.
EXPECT_LT(TimeTicks::UnixEpoch(), subtle::TimeTicksNowIgnoringOverride());
EXPECT_GT(TimeTicks::Max(), subtle::TimeTicksNowIgnoringOverride());
// IgnoringOverride methods didn't call NowOverrideTickClock::NowTicks().
EXPECT_EQ(TimeTicks::Min() + TimeDelta::FromSeconds(3), TimeTicks::Now());
}
// All methods return real ticks again.
EXPECT_LT(TimeTicks::UnixEpoch(), TimeTicks::Now());
EXPECT_GT(TimeTicks::Max(), TimeTicks::Now());
EXPECT_LT(TimeTicks::UnixEpoch(), subtle::TimeTicksNowIgnoringOverride());
EXPECT_GT(TimeTicks::Max(), subtle::TimeTicksNowIgnoringOverride());
}
class ThreadTicksOverride {
public:
static ThreadTicks Now() {
now_ticks_ += TimeDelta::FromSeconds(1);
return now_ticks_;
}
static ThreadTicks now_ticks_;
};
// static
ThreadTicks ThreadTicksOverride::now_ticks_;
// IOS doesn't support ThreadTicks::Now().
#if defined(OS_IOS)
#define MAYBE_NowOverride DISABLED_NowOverride
#else
#define MAYBE_NowOverride NowOverride
#endif
TEST(ThreadTicks, MAYBE_NowOverride) {
ThreadTicksOverride::now_ticks_ = ThreadTicks::Min();
// Override is not active. All Now() methods should return a sensible value.
ThreadTicks initial_thread_ticks = ThreadTicks::Now();
EXPECT_LE(initial_thread_ticks, ThreadTicks::Now());
EXPECT_GT(ThreadTicks::Max(), ThreadTicks::Now());
EXPECT_LE(initial_thread_ticks, subtle::ThreadTicksNowIgnoringOverride());
EXPECT_GT(ThreadTicks::Max(), subtle::ThreadTicksNowIgnoringOverride());
{
// Set override.
subtle::ScopedTimeClockOverrides overrides(nullptr, nullptr,
&ThreadTicksOverride::Now);
// Overridden value is returned and incremented when Now() is called.
EXPECT_EQ(ThreadTicks::Min() + TimeDelta::FromSeconds(1),
ThreadTicks::Now());
EXPECT_EQ(ThreadTicks::Min() + TimeDelta::FromSeconds(2),
ThreadTicks::Now());
// NowIgnoringOverride() still returns real ticks.
EXPECT_LE(initial_thread_ticks, subtle::ThreadTicksNowIgnoringOverride());
EXPECT_GT(ThreadTicks::Max(), subtle::ThreadTicksNowIgnoringOverride());
// IgnoringOverride methods didn't call NowOverrideTickClock::NowTicks().
EXPECT_EQ(ThreadTicks::Min() + TimeDelta::FromSeconds(3),
ThreadTicks::Now());
}
// All methods return real ticks again.
EXPECT_LE(initial_thread_ticks, ThreadTicks::Now());
EXPECT_GT(ThreadTicks::Max(), ThreadTicks::Now());
EXPECT_LE(initial_thread_ticks, subtle::ThreadTicksNowIgnoringOverride());
EXPECT_GT(ThreadTicks::Max(), subtle::ThreadTicksNowIgnoringOverride());
}
// Fails frequently on Android http://crbug.com/352633 with: // Fails frequently on Android http://crbug.com/352633 with:
// Expected: (delta_thread.InMicroseconds()) > (0), actual: 0 vs 0 // Expected: (delta_thread.InMicroseconds()) > (0), actual: 0 vs 0
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment