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 21namespace v8 { 22namespace base { 23 24TEST(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 44TEST(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 55TEST(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 62TEST(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 78TEST(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 96TEST(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 113namespace { 114 115template <typename T> 116static 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 145TEST(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 152TEST(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 159TEST(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 168TEST(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