1 | /* |
2 | * Copyright 2017-present Facebook, Inc. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | #include <folly/chrono/Conv.h> |
17 | |
18 | #include <folly/portability/GTest.h> |
19 | |
20 | using namespace folly; |
21 | using namespace std::chrono; |
22 | using namespace std::chrono_literals; |
23 | |
24 | namespace { |
25 | /** |
26 | * A helper function to create a time_point even if the input duration type has |
27 | * finer resolution than the clock duration type. |
28 | */ |
29 | template <typename Clock, typename Duration> |
30 | typename Clock::time_point createTimePoint(const Duration& d) { |
31 | return typename Clock::time_point( |
32 | std::chrono::duration_cast<typename Clock::duration>(d)); |
33 | } |
34 | } // namespace |
35 | |
36 | TEST(Conv, timespecToStdChrono) { |
37 | struct timespec ts; |
38 | |
39 | ts.tv_sec = 0; |
40 | ts.tv_nsec = 10; |
41 | EXPECT_EQ(10ns, to<nanoseconds>(ts)); |
42 | EXPECT_EQ(0us, to<microseconds>(ts)); |
43 | EXPECT_EQ(0ms, to<milliseconds>(ts)); |
44 | EXPECT_EQ(0s, to<seconds>(ts)); |
45 | |
46 | ts.tv_sec = 1; |
47 | ts.tv_nsec = 10; |
48 | EXPECT_EQ(1000000010ns, to<nanoseconds>(ts)); |
49 | EXPECT_EQ(1000000us, to<microseconds>(ts)); |
50 | EXPECT_EQ(1000ms, to<milliseconds>(ts)); |
51 | EXPECT_EQ(1s, to<seconds>(ts)); |
52 | EXPECT_EQ( |
53 | createTimePoint<system_clock>(1000000010ns), |
54 | to<system_clock::time_point>(ts)); |
55 | EXPECT_EQ( |
56 | createTimePoint<steady_clock>(1000000010ns), |
57 | to<steady_clock::time_point>(ts)); |
58 | |
59 | // Test a non-canonical value with tv_nsec larger than 1 second |
60 | ts.tv_sec = 5; |
61 | ts.tv_nsec = 3219876543; |
62 | // Beware about using std::chrono_literals suffixes with very literals: |
63 | // older versions of GCC are buggy and would truncate these to 32-bits. |
64 | EXPECT_EQ(8219876543LL, to<nanoseconds>(ts).count()); |
65 | EXPECT_EQ(8219876us, to<microseconds>(ts)); |
66 | EXPECT_EQ(8219ms, to<milliseconds>(ts)); |
67 | EXPECT_EQ(8s, to<seconds>(ts)); |
68 | EXPECT_EQ( |
69 | createTimePoint<system_clock>(nanoseconds(8219876543LL)), |
70 | to<system_clock::time_point>(ts)); |
71 | EXPECT_EQ( |
72 | createTimePoint<steady_clock>(nanoseconds(8219876543LL)), |
73 | to<steady_clock::time_point>(ts)); |
74 | |
75 | // Test negative values |
76 | // When going to coarser grained types these should be rounded up towards 0. |
77 | ts.tv_sec = -5; |
78 | ts.tv_nsec = 123456; |
79 | EXPECT_EQ(-4999876544, to<nanoseconds>(ts).count()); |
80 | EXPECT_EQ(-4999876544, duration_cast<nanoseconds>(-5s + 123456ns).count()); |
81 | EXPECT_EQ(-4999876, to<microseconds>(ts).count()); |
82 | EXPECT_EQ(-4999876, duration_cast<microseconds>(-5s + 123456ns).count()); |
83 | EXPECT_EQ(-4999, to<milliseconds>(ts).count()); |
84 | EXPECT_EQ(-4999, duration_cast<milliseconds>(-5s + 123456ns).count()); |
85 | EXPECT_EQ(-4s, to<seconds>(ts)); |
86 | EXPECT_EQ(-4, duration_cast<seconds>(-5s + 123456ns).count()); |
87 | ts.tv_sec = -7200; |
88 | ts.tv_nsec = 123456; |
89 | EXPECT_EQ(-1h, to<hours>(ts)); |
90 | EXPECT_EQ( |
91 | -1, |
92 | duration_cast<hours>(seconds{ts.tv_sec} + nanoseconds{ts.tv_nsec}) |
93 | .count()); |
94 | ts.tv_sec = -7000; |
95 | ts.tv_nsec = 123456; |
96 | EXPECT_EQ(-1h, to<hours>(ts)); |
97 | EXPECT_EQ( |
98 | -1, |
99 | duration_cast<hours>(seconds{ts.tv_sec} + nanoseconds{ts.tv_nsec}) |
100 | .count()); |
101 | ts.tv_sec = -7201; |
102 | ts.tv_nsec = 123456; |
103 | EXPECT_EQ(-2h, to<hours>(ts)); |
104 | EXPECT_EQ( |
105 | -2, |
106 | duration_cast<hours>(seconds{ts.tv_sec} + nanoseconds{ts.tv_nsec}) |
107 | .count()); |
108 | |
109 | // Test converions to floating point durations |
110 | ts.tv_sec = 1; |
111 | ts.tv_nsec = 500000000; |
112 | EXPECT_EQ(1.5, to<duration<double>>(ts).count()); |
113 | ts.tv_sec = -1; |
114 | ts.tv_nsec = 500000000; |
115 | EXPECT_EQ(-0.5, to<duration<double>>(ts).count()); |
116 | ts.tv_sec = -1; |
117 | ts.tv_nsec = -500000000; |
118 | EXPECT_EQ(-1.5, to<duration<double>>(ts).count()); |
119 | ts.tv_sec = 1; |
120 | ts.tv_nsec = 500000000; |
121 | auto doubleNanos = to<duration<double, std::nano>>(ts); |
122 | EXPECT_EQ(1500000000, doubleNanos.count()); |
123 | ts.tv_sec = 90; |
124 | ts.tv_nsec = 0; |
125 | auto doubleMinutes = to<duration<double, std::ratio<60>>>(ts); |
126 | EXPECT_EQ(1.5, doubleMinutes.count()); |
127 | |
128 | // Test with unusual durations where neither the numerator nor denominator |
129 | // are 1. |
130 | using five_sevenths = std::chrono::duration<int64_t, std::ratio<5, 7>>; |
131 | ts.tv_sec = 1; |
132 | ts.tv_nsec = 0; |
133 | EXPECT_EQ(1, to<five_sevenths>(ts).count()); |
134 | ts.tv_sec = 1; |
135 | ts.tv_nsec = 428571500; |
136 | EXPECT_EQ(2, to<five_sevenths>(ts).count()); |
137 | |
138 | using thirteen_thirds = std::chrono::duration<double, std::ratio<13, 3>>; |
139 | ts.tv_sec = 39; |
140 | ts.tv_nsec = 0; |
141 | EXPECT_NEAR(9.0, to<thirteen_thirds>(ts).count(), 0.000000001); |
142 | ts.tv_sec = 1; |
143 | ts.tv_nsec = 0; |
144 | EXPECT_NEAR(0.230769230, to<thirteen_thirds>(ts).count(), 0.000000001); |
145 | } |
146 | |
147 | TEST(Conv, timespecToStdChronoOverflow) { |
148 | struct timespec ts; |
149 | |
150 | // All of our boundary conditions below assume time_t is int64_t. |
151 | // This is true on most modern platforms. |
152 | if (!std::is_same<decltype(ts.tv_sec), int64_t>::value) { |
153 | LOG(INFO) << "skipping most overflow tests: time_t is not int64_t" ; |
154 | } else { |
155 | // Test the upper boundary of conversion to uint64_t nanoseconds |
156 | using nsec_u64 = std::chrono::duration<uint64_t, std::nano>; |
157 | ts.tv_sec = 18446744073; |
158 | ts.tv_nsec = 709551615; |
159 | EXPECT_EQ(std::numeric_limits<uint64_t>::max(), to<nsec_u64>(ts).count()); |
160 | |
161 | ts.tv_nsec += 1; |
162 | EXPECT_THROW(to<nsec_u64>(ts), std::range_error); |
163 | |
164 | // Test the lower boundary of conversion to uint64_t nanoseconds |
165 | ts.tv_sec = 0; |
166 | ts.tv_nsec = 0; |
167 | EXPECT_EQ(0, to<nsec_u64>(ts).count()); |
168 | ts.tv_sec = -1; |
169 | ts.tv_nsec = 0; |
170 | EXPECT_THROW(to<nsec_u64>(ts), std::range_error); |
171 | |
172 | // Test the upper boundary of conversion to int64_t microseconds |
173 | using usec_i64 = std::chrono::duration<int64_t, std::micro>; |
174 | ts.tv_sec = 9223372036854LL; |
175 | ts.tv_nsec = 775807000; |
176 | EXPECT_EQ(std::numeric_limits<int64_t>::max(), to<usec_i64>(ts).count()); |
177 | |
178 | ts.tv_nsec += 1; |
179 | EXPECT_THROW(to<usec_i64>(ts), std::range_error); |
180 | |
181 | // Test the lower boundary of conversion to int64_t microseconds |
182 | ts.tv_sec = -9223372036855LL; |
183 | ts.tv_nsec = 224192000; |
184 | EXPECT_EQ(std::numeric_limits<int64_t>::min(), to<usec_i64>(ts).count()); |
185 | |
186 | ts.tv_nsec -= 1; |
187 | EXPECT_THROW(to<usec_i64>(ts), std::range_error); |
188 | |
189 | // Test the boundaries of conversion to int32_t seconds |
190 | using sec_i32 = std::chrono::duration<int32_t>; |
191 | ts.tv_sec = 2147483647; |
192 | ts.tv_nsec = 0; |
193 | EXPECT_EQ(std::numeric_limits<int32_t>::max(), to<sec_i32>(ts).count()); |
194 | ts.tv_nsec = 1000000000; |
195 | EXPECT_THROW(to<sec_i32>(ts), std::range_error); |
196 | ts.tv_sec = -2147483648; |
197 | ts.tv_nsec = 0; |
198 | EXPECT_EQ(std::numeric_limits<int32_t>::min(), to<sec_i32>(ts).count()); |
199 | ts.tv_sec = -2147483649; |
200 | ts.tv_nsec = 999999999; |
201 | EXPECT_THROW(to<sec_i32>(ts), std::range_error); |
202 | ts.tv_sec = -2147483649; |
203 | ts.tv_nsec = 0; |
204 | EXPECT_THROW(to<sec_i32>(ts), std::range_error); |
205 | ts.tv_sec = -2147483650; |
206 | ts.tv_nsec = 0; |
207 | EXPECT_THROW(to<sec_i32>(ts), std::range_error); |
208 | |
209 | // Test the upper boundary of conversion to uint32_t hours |
210 | using hours_u32 = std::chrono::duration<uint32_t, std::ratio<3600>>; |
211 | ts.tv_sec = 15461882262000LL; |
212 | ts.tv_nsec = 0; |
213 | EXPECT_EQ(std::numeric_limits<uint32_t>::max(), to<hours_u32>(ts).count()); |
214 | ts.tv_sec = 15461882265599LL; |
215 | EXPECT_EQ(std::numeric_limits<uint32_t>::max(), to<hours_u32>(ts).count()); |
216 | ts.tv_sec = 15461882265600LL; |
217 | EXPECT_THROW(to<hours_u32>(ts), std::range_error); |
218 | |
219 | using nsec_i64 = std::chrono::duration<int64_t, std::nano>; |
220 | ts.tv_sec = std::numeric_limits<int64_t>::max(); |
221 | ts.tv_nsec = std::numeric_limits<int64_t>::max(); |
222 | EXPECT_THROW(to<nsec_i64>(ts), std::range_error); |
223 | |
224 | ts.tv_sec = std::numeric_limits<int64_t>::min(); |
225 | ts.tv_nsec = std::numeric_limits<int64_t>::min(); |
226 | EXPECT_THROW(to<nsec_i64>(ts), std::range_error); |
227 | |
228 | // Test some non-normal inputs near the int64_t limit |
229 | ts.tv_sec = 0; |
230 | ts.tv_nsec = std::numeric_limits<int64_t>::min(); |
231 | EXPECT_EQ(std::numeric_limits<int64_t>::min(), to<nsec_i64>(ts).count()); |
232 | ts.tv_sec = -1; |
233 | ts.tv_nsec = std::numeric_limits<int64_t>::min() + std::nano::den; |
234 | EXPECT_EQ(std::numeric_limits<int64_t>::min(), to<nsec_i64>(ts).count()); |
235 | ts.tv_sec = -1; |
236 | ts.tv_nsec = std::numeric_limits<int64_t>::min() + std::nano::den - 1; |
237 | EXPECT_THROW(to<nsec_i64>(ts), std::range_error); |
238 | |
239 | ts.tv_sec = 0; |
240 | ts.tv_nsec = std::numeric_limits<int64_t>::max(); |
241 | EXPECT_EQ(std::numeric_limits<int64_t>::max(), to<nsec_i64>(ts).count()); |
242 | ts.tv_sec = 1; |
243 | ts.tv_nsec = std::numeric_limits<int64_t>::max() - std::nano::den; |
244 | EXPECT_EQ(std::numeric_limits<int64_t>::max(), to<nsec_i64>(ts).count()); |
245 | ts.tv_sec = 1; |
246 | ts.tv_nsec = std::numeric_limits<int64_t>::max() - std::nano::den + 1; |
247 | EXPECT_THROW(to<nsec_i64>(ts), std::range_error); |
248 | } |
249 | |
250 | // Theoretically conversion is representable in the output type, |
251 | // but we normalize the input first, and normalization would trigger an |
252 | // overflow. |
253 | using hours_u64 = std::chrono::duration<uint64_t, std::ratio<3600>>; |
254 | ts.tv_sec = std::numeric_limits<decltype(ts.tv_sec)>::max(); |
255 | ts.tv_nsec = 1000000000; |
256 | EXPECT_THROW(to<hours_u64>(ts), std::range_error); |
257 | // If we drop it back down to the normal range it should succeed |
258 | ts.tv_nsec = 999999999; |
259 | EXPECT_EQ( |
260 | std::numeric_limits<decltype(ts.tv_sec)>::max() / 3600, |
261 | to<hours_u64>(ts).count()); |
262 | |
263 | // Test overflow with an unusual duration where neither the numerator nor |
264 | // denominator are 1. |
265 | using unusual_time = std::chrono::duration<int16_t, std::ratio<13, 3>>; |
266 | ts.tv_sec = 141994; |
267 | ts.tv_nsec = 666666666; |
268 | EXPECT_EQ(32767, to<unusual_time>(ts).count()); |
269 | ts.tv_nsec = 666666667; |
270 | EXPECT_THROW(to<unusual_time>(ts), std::range_error); |
271 | |
272 | ts.tv_sec = -141998; |
273 | ts.tv_nsec = 999999999; |
274 | EXPECT_EQ(-32768, to<unusual_time>(ts).count()); |
275 | ts.tv_sec = -141999; |
276 | ts.tv_nsec = 0; |
277 | EXPECT_THROW(to<unusual_time>(ts), std::range_error); |
278 | } |
279 | |
280 | TEST(Conv, timevalToStdChrono) { |
281 | struct timeval tv; |
282 | |
283 | tv.tv_sec = 0; |
284 | tv.tv_usec = 10; |
285 | EXPECT_EQ(10000ns, to<nanoseconds>(tv)); |
286 | EXPECT_EQ(10us, to<microseconds>(tv)); |
287 | EXPECT_EQ(0ms, to<milliseconds>(tv)); |
288 | EXPECT_EQ(0s, to<seconds>(tv)); |
289 | |
290 | tv.tv_sec = 1; |
291 | tv.tv_usec = 10; |
292 | EXPECT_EQ(1000010000ns, to<nanoseconds>(tv)); |
293 | EXPECT_EQ(1000010us, to<microseconds>(tv)); |
294 | EXPECT_EQ(1000ms, to<milliseconds>(tv)); |
295 | EXPECT_EQ(1s, to<seconds>(tv)); |
296 | EXPECT_EQ( |
297 | createTimePoint<system_clock>(1000010000ns), |
298 | to<system_clock::time_point>(tv)); |
299 | EXPECT_EQ( |
300 | createTimePoint<steady_clock>(1000010000ns), |
301 | to<steady_clock::time_point>(tv)); |
302 | |
303 | // Test a non-canonical value with tv_usec larger than 1 second |
304 | tv.tv_sec = 5; |
305 | tv.tv_usec = 3219876; |
306 | EXPECT_EQ(8219876000LL, to<nanoseconds>(tv).count()); |
307 | EXPECT_EQ(8219876us, to<microseconds>(tv)); |
308 | EXPECT_EQ(8219ms, to<milliseconds>(tv)); |
309 | EXPECT_EQ(8s, to<seconds>(tv)); |
310 | EXPECT_EQ( |
311 | createTimePoint<system_clock>(nanoseconds(8219876000LL)), |
312 | to<system_clock::time_point>(tv)); |
313 | EXPECT_EQ( |
314 | createTimePoint<steady_clock>(nanoseconds(8219876000LL)), |
315 | to<steady_clock::time_point>(tv)); |
316 | |
317 | // Test for overflow. |
318 | if (std::numeric_limits<decltype(tv.tv_sec)>::max() >= |
319 | std::numeric_limits<int64_t>::max()) { |
320 | // Use our own type alias here rather than std::chrono::nanoseconds |
321 | // to ensure we have 64-bit rep type. |
322 | using nsec_i64 = std::chrono::duration<int64_t, std::nano>; |
323 | tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max(); |
324 | tv.tv_usec = std::numeric_limits<decltype(tv.tv_usec)>::max(); |
325 | EXPECT_THROW(to<nsec_i64>(tv), std::range_error); |
326 | |
327 | tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min(); |
328 | tv.tv_usec = std::numeric_limits<decltype(tv.tv_usec)>::max(); |
329 | EXPECT_THROW(to<nsec_i64>(tv), std::range_error); |
330 | } |
331 | } |
332 | |
333 | TEST(Conv, stdChronoToTimespec) { |
334 | auto ts = to<struct timespec>(10ns); |
335 | EXPECT_EQ(0, ts.tv_sec); |
336 | EXPECT_EQ(10, ts.tv_nsec); |
337 | |
338 | // We don't use std::chrono_literals suffixes here since older |
339 | // gcc versions silently truncate the literals to 32-bits. |
340 | ts = to<struct timespec>(nanoseconds(987654321012LL)); |
341 | EXPECT_EQ(987, ts.tv_sec); |
342 | EXPECT_EQ(654321012, ts.tv_nsec); |
343 | |
344 | ts = to<struct timespec>(nanoseconds(-987654321012LL)); |
345 | EXPECT_EQ(-988, ts.tv_sec); |
346 | EXPECT_EQ(345678988, ts.tv_nsec); |
347 | |
348 | ts = to<struct timespec>(microseconds(987654321012LL)); |
349 | EXPECT_EQ(987654, ts.tv_sec); |
350 | EXPECT_EQ(321012000, ts.tv_nsec); |
351 | |
352 | ts = to<struct timespec>(milliseconds(987654321012LL)); |
353 | EXPECT_EQ(987654321, ts.tv_sec); |
354 | EXPECT_EQ(12000000, ts.tv_nsec); |
355 | |
356 | ts = to<struct timespec>(seconds(987654321012LL)); |
357 | EXPECT_EQ(987654321012, ts.tv_sec); |
358 | EXPECT_EQ(0, ts.tv_nsec); |
359 | |
360 | ts = to<struct timespec>(10h); |
361 | EXPECT_EQ(36000, ts.tv_sec); |
362 | EXPECT_EQ(0, ts.tv_nsec); |
363 | |
364 | ts = to<struct timespec>(createTimePoint<steady_clock>(123ns)); |
365 | EXPECT_EQ(0, ts.tv_sec); |
366 | EXPECT_EQ(123, ts.tv_nsec); |
367 | |
368 | ts = to<struct timespec>(createTimePoint<system_clock>(123ns)); |
369 | EXPECT_EQ(0, ts.tv_sec); |
370 | EXPECT_EQ(123, ts.tv_nsec); |
371 | |
372 | // Test with some unusual durations where neither the numerator nor |
373 | // denominator are 1. |
374 | using five_sevenths = std::chrono::duration<int64_t, std::ratio<5, 7>>; |
375 | ts = to<struct timespec>(five_sevenths(7)); |
376 | EXPECT_EQ(5, ts.tv_sec); |
377 | EXPECT_EQ(0, ts.tv_nsec); |
378 | ts = to<struct timespec>(five_sevenths(19)); |
379 | EXPECT_EQ(13, ts.tv_sec); |
380 | EXPECT_EQ(571428571, ts.tv_nsec); |
381 | using seven_fifths = std::chrono::duration<int64_t, std::ratio<7, 5>>; |
382 | ts = to<struct timespec>(seven_fifths(5)); |
383 | EXPECT_EQ(7, ts.tv_sec); |
384 | EXPECT_EQ(0, ts.tv_nsec); |
385 | } |
386 | |
387 | TEST(Conv, stdChronoToTimespecOverflow) { |
388 | EXPECT_THROW(to<uint8_t>(1234), std::range_error); |
389 | |
390 | struct timespec ts; |
391 | if (!std::is_same<decltype(ts.tv_sec), int64_t>::value) { |
392 | LOG(INFO) << "skipping most overflow tests: time_t is not int64_t" ; |
393 | } else { |
394 | // Check for overflow converting from uint64_t seconds to time_t |
395 | using sec_u64 = duration<uint64_t>; |
396 | ts = to<struct timespec>(sec_u64(9223372036854775807ULL)); |
397 | EXPECT_EQ(ts.tv_sec, 9223372036854775807ULL); |
398 | EXPECT_EQ(ts.tv_nsec, 0); |
399 | |
400 | EXPECT_THROW( |
401 | to<struct timespec>(sec_u64(9223372036854775808ULL)), std::range_error); |
402 | |
403 | // Check for overflow converting from int64_t hours to time_t |
404 | using hours_i64 = duration<int64_t, std::ratio<3600>>; |
405 | ts = to<struct timespec>(hours_i64(2562047788015215LL)); |
406 | EXPECT_EQ(ts.tv_sec, 9223372036854774000LL); |
407 | EXPECT_EQ(ts.tv_nsec, 0); |
408 | EXPECT_THROW( |
409 | to<struct timespec>(hours_i64(2562047788015216LL)), std::range_error); |
410 | |
411 | // Test overflows from an unusual duration where neither the numerator nor |
412 | // denominator are 1. |
413 | using three_halves = std::chrono::duration<uint64_t, std::ratio<3, 2>>; |
414 | EXPECT_THROW( |
415 | to<struct timespec>(three_halves(6148914691236517206ULL)), |
416 | std::range_error); |
417 | } |
418 | |
419 | // Test for overflow. |
420 | // Use a custom hours type using time_t as the underlying storage type to |
421 | // guarantee that we can overflow. |
422 | using hours_timet = std::chrono::duration<time_t, std::ratio<3600>>; |
423 | EXPECT_THROW( |
424 | to<struct timespec>(hours_timet(std::numeric_limits<time_t>::max())), |
425 | std::range_error); |
426 | } |
427 | |
428 | TEST(Conv, stdChronoToTimeval) { |
429 | auto tv = to<struct timeval>(10ns); |
430 | EXPECT_EQ(0, tv.tv_sec); |
431 | EXPECT_EQ(0, tv.tv_usec); |
432 | |
433 | tv = to<struct timeval>(10us); |
434 | EXPECT_EQ(0, tv.tv_sec); |
435 | EXPECT_EQ(10, tv.tv_usec); |
436 | |
437 | tv = to<struct timeval>(nanoseconds(987654321012LL)); |
438 | EXPECT_EQ(987, tv.tv_sec); |
439 | EXPECT_EQ(654321, tv.tv_usec); |
440 | |
441 | tv = to<struct timeval>(nanoseconds(-987654321012LL)); |
442 | EXPECT_EQ(-988, tv.tv_sec); |
443 | EXPECT_EQ(345679, tv.tv_usec); |
444 | |
445 | tv = to<struct timeval>(microseconds(987654321012LL)); |
446 | EXPECT_EQ(987654, tv.tv_sec); |
447 | EXPECT_EQ(321012, tv.tv_usec); |
448 | |
449 | tv = to<struct timeval>(milliseconds(987654321012LL)); |
450 | EXPECT_EQ(987654321, tv.tv_sec); |
451 | EXPECT_EQ(12000, tv.tv_usec); |
452 | |
453 | tv = to<struct timeval>(seconds(987654321012LL)); |
454 | EXPECT_EQ(987654321012, tv.tv_sec); |
455 | EXPECT_EQ(0, tv.tv_usec); |
456 | |
457 | // Try converting fractional seconds |
458 | tv = to<struct timeval>(duration<double>{3.456789}); |
459 | EXPECT_EQ(3, tv.tv_sec); |
460 | EXPECT_EQ(456789, tv.tv_usec); |
461 | tv = to<struct timeval>(duration<double>{-3.456789}); |
462 | EXPECT_EQ(-4, tv.tv_sec); |
463 | EXPECT_EQ(543211, tv.tv_usec); |
464 | |
465 | // Try converting fractional hours |
466 | tv = to<struct timeval>(duration<double, std::ratio<3600>>{3.456789}); |
467 | EXPECT_EQ(12444, tv.tv_sec); |
468 | // The usec field is generally off-by-one due to |
469 | // floating point rounding error |
470 | EXPECT_NEAR(440400, tv.tv_usec, 1); |
471 | tv = to<struct timeval>(duration<double, std::ratio<3600>>{-3.456789}); |
472 | EXPECT_EQ(-12445, tv.tv_sec); |
473 | EXPECT_NEAR(559600, tv.tv_usec, 1); |
474 | |
475 | // Try converting fractional milliseconds |
476 | tv = to<struct timeval>(duration<double, std::milli>{9123.456789}); |
477 | EXPECT_EQ(9, tv.tv_sec); |
478 | EXPECT_EQ(123456, tv.tv_usec); |
479 | tv = to<struct timeval>(duration<double, std::milli>{-9123.456789}); |
480 | EXPECT_EQ(-10, tv.tv_sec); |
481 | EXPECT_NEAR(876544, tv.tv_usec, 1); |
482 | |
483 | tv = to<struct timeval>(duration<uint32_t, std::ratio<3600>>{3}); |
484 | EXPECT_EQ(10800, tv.tv_sec); |
485 | EXPECT_EQ(0, tv.tv_usec); |
486 | |
487 | tv = to<struct timeval>(duration<uint32_t, std::nano>{3123}); |
488 | EXPECT_EQ(0, tv.tv_sec); |
489 | EXPECT_EQ(3, tv.tv_usec); |
490 | tv = to<struct timeval>(duration<int32_t, std::nano>{-3123}); |
491 | EXPECT_EQ(-1, tv.tv_sec); |
492 | EXPECT_EQ(999997, tv.tv_usec); |
493 | |
494 | tv = to<struct timeval>(createTimePoint<steady_clock>(123us)); |
495 | EXPECT_EQ(0, tv.tv_sec); |
496 | EXPECT_EQ(123, tv.tv_usec); |
497 | |
498 | tv = to<struct timeval>(createTimePoint<system_clock>(123us)); |
499 | EXPECT_EQ(0, tv.tv_sec); |
500 | EXPECT_EQ(123, tv.tv_usec); |
501 | } |
502 | |