Skip to content

Commit 9a9c0a1

Browse files
authored
Merge pull request #10343 from Icinga/test-formatdatetime-32bit-2.14
tests: fix FormatDateTime with 32-bit time_t
2 parents 8550829 + 4aa4a0d commit 9a9c0a1

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ various documentation improvements.
1919

2020
* Don't close anonymous connections before sending the response for a certificate request #10337
2121
* Performance data: Don't discard min/max values even if crit/warn thresholds aren’t given #10339
22+
* Fix a failing test case on systems `time_t` is only 32 bits #10343
2223

2324
### Documentation
2425

test/base-utility.cpp

+16-4
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,12 @@ BOOST_AUTO_TEST_CASE(FormatDateTime) {
183183
//
184184
// These are expected to result in an error due to the intermediate struct tm not being able to represent these
185185
// timestamps, so localtime_r() returns EOVERFLOW which makes the implementation throw an exception.
186-
BOOST_CHECK_THROW(Utility::FormatDateTime("%Y", std::nextafter(time_t_limit::min(), 0)), posix_error);
187-
BOOST_CHECK_THROW(Utility::FormatDateTime("%Y", std::nextafter(time_t_limit::max(), 0)), posix_error);
186+
if constexpr (sizeof(time_t) > sizeof(int32_t)) {
187+
BOOST_CHECK_THROW(Utility::FormatDateTime("%Y", std::nextafter(time_t_limit::min(), 0)), posix_error);
188+
BOOST_CHECK_THROW(Utility::FormatDateTime("%Y", std::nextafter(time_t_limit::max(), 0)), posix_error);
189+
} else {
190+
BOOST_WARN_MESSAGE(false, "skipping test for struct tm overflow due to 32 bit time_t");
191+
}
188192

189193
// Excessive format strings can result in something too large for the buffer, errors out to the empty string.
190194
// Note: both returning the proper result or throwing an exception would be fine too, unfortunately, that's
@@ -205,8 +209,16 @@ BOOST_AUTO_TEST_CASE(FormatDateTime) {
205209
}
206210

207211
// Out of range timestamps.
208-
BOOST_CHECK_THROW(Utility::FormatDateTime("%Y", std::nextafter(time_t_limit::min(), -double_limit::infinity())), negative_overflow);
209-
BOOST_CHECK_THROW(Utility::FormatDateTime("%Y", std::nextafter(time_t_limit::max(), +double_limit::infinity())), positive_overflow);
212+
//
213+
// At the limits of a 64 bit time_t, doubles can no longer represent each integer value, so a simple x+1 or x-1 can
214+
// have x as the result, hence std::nextafter() is used to get the next representable value. However, around the
215+
// limits of a 32 bit time_t, doubles still can represent decimal places and less than 1 is added or subtracted by
216+
// std::nextafter() and casting back to time_t simply results in the limit again, so std::ceil()/std::floor() is
217+
// used to round it to the next integer value that is actually out of range.
218+
double negative_out_of_range = std::floor(std::nextafter(time_t_limit::min(), -double_limit::infinity()));
219+
double positive_out_of_range = std::ceil(std::nextafter(time_t_limit::max(), +double_limit::infinity()));
220+
BOOST_CHECK_THROW(Utility::FormatDateTime("%Y", negative_out_of_range), negative_overflow);
221+
BOOST_CHECK_THROW(Utility::FormatDateTime("%Y", positive_out_of_range), positive_overflow);
210222
}
211223

212224
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)