time-test.c++ (5133B)
1 // Copyright (c) 2019 Cloudflare, Inc. and contributors 2 // Licensed under the MIT License: 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 #if _WIN32 23 #include "win32-api-version.h" 24 #endif 25 26 #include "time.h" 27 #include "debug.h" 28 #include <kj/test.h> 29 #include <time.h> 30 31 #if _WIN32 32 #include <windows.h> 33 #include "windows-sanity.h" 34 #else 35 #include <unistd.h> 36 #endif 37 38 namespace kj { 39 namespace { 40 41 KJ_TEST("stringify times") { 42 KJ_EXPECT(kj::str(50 * kj::SECONDS) == "50s"); 43 KJ_EXPECT(kj::str(5 * kj::SECONDS + 2 * kj::MILLISECONDS) == "5.002s"); 44 KJ_EXPECT(kj::str(256 * kj::MILLISECONDS) == "256ms"); 45 KJ_EXPECT(kj::str(5 * kj::MILLISECONDS + 2 * kj::NANOSECONDS) == "5.000002ms"); 46 KJ_EXPECT(kj::str(50 * kj::MICROSECONDS) == "50μs"); 47 KJ_EXPECT(kj::str(5 * kj::MICROSECONDS + 300 * kj::NANOSECONDS) == "5.3μs"); 48 KJ_EXPECT(kj::str(50 * kj::NANOSECONDS) == "50ns"); 49 } 50 51 #if _WIN32 52 void delay(kj::Duration d) { 53 Sleep(d / kj::MILLISECONDS); 54 } 55 #else 56 void delay(kj::Duration d) { 57 usleep(d / kj::MICROSECONDS); 58 } 59 #endif 60 61 KJ_TEST("calendar clocks matches unix time") { 62 // Check that the times returned by the calendar clock are within 1s of what time() returns. 63 64 auto& coarse = systemCoarseCalendarClock(); 65 auto& precise = systemPreciseCalendarClock(); 66 67 Date p = precise.now(); 68 Date c = coarse.now(); 69 time_t t = time(nullptr); 70 71 int64_t pi = (p - UNIX_EPOCH) / kj::SECONDS; 72 int64_t ci = (c - UNIX_EPOCH) / kj::SECONDS; 73 74 KJ_EXPECT(pi >= t - 1); 75 KJ_EXPECT(pi <= t + 1); 76 KJ_EXPECT(ci >= t - 1); 77 KJ_EXPECT(ci <= t + 1); 78 } 79 80 KJ_TEST("monotonic clocks match each other") { 81 // Check that the monotonic clocks return comparable times. 82 83 auto& coarse = systemCoarseMonotonicClock(); 84 auto& precise = systemPreciseMonotonicClock(); 85 86 TimePoint p = precise.now(); 87 TimePoint c = coarse.now(); 88 89 // 40ms tolerance due to Windows timeslices being quite long, especially on GitHub Actions where 90 // Windows is drunk and has completely lost track of time. 91 KJ_EXPECT(p < c + 40 * kj::MILLISECONDS, p - c); 92 KJ_EXPECT(p > c - 40 * kj::MILLISECONDS, c - p); 93 } 94 95 KJ_TEST("all clocks advance in real time") { 96 Duration coarseCalDiff; 97 Duration preciseCalDiff; 98 Duration coarseMonoDiff; 99 Duration preciseMonoDiff; 100 101 for (uint retryCount KJ_UNUSED: kj::zeroTo(20)) { 102 auto& coarseCal = systemCoarseCalendarClock(); 103 auto& preciseCal = systemPreciseCalendarClock(); 104 auto& coarseMono = systemCoarseMonotonicClock(); 105 auto& preciseMono = systemPreciseMonotonicClock(); 106 107 Date coarseCalBefore = coarseCal.now(); 108 Date preciseCalBefore = preciseCal.now(); 109 TimePoint coarseMonoBefore = coarseMono.now(); 110 TimePoint preciseMonoBefore = preciseMono.now(); 111 112 Duration delayTime = 150 * kj::MILLISECONDS; 113 delay(delayTime); 114 115 Date coarseCalAfter = coarseCal.now(); 116 Date preciseCalAfter = preciseCal.now(); 117 TimePoint coarseMonoAfter = coarseMono.now(); 118 TimePoint preciseMonoAfter = preciseMono.now(); 119 120 coarseCalDiff = coarseCalAfter - coarseCalBefore; 121 preciseCalDiff = preciseCalAfter - preciseCalBefore; 122 coarseMonoDiff = coarseMonoAfter - coarseMonoBefore; 123 preciseMonoDiff = preciseMonoAfter - preciseMonoBefore; 124 125 // 20ms tolerance due to Windows timeslices being quite long (and Windows sleeps being only 126 // accurate to the timeslice). 127 if (coarseCalDiff > delayTime - 20 * kj::MILLISECONDS && 128 coarseCalDiff < delayTime + 20 * kj::MILLISECONDS && 129 preciseCalDiff > delayTime - 20 * kj::MILLISECONDS && 130 preciseCalDiff < delayTime + 20 * kj::MILLISECONDS && 131 coarseMonoDiff > delayTime - 20 * kj::MILLISECONDS && 132 coarseMonoDiff < delayTime + 20 * kj::MILLISECONDS && 133 preciseMonoDiff > delayTime - 20 * kj::MILLISECONDS && 134 preciseMonoDiff < delayTime + 20 * kj::MILLISECONDS) { 135 // success 136 return; 137 } 138 } 139 140 KJ_FAIL_EXPECT("clocks seem inaccurate even after 20 tries", 141 coarseCalDiff / kj::MICROSECONDS, preciseCalDiff / kj::MICROSECONDS, 142 coarseMonoDiff / kj::MICROSECONDS, preciseMonoDiff / kj::MICROSECONDS); 143 } 144 145 } // namespace 146 } // namespace kj