Skip to content

Commit 4e674c7

Browse files
authored
Fix unreliable clock epoch tests (#1277)
1 parent 419c33a commit 4e674c7

File tree

1 file changed

+39
-26
lines changed

1 file changed

+39
-26
lines changed

test/old_tests/UnitTests/clock.cpp

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ namespace winrt
1717
}
1818
}
1919

20+
// To confirm that two clocks have the same epoch, we
21+
// capture one clock, then the other, then the first again,
22+
// and verify that the three timestamps are ordered. This avoids
23+
// spurious failures if a test machine is slow or experiences a
24+
// clock tick at just the wrong time.
25+
//
26+
// We use a duration_cast to milliseconds so that the assertion
27+
// failure message tells us how many milliseconds of error we encountered.
28+
#define REQUIRE_ORDERED(a, b, c) \
29+
REQUIRE(duration_cast<milliseconds>((b) - (a)).count() >= 0); \
30+
REQUIRE(duration_cast<milliseconds>((c) - (b)).count() >= 0)
31+
2032
namespace Catch
2133
{
2234
template<typename Rep, typename Period>
@@ -46,11 +58,13 @@ namespace Catch
4658

4759
TEST_CASE("clock, now")
4860
{
49-
Calendar calendar;
50-
calendar.SetToNow();
61+
// Confirm that clock::now agrees with Calendar::SetToNow.
62+
Calendar calendar1;
63+
calendar1.SetToNow();
5164
auto time = clock::now();
52-
auto diff = calendar.GetDateTime() - time;
53-
REQUIRE(abs(diff) < milliseconds{ 100 });
65+
Calendar calendar2;
66+
calendar2.SetToNow();
67+
REQUIRE_ORDERED(calendar1.GetDateTime(), time, calendar2.GetDateTime());
5468
}
5569

5670
TEST_CASE("clock, units")
@@ -66,73 +80,72 @@ TEST_CASE("clock, units")
6680

6781
TEST_CASE("clock, time_t")
6882
{
69-
const DateTime now_dt = clock::now();
83+
const DateTime now1_dt = clock::now();
7084
const time_t now_tt = time(nullptr);
85+
const DateTime now2_dt = clock::now();
7186

7287
// Round trip from DateTime to time_t and back.
7388
// confirm that nothing happens other than truncating the fractional seconds
74-
REQUIRE(clock::from_time_t(clock::to_time_t(now_dt)) == time_point_cast<seconds>(now_dt));
89+
REQUIRE(clock::from_time_t(clock::to_time_t(now1_dt)) == time_point_cast<seconds>(now1_dt));
7590

7691
// Same thing in reverse
7792
REQUIRE(clock::to_time_t(clock::from_time_t(now_tt)) == now_tt);
7893

7994
// Conversions are verified to be consistent. Now, verify that we're correctly converting epochs
80-
const auto diff = duration_cast<milliseconds>(abs(now_dt - clock::from_time_t(now_tt))).count();
81-
REQUIRE(diff < 1000);
95+
// Note that time_t has only 1s resolution, so we need to add 1 second of slop on either side.
96+
REQUIRE_ORDERED(now1_dt - 1s, clock::from_time_t(now_tt), now2_dt + 1s);
8297
}
8398

8499
TEST_CASE("clock, FILETIME")
85100
{
86-
const DateTime now_dt = clock::now();
101+
const DateTime now1_dt = clock::now();
87102
FILETIME now_ft;
88103
::GetSystemTimePreciseAsFileTime(&now_ft);
104+
const DateTime now2_dt = clock::now();
89105

90106
// Round trip conversions
91-
REQUIRE(clock::from_file_time(clock::to_file_time(now_dt)) == now_dt);
107+
REQUIRE(clock::from_file_time(clock::to_file_time(now1_dt)) == now1_dt);
92108

93109
REQUIRE(clock::to_file_time(clock::from_file_time(now_ft)) == now_ft);
94110

95111
// Verify epoch
96-
const auto diff = abs(now_dt - clock::from_file_time(now_ft));
97-
REQUIRE(diff < milliseconds{ 100 });
112+
REQUIRE_ORDERED(now1_dt, clock::from_file_time(now_ft), now2_dt);
98113
}
99114

100115
TEST_CASE("clock, system_clock")
101116
{
102-
DateTime const now_dt = clock::now();
103-
auto const now_sys = system_clock::now();
117+
DateTime const now1_dt = clock::now();
118+
auto const now1_sys = system_clock::now();
119+
DateTime const now2_dt = clock::now();
120+
auto const now2_sys = system_clock::now();
104121

105122
// Round trip DateTime to std::chrono::system_clock::time_point and back
106-
REQUIRE(clock::from_sys(clock::to_sys(now_dt)) == now_dt);
123+
REQUIRE(clock::from_sys(clock::to_sys(now1_dt)) == now1_dt);
107124

108125
// Round trip other direction
109-
REQUIRE(clock::to_sys(clock::from_sys(now_sys)) == now_sys);
126+
REQUIRE(clock::to_sys(clock::from_sys(now1_sys)) == now1_sys);
110127

111128
// Round trip with custom resolution
112129
{
113-
auto const now_dt_sec = time_point_cast<seconds>(now_dt);
130+
auto const now_dt_sec = time_point_cast<seconds>(now1_dt);
114131
REQUIRE(clock::from_sys(clock::to_sys(now_dt_sec)) == now_dt_sec);
115132
}
116133
{
117-
auto const now_dt_mins = time_point_cast<minutes>(now_dt);
134+
auto const now_dt_mins = time_point_cast<minutes>(now1_dt);
118135
REQUIRE(clock::from_sys(clock::to_sys(now_dt_mins)) == now_dt_mins);
119136
}
120137
{
121-
auto const now_sys_sec = time_point_cast<seconds>(now_sys);
138+
auto const now_sys_sec = time_point_cast<seconds>(now1_sys);
122139
REQUIRE(clock::to_sys(clock::from_sys(now_sys_sec)) == now_sys_sec);
123140
}
124141
{
125-
auto const now_sys_mins = time_point_cast<seconds>(now_sys);
142+
auto const now_sys_mins = time_point_cast<seconds>(now1_sys);
126143
REQUIRE(clock::to_sys(clock::from_sys(now_sys_mins)) == now_sys_mins);
127144
}
128145

129146
// Verify that the epoch calculations are correct.
130147
{
131-
auto const diff = now_dt - clock::from_sys(now_sys);
132-
REQUIRE(abs(diff) < milliseconds{ 100 });
133-
}
134-
{
135-
auto const diff = now_sys - clock::to_sys(now_dt);
136-
REQUIRE(abs(diff) < milliseconds{ 100 });
148+
REQUIRE_ORDERED(now1_dt, clock::from_sys(now1_sys), now2_dt);
149+
REQUIRE_ORDERED(clock::from_sys(now1_sys), now2_dt, clock::from_sys(now2_sys));
137150
}
138151
}

0 commit comments

Comments
 (0)