Skip to content

Commit af96e17

Browse files
committed
tests: fix FormatDateTime with 32-bit time_t
With a 32-bit time_t, two checks in the FormatDateTime test case didn't work properly so far: 1. Every time_t value can be represented by struct tm, hence the test makes no sense on such platforms and is now disabled there similar to how it's already done with other checks in the same function. 2. std::nextafter(2147483647, +double_limit::infinity())) results in something like 2147483647.000000238 which simply results in the limit when cast back to an integer type, so it didn't actually test the overflow. This is fixed by an additional std::ceil()/std::floor().
1 parent 8550829 commit af96e17

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

test/base-utility.cpp

Lines changed: 16 additions & 4 deletions
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)