aboutsummaryrefslogtreecommitdiff
path: root/third_party/chromium/base/time
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/chromium/base/time')
-rw-r--r--third_party/chromium/base/time/clock.cc11
-rw-r--r--third_party/chromium/base/time/clock.h40
-rw-r--r--third_party/chromium/base/time/default_clock.cc15
-rw-r--r--third_party/chromium/base/time/default_clock.h25
-rw-r--r--third_party/chromium/base/time/time.cc325
-rw-r--r--third_party/chromium/base/time/time.h784
-rw-r--r--third_party/chromium/base/time/time_posix.cc368
-rw-r--r--third_party/chromium/base/time/time_unittest.cc848
8 files changed, 2416 insertions, 0 deletions
diff --git a/third_party/chromium/base/time/clock.cc b/third_party/chromium/base/time/clock.cc
new file mode 100644
index 0000000..34dc37e
--- /dev/null
+++ b/third_party/chromium/base/time/clock.cc
@@ -0,0 +1,11 @@
+// Copyright (c) 2012 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/clock.h"
+
+namespace base {
+
+Clock::~Clock() {}
+
+} // namespace base
diff --git a/third_party/chromium/base/time/clock.h b/third_party/chromium/base/time/clock.h
new file mode 100644
index 0000000..507a850
--- /dev/null
+++ b/third_party/chromium/base/time/clock.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 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_CLOCK_H_
+#define BASE_TIME_CLOCK_H_
+
+#include "base/base_export.h"
+#include "base/time/time.h"
+
+namespace base {
+
+// A Clock is an interface for objects that vend Times. It is
+// intended to be able to test the behavior of classes with respect to
+// time.
+//
+// See DefaultClock (base/time/default_clock.h) for the default
+// implementation that simply uses Time::Now().
+//
+// (An implementation that uses Time::SystemTime() should be added as
+// needed.)
+//
+// See SimpleTestClock (base/test/simple_test_clock.h) for a simple
+// test implementation.
+//
+// See TickClock (base/time/tick_clock.h) for the equivalent interface for
+// TimeTicks.
+class BASE_EXPORT Clock {
+ public:
+ virtual ~Clock();
+
+ // Now() must be safe to call from any thread. The caller cannot
+ // make any ordering assumptions about the returned Time. For
+ // example, the system clock may change to an earlier time.
+ virtual Time Now() = 0;
+};
+
+} // namespace base
+
+#endif // BASE_TIME_CLOCK_H_
diff --git a/third_party/chromium/base/time/default_clock.cc b/third_party/chromium/base/time/default_clock.cc
new file mode 100644
index 0000000..5f70114
--- /dev/null
+++ b/third_party/chromium/base/time/default_clock.cc
@@ -0,0 +1,15 @@
+// Copyright (c) 2012 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/default_clock.h"
+
+namespace base {
+
+DefaultClock::~DefaultClock() {}
+
+Time DefaultClock::Now() {
+ return Time::Now();
+}
+
+} // namespace base
diff --git a/third_party/chromium/base/time/default_clock.h b/third_party/chromium/base/time/default_clock.h
new file mode 100644
index 0000000..140e6f4
--- /dev/null
+++ b/third_party/chromium/base/time/default_clock.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2012 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_DEFAULT_CLOCK_H_
+#define BASE_TIME_DEFAULT_CLOCK_H_
+
+#include "base/base_export.h"
+#include "base/compiler_specific.h"
+#include "base/time/clock.h"
+
+namespace base {
+
+// DefaultClock is a Clock implementation that uses Time::Now().
+class DefaultClock : public Clock {
+ public:
+ ~DefaultClock() override;
+
+ // Simply returns Time::Now().
+ Time Now() override;
+};
+
+} // namespace base
+
+#endif // BASE_TIME_DEFAULT_CLOCK_H_
diff --git a/third_party/chromium/base/time/time.cc b/third_party/chromium/base/time/time.cc
new file mode 100644
index 0000000..7006407
--- /dev/null
+++ b/third_party/chromium/base/time/time.cc
@@ -0,0 +1,325 @@
+// Copyright (c) 2012 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.h"
+
+#include <cmath>
+#include <ios>
+#include <limits>
+#include <ostream>
+#include <sstream>
+
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+
+namespace base {
+
+// TimeDelta ------------------------------------------------------------------
+
+// static
+TimeDelta TimeDelta::Max() {
+ return TimeDelta(std::numeric_limits<int64>::max());
+}
+
+int TimeDelta::InDays() const {
+ if (is_max()) {
+ // Preserve max to prevent overflow.
+ return std::numeric_limits<int>::max();
+ }
+ return static_cast<int>(delta_ / Time::kMicrosecondsPerDay);
+}
+
+int TimeDelta::InHours() const {
+ if (is_max()) {
+ // Preserve max to prevent overflow.
+ return std::numeric_limits<int>::max();
+ }
+ return static_cast<int>(delta_ / Time::kMicrosecondsPerHour);
+}
+
+int TimeDelta::InMinutes() const {
+ if (is_max()) {
+ // Preserve max to prevent overflow.
+ return std::numeric_limits<int>::max();
+ }
+ return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute);
+}
+
+double TimeDelta::InSecondsF() const {
+ if (is_max()) {
+ // Preserve max to prevent overflow.
+ return std::numeric_limits<double>::infinity();
+ }
+ return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond;
+}
+
+int64 TimeDelta::InSeconds() const {
+ if (is_max()) {
+ // Preserve max to prevent overflow.
+ return std::numeric_limits<int64>::max();
+ }
+ return delta_ / Time::kMicrosecondsPerSecond;
+}
+
+double TimeDelta::InMillisecondsF() const {
+ if (is_max()) {
+ // Preserve max to prevent overflow.
+ return std::numeric_limits<double>::infinity();
+ }
+ return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond;
+}
+
+int64 TimeDelta::InMilliseconds() const {
+ if (is_max()) {
+ // Preserve max to prevent overflow.
+ return std::numeric_limits<int64>::max();
+ }
+ return delta_ / Time::kMicrosecondsPerMillisecond;
+}
+
+int64 TimeDelta::InMillisecondsRoundedUp() const {
+ if (is_max()) {
+ // Preserve max to prevent overflow.
+ return std::numeric_limits<int64>::max();
+ }
+ return (delta_ + Time::kMicrosecondsPerMillisecond - 1) /
+ Time::kMicrosecondsPerMillisecond;
+}
+
+int64 TimeDelta::InMicroseconds() const {
+ if (is_max()) {
+ // Preserve max to prevent overflow.
+ return std::numeric_limits<int64>::max();
+ }
+ return delta_;
+}
+
+namespace time_internal {
+
+int64 SaturatedAdd(TimeDelta delta, int64 value) {
+ CheckedNumeric<int64> rv(delta.delta_);
+ rv += value;
+ return FromCheckedNumeric(rv);
+}
+
+int64 SaturatedSub(TimeDelta delta, int64 value) {
+ CheckedNumeric<int64> rv(delta.delta_);
+ rv -= value;
+ return FromCheckedNumeric(rv);
+}
+
+int64 FromCheckedNumeric(const CheckedNumeric<int64> value) {
+ if (value.IsValid())
+ return value.ValueUnsafe();
+
+ // We could return max/min but we don't really expose what the maximum delta
+ // is. Instead, return max/(-max), which is something that clients can reason
+ // about.
+ // TODO(rvargas) crbug.com/332611: don't use internal values.
+ int64 limit = std::numeric_limits<int64>::max();
+ if (value.validity() == internal::RANGE_UNDERFLOW)
+ limit = -limit;
+ return value.ValueOrDefault(limit);
+}
+
+} // namespace time_internal
+
+std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) {
+ return os << time_delta.InSecondsF() << "s";
+}
+
+// Time -----------------------------------------------------------------------
+
+// static
+Time Time::Max() {
+ return Time(std::numeric_limits<int64>::max());
+}
+
+// static
+Time Time::FromTimeT(time_t tt) {
+ if (tt == 0)
+ return Time(); // Preserve 0 so we can tell it doesn't exist.
+ if (tt == std::numeric_limits<time_t>::max())
+ return Max();
+ return Time((tt * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset);
+}
+
+time_t Time::ToTimeT() const {
+ if (is_null())
+ return 0; // Preserve 0 so we can tell it doesn't exist.
+ if (is_max()) {
+ // Preserve max without offset to prevent overflow.
+ return std::numeric_limits<time_t>::max();
+ }
+ if (std::numeric_limits<int64>::max() - kTimeTToMicrosecondsOffset <= us_) {
+ DLOG(WARNING) << "Overflow when converting base::Time with internal " <<
+ "value " << us_ << " to time_t.";
+ return std::numeric_limits<time_t>::max();
+ }
+ return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond;
+}
+
+// static
+Time Time::FromDoubleT(double dt) {
+ if (dt == 0 || std::isnan(dt))
+ return Time(); // Preserve 0 so we can tell it doesn't exist.
+ if (dt == std::numeric_limits<double>::infinity())
+ return Max();
+ return Time(static_cast<int64>((dt *
+ static_cast<double>(kMicrosecondsPerSecond)) +
+ kTimeTToMicrosecondsOffset));
+}
+
+double Time::ToDoubleT() const {
+ if (is_null())
+ return 0; // Preserve 0 so we can tell it doesn't exist.
+ if (is_max()) {
+ // Preserve max without offset to prevent overflow.
+ return std::numeric_limits<double>::infinity();
+ }
+ return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
+ static_cast<double>(kMicrosecondsPerSecond));
+}
+
+#if defined(OS_POSIX)
+// static
+Time Time::FromTimeSpec(const timespec& ts) {
+ return FromDoubleT(ts.tv_sec +
+ static_cast<double>(ts.tv_nsec) /
+ base::Time::kNanosecondsPerSecond);
+}
+#endif
+
+// static
+Time Time::FromJsTime(double ms_since_epoch) {
+ // The epoch is a valid time, so this constructor doesn't interpret
+ // 0 as the null time.
+ if (ms_since_epoch == std::numeric_limits<double>::infinity())
+ return Max();
+ return Time(static_cast<int64>(ms_since_epoch * kMicrosecondsPerMillisecond) +
+ kTimeTToMicrosecondsOffset);
+}
+
+double Time::ToJsTime() const {
+ if (is_null()) {
+ // Preserve 0 so the invalid result doesn't depend on the platform.
+ return 0;
+ }
+ if (is_max()) {
+ // Preserve max without offset to prevent overflow.
+ return std::numeric_limits<double>::infinity();
+ }
+ return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
+ kMicrosecondsPerMillisecond);
+}
+
+int64 Time::ToJavaTime() const {
+ if (is_null()) {
+ // Preserve 0 so the invalid result doesn't depend on the platform.
+ return 0;
+ }
+ if (is_max()) {
+ // Preserve max without offset to prevent overflow.
+ return std::numeric_limits<int64>::max();
+ }
+ return ((us_ - kTimeTToMicrosecondsOffset) /
+ kMicrosecondsPerMillisecond);
+}
+
+// static
+Time Time::UnixEpoch() {
+ Time time;
+ time.us_ = kTimeTToMicrosecondsOffset;
+ return time;
+}
+
+Time Time::LocalMidnight() const {
+ Exploded exploded;
+ LocalExplode(&exploded);
+ exploded.hour = 0;
+ exploded.minute = 0;
+ exploded.second = 0;
+ exploded.millisecond = 0;
+ return FromLocalExploded(exploded);
+}
+
+std::ostream& operator<<(std::ostream& os, Time time) {
+ Time::Exploded exploded;
+ time.UTCExplode(&exploded);
+ // Use StringPrintf because iostreams formatting is painful.
+ return os << StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d UTC",
+ exploded.year,
+ exploded.month,
+ exploded.day_of_month,
+ exploded.hour,
+ exploded.minute,
+ exploded.second,
+ exploded.millisecond);
+}
+
+// Local helper class to hold the conversion from Time to TickTime at the
+// time of the Unix epoch.
+class UnixEpochSingleton {
+ public:
+ UnixEpochSingleton()
+ : unix_epoch_(TimeTicks::Now() - (Time::Now() - Time::UnixEpoch())) {}
+
+ TimeTicks unix_epoch() const { return unix_epoch_; }
+
+ private:
+ const TimeTicks unix_epoch_;
+
+ DISALLOW_COPY_AND_ASSIGN(UnixEpochSingleton);
+};
+
+TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase,
+ TimeDelta tick_interval) const {
+ // |interval_offset| is the offset from |this| to the next multiple of
+ // |tick_interval| after |tick_phase|, possibly negative if in the past.
+ TimeDelta interval_offset = (tick_phase - *this) % tick_interval;
+ // If |this| is exactly on the interval (i.e. offset==0), don't adjust.
+ // Otherwise, if |tick_phase| was in the past, adjust forward to the next
+ // tick after |this|.
+ if (!interval_offset.is_zero() && tick_phase < *this)
+ interval_offset += tick_interval;
+ return *this + interval_offset;
+}
+
+std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
+ // This function formats a TimeTicks object as "bogo-microseconds".
+ // The origin and granularity of the count are platform-specific, and may very
+ // from run to run. Although bogo-microseconds usually roughly correspond to
+ // real microseconds, the only real guarantee is that the number never goes
+ // down during a single run.
+ const TimeDelta as_time_delta = time_ticks - TimeTicks();
+ return os << as_time_delta.InMicroseconds() << " bogo-microseconds";
+}
+
+std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) {
+ const TimeDelta as_time_delta = thread_ticks - ThreadTicks();
+ return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds";
+}
+
+std::ostream& operator<<(std::ostream& os, TraceTicks trace_ticks) {
+ const TimeDelta as_time_delta = trace_ticks - TraceTicks();
+ return os << as_time_delta.InMicroseconds() << " bogo-trace-microseconds";
+}
+
+// Time::Exploded -------------------------------------------------------------
+
+inline bool is_in_range(int value, int lo, int hi) {
+ return lo <= value && value <= hi;
+}
+
+bool Time::Exploded::HasValidValues() const {
+ return is_in_range(month, 1, 12) &&
+ is_in_range(day_of_week, 0, 6) &&
+ is_in_range(day_of_month, 1, 31) &&
+ is_in_range(hour, 0, 23) &&
+ is_in_range(minute, 0, 59) &&
+ is_in_range(second, 0, 60) &&
+ is_in_range(millisecond, 0, 999);
+}
+
+} // namespace base
diff --git a/third_party/chromium/base/time/time.h b/third_party/chromium/base/time/time.h
new file mode 100644
index 0000000..f421539
--- /dev/null
+++ b/third_party/chromium/base/time/time.h
@@ -0,0 +1,784 @@
+// Copyright (c) 2012 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.
+
+// Time represents an absolute point in coordinated universal time (UTC),
+// internally represented as microseconds (s/1,000,000) since the Windows epoch
+// (1601-01-01 00:00:00 UTC). System-dependent clock interface routines are
+// defined in time_PLATFORM.cc. Note that values for Time may skew and jump
+// around as the operating system makes adjustments to synchronize (e.g., with
+// NTP servers). Thus, client code that uses the Time class must account for
+// this.
+//
+// TimeDelta represents a duration of time, internally represented in
+// microseconds.
+//
+// TimeTicks, ThreadTicks, and TraceTicks represent an abstract time that is
+// most of the time incrementing, for use in measuring time durations.
+// Internally, they are represented in microseconds. They can not be converted
+// to a human-readable time, but are guaranteed not to decrease (unlike the Time
+// class). Note that TimeTicks may "stand still" (e.g., if the computer is
+// suspended), and ThreadTicks will "stand still" whenever the thread has been
+// de-scheduled by the operating system.
+//
+// All time classes are copyable, assignable, and occupy 64-bits per
+// instance. Thus, they can be efficiently passed by-value (as opposed to
+// by-reference).
+//
+// Definitions of operator<< are provided to make these types work with
+// DCHECK_EQ() and other log macros. For human-readable formatting, see
+// "base/i18n/time_formatting.h".
+//
+// So many choices! Which time class should you use? Examples:
+//
+// Time: Interpreting the wall-clock time provided by a remote
+// system. Detecting whether cached resources have
+// expired. Providing the user with a display of the current date
+// and time. Determining the amount of time between events across
+// re-boots of the machine.
+//
+// TimeTicks: Tracking the amount of time a task runs. Executing delayed
+// tasks at the right time. Computing presentation timestamps.
+// Synchronizing audio and video using TimeTicks as a common
+// reference clock (lip-sync). Measuring network round-trip
+// latency.
+//
+// ThreadTicks: Benchmarking how long the current thread has been doing actual
+// work.
+//
+// TraceTicks: This is only meant to be used by the event tracing
+// infrastructure, and by outside code modules in special
+// circumstances. Please be sure to consult a
+// base/trace_event/OWNER before committing any new code that
+// uses this.
+
+#ifndef BASE_TIME_TIME_H_
+#define BASE_TIME_TIME_H_
+
+#include <time.h>
+
+#include <iosfwd>
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/build/build_config.h"
+#include "base/numerics/safe_math.h"
+
+#if defined(OS_MACOSX)
+#include <CoreFoundation/CoreFoundation.h>
+// Avoid Mac system header macro leak.
+#undef TYPE_BOOL
+#endif
+
+#if defined(OS_POSIX)
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+
+#if defined(OS_WIN)
+// For FILETIME in FromFileTime, until it moves to a new converter class.
+// See TODO(iyengar) below.
+#include <windows.h>
+#endif
+
+#include <limits>
+
+namespace base {
+
+class TimeDelta;
+
+// The functions in the time_internal namespace are meant to be used only by the
+// time classes and functions. Please use the math operators defined in the
+// time classes instead.
+namespace time_internal {
+
+// Add or subtract |value| from a TimeDelta. The int64 argument and return value
+// are in terms of a microsecond timebase.
+BASE_EXPORT int64 SaturatedAdd(TimeDelta delta, int64 value);
+BASE_EXPORT int64 SaturatedSub(TimeDelta delta, int64 value);
+
+// Clamp |value| on overflow and underflow conditions. The int64 argument and
+// return value are in terms of a microsecond timebase.
+BASE_EXPORT int64 FromCheckedNumeric(const CheckedNumeric<int64> value);
+
+} // namespace time_internal
+
+// TimeDelta ------------------------------------------------------------------
+
+class BASE_EXPORT TimeDelta {
+ public:
+ TimeDelta() : delta_(0) {
+ }
+
+ // Converts units of time to TimeDeltas.
+ static TimeDelta FromDays(int days);
+ static TimeDelta FromHours(int hours);
+ static TimeDelta FromMinutes(int minutes);
+ static TimeDelta FromSeconds(int64 secs);
+ static TimeDelta FromMilliseconds(int64 ms);
+ static TimeDelta FromSecondsD(double secs);
+ static TimeDelta FromMillisecondsD(double ms);
+ static TimeDelta FromMicroseconds(int64 us);
+#if defined(OS_WIN)
+ static TimeDelta FromQPCValue(LONGLONG qpc_value);
+#endif
+
+ // Converts an integer value representing TimeDelta to a class. This is used
+ // when deserializing a |TimeDelta| structure, using a value known to be
+ // compatible. It is not provided as a constructor because the integer type
+ // may be unclear from the perspective of a caller.
+ static TimeDelta FromInternalValue(int64 delta) {
+ return TimeDelta(delta);
+ }
+
+ // Returns the maximum time delta, which should be greater than any reasonable
+ // time delta we might compare it to. Adding or subtracting the maximum time
+ // delta to a time or another time delta has an undefined result.
+ static TimeDelta Max();
+
+ // Returns the internal numeric value of the TimeDelta object. Please don't
+ // use this and do arithmetic on it, as it is more error prone than using the
+ // provided operators.
+ // For serializing, use FromInternalValue to reconstitute.
+ int64 ToInternalValue() const {
+ return delta_;
+ }
+
+ // Returns the magnitude (absolute value) of this TimeDelta.
+ TimeDelta magnitude() const {
+ // Some toolchains provide an incomplete C++11 implementation and lack an
+ // int64 overload for std::abs(). The following is a simple branchless
+ // implementation:
+ const int64 mask = delta_ >> (sizeof(delta_) * 8 - 1);
+ return TimeDelta((delta_ + mask) ^ mask);
+ }
+
+ // Returns true if the time delta is zero.
+ bool is_zero() const {
+ return delta_ == 0;
+ }
+
+ // Returns true if the time delta is the maximum time delta.
+ bool is_max() const {
+ return delta_ == std::numeric_limits<int64>::max();
+ }
+
+#if defined(OS_POSIX)
+ struct timespec ToTimeSpec() const;
+#endif
+
+ // Returns the time delta in some unit. The F versions return a floating
+ // point value, the "regular" versions return a rounded-down value.
+ //
+ // InMillisecondsRoundedUp() instead returns an integer that is rounded up
+ // to the next full millisecond.
+ int InDays() const;
+ int InHours() const;
+ int InMinutes() const;
+ double InSecondsF() const;
+ int64 InSeconds() const;
+ double InMillisecondsF() const;
+ int64 InMilliseconds() const;
+ int64 InMillisecondsRoundedUp() const;
+ int64 InMicroseconds() const;
+
+ TimeDelta& operator=(TimeDelta other) {
+ delta_ = other.delta_;
+ return *this;
+ }
+
+ // Computations with other deltas.
+ TimeDelta operator+(TimeDelta other) const {
+ return TimeDelta(time_internal::SaturatedAdd(*this, other.delta_));
+ }
+ TimeDelta operator-(TimeDelta other) const {
+ return TimeDelta(time_internal::SaturatedSub(*this, other.delta_));
+ }
+
+ TimeDelta& operator+=(TimeDelta other) {
+ return *this = (*this + other);
+ }
+ TimeDelta& operator-=(TimeDelta other) {
+ return *this = (*this - other);
+ }
+ TimeDelta operator-() const {
+ return TimeDelta(-delta_);
+ }
+
+ // Computations with numeric types.
+ template<typename T>
+ TimeDelta operator*(T a) const {
+ CheckedNumeric<int64> rv(delta_);
+ rv *= a;
+ return TimeDelta(time_internal::FromCheckedNumeric(rv));
+ }
+ template<typename T>
+ TimeDelta operator/(T a) const {
+ CheckedNumeric<int64> rv(delta_);
+ rv /= a;
+ return TimeDelta(time_internal::FromCheckedNumeric(rv));
+ }
+ template<typename T>
+ TimeDelta& operator*=(T a) {
+ return *this = (*this * a);
+ }
+ template<typename T>
+ TimeDelta& operator/=(T a) {
+ return *this = (*this / a);
+ }
+
+ int64 operator/(TimeDelta a) const {
+ return delta_ / a.delta_;
+ }
+ TimeDelta operator%(TimeDelta a) const {
+ return TimeDelta(delta_ % a.delta_);
+ }
+
+ // Comparison operators.
+ bool operator==(TimeDelta other) const {
+ return delta_ == other.delta_;
+ }
+ bool operator!=(TimeDelta other) const {
+ return delta_ != other.delta_;
+ }
+ bool operator<(TimeDelta other) const {
+ return delta_ < other.delta_;
+ }
+ bool operator<=(TimeDelta other) const {
+ return delta_ <= other.delta_;
+ }
+ bool operator>(TimeDelta other) const {
+ return delta_ > other.delta_;
+ }
+ bool operator>=(TimeDelta other) const {
+ return delta_ >= other.delta_;
+ }
+
+ private:
+ friend int64 time_internal::SaturatedAdd(TimeDelta delta, int64 value);
+ friend int64 time_internal::SaturatedSub(TimeDelta delta, int64 value);
+
+ // Constructs a delta given the duration in microseconds. This is private
+ // to avoid confusion by callers with an integer constructor. Use
+ // FromSeconds, FromMilliseconds, etc. instead.
+ explicit TimeDelta(int64 delta_us) : delta_(delta_us) {
+ }
+
+ // Delta in microseconds.
+ int64 delta_;
+};
+
+template<typename T>
+inline TimeDelta operator*(T a, TimeDelta td) {
+ return td * a;
+}
+
+// For logging use only.
+BASE_EXPORT std::ostream& operator<<(std::ostream& os, TimeDelta time_delta);
+
+// Do not reference the time_internal::TimeBase template class directly. Please
+// use one of the time subclasses instead, and only reference the public
+// TimeBase members via those classes.
+namespace time_internal {
+
+// TimeBase--------------------------------------------------------------------
+
+// Provides value storage and comparison/math operations common to all time
+// classes. Each subclass provides for strong type-checking to ensure
+// semantically meaningful comparison/math of time values from the same clock
+// source or timeline.
+template<class TimeClass>
+class TimeBase {
+ public:
+ static const int64 kHoursPerDay = 24;
+ static const int64 kMillisecondsPerSecond = 1000;
+ static const int64 kMillisecondsPerDay = kMillisecondsPerSecond * 60 * 60 *
+ kHoursPerDay;
+ static const int64 kMicrosecondsPerMillisecond = 1000;
+ static const int64 kMicrosecondsPerSecond = kMicrosecondsPerMillisecond *
+ kMillisecondsPerSecond;
+ static const int64 kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60;
+ static const int64 kMicrosecondsPerHour = kMicrosecondsPerMinute * 60;
+ static const int64 kMicrosecondsPerDay = kMicrosecondsPerHour * kHoursPerDay;
+ static const int64 kMicrosecondsPerWeek = kMicrosecondsPerDay * 7;
+ static const int64 kNanosecondsPerMicrosecond = 1000;
+ static const int64 kNanosecondsPerSecond = kNanosecondsPerMicrosecond *
+ kMicrosecondsPerSecond;
+
+ // Returns true if this object has not been initialized.
+ //
+ // Warning: Be careful when writing code that performs math on time values,
+ // since it's possible to produce a valid "zero" result that should not be
+ // interpreted as a "null" value.
+ bool is_null() const {
+ return us_ == 0;
+ }
+
+ // Returns true if this object represents the maximum time.
+ bool is_max() const {
+ return us_ == std::numeric_limits<int64>::max();
+ }
+
+ // For serializing only. Use FromInternalValue() to reconstitute. Please don't
+ // use this and do arithmetic on it, as it is more error prone than using the
+ // provided operators.
+ int64 ToInternalValue() const {
+ return us_;
+ }
+
+ TimeClass& operator=(TimeClass other) {
+ us_ = other.us_;
+ return *(static_cast<TimeClass*>(this));
+ }
+
+ // Compute the difference between two times.
+ TimeDelta operator-(TimeClass other) const {
+ return TimeDelta::FromMicroseconds(us_ - other.us_);
+ }
+
+ // Return a new time modified by some delta.
+ TimeClass operator+(TimeDelta delta) const {
+ return TimeClass(time_internal::SaturatedAdd(delta, us_));
+ }
+ TimeClass operator-(TimeDelta delta) const {
+ return TimeClass(-time_internal::SaturatedSub(delta, us_));
+ }
+
+ // Modify by some time delta.
+ TimeClass& operator+=(TimeDelta delta) {
+ return static_cast<TimeClass&>(*this = (*this + delta));
+ }
+ TimeClass& operator-=(TimeDelta delta) {
+ return static_cast<TimeClass&>(*this = (*this - delta));
+ }
+
+ // Comparison operators
+ bool operator==(TimeClass other) const {
+ return us_ == other.us_;
+ }
+ bool operator!=(TimeClass other) const {
+ return us_ != other.us_;
+ }
+ bool operator<(TimeClass other) const {
+ return us_ < other.us_;
+ }
+ bool operator<=(TimeClass other) const {
+ return us_ <= other.us_;
+ }
+ bool operator>(TimeClass other) const {
+ return us_ > other.us_;
+ }
+ bool operator>=(TimeClass other) const {
+ return us_ >= other.us_;
+ }
+
+ // Converts an integer value representing TimeClass to a class. This is used
+ // when deserializing a |TimeClass| structure, using a value known to be
+ // compatible. It is not provided as a constructor because the integer type
+ // may be unclear from the perspective of a caller.
+ static TimeClass FromInternalValue(int64 us) {
+ return TimeClass(us);
+ }
+
+ protected:
+ explicit TimeBase(int64 us) : us_(us) {
+ }
+
+ // Time value in a microsecond timebase.
+ int64 us_;
+};
+
+} // namespace time_internal
+
+template<class TimeClass>
+inline TimeClass operator+(TimeDelta delta, TimeClass t) {
+ return t + delta;
+}
+
+// Time -----------------------------------------------------------------------
+
+// Represents a wall clock time in UTC. Values are not guaranteed to be
+// monotonically non-decreasing and are subject to large amounts of skew.
+class BASE_EXPORT Time : public time_internal::TimeBase<Time> {
+ public:
+ // The representation of Jan 1, 1970 UTC in microseconds since the
+ // platform-dependent epoch.
+ static const int64 kTimeTToMicrosecondsOffset;
+
+#if !defined(OS_WIN)
+ // On Mac & Linux, this value is the delta from the Windows epoch of 1601 to
+ // the Posix delta of 1970. This is used for migrating between the old
+ // 1970-based epochs to the new 1601-based ones. It should be removed from
+ // this global header and put in the platform-specific ones when we remove the
+ // migration code.
+ static const int64 kWindowsEpochDeltaMicroseconds;
+#else
+ // To avoid overflow in QPC to Microseconds calculations, since we multiply
+ // by kMicrosecondsPerSecond, then the QPC value should not exceed
+ // (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply.
+ static const int64 kQPCOverflowThreshold = 0x8637BD05AF7;
+#endif
+
+ // Represents an exploded time that can be formatted nicely. This is kind of
+ // like the Win32 SYSTEMTIME structure or the Unix "struct tm" with a few
+ // additions and changes to prevent errors.
+ struct Exploded {
+ int year; // Four digit year "2007"
+ int month; // 1-based month (values 1 = January, etc.)
+ int day_of_week; // 0-based day of week (0 = Sunday, etc.)
+ int day_of_month; // 1-based day of month (1-31)
+ int hour; // Hour within the current day (0-23)
+ int minute; // Minute within the current hour (0-59)
+ int second; // Second within the current minute (0-59 plus leap
+ // seconds which may take it up to 60).
+ int millisecond; // Milliseconds within the current second (0-999)
+
+ // A cursory test for whether the data members are within their
+ // respective ranges. A 'true' return value does not guarantee the
+ // Exploded value can be successfully converted to a Time value.
+ bool HasValidValues() const;
+ };
+
+ // Contains the NULL time. Use Time::Now() to get the current time.
+ Time() : TimeBase(0) {
+ }
+
+ // Returns the time for epoch in Unix-like system (Jan 1, 1970).
+ static Time UnixEpoch();
+
+ // Returns the current time. Watch out, the system might adjust its clock
+ // in which case time will actually go backwards. We don't guarantee that
+ // times are increasing, or that two calls to Now() won't be the same.
+ static Time Now();
+
+ // Returns the maximum time, which should be greater than any reasonable time
+ // with which we might compare it.
+ static Time Max();
+
+ // Returns the current time. Same as Now() except that this function always
+ // uses system time so that there are no discrepancies between the returned
+ // time and system time even on virtual environments including our test bot.
+ // For timing sensitive unittests, this function should be used.
+ static Time NowFromSystemTime();
+
+ // Converts to/from time_t in UTC and a Time class.
+ // TODO(brettw) this should be removed once everybody starts using the |Time|
+ // class.
+ static Time FromTimeT(time_t tt);
+ time_t ToTimeT() const;
+
+ // Converts time to/from a double which is the number of seconds since epoch
+ // (Jan 1, 1970). Webkit uses this format to represent time.
+ // Because WebKit initializes double time value to 0 to indicate "not
+ // initialized", we map it to empty Time object that also means "not
+ // initialized".
+ static Time FromDoubleT(double dt);
+ double ToDoubleT() const;
+
+#if defined(OS_POSIX)
+ // Converts the timespec structure to time. MacOS X 10.8.3 (and tentatively,
+ // earlier versions) will have the |ts|'s tv_nsec component zeroed out,
+ // having a 1 second resolution, which agrees with
+ // https://developer.apple.com/legacy/library/#technotes/tn/tn1150.html#HFSPlusDates.
+ static Time FromTimeSpec(const timespec& ts);
+#endif
+
+ // Converts to/from the Javascript convention for times, a number of
+ // milliseconds since the epoch:
+ // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/getTime.
+ static Time FromJsTime(double ms_since_epoch);
+ double ToJsTime() const;
+
+ // Converts to Java convention for times, a number of
+ // milliseconds since the epoch.
+ int64 ToJavaTime() const;
+
+#if defined(OS_POSIX)
+ static Time FromTimeVal(struct timeval t);
+ struct timeval ToTimeVal() const;
+#endif
+
+#if defined(OS_MACOSX)
+ static Time FromCFAbsoluteTime(CFAbsoluteTime t);
+ CFAbsoluteTime ToCFAbsoluteTime() const;
+#endif
+
+#if defined(OS_WIN)
+ static Time FromFileTime(FILETIME ft);
+ FILETIME ToFileTime() const;
+
+ // The minimum time of a low resolution timer. This is basically a windows
+ // constant of ~15.6ms. While it does vary on some older OS versions, we'll
+ // treat it as static across all windows versions.
+ static const int kMinLowResolutionThresholdMs = 16;
+
+ // Enable or disable Windows high resolution timer.
+ static void EnableHighResolutionTimer(bool enable);
+
+ // Activates or deactivates the high resolution timer based on the |activate|
+ // flag. If the HighResolutionTimer is not Enabled (see
+ // EnableHighResolutionTimer), this function will return false. Otherwise
+ // returns true. Each successful activate call must be paired with a
+ // subsequent deactivate call.
+ // All callers to activate the high resolution timer must eventually call
+ // this function to deactivate the high resolution timer.
+ static bool ActivateHighResolutionTimer(bool activate);
+
+ // Returns true if the high resolution timer is both enabled and activated.
+ // This is provided for testing only, and is not tracked in a thread-safe
+ // way.
+ static bool IsHighResolutionTimerInUse();
+#endif
+
+ // Converts an exploded structure representing either the local time or UTC
+ // into a Time class.
+ static Time FromUTCExploded(const Exploded& exploded) {
+ return FromExploded(false, exploded);
+ }
+ static Time FromLocalExploded(const Exploded& exploded) {
+ return FromExploded(true, exploded);
+ }
+
+ // Fills the given exploded structure with either the local time or UTC from
+ // this time structure (containing UTC).
+ void UTCExplode(Exploded* exploded) const {
+ return Explode(false, exploded);
+ }
+ void LocalExplode(Exploded* exploded) const {
+ return Explode(true, exploded);
+ }
+
+ // Rounds this time down to the nearest day in local time. It will represent
+ // midnight on that day.
+ Time LocalMidnight() const;
+
+ private:
+ friend class time_internal::TimeBase<Time>;
+
+ explicit Time(int64 us) : TimeBase(us) {
+ }
+
+ // Explodes the given time to either local time |is_local = true| or UTC
+ // |is_local = false|.
+ void Explode(bool is_local, Exploded* exploded) const;
+
+ // Unexplodes a given time assuming the source is either local time
+ // |is_local = true| or UTC |is_local = false|.
+ static Time FromExploded(bool is_local, const Exploded& exploded);
+};
+
+// Inline the TimeDelta factory methods, for fast TimeDelta construction.
+
+// static
+inline TimeDelta TimeDelta::FromDays(int days) {
+ // Preserve max to prevent overflow.
+ if (days == std::numeric_limits<int>::max())
+ return Max();
+ return TimeDelta(days * Time::kMicrosecondsPerDay);
+}
+
+// static
+inline TimeDelta TimeDelta::FromHours(int hours) {
+ // Preserve max to prevent overflow.
+ if (hours == std::numeric_limits<int>::max())
+ return Max();
+ return TimeDelta(hours * Time::kMicrosecondsPerHour);
+}
+
+// static
+inline TimeDelta TimeDelta::FromMinutes(int minutes) {
+ // Preserve max to prevent overflow.
+ if (minutes == std::numeric_limits<int>::max())
+ return Max();
+ return TimeDelta(minutes * Time::kMicrosecondsPerMinute);
+}
+
+// static
+inline TimeDelta TimeDelta::FromSeconds(int64 secs) {
+ // Preserve max to prevent overflow.
+ if (secs == std::numeric_limits<int64>::max())
+ return Max();
+ return TimeDelta(secs * Time::kMicrosecondsPerSecond);
+}
+
+// static
+inline TimeDelta TimeDelta::FromMilliseconds(int64 ms) {
+ // Preserve max to prevent overflow.
+ if (ms == std::numeric_limits<int64>::max())
+ return Max();
+ return TimeDelta(ms * Time::kMicrosecondsPerMillisecond);
+}
+
+// static
+inline TimeDelta TimeDelta::FromSecondsD(double secs) {
+ // Preserve max to prevent overflow.
+ if (secs == std::numeric_limits<double>::infinity())
+ return Max();
+ return TimeDelta(static_cast<int64>(secs * Time::kMicrosecondsPerSecond));
+}
+
+// static
+inline TimeDelta TimeDelta::FromMillisecondsD(double ms) {
+ // Preserve max to prevent overflow.
+ if (ms == std::numeric_limits<double>::infinity())
+ return Max();
+ return TimeDelta(static_cast<int64>(ms * Time::kMicrosecondsPerMillisecond));
+}
+
+// static
+inline TimeDelta TimeDelta::FromMicroseconds(int64 us) {
+ // Preserve max to prevent overflow.
+ if (us == std::numeric_limits<int64>::max())
+ return Max();
+ return TimeDelta(us);
+}
+
+// For logging use only.
+BASE_EXPORT std::ostream& operator<<(std::ostream& os, Time time);
+
+// TimeTicks ------------------------------------------------------------------
+
+// Represents monotonically non-decreasing clock time.
+class TimeTicks : public time_internal::TimeBase<TimeTicks> {
+ public:
+ TimeTicks() : TimeBase(0) {
+ }
+
+ // Platform-dependent tick count representing "right now." When
+ // IsHighResolution() returns false, the resolution of the clock could be
+ // as coarse as ~15.6ms. Otherwise, the resolution should be no worse than one
+ // microsecond.
+ static TimeTicks Now();
+
+ // Returns true if the high resolution clock is working on this system and
+ // Now() will return high resolution values. Note that, on systems where the
+ // high resolution clock works but is deemed inefficient, the low resolution
+ // clock will be used instead.
+ static bool IsHighResolution();
+
+#if defined(OS_WIN)
+ // Translates an absolute QPC timestamp into a TimeTicks value. The returned
+ // value has the same origin as Now(). Do NOT attempt to use this if
+ // IsHighResolution() returns false.
+ static TimeTicks FromQPCValue(LONGLONG qpc_value);
+#endif
+
+ // Get the TimeTick value at the time of the UnixEpoch. This is useful when
+ // you need to relate the value of TimeTicks to a real time and date.
+ // Note: Upon first invocation, this function takes a snapshot of the realtime
+ // clock to establish a reference point. This function will return the same
+ // value for the duration of the application, but will be different in future
+ // application runs.
+ static TimeTicks UnixEpoch();
+
+ // Returns |this| snapped to the next tick, given a |tick_phase| and
+ // repeating |tick_interval| in both directions. |this| may be before,
+ // after, or equal to the |tick_phase|.
+ TimeTicks SnappedToNextTick(TimeTicks tick_phase,
+ TimeDelta tick_interval) const;
+
+#if defined(OS_WIN)
+ protected:
+ typedef DWORD (*TickFunctionType)(void);
+ static TickFunctionType SetMockTickFunction(TickFunctionType ticker);
+#endif
+
+ private:
+ friend class time_internal::TimeBase<TimeTicks>;
+
+ // Please use Now() to create a new object. This is for internal use
+ // and testing.
+ explicit TimeTicks(int64 us) : TimeBase(us) {
+ }
+};
+
+// For logging use only.
+std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks);
+
+// ThreadTicks ----------------------------------------------------------------
+
+// Represents a clock, specific to a particular thread, than runs only while the
+// thread is running.
+class ThreadTicks : public time_internal::TimeBase<ThreadTicks> {
+ public:
+ ThreadTicks() : TimeBase(0) {
+ }
+
+ // Returns true if ThreadTicks::Now() is supported on this system.
+ static bool IsSupported() {
+#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
+ (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_ANDROID)
+ return true;
+#else
+ return false;
+#endif
+ }
+
+ // Returns thread-specific CPU-time on systems that support this feature.
+ // Needs to be guarded with a call to IsSupported(). Use this timer
+ // to (approximately) measure how much time the calling thread spent doing
+ // actual work vs. being de-scheduled. May return bogus results if the thread
+ // migrates to another CPU between two calls.
+ static ThreadTicks Now();
+
+ private:
+ friend class time_internal::TimeBase<ThreadTicks>;
+
+ // Please use Now() to create a new object. This is for internal use
+ // and testing.
+ explicit ThreadTicks(int64 us) : TimeBase(us) {
+ }
+};
+
+// For logging use only.
+std::ostream& operator<<(std::ostream& os, ThreadTicks time_ticks);
+
+// TraceTicks ----------------------------------------------------------------
+
+// Represents high-resolution system trace clock time.
+class TraceTicks : public time_internal::TimeBase<TraceTicks> {
+ public:
+ // We define this even without OS_CHROMEOS for seccomp sandbox testing.
+#if defined(OS_LINUX)
+ // Force definition of the system trace clock; it is a chromeos-only api
+ // at the moment and surfacing it in the right place requires mucking
+ // with glibc et al.
+ static const clockid_t kClockSystemTrace = 11;
+#endif
+
+ TraceTicks() : TimeBase(0) {
+ }
+
+ // Returns the current system trace time or, if not available on this
+ // platform, a high-resolution time value; or a low-resolution time value if
+ // neither are avalable. On systems where a global trace clock is defined,
+ // timestamping TraceEvents's with this value guarantees synchronization
+ // between events collected inside chrome and events collected outside
+ // (e.g. kernel, X server).
+ //
+ // On some platforms, the clock source used for tracing can vary depending on
+ // hardware and/or kernel support. Do not make any assumptions without
+ // consulting the documentation for this functionality in the time_win.cc,
+ // time_posix.cc, etc. files.
+ //
+ // NOTE: This is only meant to be used by the event tracing infrastructure,
+ // and by outside code modules in special circumstances. Please be sure to
+ // consult a base/trace_event/OWNER before committing any new code that uses
+ // this.
+ static TraceTicks Now();
+
+ private:
+ friend class time_internal::TimeBase<TraceTicks>;
+
+ // Please use Now() to create a new object. This is for internal use
+ // and testing.
+ explicit TraceTicks(int64 us) : TimeBase(us) {
+ }
+};
+
+// For logging use only.
+std::ostream& operator<<(std::ostream& os, TraceTicks time_ticks);
+
+} // namespace base
+
+#endif // BASE_TIME_TIME_H_
diff --git a/third_party/chromium/base/time/time_posix.cc b/third_party/chromium/base/time/time_posix.cc
new file mode 100644
index 0000000..b625af6
--- /dev/null
+++ b/third_party/chromium/base/time/time_posix.cc
@@ -0,0 +1,368 @@
+// Copyright (c) 2012 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.h"
+
+#include <stdint.h>
+#include <sys/time.h>
+#include <time.h>
+#if defined(OS_ANDROID) && !defined(__LP64__)
+#include <time64.h>
+#endif
+#include <unistd.h>
+
+#include <limits>
+#include <ostream>
+
+#include "base/basictypes.h"
+#include "base/build/build_config.h"
+#include "base/logging.h"
+
+namespace {
+
+#if !defined(OS_MACOSX)
+// Define a system-specific SysTime that wraps either to a time_t or
+// a time64_t depending on the host system, and associated convertion.
+// See crbug.com/162007
+#if defined(OS_ANDROID) && !defined(__LP64__)
+typedef time64_t SysTime;
+
+SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) {
+ if (is_local)
+ return mktime64(timestruct);
+ else
+ return timegm64(timestruct);
+}
+
+void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) {
+ if (is_local)
+ localtime64_r(&t, timestruct);
+ else
+ gmtime64_r(&t, timestruct);
+}
+
+#else // OS_ANDROID && !__LP64__
+typedef time_t SysTime;
+
+SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) {
+ if (is_local)
+ return mktime(timestruct);
+ else
+ return timegm(timestruct);
+}
+
+void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) {
+ if (is_local)
+ localtime_r(&t, timestruct);
+ else
+ gmtime_r(&t, timestruct);
+}
+#endif // OS_ANDROID
+
+int64 ConvertTimespecToMicros(const struct timespec& ts) {
+ base::CheckedNumeric<int64> result(ts.tv_sec);
+ result *= base::Time::kMicrosecondsPerSecond;
+ result += (ts.tv_nsec / base::Time::kNanosecondsPerMicrosecond);
+ return result.ValueOrDie();
+}
+
+// Helper function to get results from clock_gettime() and convert to a
+// microsecond timebase. Minimum requirement is MONOTONIC_CLOCK to be supported
+// on the system. FreeBSD 6 has CLOCK_MONOTONIC but defines
+// _POSIX_MONOTONIC_CLOCK to -1.
+#if (defined(OS_POSIX) && \
+ defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0) || \
+ defined(OS_BSD) || defined(OS_ANDROID)
+int64 ClockNow(clockid_t clk_id) {
+ struct timespec ts;
+ if (clock_gettime(clk_id, &ts) != 0) {
+ NOTREACHED() << "clock_gettime(" << clk_id << ") failed.";
+ return 0;
+ }
+ return ConvertTimespecToMicros(ts);
+}
+#else // _POSIX_MONOTONIC_CLOCK
+#error No usable tick clock function on this platform.
+#endif // _POSIX_MONOTONIC_CLOCK
+#endif // !defined(OS_MACOSX)
+
+} // namespace
+
+namespace base {
+
+struct timespec TimeDelta::ToTimeSpec() const {
+ int64 microseconds = InMicroseconds();
+ time_t seconds = 0;
+ if (microseconds >= Time::kMicrosecondsPerSecond) {
+ seconds = InSeconds();
+ microseconds -= seconds * Time::kMicrosecondsPerSecond;
+ }
+ struct timespec result =
+ {seconds,
+ static_cast<long>(microseconds * Time::kNanosecondsPerMicrosecond)};
+ return result;
+}
+
+#if !defined(OS_MACOSX)
+// The Time routines in this file use standard POSIX routines, or almost-
+// standard routines in the case of timegm. We need to use a Mach-specific
+// function for TimeTicks::Now() on Mac OS X.
+
+// Time -----------------------------------------------------------------------
+
+// Windows uses a Gregorian epoch of 1601. We need to match this internally
+// so that our time representations match across all platforms. See bug 14734.
+// irb(main):010:0> Time.at(0).getutc()
+// => Thu Jan 01 00:00:00 UTC 1970
+// irb(main):011:0> Time.at(-11644473600).getutc()
+// => Mon Jan 01 00:00:00 UTC 1601
+static const int64 kWindowsEpochDeltaSeconds = INT64_C(11644473600);
+
+// static
+const int64 Time::kWindowsEpochDeltaMicroseconds =
+ kWindowsEpochDeltaSeconds * Time::kMicrosecondsPerSecond;
+
+// Some functions in time.cc use time_t directly, so we provide an offset
+// to convert from time_t (Unix epoch) and internal (Windows epoch).
+// static
+const int64 Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds;
+
+// static
+Time Time::Now() {
+ struct timeval tv;
+ struct timezone tz = { 0, 0 }; // UTC
+ if (gettimeofday(&tv, &tz) != 0) {
+ DCHECK(0) << "Could not determine time of day";
+ LOG(ERROR) << "Call to gettimeofday failed.";
+ // Return null instead of uninitialized |tv| value, which contains random
+ // garbage data. This may result in the crash seen in crbug.com/147570.
+ return Time();
+ }
+ // Combine seconds and microseconds in a 64-bit field containing microseconds
+ // since the epoch. That's enough for nearly 600 centuries. Adjust from
+ // Unix (1970) to Windows (1601) epoch.
+ return Time((tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec) +
+ kWindowsEpochDeltaMicroseconds);
+}
+
+// static
+Time Time::NowFromSystemTime() {
+ // Just use Now() because Now() returns the system time.
+ return Now();
+}
+
+void Time::Explode(bool is_local, Exploded* exploded) const {
+ // Time stores times with microsecond resolution, but Exploded only carries
+ // millisecond resolution, so begin by being lossy. Adjust from Windows
+ // epoch (1601) to Unix epoch (1970);
+ int64 microseconds = us_ - kWindowsEpochDeltaMicroseconds;
+ // The following values are all rounded towards -infinity.
+ int64 milliseconds; // Milliseconds since epoch.
+ SysTime seconds; // Seconds since epoch.
+ int millisecond; // Exploded millisecond value (0-999).
+ if (microseconds >= 0) {
+ // Rounding towards -infinity <=> rounding towards 0, in this case.
+ milliseconds = microseconds / kMicrosecondsPerMillisecond;
+ seconds = milliseconds / kMillisecondsPerSecond;
+ millisecond = milliseconds % kMillisecondsPerSecond;
+ } else {
+ // Round these *down* (towards -infinity).
+ milliseconds = (microseconds - kMicrosecondsPerMillisecond + 1) /
+ kMicrosecondsPerMillisecond;
+ seconds = (milliseconds - kMillisecondsPerSecond + 1) /
+ kMillisecondsPerSecond;
+ // Make this nonnegative (and between 0 and 999 inclusive).
+ millisecond = milliseconds % kMillisecondsPerSecond;
+ if (millisecond < 0)
+ millisecond += kMillisecondsPerSecond;
+ }
+
+ struct tm timestruct;
+ SysTimeToTimeStruct(seconds, &timestruct, is_local);
+
+ exploded->year = timestruct.tm_year + 1900;
+ exploded->month = timestruct.tm_mon + 1;
+ exploded->day_of_week = timestruct.tm_wday;
+ exploded->day_of_month = timestruct.tm_mday;
+ exploded->hour = timestruct.tm_hour;
+ exploded->minute = timestruct.tm_min;
+ exploded->second = timestruct.tm_sec;
+ exploded->millisecond = millisecond;
+}
+
+// static
+Time Time::FromExploded(bool is_local, const Exploded& exploded) {
+ struct tm timestruct;
+ timestruct.tm_sec = exploded.second;
+ timestruct.tm_min = exploded.minute;
+ timestruct.tm_hour = exploded.hour;
+ timestruct.tm_mday = exploded.day_of_month;
+ timestruct.tm_mon = exploded.month - 1;
+ timestruct.tm_year = exploded.year - 1900;
+ timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this
+ timestruct.tm_yday = 0; // mktime/timegm ignore this
+ timestruct.tm_isdst = -1; // attempt to figure it out
+#if !defined(OS_NACL) && !defined(OS_SOLARIS)
+ timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore
+ timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore
+#endif
+
+
+ int64 milliseconds;
+ SysTime seconds;
+
+ // Certain exploded dates do not really exist due to daylight saving times,
+ // and this causes mktime() to return implementation-defined values when
+ // tm_isdst is set to -1. On Android, the function will return -1, while the
+ // C libraries of other platforms typically return a liberally-chosen value.
+ // Handling this requires the special code below.
+
+ // SysTimeFromTimeStruct() modifies the input structure, save current value.
+ struct tm timestruct0 = timestruct;
+
+ seconds = SysTimeFromTimeStruct(&timestruct, is_local);
+ if (seconds == -1) {
+ // Get the time values with tm_isdst == 0 and 1, then select the closest one
+ // to UTC 00:00:00 that isn't -1.
+ timestruct = timestruct0;
+ timestruct.tm_isdst = 0;
+ int64 seconds_isdst0 = SysTimeFromTimeStruct(&timestruct, is_local);
+
+ timestruct = timestruct0;
+ timestruct.tm_isdst = 1;
+ int64 seconds_isdst1 = SysTimeFromTimeStruct(&timestruct, is_local);
+
+ // seconds_isdst0 or seconds_isdst1 can be -1 for some timezones.
+ // E.g. "CLST" (Chile Summer Time) returns -1 for 'tm_isdt == 1'.
+ if (seconds_isdst0 < 0)
+ seconds = seconds_isdst1;
+ else if (seconds_isdst1 < 0)
+ seconds = seconds_isdst0;
+ else
+ seconds = std::min(seconds_isdst0, seconds_isdst1);
+ }
+
+ // Handle overflow. Clamping the range to what mktime and timegm might
+ // return is the best that can be done here. It's not ideal, but it's better
+ // than failing here or ignoring the overflow case and treating each time
+ // overflow as one second prior to the epoch.
+ if (seconds == -1 &&
+ (exploded.year < 1969 || exploded.year > 1970)) {
+ // If exploded.year is 1969 or 1970, take -1 as correct, with the
+ // time indicating 1 second prior to the epoch. (1970 is allowed to handle
+ // time zone and DST offsets.) Otherwise, return the most future or past
+ // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC.
+ //
+ // The minimum and maximum representible times that mktime and timegm could
+ // return are used here instead of values outside that range to allow for
+ // proper round-tripping between exploded and counter-type time
+ // representations in the presence of possible truncation to time_t by
+ // division and use with other functions that accept time_t.
+ //
+ // When representing the most distant time in the future, add in an extra
+ // 999ms to avoid the time being less than any other possible value that
+ // this function can return.
+
+ // On Android, SysTime is int64, special care must be taken to avoid
+ // overflows.
+ const int64 min_seconds = (sizeof(SysTime) < sizeof(int64))
+ ? std::numeric_limits<SysTime>::min()
+ : std::numeric_limits<int32_t>::min();
+ const int64 max_seconds = (sizeof(SysTime) < sizeof(int64))
+ ? std::numeric_limits<SysTime>::max()
+ : std::numeric_limits<int32_t>::max();
+ if (exploded.year < 1969) {
+ milliseconds = min_seconds * kMillisecondsPerSecond;
+ } else {
+ milliseconds = max_seconds * kMillisecondsPerSecond;
+ milliseconds += (kMillisecondsPerSecond - 1);
+ }
+ } else {
+ milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond;
+ }
+
+ // Adjust from Unix (1970) to Windows (1601) epoch.
+ return Time((milliseconds * kMicrosecondsPerMillisecond) +
+ kWindowsEpochDeltaMicroseconds);
+}
+
+// TimeTicks ------------------------------------------------------------------
+// static
+TimeTicks TimeTicks::Now() {
+ return TimeTicks(ClockNow(CLOCK_MONOTONIC));
+}
+
+// static
+bool TimeTicks::IsHighResolution() {
+ return true;
+}
+
+// static
+ThreadTicks ThreadTicks::Now() {
+#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
+ defined(OS_ANDROID)
+ return ThreadTicks(ClockNow(CLOCK_THREAD_CPUTIME_ID));
+#else
+ NOTREACHED();
+ return ThreadTicks();
+#endif
+}
+
+// Use the Chrome OS specific system-wide clock.
+#if defined(OS_CHROMEOS)
+// static
+TraceTicks TraceTicks::Now() {
+ struct timespec ts;
+ if (clock_gettime(kClockSystemTrace, &ts) != 0) {
+ // NB: fall-back for a chrome os build running on linux
+ return TraceTicks(ClockNow(CLOCK_MONOTONIC));
+ }
+ return TraceTicks(ConvertTimespecToMicros(ts));
+}
+
+#else // !defined(OS_CHROMEOS)
+
+// static
+TraceTicks TraceTicks::Now() {
+ return TraceTicks(ClockNow(CLOCK_MONOTONIC));
+}
+
+#endif // defined(OS_CHROMEOS)
+
+#endif // !OS_MACOSX
+
+// static
+Time Time::FromTimeVal(struct timeval t) {
+ DCHECK_LT(t.tv_usec, static_cast<int>(Time::kMicrosecondsPerSecond));
+ DCHECK_GE(t.tv_usec, 0);
+ if (t.tv_usec == 0 && t.tv_sec == 0)
+ return Time();
+ if (t.tv_usec == static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1 &&
+ t.tv_sec == std::numeric_limits<time_t>::max())
+ return Max();
+ return Time(
+ (static_cast<int64>(t.tv_sec) * Time::kMicrosecondsPerSecond) +
+ t.tv_usec +
+ kTimeTToMicrosecondsOffset);
+}
+
+struct timeval Time::ToTimeVal() const {
+ struct timeval result;
+ if (is_null()) {
+ result.tv_sec = 0;
+ result.tv_usec = 0;
+ return result;
+ }
+ if (is_max()) {
+ result.tv_sec = std::numeric_limits<time_t>::max();
+ result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1;
+ return result;
+ }
+ int64 us = us_ - kTimeTToMicrosecondsOffset;
+ result.tv_sec = us / Time::kMicrosecondsPerSecond;
+ result.tv_usec = us % Time::kMicrosecondsPerSecond;
+ return result;
+}
+
+} // namespace base
diff --git a/third_party/chromium/base/time/time_unittest.cc b/third_party/chromium/base/time/time_unittest.cc
new file mode 100644
index 0000000..43373e7
--- /dev/null
+++ b/third_party/chromium/base/time/time_unittest.cc
@@ -0,0 +1,848 @@
+// Copyright (c) 2012 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.h"
+
+#include <stdint.h>
+#include <time.h>
+#include <limits>
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "base/build/build_config.h"
+
+namespace base {
+
+namespace {
+
+// Specialized test fixture allowing time strings without timezones to be
+// tested by comparing them to a known time in the local zone.
+// See also pr_time_unittests.cc
+class TimeTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ // Use mktime to get a time_t, and turn it into a PRTime by converting
+ // seconds to microseconds. Use 15th Oct 2007 12:45:00 local. This
+ // must be a time guaranteed to be outside of a DST fallback hour in
+ // any timezone.
+ struct tm local_comparison_tm = {
+ 0, // second
+ 45, // minute
+ 12, // hour
+ 15, // day of month
+ 10 - 1, // month
+ 2007 - 1900, // year
+ 0, // day of week (ignored, output only)
+ 0, // day of year (ignored, output only)
+ -1 // DST in effect, -1 tells mktime to figure it out
+ };
+
+ time_t converted_time = mktime(&local_comparison_tm);
+ ASSERT_GT(converted_time, 0);
+ comparison_time_local_ = Time::FromTimeT(converted_time);
+
+ // time_t representation of 15th Oct 2007 12:45:00 PDT
+ comparison_time_pdt_ = Time::FromTimeT(1192477500);
+ }
+
+ Time comparison_time_local_;
+ Time comparison_time_pdt_;
+};
+
+// Test conversions to/from time_t and exploding/unexploding.
+TEST_F(TimeTest, TimeT) {
+ // C library time and exploded time.
+ time_t now_t_1 = time(NULL);
+ struct tm tms;
+#if defined(OS_WIN)
+ localtime_s(&tms, &now_t_1);
+#elif defined(OS_POSIX)
+ localtime_r(&now_t_1, &tms);
+#endif
+
+ // Convert to ours.
+ Time our_time_1 = Time::FromTimeT(now_t_1);
+ Time::Exploded exploded;
+ our_time_1.LocalExplode(&exploded);
+
+ // This will test both our exploding and our time_t -> Time conversion.
+ EXPECT_EQ(tms.tm_year + 1900, exploded.year);
+ EXPECT_EQ(tms.tm_mon + 1, exploded.month);
+ EXPECT_EQ(tms.tm_mday, exploded.day_of_month);
+ EXPECT_EQ(tms.tm_hour, exploded.hour);
+ EXPECT_EQ(tms.tm_min, exploded.minute);
+ EXPECT_EQ(tms.tm_sec, exploded.second);
+
+ // Convert exploded back to the time struct.
+ Time our_time_2 = Time::FromLocalExploded(exploded);
+ EXPECT_TRUE(our_time_1 == our_time_2);
+
+ time_t now_t_2 = our_time_2.ToTimeT();
+ EXPECT_EQ(now_t_1, now_t_2);
+
+ EXPECT_EQ(10, Time().FromTimeT(10).ToTimeT());
+ EXPECT_EQ(10.0, Time().FromTimeT(10).ToDoubleT());
+
+ // Conversions of 0 should stay 0.
+ EXPECT_EQ(0, Time().ToTimeT());
+ EXPECT_EQ(0, Time::FromTimeT(0).ToInternalValue());
+}
+
+// Test conversions to/from javascript time.
+TEST_F(TimeTest, JsTime) {
+ Time epoch = Time::FromJsTime(0.0);
+ EXPECT_EQ(epoch, Time::UnixEpoch());
+ Time t = Time::FromJsTime(700000.3);
+ EXPECT_EQ(700.0003, t.ToDoubleT());
+ t = Time::FromDoubleT(800.73);
+ EXPECT_EQ(800730.0, t.ToJsTime());
+}
+
+#if defined(OS_POSIX)
+TEST_F(TimeTest, FromTimeVal) {
+ Time now = Time::Now();
+ Time also_now = Time::FromTimeVal(now.ToTimeVal());
+ EXPECT_EQ(now, also_now);
+}
+#endif // OS_POSIX
+
+TEST_F(TimeTest, FromExplodedWithMilliseconds) {
+ // Some platform implementations of FromExploded are liable to drop
+ // milliseconds if we aren't careful.
+ Time now = Time::NowFromSystemTime();
+ Time::Exploded exploded1 = {0};
+ now.UTCExplode(&exploded1);
+ exploded1.millisecond = 500;
+ Time time = Time::FromUTCExploded(exploded1);
+ Time::Exploded exploded2 = {0};
+ time.UTCExplode(&exploded2);
+ EXPECT_EQ(exploded1.millisecond, exploded2.millisecond);
+}
+
+TEST_F(TimeTest, ZeroIsSymmetric) {
+ Time zero_time(Time::FromTimeT(0));
+ EXPECT_EQ(0, zero_time.ToTimeT());
+
+ EXPECT_EQ(0.0, zero_time.ToDoubleT());
+}
+
+TEST_F(TimeTest, LocalExplode) {
+ Time a = Time::Now();
+ Time::Exploded exploded;
+ a.LocalExplode(&exploded);
+
+ Time b = Time::FromLocalExploded(exploded);
+
+ // The exploded structure doesn't have microseconds, and on Mac & Linux, the
+ // internal OS conversion uses seconds, which will cause truncation. So we
+ // can only make sure that the delta is within one second.
+ EXPECT_TRUE((a - b) < TimeDelta::FromSeconds(1));
+}
+
+TEST_F(TimeTest, UTCExplode) {
+ Time a = Time::Now();
+ Time::Exploded exploded;
+ a.UTCExplode(&exploded);
+
+ Time b = Time::FromUTCExploded(exploded);
+ EXPECT_TRUE((a - b) < TimeDelta::FromSeconds(1));
+}
+
+TEST_F(TimeTest, LocalMidnight) {
+ Time::Exploded exploded;
+ Time::Now().LocalMidnight().LocalExplode(&exploded);
+ EXPECT_EQ(0, exploded.hour);
+ EXPECT_EQ(0, exploded.minute);
+ EXPECT_EQ(0, exploded.second);
+ EXPECT_EQ(0, exploded.millisecond);
+}
+
+TEST_F(TimeTest, ExplodeBeforeUnixEpoch) {
+ static const int kUnixEpochYear = 1970; // In case this changes (ha!).
+ Time t;
+ Time::Exploded exploded;
+
+ t = Time::UnixEpoch() - TimeDelta::FromMicroseconds(1);
+ t.UTCExplode(&exploded);
+ EXPECT_TRUE(exploded.HasValidValues());
+ // Should be 1969-12-31 23:59:59 999 milliseconds (and 999 microseconds).
+ EXPECT_EQ(kUnixEpochYear - 1, exploded.year);
+ EXPECT_EQ(12, exploded.month);
+ EXPECT_EQ(31, exploded.day_of_month);
+ EXPECT_EQ(23, exploded.hour);
+ EXPECT_EQ(59, exploded.minute);
+ EXPECT_EQ(59, exploded.second);
+ EXPECT_EQ(999, exploded.millisecond);
+
+ t = Time::UnixEpoch() - TimeDelta::FromMicroseconds(1000);
+ t.UTCExplode(&exploded);
+ EXPECT_TRUE(exploded.HasValidValues());
+ // Should be 1969-12-31 23:59:59 999 milliseconds.
+ EXPECT_EQ(kUnixEpochYear - 1, exploded.year);
+ EXPECT_EQ(12, exploded.month);
+ EXPECT_EQ(31, exploded.day_of_month);
+ EXPECT_EQ(23, exploded.hour);
+ EXPECT_EQ(59, exploded.minute);
+ EXPECT_EQ(59, exploded.second);
+ EXPECT_EQ(999, exploded.millisecond);
+
+ t = Time::UnixEpoch() - TimeDelta::FromMicroseconds(1001);
+ t.UTCExplode(&exploded);
+ EXPECT_TRUE(exploded.HasValidValues());
+ // Should be 1969-12-31 23:59:59 998 milliseconds (and 999 microseconds).
+ EXPECT_EQ(kUnixEpochYear - 1, exploded.year);
+ EXPECT_EQ(12, exploded.month);
+ EXPECT_EQ(31, exploded.day_of_month);
+ EXPECT_EQ(23, exploded.hour);
+ EXPECT_EQ(59, exploded.minute);
+ EXPECT_EQ(59, exploded.second);
+ EXPECT_EQ(998, exploded.millisecond);
+
+ t = Time::UnixEpoch() - TimeDelta::FromMilliseconds(1000);
+ t.UTCExplode(&exploded);
+ EXPECT_TRUE(exploded.HasValidValues());
+ // Should be 1969-12-31 23:59:59.
+ EXPECT_EQ(kUnixEpochYear - 1, exploded.year);
+ EXPECT_EQ(12, exploded.month);
+ EXPECT_EQ(31, exploded.day_of_month);
+ EXPECT_EQ(23, exploded.hour);
+ EXPECT_EQ(59, exploded.minute);
+ EXPECT_EQ(59, exploded.second);
+ EXPECT_EQ(0, exploded.millisecond);
+
+ t = Time::UnixEpoch() - TimeDelta::FromMilliseconds(1001);
+ t.UTCExplode(&exploded);
+ EXPECT_TRUE(exploded.HasValidValues());
+ // Should be 1969-12-31 23:59:58 999 milliseconds.
+ EXPECT_EQ(kUnixEpochYear - 1, exploded.year);
+ EXPECT_EQ(12, exploded.month);
+ EXPECT_EQ(31, exploded.day_of_month);
+ EXPECT_EQ(23, exploded.hour);
+ EXPECT_EQ(59, exploded.minute);
+ EXPECT_EQ(58, exploded.second);
+ EXPECT_EQ(999, exploded.millisecond);
+
+ // Make sure we still handle at/after Unix epoch correctly.
+ t = Time::UnixEpoch();
+ t.UTCExplode(&exploded);
+ EXPECT_TRUE(exploded.HasValidValues());
+ // Should be 1970-12-31 00:00:00 0 milliseconds.
+ EXPECT_EQ(kUnixEpochYear, exploded.year);
+ EXPECT_EQ(1, exploded.month);
+ EXPECT_EQ(1, exploded.day_of_month);
+ EXPECT_EQ(0, exploded.hour);
+ EXPECT_EQ(0, exploded.minute);
+ EXPECT_EQ(0, exploded.second);
+ EXPECT_EQ(0, exploded.millisecond);
+
+ t = Time::UnixEpoch() + TimeDelta::FromMicroseconds(1);
+ t.UTCExplode(&exploded);
+ EXPECT_TRUE(exploded.HasValidValues());
+ // Should be 1970-01-01 00:00:00 0 milliseconds (and 1 microsecond).
+ EXPECT_EQ(kUnixEpochYear, exploded.year);
+ EXPECT_EQ(1, exploded.month);
+ EXPECT_EQ(1, exploded.day_of_month);
+ EXPECT_EQ(0, exploded.hour);
+ EXPECT_EQ(0, exploded.minute);
+ EXPECT_EQ(0, exploded.second);
+ EXPECT_EQ(0, exploded.millisecond);
+
+ t = Time::UnixEpoch() + TimeDelta::FromMicroseconds(1000);
+ t.UTCExplode(&exploded);
+ EXPECT_TRUE(exploded.HasValidValues());
+ // Should be 1970-01-01 00:00:00 1 millisecond.
+ EXPECT_EQ(kUnixEpochYear, exploded.year);
+ EXPECT_EQ(1, exploded.month);
+ EXPECT_EQ(1, exploded.day_of_month);
+ EXPECT_EQ(0, exploded.hour);
+ EXPECT_EQ(0, exploded.minute);
+ EXPECT_EQ(0, exploded.second);
+ EXPECT_EQ(1, exploded.millisecond);
+
+ t = Time::UnixEpoch() + TimeDelta::FromMilliseconds(1000);
+ t.UTCExplode(&exploded);
+ EXPECT_TRUE(exploded.HasValidValues());
+ // Should be 1970-01-01 00:00:01.
+ EXPECT_EQ(kUnixEpochYear, exploded.year);
+ EXPECT_EQ(1, exploded.month);
+ EXPECT_EQ(1, exploded.day_of_month);
+ EXPECT_EQ(0, exploded.hour);
+ EXPECT_EQ(0, exploded.minute);
+ EXPECT_EQ(1, exploded.second);
+ EXPECT_EQ(0, exploded.millisecond);
+
+ t = Time::UnixEpoch() + TimeDelta::FromMilliseconds(1001);
+ t.UTCExplode(&exploded);
+ EXPECT_TRUE(exploded.HasValidValues());
+ // Should be 1970-01-01 00:00:01 1 millisecond.
+ EXPECT_EQ(kUnixEpochYear, exploded.year);
+ EXPECT_EQ(1, exploded.month);
+ EXPECT_EQ(1, exploded.day_of_month);
+ EXPECT_EQ(0, exploded.hour);
+ EXPECT_EQ(0, exploded.minute);
+ EXPECT_EQ(1, exploded.second);
+ EXPECT_EQ(1, exploded.millisecond);
+}
+
+TEST_F(TimeTest, TimeDeltaMax) {
+ TimeDelta max = TimeDelta::Max();
+ EXPECT_TRUE(max.is_max());
+ EXPECT_EQ(max, TimeDelta::Max());
+ EXPECT_GT(max, TimeDelta::FromDays(100 * 365));
+ EXPECT_GT(max, TimeDelta());
+}
+
+TEST_F(TimeTest, TimeDeltaMaxConversions) {
+ TimeDelta t = TimeDelta::Max();
+ EXPECT_EQ(std::numeric_limits<int64>::max(), t.ToInternalValue());
+
+ EXPECT_EQ(std::numeric_limits<int>::max(), t.InDays());
+ EXPECT_EQ(std::numeric_limits<int>::max(), t.InHours());
+ EXPECT_EQ(std::numeric_limits<int>::max(), t.InMinutes());
+ EXPECT_EQ(std::numeric_limits<double>::infinity(), t.InSecondsF());
+ EXPECT_EQ(std::numeric_limits<int64>::max(), t.InSeconds());
+ EXPECT_EQ(std::numeric_limits<double>::infinity(), t.InMillisecondsF());
+ EXPECT_EQ(std::numeric_limits<int64>::max(), t.InMilliseconds());
+ EXPECT_EQ(std::numeric_limits<int64>::max(), t.InMillisecondsRoundedUp());
+
+ t = TimeDelta::FromDays(std::numeric_limits<int>::max());
+ EXPECT_TRUE(t.is_max());
+
+ t = TimeDelta::FromHours(std::numeric_limits<int>::max());
+ EXPECT_TRUE(t.is_max());
+
+ t = TimeDelta::FromMinutes(std::numeric_limits<int>::max());
+ EXPECT_TRUE(t.is_max());
+
+ t = TimeDelta::FromSeconds(std::numeric_limits<int64>::max());
+ EXPECT_TRUE(t.is_max());
+
+ t = TimeDelta::FromMilliseconds(std::numeric_limits<int64>::max());
+ EXPECT_TRUE(t.is_max());
+
+ t = TimeDelta::FromSecondsD(std::numeric_limits<double>::infinity());
+ EXPECT_TRUE(t.is_max());
+
+ t = TimeDelta::FromMillisecondsD(std::numeric_limits<double>::infinity());
+ EXPECT_TRUE(t.is_max());
+
+ t = TimeDelta::FromMicroseconds(std::numeric_limits<int64>::max());
+ EXPECT_TRUE(t.is_max());
+}
+
+TEST_F(TimeTest, Max) {
+ Time max = Time::Max();
+ EXPECT_TRUE(max.is_max());
+ EXPECT_EQ(max, Time::Max());
+ EXPECT_GT(max, Time::Now());
+ EXPECT_GT(max, Time());
+}
+
+TEST_F(TimeTest, MaxConversions) {
+ Time t = Time::Max();
+ EXPECT_EQ(std::numeric_limits<int64>::max(), t.ToInternalValue());
+
+ t = Time::FromDoubleT(std::numeric_limits<double>::infinity());
+ EXPECT_TRUE(t.is_max());
+ EXPECT_EQ(std::numeric_limits<double>::infinity(), t.ToDoubleT());
+
+ t = Time::FromJsTime(std::numeric_limits<double>::infinity());
+ EXPECT_TRUE(t.is_max());
+ EXPECT_EQ(std::numeric_limits<double>::infinity(), t.ToJsTime());
+
+ t = Time::FromTimeT(std::numeric_limits<time_t>::max());
+ EXPECT_TRUE(t.is_max());
+ EXPECT_EQ(std::numeric_limits<time_t>::max(), t.ToTimeT());
+
+#if defined(OS_POSIX)
+ struct timeval tval;
+ tval.tv_sec = std::numeric_limits<time_t>::max();
+ tval.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1;
+ t = Time::FromTimeVal(tval);
+ EXPECT_TRUE(t.is_max());
+ tval = t.ToTimeVal();
+ EXPECT_EQ(std::numeric_limits<time_t>::max(), tval.tv_sec);
+ EXPECT_EQ(static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1,
+ tval.tv_usec);
+#endif
+
+#if defined(OS_MACOSX)
+ t = Time::FromCFAbsoluteTime(std::numeric_limits<CFAbsoluteTime>::infinity());
+ EXPECT_TRUE(t.is_max());
+ EXPECT_EQ(std::numeric_limits<CFAbsoluteTime>::infinity(),
+ t.ToCFAbsoluteTime());
+#endif
+
+#if defined(OS_WIN)
+ FILETIME ftime;
+ ftime.dwHighDateTime = std::numeric_limits<DWORD>::max();
+ ftime.dwLowDateTime = std::numeric_limits<DWORD>::max();
+ t = Time::FromFileTime(ftime);
+ EXPECT_TRUE(t.is_max());
+ ftime = t.ToFileTime();
+ EXPECT_EQ(std::numeric_limits<DWORD>::max(), ftime.dwHighDateTime);
+ EXPECT_EQ(std::numeric_limits<DWORD>::max(), ftime.dwLowDateTime);
+#endif
+}
+
+#if defined(OS_MACOSX)
+TEST_F(TimeTest, TimeTOverflow) {
+ Time t = Time::FromInternalValue(std::numeric_limits<int64>::max() - 1);
+ EXPECT_FALSE(t.is_max());
+ EXPECT_EQ(std::numeric_limits<time_t>::max(), t.ToTimeT());
+}
+#endif
+
+#if defined(OS_ANDROID)
+TEST_F(TimeTest, FromLocalExplodedCrashOnAndroid) {
+ // This crashed inside Time:: FromLocalExploded() on Android 4.1.2.
+ // See http://crbug.com/287821
+ Time::Exploded midnight = {2013, // year
+ 10, // month
+ 0, // day_of_week
+ 13, // day_of_month
+ 0, // hour
+ 0, // minute
+ 0, // second
+ };
+ // The string passed to putenv() must be a char* and the documentation states
+ // that it 'becomes part of the environment', so use a static buffer.
+ static char buffer[] = "TZ=America/Santiago";
+ putenv(buffer);
+ tzset();
+ Time t = Time::FromLocalExploded(midnight);
+ EXPECT_EQ(1381633200, t.ToTimeT());
+}
+#endif // OS_ANDROID
+
+static void HighResClockTest(TimeTicks (*GetTicks)()) {
+ // IsHighResolution() is false on some systems. Since the product still works
+ // even if it's false, it makes this entire test questionable.
+ if (!TimeTicks::IsHighResolution())
+ return;
+
+ // Why do we loop here?
+ // We're trying to measure that intervals increment in a VERY small amount
+ // of time -- less than 15ms. Unfortunately, if we happen to have a
+ // context switch in the middle of our test, the context switch could easily
+ // exceed our limit. So, we iterate on this several times. As long as we're
+ // able to detect the fine-granularity timers at least once, then the test
+ // has succeeded.
+
+ const int kTargetGranularityUs = 15000; // 15ms
+
+ bool success = false;
+ int retries = 100; // Arbitrary.
+ TimeDelta delta;
+ while (!success && retries--) {
+ TimeTicks ticks_start = GetTicks();
+ // Loop until we can detect that the clock has changed. Non-HighRes timers
+ // will increment in chunks, e.g. 15ms. By spinning until we see a clock
+ // change, we detect the minimum time between measurements.
+ do {
+ delta = GetTicks() - ticks_start;
+ } while (delta.InMilliseconds() == 0);
+
+ if (delta.InMicroseconds() <= kTargetGranularityUs)
+ success = true;
+ }
+
+ // In high resolution mode, we expect to see the clock increment
+ // in intervals less than 15ms.
+ EXPECT_TRUE(success);
+}
+
+TEST(TimeTicks, HighRes) {
+ HighResClockTest(&TimeTicks::Now);
+}
+
+TEST(TraceTicks, NowFromSystemTraceTime) {
+ // Re-use HighRes test for now since clock properties are identical.
+ using NowFunction = TimeTicks (*)(void);
+ HighResClockTest(reinterpret_cast<NowFunction>(&TraceTicks::Now));
+}
+
+TEST(TimeTicks, SnappedToNextTickBasic) {
+ base::TimeTicks phase = base::TimeTicks::FromInternalValue(4000);
+ base::TimeDelta interval = base::TimeDelta::FromMicroseconds(1000);
+ base::TimeTicks timestamp;
+
+ // Timestamp in previous interval.
+ timestamp = base::TimeTicks::FromInternalValue(3500);
+ EXPECT_EQ(4000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp in next interval.
+ timestamp = base::TimeTicks::FromInternalValue(4500);
+ EXPECT_EQ(5000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp multiple intervals before.
+ timestamp = base::TimeTicks::FromInternalValue(2500);
+ EXPECT_EQ(3000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp multiple intervals after.
+ timestamp = base::TimeTicks::FromInternalValue(6500);
+ EXPECT_EQ(7000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp on previous interval.
+ timestamp = base::TimeTicks::FromInternalValue(3000);
+ EXPECT_EQ(3000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp on next interval.
+ timestamp = base::TimeTicks::FromInternalValue(5000);
+ EXPECT_EQ(5000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+
+ // Timestamp equal to phase.
+ timestamp = base::TimeTicks::FromInternalValue(4000);
+ EXPECT_EQ(4000,
+ timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+}
+
+TEST(TimeTicks, SnappedToNextTickOverflow) {
+ // int(big_timestamp / interval) < 0, so this causes a crash if the number of
+ // intervals elapsed is attempted to be stored in an int.
+ base::TimeTicks phase = base::TimeTicks::FromInternalValue(0);
+ base::TimeDelta interval = base::TimeDelta::FromMicroseconds(4000);
+ base::TimeTicks big_timestamp =
+ base::TimeTicks::FromInternalValue(8635916564000);
+
+ EXPECT_EQ(8635916564000,
+ big_timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
+ EXPECT_EQ(8635916564000,
+ big_timestamp.SnappedToNextTick(big_timestamp, interval)
+ .ToInternalValue());
+}
+
+TEST(TimeDelta, FromAndIn) {
+ EXPECT_TRUE(TimeDelta::FromDays(2) == TimeDelta::FromHours(48));
+ EXPECT_TRUE(TimeDelta::FromHours(3) == TimeDelta::FromMinutes(180));
+ EXPECT_TRUE(TimeDelta::FromMinutes(2) == TimeDelta::FromSeconds(120));
+ EXPECT_TRUE(TimeDelta::FromSeconds(2) == TimeDelta::FromMilliseconds(2000));
+ EXPECT_TRUE(TimeDelta::FromMilliseconds(2) ==
+ TimeDelta::FromMicroseconds(2000));
+ EXPECT_TRUE(TimeDelta::FromSecondsD(2.3) ==
+ TimeDelta::FromMilliseconds(2300));
+ EXPECT_TRUE(TimeDelta::FromMillisecondsD(2.5) ==
+ TimeDelta::FromMicroseconds(2500));
+ EXPECT_EQ(13, TimeDelta::FromDays(13).InDays());
+ EXPECT_EQ(13, TimeDelta::FromHours(13).InHours());
+ EXPECT_EQ(13, TimeDelta::FromMinutes(13).InMinutes());
+ EXPECT_EQ(13, TimeDelta::FromSeconds(13).InSeconds());
+ EXPECT_EQ(13.0, TimeDelta::FromSeconds(13).InSecondsF());
+ EXPECT_EQ(13, TimeDelta::FromMilliseconds(13).InMilliseconds());
+ EXPECT_EQ(13.0, TimeDelta::FromMilliseconds(13).InMillisecondsF());
+ EXPECT_EQ(13, TimeDelta::FromSecondsD(13.1).InSeconds());
+ EXPECT_EQ(13.1, TimeDelta::FromSecondsD(13.1).InSecondsF());
+ EXPECT_EQ(13, TimeDelta::FromMillisecondsD(13.3).InMilliseconds());
+ EXPECT_EQ(13.3, TimeDelta::FromMillisecondsD(13.3).InMillisecondsF());
+ EXPECT_EQ(13, TimeDelta::FromMicroseconds(13).InMicroseconds());
+}
+
+#if defined(OS_POSIX)
+TEST(TimeDelta, TimeSpecConversion) {
+ struct timespec result = TimeDelta::FromSeconds(0).ToTimeSpec();
+ EXPECT_EQ(result.tv_sec, 0);
+ EXPECT_EQ(result.tv_nsec, 0);
+
+ result = TimeDelta::FromSeconds(1).ToTimeSpec();
+ EXPECT_EQ(result.tv_sec, 1);
+ EXPECT_EQ(result.tv_nsec, 0);
+
+ result = TimeDelta::FromMicroseconds(1).ToTimeSpec();
+ EXPECT_EQ(result.tv_sec, 0);
+ EXPECT_EQ(result.tv_nsec, 1000);
+
+ result = TimeDelta::FromMicroseconds(
+ Time::kMicrosecondsPerSecond + 1).ToTimeSpec();
+ EXPECT_EQ(result.tv_sec, 1);
+ EXPECT_EQ(result.tv_nsec, 1000);
+}
+#endif // OS_POSIX
+
+// Our internal time format is serialized in things like databases, so it's
+// important that it's consistent across all our platforms. We use the 1601
+// Windows epoch as the internal format across all platforms.
+TEST(TimeDelta, WindowsEpoch) {
+ Time::Exploded exploded;
+ exploded.year = 1970;
+ exploded.month = 1;
+ exploded.day_of_week = 0; // Should be unusued.
+ exploded.day_of_month = 1;
+ exploded.hour = 0;
+ exploded.minute = 0;
+ exploded.second = 0;
+ exploded.millisecond = 0;
+ Time t = Time::FromUTCExploded(exploded);
+ // Unix 1970 epoch.
+ EXPECT_EQ(INT64_C(11644473600000000), t.ToInternalValue());
+
+ // We can't test 1601 epoch, since the system time functions on Linux
+ // only compute years starting from 1900.
+}
+
+// We could define this separately for Time, TimeTicks and TimeDelta but the
+// definitions would be identical anyway.
+template <class Any>
+std::string AnyToString(Any any) {
+ std::ostringstream oss;
+ oss << any;
+ return oss.str();
+}
+
+TEST(TimeDelta, Magnitude) {
+ const int64 zero = 0;
+ EXPECT_EQ(TimeDelta::FromMicroseconds(zero),
+ TimeDelta::FromMicroseconds(zero).magnitude());
+
+ const int64 one = 1;
+ const int64 negative_one = -1;
+ EXPECT_EQ(TimeDelta::FromMicroseconds(one),
+ TimeDelta::FromMicroseconds(one).magnitude());
+ EXPECT_EQ(TimeDelta::FromMicroseconds(one),
+ TimeDelta::FromMicroseconds(negative_one).magnitude());
+
+ const int64 max_int64_minus_one = std::numeric_limits<int64>::max() - 1;
+ const int64 min_int64_plus_two = std::numeric_limits<int64>::min() + 2;
+ EXPECT_EQ(TimeDelta::FromMicroseconds(max_int64_minus_one),
+ TimeDelta::FromMicroseconds(max_int64_minus_one).magnitude());
+ EXPECT_EQ(TimeDelta::FromMicroseconds(max_int64_minus_one),
+ TimeDelta::FromMicroseconds(min_int64_plus_two).magnitude());
+}
+
+
+TEST(TimeDelta, NumericOperators) {
+ double d = 0.5;
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ TimeDelta::FromMilliseconds(1000) * d);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ TimeDelta::FromMilliseconds(1000) / d);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ TimeDelta::FromMilliseconds(1000) *= d);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ TimeDelta::FromMilliseconds(1000) /= d);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ d * TimeDelta::FromMilliseconds(1000));
+
+ float f = 0.5;
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ TimeDelta::FromMilliseconds(1000) * f);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ TimeDelta::FromMilliseconds(1000) / f);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ TimeDelta::FromMilliseconds(1000) *= f);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ TimeDelta::FromMilliseconds(1000) /= f);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ f * TimeDelta::FromMilliseconds(1000));
+
+
+ int i = 2;
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ TimeDelta::FromMilliseconds(1000) * i);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ TimeDelta::FromMilliseconds(1000) / i);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ TimeDelta::FromMilliseconds(1000) *= i);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ TimeDelta::FromMilliseconds(1000) /= i);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ i * TimeDelta::FromMilliseconds(1000));
+
+ int64_t i64 = 2;
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ TimeDelta::FromMilliseconds(1000) * i64);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ TimeDelta::FromMilliseconds(1000) / i64);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ TimeDelta::FromMilliseconds(1000) *= i64);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ TimeDelta::FromMilliseconds(1000) /= i64);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ i64 * TimeDelta::FromMilliseconds(1000));
+
+
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ TimeDelta::FromMilliseconds(1000) * 0.5);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ TimeDelta::FromMilliseconds(1000) / 0.5);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ TimeDelta::FromMilliseconds(1000) *= 0.5);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ TimeDelta::FromMilliseconds(1000) /= 0.5);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ 0.5 * TimeDelta::FromMilliseconds(1000));
+
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ TimeDelta::FromMilliseconds(1000) * 2);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ TimeDelta::FromMilliseconds(1000) / 2);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ TimeDelta::FromMilliseconds(1000) *= 2);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(500),
+ TimeDelta::FromMilliseconds(1000) /= 2);
+ EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
+ 2 * TimeDelta::FromMilliseconds(1000));
+}
+
+bool IsMin(TimeDelta delta) {
+ return (-delta).is_max();
+}
+
+TEST(TimeDelta, Overflows) {
+ // Some sanity checks.
+ EXPECT_TRUE(TimeDelta::Max().is_max());
+ EXPECT_TRUE(IsMin(-TimeDelta::Max()));
+ EXPECT_GT(TimeDelta(), -TimeDelta::Max());
+
+ TimeDelta large_delta = TimeDelta::Max() - TimeDelta::FromMilliseconds(1);
+ TimeDelta large_negative = -large_delta;
+ EXPECT_GT(TimeDelta(), large_negative);
+ EXPECT_FALSE(large_delta.is_max());
+ EXPECT_FALSE(IsMin(-large_negative));
+ TimeDelta one_second = TimeDelta::FromSeconds(1);
+
+ // Test +, -, * and / operators.
+ EXPECT_TRUE((large_delta + one_second).is_max());
+ EXPECT_TRUE(IsMin(large_negative + (-one_second)));
+ EXPECT_TRUE(IsMin(large_negative - one_second));
+ EXPECT_TRUE((large_delta - (-one_second)).is_max());
+ EXPECT_TRUE((large_delta * 2).is_max());
+ EXPECT_TRUE(IsMin(large_delta * -2));
+ EXPECT_TRUE((large_delta / 0.5).is_max());
+ EXPECT_TRUE(IsMin(large_delta / -0.5));
+
+ // Test +=, -=, *= and /= operators.
+ TimeDelta delta = large_delta;
+ delta += one_second;
+ EXPECT_TRUE(delta.is_max());
+ delta = large_negative;
+ delta += -one_second;
+ EXPECT_TRUE(IsMin(delta));
+
+ delta = large_negative;
+ delta -= one_second;
+ EXPECT_TRUE(IsMin(delta));
+ delta = large_delta;
+ delta -= -one_second;
+ EXPECT_TRUE(delta.is_max());
+
+ delta = large_delta;
+ delta *= 2;
+ EXPECT_TRUE(delta.is_max());
+ delta = large_negative;
+ delta *= 1.5;
+ EXPECT_TRUE(IsMin(delta));
+
+ delta = large_delta;
+ delta /= 0.5;
+ EXPECT_TRUE(delta.is_max());
+ delta = large_negative;
+ delta /= 0.5;
+ EXPECT_TRUE(IsMin(delta));
+
+ // Test operations with Time and TimeTicks.
+ EXPECT_TRUE((large_delta + Time::Now()).is_max());
+ EXPECT_TRUE((large_delta + TimeTicks::Now()).is_max());
+ EXPECT_TRUE((Time::Now() + large_delta).is_max());
+ EXPECT_TRUE((TimeTicks::Now() + large_delta).is_max());
+
+ Time time_now = Time::Now();
+ EXPECT_EQ(one_second, (time_now + one_second) - time_now);
+ EXPECT_EQ(-one_second, (time_now - one_second) - time_now);
+
+ TimeTicks ticks_now = TimeTicks::Now();
+ EXPECT_EQ(-one_second, (ticks_now - one_second) - ticks_now);
+ EXPECT_EQ(one_second, (ticks_now + one_second) - ticks_now);
+}
+
+TEST(TimeDeltaLogging, DCheckEqCompiles) {
+ DCHECK_EQ(TimeDelta(), TimeDelta());
+}
+
+TEST(TimeDeltaLogging, EmptyIsZero) {
+ TimeDelta zero;
+ EXPECT_EQ("0s", AnyToString(zero));
+}
+
+TEST(TimeDeltaLogging, FiveHundredMs) {
+ TimeDelta five_hundred_ms = TimeDelta::FromMilliseconds(500);
+ EXPECT_EQ("0.5s", AnyToString(five_hundred_ms));
+}
+
+TEST(TimeDeltaLogging, MinusTenSeconds) {
+ TimeDelta minus_ten_seconds = TimeDelta::FromSeconds(-10);
+ EXPECT_EQ("-10s", AnyToString(minus_ten_seconds));
+}
+
+TEST(TimeDeltaLogging, DoesNotMessUpFormattingFlags) {
+ std::ostringstream oss;
+ std::ios_base::fmtflags flags_before = oss.flags();
+ oss << TimeDelta();
+ EXPECT_EQ(flags_before, oss.flags());
+}
+
+TEST(TimeDeltaLogging, DoesNotMakeStreamBad) {
+ std::ostringstream oss;
+ oss << TimeDelta();
+ EXPECT_TRUE(oss.good());
+}
+
+TEST(TimeLogging, DCheckEqCompiles) {
+ DCHECK_EQ(Time(), Time());
+}
+
+TEST(TimeLogging, DoesNotMessUpFormattingFlags) {
+ std::ostringstream oss;
+ std::ios_base::fmtflags flags_before = oss.flags();
+ oss << Time();
+ EXPECT_EQ(flags_before, oss.flags());
+}
+
+TEST(TimeLogging, DoesNotMakeStreamBad) {
+ std::ostringstream oss;
+ oss << Time();
+ EXPECT_TRUE(oss.good());
+}
+
+TEST(TimeTicksLogging, DCheckEqCompiles) {
+ DCHECK_EQ(TimeTicks(), TimeTicks());
+}
+
+TEST(TimeTicksLogging, ZeroTime) {
+ TimeTicks zero;
+ EXPECT_EQ("0 bogo-microseconds", AnyToString(zero));
+}
+
+TEST(TimeTicksLogging, FortyYearsLater) {
+ TimeTicks forty_years_later =
+ TimeTicks() + TimeDelta::FromDays(365.25 * 40);
+ EXPECT_EQ("1262304000000000 bogo-microseconds",
+ AnyToString(forty_years_later));
+}
+
+TEST(TimeTicksLogging, DoesNotMessUpFormattingFlags) {
+ std::ostringstream oss;
+ std::ios_base::fmtflags flags_before = oss.flags();
+ oss << TimeTicks();
+ EXPECT_EQ(flags_before, oss.flags());
+}
+
+TEST(TimeTicksLogging, DoesNotMakeStreamBad) {
+ std::ostringstream oss;
+ oss << TimeTicks();
+ EXPECT_TRUE(oss.good());
+}
+
+} // namespace
+
+} // namespace base