diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/datetime/base_ut.cpp | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/datetime/base_ut.cpp')
-rw-r--r-- | util/datetime/base_ut.cpp | 654 |
1 files changed, 654 insertions, 0 deletions
diff --git a/util/datetime/base_ut.cpp b/util/datetime/base_ut.cpp new file mode 100644 index 0000000000..afc3f802eb --- /dev/null +++ b/util/datetime/base_ut.cpp @@ -0,0 +1,654 @@ +#include "base.h" + +#include <library/cpp/testing/unittest/registar.h> + +#include <util/generic/utility.h> +#include <util/generic/ylimits.h> +#include <util/generic/ymath.h> +#include <util/string/cast.h> +#include <util/stream/output.h> +#include <util/system/compat.h> +#include <util/random/random.h> + +#include <limits.h> + +using namespace std::chrono_literals; + +struct TTestTime { + const time_t T_ = 987654321; + const char* Date_ = "Thu Apr 19 04:25:21 2001\n"; + const char* SprintDate_ = "20010419"; + const long SprintSecs_ = 15921; + struct tm Tm_; + TTestTime() { + Tm_.tm_sec = 21; + Tm_.tm_min = 25; + Tm_.tm_hour = 4; + Tm_.tm_mday = 19; + Tm_.tm_mon = 3; + Tm_.tm_year = 101; + Tm_.tm_wday = 4; + Tm_.tm_yday = 108; + } +}; + +namespace { + inline void OldDate8601(char* buf, time_t when) { + struct tm theTm; + struct tm* ret = nullptr; + + ret = GmTimeR(&when, &theTm); + + if (ret) { + sprintf(buf, "%04d-%02d-%02dT%02d:%02d:%02dZ", theTm.tm_year + 1900, theTm.tm_mon + 1, theTm.tm_mday, theTm.tm_hour, theTm.tm_min, theTm.tm_sec); + } else { + *buf = '\0'; + } + } +} + +Y_UNIT_TEST_SUITE(TestSprintDate) { + Y_UNIT_TEST(Year9999) { + struct tm t; + t.tm_year = 9999 - 1900; + t.tm_mday = 1; + t.tm_mon = 10; + + char buf[DATE_BUF_LEN]; + DateToString(buf, t); + + TString expectedDate = "99991101"; + + UNIT_ASSERT_VALUES_EQUAL(expectedDate, ToString(buf)); + } + Y_UNIT_TEST(YearAfter9999) { + struct tm t; + t.tm_year = 123456 - 1900; + t.tm_mday = 1; + t.tm_mon = 10; + + char buf[DATE_BUF_LEN]; + UNIT_ASSERT_EXCEPTION(DateToString(buf, t), yexception); + } + Y_UNIT_TEST(SmallYear) { + struct tm t; + t.tm_year = 0 - 1900; + t.tm_mday = 1; + t.tm_mon = 10; + + char buf[DATE_BUF_LEN]; + DateToString(buf, t); + + const TString expectedDate = TString("00001101"); + + UNIT_ASSERT_VALUES_EQUAL(expectedDate, ToString(buf)); + } + Y_UNIT_TEST(SmallYearAndMonth) { + struct tm t; + t.tm_year = 99 - 1900; + t.tm_mday = 1; + t.tm_mon = 0; + + char buf[DATE_BUF_LEN]; + DateToString(buf, t); + + const TString expectedDate = TString("00990101"); + + UNIT_ASSERT_VALUES_EQUAL(expectedDate, ToString(buf)); + } + Y_UNIT_TEST(FromZeroTimestamp) { + const time_t timestamp = 0; + + char buf[DATE_BUF_LEN]; + DateToString(buf, timestamp); + + const TString expectedDate = TString("19700101"); + + UNIT_ASSERT_VALUES_EQUAL(expectedDate, ToString(buf)); + } + Y_UNIT_TEST(FromTimestamp) { + const time_t timestamp = 1524817858; + + char buf[DATE_BUF_LEN]; + DateToString(buf, timestamp); + + const TString expectedDate = TString("20180427"); + + UNIT_ASSERT_VALUES_EQUAL(expectedDate, ToString(buf)); + } + Y_UNIT_TEST(FromTimestampAsTString) { + const time_t timestamp = 1524817858; + + const TString expectedDate = TString("20180427"); + + UNIT_ASSERT_VALUES_EQUAL(expectedDate, DateToString(timestamp)); + } + Y_UNIT_TEST(YearToString) { + struct tm t; + t.tm_year = 99 - 1900; + t.tm_mday = 1; + t.tm_mon = 0; + + TString expectedYear = TString("0099"); + + UNIT_ASSERT_VALUES_EQUAL(expectedYear, YearToString(t)); + } + Y_UNIT_TEST(YearToStringBigYear) { + struct tm t; + t.tm_year = 123456 - 1900; + t.tm_mday = 1; + t.tm_mon = 0; + + UNIT_ASSERT_EXCEPTION(YearToString(t), yexception); + } + Y_UNIT_TEST(YearToStringAsTimestamp) { + const time_t timestamp = 1524817858; + + const TString expectedYear = TString("2018"); + + UNIT_ASSERT_VALUES_EQUAL(expectedYear, YearToString(timestamp)); + } +} + +Y_UNIT_TEST_SUITE(TDateTimeTest) { + Y_UNIT_TEST(Test8601) { + char buf1[100]; + char buf2[100]; + + for (size_t i = 0; i < 1000000; ++i) { + const time_t t = RandomNumber<ui32>(); + + OldDate8601(buf1, t); + sprint_date8601(buf2, t); + + UNIT_ASSERT_VALUES_EQUAL(TStringBuf(buf1), TStringBuf(buf2)); + } + } + + inline bool CompareTM(const struct tm& a, const struct tm& b) { + return ( + a.tm_sec == b.tm_sec && + a.tm_min == b.tm_min && + a.tm_hour == b.tm_hour && + a.tm_mday == b.tm_mday && + a.tm_mon == b.tm_mon && + a.tm_year == b.tm_year && + a.tm_wday == b.tm_wday && + a.tm_yday == b.tm_yday); + } + + static inline TString Str(const struct tm& a) { + return TStringBuilder() << "(" + << a.tm_sec << ", " + << a.tm_min << ", " + << a.tm_hour << ", " + << a.tm_mday << ", " + << a.tm_mon << ", " + << a.tm_year << ", " + << a.tm_wday << ", " +#if !defined(_musl_) && !defined(_win_) + << a.tm_yday +#endif + << ")"; + } + + Y_UNIT_TEST(TestBasicFuncs) { + ui64 mlsecB = millisec(); + ui64 mcrsecB = MicroSeconds(); + struct timeval tvB; + gettimeofday(&tvB, nullptr); + + usleep(100000); + + ui64 mlsecA = millisec(); + ui64 mcrsecA = MicroSeconds(); + struct timeval tvA; + gettimeofday(&tvA, nullptr); + + UNIT_ASSERT(mlsecB + 90 < mlsecA); + UNIT_ASSERT((mcrsecB + 90000 < mcrsecA)); + //UNIT_ASSERT(ToMicroSeconds(&tvB) + 90000 < ToMicroSeconds(&tvA)); + //UNIT_ASSERT(TVdiff(tvB, tvA) == long(ToMicroSeconds(&tvA) - ToMicroSeconds(&tvB))); + } + + Y_UNIT_TEST(TestCompatFuncs) { + struct tm t; + struct tm* tret = nullptr; + TTestTime e; + tret = gmtime_r(&e.T_, &t); + UNIT_ASSERT(tret == &t); + UNIT_ASSERT(CompareTM(e.Tm_, t)); + + /* + * strptime seems to be broken on Mac OS X: + * + * struct tm t; + * char *ret = strptime("Jul", "%b ", &t); + * printf("-%s-\n", ret); + * + * yields "- -": ret contains a pointer to a substring of the format string, + * that should never occur: function returns either NULL or pointer to buf substring. + * + * So this test fails on Mac OS X. + */ + + struct tm t2; + Zero(t2); + char* ret = strptime(e.Date_, "%a %b %d %H:%M:%S %Y\n ", &t2); + UNIT_ASSERT(ret == e.Date_ + strlen(e.Date_)); + UNIT_ASSERT_VALUES_EQUAL(Str(e.Tm_), Str(t2)); + time_t t3 = timegm(&t); + UNIT_ASSERT(t3 == e.T_); + } + + Y_UNIT_TEST(TestSprintSscan) { + char buf[256]; + long secs; + TTestTime e; + + sprint_gm_date(buf, e.T_, &secs); + UNIT_ASSERT(strcmp(buf, e.SprintDate_) == 0); + UNIT_ASSERT(secs == e.SprintSecs_); + + struct tm t; + Zero(t); + bool ret = sscan_date(buf, t); + UNIT_ASSERT(ret); + UNIT_ASSERT( + t.tm_year == e.Tm_.tm_year && + t.tm_mon == e.Tm_.tm_mon && + t.tm_mday == e.Tm_.tm_mday); + + buf[0] = 'a'; + ret = sscan_date(buf, t); + UNIT_ASSERT(!ret); + } + + Y_UNIT_TEST(TestNow) { + i64 seconds = Seconds(); + i64 milliseconds = millisec(); + i64 microseconds = MicroSeconds(); + UNIT_ASSERT(Abs(seconds - milliseconds / 1000) <= 1); + UNIT_ASSERT(Abs(milliseconds - microseconds / 1000) < 100); + UNIT_ASSERT(seconds > 1243008607); // > time when test was written + } + + Y_UNIT_TEST(TestStrftime) { + struct tm tm; + Zero(tm); + tm.tm_year = 109; + tm.tm_mon = 4; + tm.tm_mday = 29; + UNIT_ASSERT_STRINGS_EQUAL("2009-05-29", Strftime("%Y-%m-%d", &tm)); + } + + Y_UNIT_TEST(TestNanoSleep) { + NanoSleep(0); + NanoSleep(1); + NanoSleep(1000); + NanoSleep(1000000); + } + + static bool TimeZoneEq(const char* zone0, const char* zone1) { + if (strcmp(zone0, "GMT") == 0) { + zone0 = "UTC"; + } + if (strcmp(zone1, "GMT") == 0) { + zone1 = "UTC"; + } + return strcmp(zone0, zone1) == 0; + } + + static bool CompareTMFull(const tm* t0, const tm* t1) { + return t0 && t1 && + CompareTM(*t0, *t1) && + (t0->tm_isdst == t1->tm_isdst) +#ifndef _win_ + && (t0->tm_gmtoff == t1->tm_gmtoff) && + TimeZoneEq(t0->tm_zone, t1->tm_zone) +#endif // _win_ + && true; + } + + Y_UNIT_TEST(TestGmTimeR) { + time_t starttime = static_cast<time_t>(Max<i64>(-12244089600LL, Min<time_t>())); // 1-Jan-1582 + time_t finishtime = static_cast<time_t>(Min<i64>(0xFFFFFFFF * 20, Max<time_t>())); + time_t step = (finishtime - starttime) / 25; + struct tm tms0, tms1; + struct tm* ptm0 = nullptr; + struct tm* ptm1 = nullptr; + for (time_t t = starttime; t < finishtime; t += step) { + ptm0 = GmTimeR(&t, &tms0); + UNIT_ASSERT_EQUAL(ptm0, &tms0); + +#ifdef _win_ + if (tms0.tm_year + 1900 > 3000) { + // Windows: _MAX__TIME64_T == 23:59:59. 12/31/3000 UTC + continue; + } +#endif + + ptm1 = gmtime_r(&t, &tms1); + if (!ptm1) { + continue; + } + UNIT_ASSERT_EQUAL(ptm1, &tms1); + UNIT_ASSERT(CompareTMFull(ptm0, ptm1)); + } + } +} + +Y_UNIT_TEST_SUITE(DateTimeTest) { + Y_UNIT_TEST(TestDurationFromFloat) { + UNIT_ASSERT_EQUAL(TDuration::MilliSeconds(500), TDuration::Seconds(0.5)); + UNIT_ASSERT_EQUAL(TDuration::MilliSeconds(500), TDuration::Seconds(0.5f)); + } + + Y_UNIT_TEST(TestSecondsLargeValue) { + unsigned int seconds = UINT_MAX; + UNIT_ASSERT_VALUES_EQUAL(((ui64)seconds) * 1000000, TDuration::Seconds(seconds).MicroSeconds()); + } + + Y_UNIT_TEST(TestToString) { +#define CHECK_CONVERTIBLE(v) \ + do { \ + UNIT_ASSERT_VALUES_EQUAL(v, ToString(TDuration::Parse(v))); \ + UNIT_ASSERT_VALUES_EQUAL(v, TDuration::Parse(v).ToString()); \ + } while (0) +#if 0 + + CHECK_CONVERTIBLE("10s"); + CHECK_CONVERTIBLE("1234s"); + CHECK_CONVERTIBLE("1234ms"); + CHECK_CONVERTIBLE("12ms"); + CHECK_CONVERTIBLE("12us"); + CHECK_CONVERTIBLE("1234us"); +#endif + + CHECK_CONVERTIBLE("1.000000s"); + CHECK_CONVERTIBLE("11234.000000s"); + CHECK_CONVERTIBLE("0.011122s"); + CHECK_CONVERTIBLE("33.011122s"); + } + + Y_UNIT_TEST(TestFromString) { + static const struct T { + const char* const Str; + const TDuration::TValue MicroSeconds; + const bool Parseable; + } tests[] = { + {"0", 0, true}, + {"1", 1000000, true}, + {"2s", 2000000, true}, + {"3ms", 3000, true}, + {"x3ms", 0, false}, + }; + + for (const T* t = tests; t != std::end(tests); ++t) { + // FromString + bool parsed = false; + try { + TDuration time = FromString<TDuration>(t->Str); + parsed = true; + UNIT_ASSERT_EQUAL(t->MicroSeconds, time.MicroSeconds()); + } catch (const yexception&) { + UNIT_ASSERT_VALUES_EQUAL(parsed, t->Parseable); + } + // TryFromString + TDuration tryTime; + UNIT_ASSERT_VALUES_EQUAL(TryFromString<TDuration>(t->Str, tryTime), t->Parseable); + if (t->Parseable) { + UNIT_ASSERT_EQUAL(t->MicroSeconds, tryTime.MicroSeconds()); + } + } + } + + Y_UNIT_TEST(TestSleep) { + // check does not throw + Sleep(TDuration::Seconds(0)); + Sleep(TDuration::MicroSeconds(1)); + Sleep(TDuration::MilliSeconds(1)); + } + + Y_UNIT_TEST(TestInstantToString) { + UNIT_ASSERT_VALUES_EQUAL(TString("2009-08-06T15:19:06.023455Z"), ToString(TInstant::Seconds(1249571946) + TDuration::MicroSeconds(23455))); + UNIT_ASSERT_VALUES_EQUAL(TString("2009-08-06T15:19:06.023455Z"), (TInstant::Seconds(1249571946) + TDuration::MicroSeconds(23455)).ToString()); + UNIT_ASSERT_VALUES_EQUAL(TString("2009-08-06T15:19:06Z"), (TInstant::Seconds(1249571946) + TDuration::MicroSeconds(23455)).ToStringUpToSeconds()); + } + + Y_UNIT_TEST(TestInstantToRfc822String) { + UNIT_ASSERT_VALUES_EQUAL(TString("Thu, 06 Aug 2009 15:19:06 GMT"), (TInstant::Seconds(1249571946) + TDuration::MicroSeconds(23455)).ToRfc822String()); + } + + Y_UNIT_TEST(TestInstantMath) { + UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1719), TInstant::Seconds(1700) + TDuration::Seconds(19)); + // overflow + UNIT_ASSERT_VALUES_EQUAL(TInstant::Max(), TInstant::Max() - TDuration::Seconds(10) + TDuration::Seconds(19)); + // underflow + UNIT_ASSERT_VALUES_EQUAL(TInstant::Zero(), TInstant::Seconds(1000) - TDuration::Seconds(2000)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TInstant::Seconds(1000) - TInstant::Seconds(2000)); + } + + Y_UNIT_TEST(TestDurationMath) { + TDuration empty; + UNIT_ASSERT(!empty); + // ensure that this compiles too + if (empty) { + UNIT_ASSERT(false); + } + TDuration nonEmpty = TDuration::MicroSeconds(1); + UNIT_ASSERT(nonEmpty); + + UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(110), TDuration::Seconds(77) + TDuration::Seconds(33)); + // overflow + UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(), TDuration::Max() - TDuration::Seconds(1) + TDuration::Seconds(10)); + // underflow + UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TDuration::Seconds(20) - TDuration::Seconds(200)); + // division + UNIT_ASSERT_DOUBLES_EQUAL(TDuration::Minutes(1) / TDuration::Seconds(10), 6.0, 1e-9); + } + + Y_UNIT_TEST(TestDurationGetters) { + const TDuration value = TDuration::MicroSeconds(1234567); + UNIT_ASSERT_VALUES_EQUAL(value.Seconds(), 1); + UNIT_ASSERT_DOUBLES_EQUAL(value.SecondsFloat(), 1.234567, 1e-9); + + UNIT_ASSERT_VALUES_EQUAL(value.MilliSeconds(), 1234); + UNIT_ASSERT_DOUBLES_EQUAL(value.MillisecondsFloat(), 1234.567, 1e-9); + + UNIT_ASSERT_VALUES_EQUAL(value.MicroSeconds(), 1234567); + } + + template <class T> + void TestTimeUnits() { + T withTime = T::MicroSeconds(1249571946000000L); + T onlyMinutes = T::MicroSeconds(1249571940000000L); + T onlyHours = T::MicroSeconds(1249570800000000L); + T onlyDays = T::MicroSeconds(1249516800000000L); + ui64 minutes = 20826199; + ui64 hours = 347103; + ui64 days = 14462; + + UNIT_ASSERT_VALUES_EQUAL(withTime.Minutes(), minutes); + UNIT_ASSERT_VALUES_EQUAL(onlyMinutes, T::Minutes(minutes)); + UNIT_ASSERT_VALUES_EQUAL(onlyMinutes.Minutes(), minutes); + + UNIT_ASSERT_VALUES_EQUAL(withTime.Hours(), hours); + UNIT_ASSERT_VALUES_EQUAL(onlyMinutes.Hours(), hours); + UNIT_ASSERT_VALUES_EQUAL(onlyHours, T::Hours(hours)); + UNIT_ASSERT_VALUES_EQUAL(onlyHours.Hours(), hours); + + UNIT_ASSERT_VALUES_EQUAL(withTime.Days(), days); + UNIT_ASSERT_VALUES_EQUAL(onlyHours.Days(), days); + UNIT_ASSERT_VALUES_EQUAL(onlyDays, T::Days(days)); + UNIT_ASSERT_VALUES_EQUAL(onlyDays.Days(), days); + } + + Y_UNIT_TEST(TestInstantUnits) { + TestTimeUnits<TInstant>(); + } + + Y_UNIT_TEST(TestDurationUnits) { + TestTimeUnits<TDuration>(); + } + + Y_UNIT_TEST(TestNoexceptConstruction) { + UNIT_ASSERT_EXCEPTION(TDuration::MilliSeconds(FromString(TStringBuf("not a number"))), yexception); + UNIT_ASSERT_EXCEPTION(TDuration::Seconds(FromString(TStringBuf("not a number"))), yexception); + } + + Y_UNIT_TEST(TestFromValueForTDuration) { + // check that FromValue creates the same TDuration + TDuration d1 = TDuration::MicroSeconds(12345); + TDuration d2 = TDuration::FromValue(d1.GetValue()); + + UNIT_ASSERT_VALUES_EQUAL(d1, d2); + } + + Y_UNIT_TEST(TestFromValueForTInstant) { + // check that FromValue creates the same TInstant + TInstant i1 = TInstant::MicroSeconds(12345); + TInstant i2 = TInstant::FromValue(i1.GetValue()); + + UNIT_ASSERT_VALUES_EQUAL(i1, i2); + } + + Y_UNIT_TEST(TestTimeGmDateConversion) { + tm time{}; + time_t timestamp = 0; + + // Check all days till year 2106 (max year representable if time_t is 32 bit) + while (time.tm_year < 2106 - 1900) { + timestamp += 86400; + + GmTimeR(×tamp, &time); + time_t newTimestamp = TimeGM(&time); + + UNIT_ASSERT_VALUES_EQUAL_C( + newTimestamp, + timestamp, + "incorrect date " << (1900 + time.tm_year) << "-" << (time.tm_mon + 1) << "-" << time.tm_mday); + } + } + + Y_UNIT_TEST(TestTDurationConstructorFromStdChronoDuration) { + + UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TDuration(0ms)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::MicroSeconds(42), TDuration(42us)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::MicroSeconds(42000000000000L), TDuration(42000000000000us)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(42), TDuration(42ms)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(42.75), TDuration(42.75ms)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(42), TDuration(42s)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(42.25), TDuration(42.25s)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Minutes(42), TDuration(42min)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Hours(42), TDuration(42h)); + + // TDuration doesn't support negative durations + UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TDuration(-5min)); + + UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(5), TDuration(std::chrono::duration<i8, std::milli>{5ms})); + +#if defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER > 17 + // libstdc++ does not provide std::chrono::days at the time + // Consider removing this code upon OS_SDK update + UNIT_ASSERT_VALUES_EQUAL(TDuration::Days(1), TDuration(std::chrono::days{1})); +#endif + + // clump + UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TDuration(std::chrono::duration<i64>{-1})); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TDuration(std::chrono::duration<double>{-1})); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(), + TDuration(std::chrono::duration<ui64, std::ratio<3600>>{static_cast<ui64>(1e18)})); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(), + TDuration(std::chrono::duration<i64, std::milli>{static_cast<i64>(::Max<ui64>() / 1000)})); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(), + TDuration(std::chrono::duration<double, std::ratio<3600>>{1e18})); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(), + TDuration(std::chrono::duration<double, std::milli>{::Max<ui64>() / 1000})); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(), TDuration(std::chrono::duration<double, std::milli>{ + static_cast<double>(::Max<ui64>()) / 1000 + 0.1})); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(), TDuration(std::chrono::duration<float, std::milli>{ + static_cast<float>(::Max<ui64>()) / 1000 + 0.1})); + } + + Y_UNIT_TEST(TestTDurationCompareWithStdChronoDuration) { + UNIT_ASSERT(TDuration::Zero() == 0ms); + UNIT_ASSERT(TDuration::Seconds(42) == 42s); + + UNIT_ASSERT(0ms == TDuration::Zero()); + + UNIT_ASSERT(TDuration::Zero() != 1ms); + UNIT_ASSERT(TDuration::Zero() != -1ms); + UNIT_ASSERT(TDuration::MilliSeconds(1) != -1ms); + UNIT_ASSERT(TDuration::MilliSeconds(1) != -1ms); + + UNIT_ASSERT(1ms != TDuration::Zero()); + + UNIT_ASSERT(TDuration::Seconds(2) < 3s); + UNIT_ASSERT(3s > TDuration::Seconds(2)); + UNIT_ASSERT(!(TDuration::Seconds(2) < 1s)); + UNIT_ASSERT(!(TDuration::Seconds(2) < -3s)); + UNIT_ASSERT(!(TDuration::Seconds(2) < 2s)); + + UNIT_ASSERT(2s < TDuration::Seconds(3)); + + UNIT_ASSERT(TDuration::Seconds(2) <= 3s); + UNIT_ASSERT(!(TDuration::Seconds(2) <= 1s)); + UNIT_ASSERT(!(TDuration::Seconds(2) <= -3s)); + UNIT_ASSERT(TDuration::Seconds(2) <= 2s); + + UNIT_ASSERT(2s <= TDuration::Seconds(2)); + + UNIT_ASSERT(TDuration::Seconds(2) > -2s); + UNIT_ASSERT(TDuration::Seconds(2) > 1s); + UNIT_ASSERT(TDuration::Seconds(2) > 0s); + UNIT_ASSERT(!(TDuration::Seconds(2) > 3s)); + UNIT_ASSERT(!(TDuration::Seconds(2) > 2s)); + + UNIT_ASSERT(2s > TDuration::Seconds(1)); + + UNIT_ASSERT(TDuration::Seconds(2) >= -2s); + UNIT_ASSERT(TDuration::Seconds(2) >= 1s); + UNIT_ASSERT(TDuration::Seconds(2) >= 0s); + UNIT_ASSERT(!(TDuration::Seconds(2) >= 3s)); + UNIT_ASSERT(TDuration::Seconds(2) >= 2s); + + UNIT_ASSERT(2s >= TDuration::Seconds(2)); + + static_assert(TDuration::Zero() == 0ms); + static_assert(TDuration::Zero() < 1ms); + } + + Y_UNIT_TEST(TestAdditionOfStdChronoDuration) { + UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(1) + 2s, TDuration::Seconds(3)); + UNIT_ASSERT_VALUES_EQUAL(2s + TDuration::Seconds(1), TDuration::Seconds(3)); + UNIT_ASSERT_VALUES_EQUAL(-2s + TDuration::Seconds(3), TDuration::Seconds(1)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(3) + (-2s), TDuration::Seconds(1)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(3) - 2s, TDuration::Seconds(1)); + UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(1) - (-2s), TDuration::Seconds(3)); + UNIT_ASSERT_VALUES_EQUAL(3s - TDuration::Seconds(2), TDuration::Seconds(1)); + UNIT_ASSERT_VALUES_EQUAL(3s - TDuration::Seconds(4), TDuration::Zero()); + + UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1) + 2s, TInstant::Seconds(3)); + UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(3) + (-2s), TInstant::Seconds(1)); + UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(3) - 2s, TInstant::Seconds(1)); + UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1) - (-2s), TInstant::Seconds(3)); + + // Operations between TDuration/TInstant and std::chrono::duration are performed + // with saturation according to the rules of TDuration/TInstant + UNIT_ASSERT_VALUES_EQUAL(TDuration::Max() + 1h, TDuration::Max()); + UNIT_ASSERT_VALUES_EQUAL(TInstant::Max() + 1h, TInstant::Max()); + UNIT_ASSERT_VALUES_EQUAL(1h + TDuration::Max(), TDuration::Max()); + UNIT_ASSERT_VALUES_EQUAL(TInstant::Max() + 1h, TInstant::Max()); + + UNIT_ASSERT_VALUES_EQUAL(TDuration::Max() - (-1h), TDuration::Max()); + UNIT_ASSERT_VALUES_EQUAL(TInstant::Max() - (-1h), TInstant::Max()); + UNIT_ASSERT_VALUES_EQUAL(TInstant::Max() - (-1h), TInstant::Max()); + + UNIT_ASSERT_VALUES_EQUAL(-1h - TDuration::Max(), TDuration::Zero()); + UNIT_ASSERT_VALUES_EQUAL(1h - TDuration::Max(), TDuration::Zero()); + + static_assert(TDuration::Zero() + 1s == 1s); + static_assert(TInstant::Seconds(1) + 1s == TInstant::Seconds(2)); + } +} |