summaryrefslogtreecommitdiffstats
path: root/util/datetime/base_ut.cpp
diff options
context:
space:
mode:
authorswarmer <[email protected]>2025-10-03 20:25:26 +0300
committerswarmer <[email protected]>2025-10-03 20:50:00 +0300
commit08d7ed83f95bdff4ddd3fd1b05b16d12f6bedbb1 (patch)
treee7c89fa017ee7154ef1a16761d4e9fa4d816e785 /util/datetime/base_ut.cpp
parente8e38bf51bdfebc163b2fa9310c302f4f9e1c720 (diff)
TDuration/TInstant named constructors should return staturated value on overflow
`TDuration::Seconds(sec)` now returns `TDuration::Max()` if `sec` is greater than the largest representable value. Previously, a silent wrap-around could produce a significantly shorter interval (even a zero one). commit_hash:552fde08fa3b8201ede23894bb363df2d6bbd5af
Diffstat (limited to 'util/datetime/base_ut.cpp')
-rw-r--r--util/datetime/base_ut.cpp44
1 files changed, 44 insertions, 0 deletions
diff --git a/util/datetime/base_ut.cpp b/util/datetime/base_ut.cpp
index 3ac1a90a908..ed437da4e8f 100644
--- a/util/datetime/base_ut.cpp
+++ b/util/datetime/base_ut.cpp
@@ -413,6 +413,11 @@ Y_UNIT_TEST_SUITE(DateTimeTest) {
}
}
+ Y_UNIT_TEST(TestFromConverableType) {
+ std::atomic<ui64> timestamp{42};
+ UNIT_ASSERT_EQUAL(TInstant::Seconds(42), TInstant::Seconds(timestamp));
+ }
+
Y_UNIT_TEST(TestSleep) {
// check does not throw
Sleep(TDuration::Seconds(0));
@@ -582,6 +587,45 @@ Y_UNIT_TEST_SUITE(DateTimeTest) {
static_cast<float>(::Max<ui64>()) / 1000 + 0.1}));
}
+ template <class T>
+ void TestDurationCurationConstructorFunctionSaturation() {
+ const ui64 maxMilliseconds = ::Max<ui64>() / T::MilliSeconds(1).GetValue();
+ const ui64 maxSeconds = ::Max<ui64>() / T::Seconds(1).GetValue();
+ const ui64 maxMinutes = ::Max<ui64>() / T::Minutes(1).GetValue();
+ const ui64 maxHours = ::Max<ui64>() / T::Hours(1).GetValue();
+ const ui64 maxDays = ::Max<ui64>() / T::Days(1).GetValue();
+
+ auto test = [](ui64 maxValue, T (*constructor)(ui64), TStringBuf name) {
+ UNIT_ASSERT_VALUES_UNEQUAL_C(constructor(maxValue), T::Max(), LabeledOutput(name));
+ UNIT_ASSERT_VALUES_EQUAL_C(constructor(Max<ui64>()), T::Max(), LabeledOutput(name));
+ for (ui64 v = maxValue + 1; v != Max<ui64>(); v = std::midpoint(Max<ui64>(), v)) {
+ UNIT_ASSERT_VALUES_EQUAL_C(constructor(v), T::Max(), LabeledOutput(name, v));
+ }
+ for (ui64 v = maxValue; v != 0; v = std::midpoint(ui64(0), v)) {
+ UNIT_ASSERT_VALUES_UNEQUAL_C(constructor(v), T::Max(), LabeledOutput(name, v));
+ }
+ };
+ test(maxMilliseconds, &T::MilliSeconds, "MilliSeconds");
+ test(maxSeconds, &T::Seconds, "Seconds");
+ test(maxMinutes, &T::Minutes, "Minutes");
+ test(maxHours, &T::Hours, "Hours");
+ test(maxDays, &T::Days, "Days");
+ }
+
+ Y_UNIT_TEST(TestDurationCurationConstructorFunctionSaturation) {
+ UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(-5.f), TDuration::Zero());
+ UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(-5.f), TDuration::Zero());
+ UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(0x1p63), TDuration::Max());
+ UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(0x1p45), TDuration::Max());
+ UNIT_ASSERT_VALUES_UNEQUAL(TDuration::Seconds(0x1p44), TDuration::Max());
+
+ TestDurationCurationConstructorFunctionSaturation<TDuration>();
+ }
+
+ Y_UNIT_TEST(TestInstantCurationConstructorFunctionSaturation) {
+ TestDurationCurationConstructorFunctionSaturation<TInstant>();
+ }
+
Y_UNIT_TEST(TestTDurationCompareWithStdChronoDuration) {
UNIT_ASSERT(TDuration::Zero() == 0ms);
UNIT_ASSERT(TDuration::Seconds(42) == 42s);