chromium/base/time/time_unittest.cc

// Copyright 2012 The Chromium Authors
// 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 <optional>
#include <string>

#include "base/build_time.h"
#include "base/check_op.h"
#include "base/compiler_specific.h"
#include "base/environment.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/to_string.h"
#include "base/test/gtest_util.h"
#include "base/threading/platform_thread.h"
#include "base/time/time_override.h"
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/icu/source/common/unicode/utypes.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"

#if BUILDFLAG(IS_ANDROID)
#include "base/android/jni_android.h"
#elif BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_CHROMEOS)
#include "base/test/icu_test_util.h"
#elif BUILDFLAG(IS_WIN)
#include <windows.h>
#endif

namespace base {

namespace {

#if BUILDFLAG(IS_FUCHSIA)
// Hawaii does not observe daylight saving time, which is useful for having a
// constant offset when faking the time zone.
const char kHonoluluTimeZoneId[] = "Pacific/Honolulu";
const int kHonoluluOffsetHours = -10;
const int kHonoluluOffsetSeconds = kHonoluluOffsetHours * 60 * 60;
#endif

#if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_CHROMEOS)

const char kThaiLocale[] = "th-TH";
const char kBangkokTimeZoneId[] = "Asia/Bangkok";

// Returns the total offset (including Daylight Saving Time) of the timezone
// with |timezone_id| at |time|, or std::nullopt in case of failure.
std::optional<base::TimeDelta> GetTimeZoneOffsetAtTime(const char* timezone_id,
                                                       Time time) {
  std::unique_ptr<icu::TimeZone> tz(icu::TimeZone::createTimeZone(timezone_id));
  if (*tz == icu::TimeZone::getUnknown()) {
    return {};
  }
  int32_t raw_offset = 0;
  int32_t dst_offset = 0;
  UErrorCode ec = U_ZERO_ERROR;
  tz->getOffset(time.InSecondsFSinceUnixEpoch(), false, raw_offset, dst_offset,
                ec);
  if (!U_SUCCESS(ec)) {
    return {};
  }
  return base::Milliseconds(raw_offset + dst_offset);
}

TimeDelta TimePassedAfterMidnight(const Time::Exploded& time) {
  return base::Hours(time.hour) + base::Minutes(time.minute) +
         base::Seconds(time.second) + base::Milliseconds(time.millisecond);
}

// Timezone environment variable

class ScopedLibcTZ {
 public:
  explicit ScopedLibcTZ(const std::string& timezone) {
    auto env = base::Environment::Create();
    std::string old_timezone_value;
    if (env->GetVar(kTZ, &old_timezone_value)) {
      old_timezone_ = old_timezone_value;
    }
    if (!env->SetVar(kTZ, timezone)) {
      success_ = false;
    }
    tzset();
  }

  ~ScopedLibcTZ() {
    auto env = base::Environment::Create();
    if (old_timezone_.has_value()) {
      CHECK(env->SetVar(kTZ, old_timezone_.value()));
    } else {
      CHECK(env->UnSetVar(kTZ));
    }
  }

  ScopedLibcTZ(const ScopedLibcTZ& other) = delete;
  ScopedLibcTZ& operator=(const ScopedLibcTZ& other) = delete;

  bool is_success() const { return success_; }

 private:
  static constexpr char kTZ[] = "TZ";

