Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <time.h>
      6 
      7 #include "base/threading/platform_thread.h"
      8 #include "base/time.h"
      9 #include "build/build_config.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 using base::Time;
     13 using base::TimeDelta;
     14 using base::TimeTicks;
     15 
     16 // Test conversions to/from time_t and exploding/unexploding.
     17 TEST(Time, TimeT) {
     18   // C library time and exploded time.
     19   time_t now_t_1 = time(NULL);
     20   struct tm tms;
     21 #if defined(OS_WIN)
     22   localtime_s(&tms, &now_t_1);
     23 #elif defined(OS_POSIX)
     24   localtime_r(&now_t_1, &tms);
     25 #endif
     26 
     27   // Convert to ours.
     28   Time our_time_1 = Time::FromTimeT(now_t_1);
     29   Time::Exploded exploded;
     30   our_time_1.LocalExplode(&exploded);
     31 
     32   // This will test both our exploding and our time_t -> Time conversion.
     33   EXPECT_EQ(tms.tm_year + 1900, exploded.year);
     34   EXPECT_EQ(tms.tm_mon + 1, exploded.month);
     35   EXPECT_EQ(tms.tm_mday, exploded.day_of_month);
     36   EXPECT_EQ(tms.tm_hour, exploded.hour);
     37   EXPECT_EQ(tms.tm_min, exploded.minute);
     38   EXPECT_EQ(tms.tm_sec, exploded.second);
     39 
     40   // Convert exploded back to the time struct.
     41   Time our_time_2 = Time::FromLocalExploded(exploded);
     42   EXPECT_TRUE(our_time_1 == our_time_2);
     43 
     44   time_t now_t_2 = our_time_2.ToTimeT();
     45   EXPECT_EQ(now_t_1, now_t_2);
     46 
     47   EXPECT_EQ(10, Time().FromTimeT(10).ToTimeT());
     48   EXPECT_EQ(10.0, Time().FromTimeT(10).ToDoubleT());
     49 
     50   // Conversions of 0 should stay 0.
     51   EXPECT_EQ(0, Time().ToTimeT());
     52   EXPECT_EQ(0, Time::FromTimeT(0).ToInternalValue());
     53 }
     54 
     55 TEST(Time, FromExplodedWithMilliseconds) {
     56   // Some platform implementations of FromExploded are liable to drop
     57   // milliseconds if we aren't careful.
     58   Time now = Time::NowFromSystemTime();
     59   Time::Exploded exploded1 = {0};
     60   now.UTCExplode(&exploded1);
     61   exploded1.millisecond = 500;
     62   Time time = Time::FromUTCExploded(exploded1);
     63   Time::Exploded exploded2 = {0};
     64   time.UTCExplode(&exploded2);
     65   EXPECT_EQ(exploded1.millisecond, exploded2.millisecond);
     66 }
     67 
     68 TEST(Time, ZeroIsSymmetric) {
     69   Time zero_time(Time::FromTimeT(0));
     70   EXPECT_EQ(0, zero_time.ToTimeT());
     71 
     72   EXPECT_EQ(0.0, zero_time.ToDoubleT());
     73 }
     74 
     75 TEST(Time, LocalExplode) {
     76   Time a = Time::Now();
     77   Time::Exploded exploded;
     78   a.LocalExplode(&exploded);
     79 
     80   Time b = Time::FromLocalExploded(exploded);
     81 
     82   // The exploded structure doesn't have microseconds, and on Mac & Linux, the
     83   // internal OS conversion uses seconds, which will cause truncation. So we
     84   // can only make sure that the delta is within one second.
     85   EXPECT_TRUE((a - b) < TimeDelta::FromSeconds(1));
     86 }
     87 
     88 TEST(Time, UTCExplode) {
     89   Time a = Time::Now();
     90   Time::Exploded exploded;
     91   a.UTCExplode(&exploded);
     92 
     93   Time b = Time::FromUTCExploded(exploded);
     94   EXPECT_TRUE((a - b) < TimeDelta::FromSeconds(1));
     95 }
     96 
     97 TEST(Time, LocalMidnight) {
     98   Time::Exploded exploded;
     99   Time::Now().LocalMidnight().LocalExplode(&exploded);
    100   EXPECT_EQ(0, exploded.hour);
    101   EXPECT_EQ(0, exploded.minute);
    102   EXPECT_EQ(0, exploded.second);
    103   EXPECT_EQ(0, exploded.millisecond);
    104 }
    105 
    106 TEST(TimeTicks, Deltas) {
    107   for (int index = 0; index < 50; index++) {
    108     TimeTicks ticks_start = TimeTicks::Now();
    109     base::PlatformThread::Sleep(10);
    110     TimeTicks ticks_stop = TimeTicks::Now();
    111     TimeDelta delta = ticks_stop - ticks_start;
    112     // Note:  Although we asked for a 10ms sleep, if the
    113     // time clock has a finer granularity than the Sleep()
    114     // clock, it is quite possible to wakeup early.  Here
    115     // is how that works:
    116     //      Time(ms timer)      Time(us timer)
    117     //          5                   5010
    118     //          6                   6010
    119     //          7                   7010
    120     //          8                   8010
    121     //          9                   9000
    122     // Elapsed  4ms                 3990us
    123     //
    124     // Unfortunately, our InMilliseconds() function truncates
    125     // rather than rounds.  We should consider fixing this
    126     // so that our averages come out better.
    127     EXPECT_GE(delta.InMilliseconds(), 9);
    128     EXPECT_GE(delta.InMicroseconds(), 9000);
    129     EXPECT_EQ(delta.InSeconds(), 0);
    130   }
    131 }
    132 
    133 TEST(TimeTicks, HighResNow) {
    134 #if defined(OS_WIN)
    135   // HighResNow doesn't work on some systems.  Since the product still works
    136   // even if it doesn't work, it makes this entire test questionable.
    137   if (!TimeTicks::IsHighResClockWorking())
    138     return;
    139 #endif
    140 
    141   // Why do we loop here?
    142   // We're trying to measure that intervals increment in a VERY small amount
    143   // of time --  less than 15ms.  Unfortunately, if we happen to have a
    144   // context switch in the middle of our test, the context switch could easily
    145   // exceed our limit.  So, we iterate on this several times.  As long as we're
    146   // able to detect the fine-granularity timers at least once, then the test
    147   // has succeeded.
    148 
    149   const int kTargetGranularityUs = 15000;  // 15ms
    150 
    151   bool success = false;
    152   int retries = 100;  // Arbitrary.
    153   TimeDelta delta;
    154   while (!success && retries--) {
    155     TimeTicks ticks_start = TimeTicks::HighResNow();
    156     // Loop until we can detect that the clock has changed.  Non-HighRes timers
    157     // will increment in chunks, e.g. 15ms.  By spinning until we see a clock
    158     // change, we detect the minimum time between measurements.
    159     do {
    160       delta = TimeTicks::HighResNow() - ticks_start;
    161     } while (delta.InMilliseconds() == 0);
    162 
    163     if (delta.InMicroseconds() <= kTargetGranularityUs)
    164       success = true;
    165   }
    166 
    167   // In high resolution mode, we expect to see the clock increment
    168   // in intervals less than 15ms.
    169   EXPECT_TRUE(success);
    170 }
    171 
    172 TEST(TimeDelta, FromAndIn) {
    173   EXPECT_TRUE(TimeDelta::FromDays(2) == TimeDelta::FromHours(48));
    174   EXPECT_TRUE(TimeDelta::FromHours(3) == TimeDelta::FromMinutes(180));
    175   EXPECT_TRUE(TimeDelta::FromMinutes(2) == TimeDelta::FromSeconds(120));
    176   EXPECT_TRUE(TimeDelta::FromSeconds(2) == TimeDelta::FromMilliseconds(2000));
    177   EXPECT_TRUE(TimeDelta::FromMilliseconds(2) ==
    178               TimeDelta::FromMicroseconds(2000));
    179   EXPECT_EQ(13, TimeDelta::FromDays(13).InDays());
    180   EXPECT_EQ(13, TimeDelta::FromHours(13).InHours());
    181   EXPECT_EQ(13, TimeDelta::FromMinutes(13).InMinutes());
    182   EXPECT_EQ(13, TimeDelta::FromSeconds(13).InSeconds());
    183   EXPECT_EQ(13.0, TimeDelta::FromSeconds(13).InSecondsF());
    184   EXPECT_EQ(13, TimeDelta::FromMilliseconds(13).InMilliseconds());
    185   EXPECT_EQ(13.0, TimeDelta::FromMilliseconds(13).InMillisecondsF());
    186   EXPECT_EQ(13, TimeDelta::FromMicroseconds(13).InMicroseconds());
    187 }
    188 
    189 #if defined(OS_POSIX)
    190 TEST(TimeDelta, TimeSpecConversion) {
    191   struct timespec result = TimeDelta::FromSeconds(0).ToTimeSpec();
    192   EXPECT_EQ(result.tv_sec, 0);
    193   EXPECT_EQ(result.tv_nsec, 0);
    194 
    195   result = TimeDelta::FromSeconds(1).ToTimeSpec();
    196   EXPECT_EQ(result.tv_sec, 1);
    197   EXPECT_EQ(result.tv_nsec, 0);
    198 
    199   result = TimeDelta::FromMicroseconds(1).ToTimeSpec();
    200   EXPECT_EQ(result.tv_sec, 0);
    201   EXPECT_EQ(result.tv_nsec, 1000);
    202 
    203   result = TimeDelta::FromMicroseconds(
    204       Time::kMicrosecondsPerSecond + 1).ToTimeSpec();
    205   EXPECT_EQ(result.tv_sec, 1);
    206   EXPECT_EQ(result.tv_nsec, 1000);
    207 }
    208 #endif  // OS_POSIX
    209 
    210 // Our internal time format is serialized in things like databases, so it's
    211 // important that it's consistent across all our platforms.  We use the 1601
    212 // Windows epoch as the internal format across all platforms.
    213 TEST(TimeDelta, WindowsEpoch) {
    214   Time::Exploded exploded;
    215   exploded.year = 1970;
    216   exploded.month = 1;
    217   exploded.day_of_week = 0;  // Should be unusued.
    218   exploded.day_of_month = 1;
    219   exploded.hour = 0;
    220   exploded.minute = 0;
    221   exploded.second = 0;
    222   exploded.millisecond = 0;
    223   Time t = Time::FromUTCExploded(exploded);
    224   // Unix 1970 epoch.
    225   EXPECT_EQ(GG_INT64_C(11644473600000000), t.ToInternalValue());
    226 
    227   // We can't test 1601 epoch, since the system time functions on Linux
    228   // only compute years starting from 1900.
    229 }
    230