Home | History | Annotate | Download | only in platform
      1 // Copyright 2014 the V8 project 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 "src/base/platform/time.h"
      6 
      7 #if V8_OS_MACOSX
      8 #include <mach/mach_time.h>
      9 #endif
     10 #if V8_OS_POSIX
     11 #include <sys/time.h>
     12 #endif
     13 
     14 #if V8_OS_WIN
     15 #include "src/base/win32-headers.h"
     16 #endif
     17 
     18 #include "src/base/platform/elapsed-timer.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 
     21 namespace v8 {
     22 namespace base {
     23 
     24 TEST(TimeDelta, FromAndIn) {
     25   EXPECT_EQ(TimeDelta::FromDays(2), TimeDelta::FromHours(48));
     26   EXPECT_EQ(TimeDelta::FromHours(3), TimeDelta::FromMinutes(180));
     27   EXPECT_EQ(TimeDelta::FromMinutes(2), TimeDelta::FromSeconds(120));
     28   EXPECT_EQ(TimeDelta::FromSeconds(2), TimeDelta::FromMilliseconds(2000));
     29   EXPECT_EQ(TimeDelta::FromMilliseconds(2), TimeDelta::FromMicroseconds(2000));
     30   EXPECT_EQ(static_cast<int>(13), TimeDelta::FromDays(13).InDays());
     31   EXPECT_EQ(static_cast<int>(13), TimeDelta::FromHours(13).InHours());
     32   EXPECT_EQ(static_cast<int>(13), TimeDelta::FromMinutes(13).InMinutes());
     33   EXPECT_EQ(static_cast<int64_t>(13), TimeDelta::FromSeconds(13).InSeconds());
     34   EXPECT_DOUBLE_EQ(13.0, TimeDelta::FromSeconds(13).InSecondsF());
     35   EXPECT_EQ(static_cast<int64_t>(13),
     36             TimeDelta::FromMilliseconds(13).InMilliseconds());
     37   EXPECT_DOUBLE_EQ(13.0, TimeDelta::FromMilliseconds(13).InMillisecondsF());
     38   EXPECT_EQ(static_cast<int64_t>(13),
     39             TimeDelta::FromMicroseconds(13).InMicroseconds());
     40 }
     41 
     42 
     43 #if V8_OS_MACOSX
     44 TEST(TimeDelta, MachTimespec) {
     45   TimeDelta null = TimeDelta();
     46   EXPECT_EQ(null, TimeDelta::FromMachTimespec(null.ToMachTimespec()));
     47   TimeDelta delta1 = TimeDelta::FromMilliseconds(42);
     48   EXPECT_EQ(delta1, TimeDelta::FromMachTimespec(delta1.ToMachTimespec()));
     49   TimeDelta delta2 = TimeDelta::FromDays(42);
     50   EXPECT_EQ(delta2, TimeDelta::FromMachTimespec(delta2.ToMachTimespec()));
     51 }
     52 #endif
     53 
     54 
     55 TEST(Time, JsTime) {
     56   Time t = Time::FromJsTime(700000.3);
     57   EXPECT_DOUBLE_EQ(700000.3, t.ToJsTime());
     58 }
     59 
     60 
     61 #if V8_OS_POSIX
     62 TEST(Time, Timespec) {
     63   Time null;
     64   EXPECT_TRUE(null.IsNull());
     65   EXPECT_EQ(null, Time::FromTimespec(null.ToTimespec()));
     66   Time now = Time::Now();
     67   EXPECT_EQ(now, Time::FromTimespec(now.ToTimespec()));
     68   Time now_sys = Time::NowFromSystemTime();
     69   EXPECT_EQ(now_sys, Time::FromTimespec(now_sys.ToTimespec()));
     70   Time unix_epoch = Time::UnixEpoch();
     71   EXPECT_EQ(unix_epoch, Time::FromTimespec(unix_epoch.ToTimespec()));
     72   Time max = Time::Max();
     73   EXPECT_TRUE(max.IsMax());
     74   EXPECT_EQ(max, Time::FromTimespec(max.ToTimespec()));
     75 }
     76 
     77 
     78 TEST(Time, Timeval) {
     79   Time null;
     80   EXPECT_TRUE(null.IsNull());
     81   EXPECT_EQ(null, Time::FromTimeval(null.ToTimeval()));
     82   Time now = Time::Now();
     83   EXPECT_EQ(now, Time::FromTimeval(now.ToTimeval()));
     84   Time now_sys = Time::NowFromSystemTime();
     85   EXPECT_EQ(now_sys, Time::FromTimeval(now_sys.ToTimeval()));
     86   Time unix_epoch = Time::UnixEpoch();
     87   EXPECT_EQ(unix_epoch, Time::FromTimeval(unix_epoch.ToTimeval()));
     88   Time max = Time::Max();
     89   EXPECT_TRUE(max.IsMax());
     90   EXPECT_EQ(max, Time::FromTimeval(max.ToTimeval()));
     91 }
     92 #endif
     93 
     94 
     95 #if V8_OS_WIN
     96 TEST(Time, Filetime) {
     97   Time null;
     98   EXPECT_TRUE(null.IsNull());
     99   EXPECT_EQ(null, Time::FromFiletime(null.ToFiletime()));
    100   Time now = Time::Now();
    101   EXPECT_EQ(now, Time::FromFiletime(now.ToFiletime()));
    102   Time now_sys = Time::NowFromSystemTime();
    103   EXPECT_EQ(now_sys, Time::FromFiletime(now_sys.ToFiletime()));
    104   Time unix_epoch = Time::UnixEpoch();
    105   EXPECT_EQ(unix_epoch, Time::FromFiletime(unix_epoch.ToFiletime()));
    106   Time max = Time::Max();
    107   EXPECT_TRUE(max.IsMax());
    108   EXPECT_EQ(max, Time::FromFiletime(max.ToFiletime()));
    109 }
    110 #endif
    111 
    112 
    113 namespace {
    114 
    115 template <typename T>
    116 static void ResolutionTest(T (*Now)(), TimeDelta target_granularity) {
    117   // We're trying to measure that intervals increment in a VERY small amount
    118   // of time -- according to the specified target granularity. Unfortunately,
    119   // if we happen to have a context switch in the middle of our test, the
    120   // context switch could easily exceed our limit. So, we iterate on this
    121   // several times. As long as we're able to detect the fine-granularity
    122   // timers at least once, then the test has succeeded.
    123   static const TimeDelta kExpirationTimeout = TimeDelta::FromSeconds(1);
    124   ElapsedTimer timer;
    125   timer.Start();
    126   TimeDelta delta;
    127   do {
    128     T start = Now();
    129     T now = start;
    130     // Loop until we can detect that the clock has changed. Non-HighRes timers
    131     // will increment in chunks, i.e. 15ms. By spinning until we see a clock
    132     // change, we detect the minimum time between measurements.
    133     do {
    134       now = Now();
    135       delta = now - start;
    136     } while (now <= start);
    137     EXPECT_NE(static_cast<int64_t>(0), delta.InMicroseconds());
    138   } while (delta > target_granularity && !timer.HasExpired(kExpirationTimeout));
    139   EXPECT_LE(delta, target_granularity);
    140 }
    141 
    142 }  // namespace
    143 
    144 
    145 TEST(Time, NowResolution) {
    146   // We assume that Time::Now() has at least 16ms resolution.
    147   static const TimeDelta kTargetGranularity = TimeDelta::FromMilliseconds(16);
    148   ResolutionTest<Time>(&Time::Now, kTargetGranularity);
    149 }
    150 
    151 
    152 TEST(TimeTicks, NowResolution) {
    153   // We assume that TimeTicks::Now() has at least 16ms resolution.
    154   static const TimeDelta kTargetGranularity = TimeDelta::FromMilliseconds(16);
    155   ResolutionTest<TimeTicks>(&TimeTicks::Now, kTargetGranularity);
    156 }
    157 
    158 
    159 TEST(TimeTicks, HighResolutionNowResolution) {
    160   if (!TimeTicks::IsHighResolutionClockWorking()) return;
    161 
    162   // We assume that TimeTicks::HighResolutionNow() has sub-ms resolution.
    163   static const TimeDelta kTargetGranularity = TimeDelta::FromMilliseconds(1);
    164   ResolutionTest<TimeTicks>(&TimeTicks::HighResolutionNow, kTargetGranularity);
    165 }
    166 
    167 
    168 TEST(TimeTicks, IsMonotonic) {
    169   TimeTicks previous_normal_ticks;
    170   TimeTicks previous_highres_ticks;
    171   ElapsedTimer timer;
    172   timer.Start();
    173   while (!timer.HasExpired(TimeDelta::FromMilliseconds(100))) {
    174     TimeTicks normal_ticks = TimeTicks::Now();
    175     TimeTicks highres_ticks = TimeTicks::HighResolutionNow();
    176     EXPECT_GE(normal_ticks, previous_normal_ticks);
    177     EXPECT_GE((normal_ticks - previous_normal_ticks).InMicroseconds(), 0);
    178     EXPECT_GE(highres_ticks, previous_highres_ticks);
    179     EXPECT_GE((highres_ticks - previous_highres_ticks).InMicroseconds(), 0);
    180     previous_normal_ticks = normal_ticks;
    181     previous_highres_ticks = highres_ticks;
    182   }
    183 }
    184 
    185 }  // namespace base
    186 }  // namespace v8
    187