  bool success_ = true;
  std::optional<std::string> old_timezone_;
};

constexpr char ScopedLibcTZ::kTZ[];

#endif  //  BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_CHROMEOS)

TEST(TimeTestOutOfBounds, FromExplodedOutOfBoundsTime) {}

// 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 {};

// Test conversion to/from TimeDeltas elapsed since the Windows epoch.
// Conversions should be idempotent and non-lossy.
TEST_F(TimeTest, DeltaSinceWindowsEpoch) {}

// Test conversion to/from time_t.
TEST_F(TimeTest, TimeT) {}

// Test conversions to/from time_t and exploding/unexploding (utc time).
TEST_F(TimeTest, UTCTimeT) {}

// Test conversions to/from time_t and exploding/unexploding (local time).
TEST_F(TimeTest, LocalTimeT) {}

// Test conversions to/from javascript time.
TEST_F(TimeTest, JsTime) {}

#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
TEST_F(TimeTest, FromTimeVal) {}
#endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)

TEST_F(TimeTest, FromExplodedWithMilliseconds) {}

TEST_F(TimeTest, ZeroIsSymmetric) {}

// Note that this test does not check whether the implementation correctly
// accounts for the local time zone.
TEST_F(TimeTest, LocalExplode) {}

TEST_F(TimeTest, UTCExplode) {}

TEST_F(TimeTest, UTCMidnight) {}

// Note that this test does not check whether the implementation correctly
// accounts for the local time zone.
TEST_F(TimeTest, LocalMidnight) {}

// These tests require the ability to fake the local time zone.
#if BUILDFLAG(IS_FUCHSIA)
TEST_F(TimeTest, LocalExplodeIsLocal) {
  // Set the default time zone to a zone with an offset different from UTC.
  test::ScopedRestoreDefaultTimezone honolulu_time(kHonoluluTimeZoneId);

  // The member contains useful values for this test, which uses it as UTC.
  Time comparison_time_utc(comparison_time_local_);

  Time::Exploded utc_exploded;
  comparison_time_utc.UTCExplode(&utc_exploded);

  Time::Exploded local_exploded;
  comparison_time_utc.LocalExplode(&local_exploded);

  // The year, month, and day are the same because the (negative) offset is
  // smaller than the hour in the test time. Similarly, there is no underflow
  // for hour.
  EXPECT_EQ(utc_exploded.year, local_exploded.year);
  EXPECT_EQ(utc_exploded.month, local_exploded.month);
  EXPECT_EQ(utc_exploded.day_of_week, local_exploded.day_of_week);
  EXPECT_EQ(utc_exploded.day_of_month, local_exploded.day_of_month);
  EXPECT_EQ(utc_exploded.hour + kHonoluluOffsetHours, local_exploded.hour);
  EXPECT_EQ(utc_exploded.minute, local_exploded.minute);
  EXPECT_EQ(utc_exploded.second, local_exploded.second);
  EXPECT_EQ(utc_exploded.millisecond, local_exploded.millisecond);

  Time time_from_local_exploded;
  EXPECT_TRUE(
      Time::FromLocalExploded(local_exploded, &time_from_local_exploded));

  EXPECT_EQ(comparison_time_utc, time_from_local_exploded);

  // Unexplode the local time using the non-local method.
  // The resulting time should be offset hours earlier.
  Time time_from_utc_exploded;
  EXPECT_TRUE(Time::FromUTCExploded(local_exploded, &time_from_utc_exploded));
  EXPECT_EQ(comparison_time_utc + Hours(kHonoluluOffsetHours),
            time_from_utc_exploded);
}

TEST_F(TimeTest, LocalMidnightIsLocal) {
  // Set the default time zone to a zone with an offset different from UTC.
  test::ScopedRestoreDefaultTimezone honolulu_time(kHonoluluTimeZoneId);

  // The member contains useful values for this test, which uses it as UTC.
  Time comparison_time_utc(comparison_time_local_);

  Time::Exploded utc_midnight_exploded;
  comparison_time_utc.UTCMidnight().UTCExplode(&utc_midnight_exploded);

  // Local midnight exploded in UTC will have an offset hour instead of 0.
  Time::Exploded local_midnight_utc_exploded;
  comparison_time_utc.LocalMidnight().UTCExplode(&local_midnight_utc_exploded);

  // The year, month, and day are the same because the (negative) offset is
  // smaller than the hour in the test time and thus both midnights round down
  // on the same day.
  EXPECT_EQ(utc_midnight_exploded.year, local_midnight_utc_exploded.year);
  EXPECT_EQ(utc_midnight_exploded.month, local_midnight_utc_exploded.month);
  EXPECT_EQ(utc_midnight_exploded.day_of_week,
            local_midnight_utc_exploded.day_of_week);
  EXPECT_EQ(utc_midnight_exploded.day_of_month,
            local_midnight_utc_exploded.day_of_month);
  EXPECT_EQ(0, utc_midnight_exploded.hour);
  EXPECT_EQ(0 - kHonoluluOffsetHours, local_midnight_utc_exploded.hour);
  EXPECT_EQ(0, local_midnight_utc_exploded.minute);
  EXPECT_EQ(0, local_midnight_utc_exploded.second);
  EXPECT_EQ(0, local_midnight_utc_exploded.millisecond);

  // Local midnight exploded in local time will have no offset.
  Time::Exploded local_midnight_exploded;
  comparison_time_utc.LocalMidnight().LocalExplode(&local_midnight_exploded);

  EXPECT_EQ(utc_midnight_exploded.year, local_midnight_exploded.year);
  EXPECT_EQ(utc_midnight_exploded.month, local_midnight_exploded.month);
  EXPECT_EQ(utc_midnight_exploded.day_of_week,
            local_midnight_exploded.day_of_week);
  EXPECT_EQ(utc_midnight_exploded.day_of_month,
            local_midnight_exploded.day_of_month);
  EXPECT_EQ(0, local_midnight_exploded.hour);
  EXPECT_EQ(0, local_midnight_exploded.minute);
  EXPECT_EQ(0, local_midnight_exploded.second);
  EXPECT_EQ(0, local_midnight_exploded.millisecond);
}
#endif  // BUILDFLAG(IS_FUCHSIA)

TEST_F(TimeTest, ParseTimeTest1) {}

TEST_F(TimeTest, DayOfWeekSunday) {}

TEST_F(TimeTest, DayOfWeekWednesday) {}

TEST_F(TimeTest, DayOfWeekSaturday) {}

TEST_F(TimeTest, ParseTimeTest2) {}

TEST_F(TimeTest, ParseTimeTest3) {}

TEST_F(TimeTest, ParseTimeTest4) {}

TEST_F(TimeTest, ParseTimeTest5) {}

TEST_F(TimeTest, ParseTimeTest6) {}

TEST_F(TimeTest, ParseTimeTest7) {}

TEST_F(TimeTest, ParseTimeTest8) {}

TEST_F(TimeTest, ParseTimeTest9) {}

TEST_F(TimeTest, ParseTimeTest10) {}

TEST_F(TimeTest, ParseTimeTest11) {}

// Test some of edge cases around epoch, etc.
TEST_F(TimeTest, ParseTimeTestEpoch0) {}

TEST_F(TimeTest, ParseTimeTestEpoch1) {}

TEST_F(TimeTest, ParseTimeTestEpoch2) {}

TEST_F(TimeTest, ParseTimeTestEpochNeg1) {}

// If time_t is 32 bits, a date after year 2038 will overflow time_t and
// cause timegm() to return -1.  The parsed time should not be 1 second
// before epoch.
TEST_F(TimeTest, ParseTimeTestEpochNotNeg1) {}

TEST_F(TimeTest, ParseTimeTestEpochNeg2) {}

TEST_F(TimeTest, ParseTimeTestEpoch1960) {}

TEST_F(TimeTest, ParseTimeTestEmpty) {}

TEST_F(TimeTest, ParseTimeTestInvalidString) {}

TEST_F(TimeTest, ExplodeBeforeUnixEpoch) {}

TEST_F(TimeTest, Max) {}

TEST_F(TimeTest, MaxConversions) {}

TEST_F(TimeTest, Min) {}

TEST_F(TimeTest, TimeTOverflow) {}

#if BUILDFLAG(IS_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;
  EXPECT_TRUE(Time::FromLocalExploded(midnight, &t));
  EXPECT_EQ(1381633200, t.ToTimeT());
}
#endif  // BUILDFLAG(IS_ANDROID)

// Regression test for https://crbug.com/1104442
TEST_F(TimeTest, Explode_Y10KCompliance) {}

#if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_CHROMEOS)
// Regression tests for https://crbug.com/1198313: base::Time::UTCExplode and
// base::Time::LocalExplode should not be locale-dependent.
TEST_F(TimeTest, UTCExplodedIsLocaleIndependent) {
  // Time-to-Exploded could be using libc or ICU functions.
  // Set the ICU locale and timezone and the libc timezone.
  // We're not setting the libc locale because the libc time functions are
  // locale-independent and the th_TH.utf8 locale was not available on all
  // trybots at the time this test was added.
  // th-TH maps to a non-gregorian calendar.
  test::ScopedRestoreICUDefaultLocale scoped_icu_locale(kThaiLocale);
  test::ScopedRestoreDefaultTimezone scoped_timezone(kBangkokTimeZoneId);
  ScopedLibcTZ scoped_libc_tz(kBangkokTimeZoneId);
  ASSERT_TRUE(scoped_libc_tz.is_success());

  Time::Exploded utc_exploded_orig;
  utc_exploded_orig.year = 2020;
  utc_exploded_orig.month = 7;
  utc_exploded_orig.day_of_week = 5;  // Friday
  utc_exploded_orig.day_of_month = 3;
  utc_exploded_orig.hour = 12;
  utc_exploded_orig.minute = 0;
  utc_exploded_orig.second = 0;
  utc_exploded_orig.millisecond = 0;

  Time time;
  ASSERT_TRUE(base::Time::FromUTCExploded(utc_exploded_orig, &time));

  // Round trip to UTC Exploded should produce the exact same result.
  Time::Exploded utc_exploded;
  time.UTCExplode(&utc_exploded);
  EXPECT_EQ(utc_exploded_orig.year, utc_exploded.year);
  EXPECT_EQ(utc_exploded_orig.month, utc_exploded.month);
  EXPECT_EQ(utc_exploded_orig.day_of_week, utc_exploded.day_of_week);
  EXPECT_EQ(utc_exploded_orig.day_of_month, utc_exploded.day_of_month);
  EXPECT_EQ(utc_exploded_orig.hour, utc_exploded.hour);
  EXPECT_EQ(utc_exploded_orig.minute, utc_exploded.minute);
  EXPECT_EQ(utc_exploded_orig.second, utc_exploded.second);
  EXPECT_EQ(utc_exploded_orig.millisecond, utc_exploded.millisecond);
}

TEST_F(TimeTest, LocalExplodedIsLocaleIndependent) {
  // Time-to-Exploded could be using libc or ICU functions.
  // Set the ICU locale and timezone and the libc timezone.
  // We're not setting the libc locale because the libc time functions are
  // locale-independent and the th_TH.utf8 locale was not available on all
  // trybots at the time this test was added.
  // th-TH maps to a non-gregorian calendar.
  test::ScopedRestoreICUDefaultLocale scoped_icu_locale(kThaiLocale);
  test::ScopedRestoreDefaultTimezone scoped_timezone(kBangkokTimeZoneId);
  ScopedLibcTZ scoped_libc_tz(kBangkokTimeZoneId);
  ASSERT_TRUE(scoped_libc_tz.is_success());

  Time::Exploded utc_exploded_orig;
  utc_exploded_orig.year = 2020;
  utc_exploded_orig.month = 7;
  utc_exploded_orig.day_of_week = 5;  // Friday
  utc_exploded_orig.day_of_month = 3;
  utc_exploded_orig.hour = 12;
  utc_exploded_orig.minute = 0;
  utc_exploded_orig.second = 0;
  utc_exploded_orig.millisecond = 0;

  Time time;
  ASSERT_TRUE(base::Time::FromUTCExploded(utc_exploded_orig, &time));

  std::optional<TimeDelta> expected_delta =
      GetTimeZoneOffsetAtTime(kBangkokTimeZoneId, time);

  ASSERT_TRUE(expected_delta.has_value());

  // This is to be sure that the day has not changed
  ASSERT_LT(*expected_delta, base::Hours(12));

  Time::Exploded local_exploded;
  time.LocalExplode(&local_exploded);

  TimeDelta actual_delta = TimePassedAfterMidnight(local_exploded) -
                           TimePassedAfterMidnight(utc_exploded_orig);

  EXPECT_EQ(utc_exploded_orig.year, local_exploded.year);
  EXPECT_EQ(utc_exploded_orig.month, local_exploded.month);
  EXPECT_EQ(utc_exploded_orig.day_of_week, local_exploded.day_of_week);
  EXPECT_EQ(utc_exploded_orig.day_of_month, local_exploded.day_of_month);
  EXPECT_EQ(actual_delta, *expected_delta);
}
#endif  // BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_CHROMEOS)

TEST_F(TimeTest, FromExploded_MinMax) {}

class TimeOverride {};

// static
Time TimeOverride::now_time_;

// Disabled on Android due to flakes; see https://crbug.com/1474884.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_NowOverride
#else
#define MAYBE_NowOverride
#endif
TEST_F(TimeTest, MAYBE_NowOverride) {}

#undef MAYBE_NowOverride

#if BUILDFLAG(IS_FUCHSIA)
TEST(ZxTimeTest, ToFromConversions) {
  Time unix_epoch = Time::UnixEpoch();
  EXPECT_EQ(unix_epoch.ToZxTime(), 0);
  EXPECT_EQ(Time::FromZxTime(6000000000), unix_epoch + Seconds(6));

  TimeTicks ticks_now = TimeTicks::Now();
  EXPECT_GE(ticks_now.ToZxTime(), 0);
  TimeTicks ticks_later = ticks_now + Seconds(2);
  EXPECT_EQ((ticks_later.ToZxTime() - ticks_now.ToZxTime()), 2000000000);
  EXPECT_EQ(TimeTicks::FromZxTime(3000000000), TimeTicks() + Seconds(3));

  EXPECT_EQ(TimeDelta().ToZxDuration(), 0);
  EXPECT_EQ(TimeDelta::FromZxDuration(0), TimeDelta());

  EXPECT_EQ(Seconds(2).ToZxDuration(), 2000000000);
  EXPECT_EQ(TimeDelta::FromZxDuration(4000000000), Seconds(4));
}
#endif  // BUILDFLAG(IS_FUCHSIA)

TEST(TimeTicks, Deltas) {}

static void HighResClockTest(TimeTicks (*GetTicks)()) {}

TEST(TimeTicks, HighRes) {}

class TimeTicksOverride {};

// static
TimeTicks TimeTicksOverride::now_ticks_;

TEST(TimeTicks, NowOverride) {}

class ThreadTicksOverride {};

// static
ThreadTicks ThreadTicksOverride::now_ticks_;

// IOS doesn't support ThreadTicks::Now().
#if BUILDFLAG(IS_IOS)
#define MAYBE_NowOverride
#else
#define MAYBE_NowOverride
#endif
TEST(ThreadTicks, MAYBE_NowOverride) {}

TEST(ThreadTicks, ThreadNow) {}

TEST(TimeTicks, SnappedToNextTickBasic) {}

TEST(TimeTicks, SnappedToNextTickOverflow) {}

#if BUILDFLAG(IS_ANDROID)
TEST(TimeTicks, Android_FromUptimeMillis_ClocksMatch) {
  JNIEnv* const env = android::AttachCurrentThread();
  android::ScopedJavaLocalRef<jclass> clazz(
      android::GetClass(env, "android/os/SystemClock"));
  ASSERT_TRUE(clazz.obj());
  const jmethodID method_id =
      android::MethodID::Get<android::MethodID::TYPE_STATIC>(
          env, clazz.obj(), "uptimeMillis", "()J");
  ASSERT_FALSE(!method_id);
  // Subtract 1ms from the expected lower bound to allow millisecond-level
  // truncation performed in uptimeMillis().
  const TimeTicks lower_bound_ticks = TimeTicks::Now() - Milliseconds(1);
  const TimeTicks converted_ticks = TimeTicks::FromUptimeMillis(
      env->CallStaticLongMethod(clazz.obj(), method_id));
  const TimeTicks upper_bound_ticks = TimeTicks::Now();
  EXPECT_LE(lower_bound_ticks, converted_ticks);
  EXPECT_GE(upper_bound_ticks, converted_ticks);
}

TEST(TimeTicks, Android_FromJavaNanoTime_ClocksMatch) {
  JNIEnv* const env = android::AttachCurrentThread();
  android::ScopedJavaLocalRef<jclass> clazz(
      android::GetClass(env, "java/lang/System"));
  ASSERT_TRUE(clazz.obj());
  const jmethodID method_id =
      android::MethodID::Get<android::MethodID::TYPE_STATIC>(env, clazz.obj(),
                                                             "nanoTime", "()J");
  ASSERT_FALSE(!method_id);
  const TimeTicks lower_bound_ticks = TimeTicks::Now();
  const TimeTicks converted_ticks = TimeTicks::FromJavaNanoTime(
      env->CallStaticLongMethod(clazz.obj(), method_id));
  // Add 1us to the expected upper bound to allow microsecond-level
  // truncation performed in TimeTicks::Now().
  const TimeTicks upper_bound_ticks = TimeTicks::Now() + Microseconds(1);
  EXPECT_LE(lower_bound_ticks, converted_ticks);
  EXPECT_GE(upper_bound_ticks, converted_ticks);
}
#endif  // BUILDFLAG(IS_ANDROID)

class LiveTicksOverride {};

// static
LiveTicks LiveTicksOverride::now_ticks_;

TEST(LiveTicks, NowOverride) {}

TEST(TimeDelta, FromAndIn) {}

TEST(TimeDelta, InRoundsTowardsZero) {}

TEST(TimeDelta, InDaysFloored) {}

TEST(TimeDelta, InSecondsFloored) {}

TEST(TimeDelta, InMillisecondsRoundedUp) {}

// Check that near-min/max values saturate rather than overflow when converted
// lossily with InXXX() functions.  Only integral hour, minute, and nanosecond
// conversions are checked, since those are the only cases where the return type
// is small enough for saturation or overflow to occur.
TEST(TimeDelta, InXXXOverflow) {}

#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
TEST(TimeDelta, TimeSpecConversion) {}
#endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)

// 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) {}

TEST(TimeDelta, Hz) {}

TEST(TimeDelta, Magnitude) {}

TEST(TimeDelta, ZeroMinMax) {}

TEST(TimeDelta, MaxConversions) {}

TEST(TimeDelta, MinConversions) {}

TEST(TimeDelta, FiniteMaxMin) {}

TEST(TimeDelta, NumericOperators) {}

// Basic test of operators between TimeDeltas (without overflow -- next test
// handles overflow).
TEST(TimeDelta, TimeDeltaOperators) {}

TEST(TimeDelta, Overflows) {}

TEST(TimeDelta, CeilToMultiple) {}

TEST(TimeDelta, FloorToMultiple) {}

TEST(TimeDelta, RoundToMultiple) {}

TEST(TimeBase, AddSubDeltaSaturates) {}

TEST(TimeBase, AddSubInfinities) {}

constexpr TimeTicks TestTimeTicksConstexprCopyAssignment() {}

TEST(TimeTicks, ConstexprAndTriviallyCopiable) {}

constexpr ThreadTicks TestThreadTicksConstexprCopyAssignment() {}

TEST(ThreadTicks, ConstexprAndTriviallyCopiable) {}

constexpr TimeDelta TestTimeDeltaConstexprCopyAssignment() {}

TEST(TimeDelta, ConstexprAndTriviallyCopiable) {}

TEST(TimeDeltaLogging, DCheckEqCompiles) {}

TEST(TimeDeltaLogging, EmptyIsZero) {}

TEST(TimeDeltaLogging, FiveHundredMs) {}

TEST(TimeDeltaLogging, MinusTenSeconds) {}

TEST(TimeDeltaLogging, DoesNotMessUpFormattingFlags) {}

TEST(TimeDeltaLogging, DoesNotMakeStreamBad) {}

TEST(TimeLogging, DCheckEqCompiles) {}

TEST(TimeLogging, ChromeBirthdate) {}

TEST(TimeLogging, Microseconds) {}

TEST(TimeLogging, DoesNotMessUpFormattingFlags) {}

TEST(TimeLogging, DoesNotMakeStreamBad) {}

TEST(TimeTicksLogging, DCheckEqCompiles) {}

TEST(TimeTicksLogging, ZeroTime) {}

TEST(TimeTicksLogging, FortyYearsLater) {}

TEST(TimeTicksLogging, DoesNotMessUpFormattingFlags) {}

TEST(TimeTicksLogging, DoesNotMakeStreamBad) {}

}  // namespace

}  // namespace base