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.
TEST(Time,TimeT)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
TEST(Time,FromExplodedWithMilliseconds)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
TEST(Time,ZeroIsSymmetric)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
TEST(Time,LocalExplode)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
TEST(Time,UTCExplode)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
TEST(Time,LocalMidnight)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
TEST(TimeTicks,Deltas)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
TEST(TimeTicks,HighResNow)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
TEST(TimeDelta,FromAndIn)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)
TEST(TimeDelta,TimeSpecConversion)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.
TEST(TimeDelta,WindowsEpoch)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