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