base_ut.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656
  1. #include "base.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <util/generic/utility.h>
  4. #include <util/generic/ylimits.h>
  5. #include <util/generic/ymath.h>
  6. #include <util/string/cast.h>
  7. #include <util/stream/output.h>
  8. #include <util/system/compat.h>
  9. #include <util/random/random.h>
  10. #include <climits>
  11. using namespace std::chrono_literals;
  12. struct TTestTime {
  13. const time_t T_ = 987654321;
  14. const char* Date_ = "Thu Apr 19 04:25:21 2001\n";
  15. const char* SprintDate_ = "20010419";
  16. const long SprintSecs_ = 15921;
  17. struct tm Tm_;
  18. TTestTime() {
  19. Tm_.tm_sec = 21;
  20. Tm_.tm_min = 25;
  21. Tm_.tm_hour = 4;
  22. Tm_.tm_mday = 19;
  23. Tm_.tm_mon = 3;
  24. Tm_.tm_year = 101;
  25. Tm_.tm_wday = 4;
  26. Tm_.tm_yday = 108;
  27. }
  28. };
  29. namespace {
  30. inline void OldDate8601(char* buf, size_t bufLen, time_t when) {
  31. struct tm theTm;
  32. struct tm* ret = nullptr;
  33. ret = GmTimeR(&when, &theTm);
  34. if (ret) {
  35. snprintf(buf, bufLen, "%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);
  36. } else {
  37. *buf = '\0';
  38. }
  39. }
  40. }
  41. Y_UNIT_TEST_SUITE(TestSprintDate) {
  42. Y_UNIT_TEST(Year9999) {
  43. struct tm t;
  44. t.tm_year = 9999 - 1900;
  45. t.tm_mday = 1;
  46. t.tm_mon = 10;
  47. char buf[DATE_BUF_LEN];
  48. DateToString(buf, t);
  49. TString expectedDate = "99991101";
  50. UNIT_ASSERT_VALUES_EQUAL(expectedDate, ToString(buf));
  51. }
  52. Y_UNIT_TEST(YearAfter9999) {
  53. struct tm t;
  54. t.tm_year = 123456 - 1900;
  55. t.tm_mday = 1;
  56. t.tm_mon = 10;
  57. char buf[DATE_BUF_LEN];
  58. UNIT_ASSERT_EXCEPTION(DateToString(buf, t), yexception);
  59. }
  60. Y_UNIT_TEST(SmallYear) {
  61. struct tm t;
  62. t.tm_year = 0 - 1900;
  63. t.tm_mday = 1;
  64. t.tm_mon = 10;
  65. char buf[DATE_BUF_LEN];
  66. DateToString(buf, t);
  67. const TString expectedDate = TString("00001101");
  68. UNIT_ASSERT_VALUES_EQUAL(expectedDate, ToString(buf));
  69. }
  70. Y_UNIT_TEST(SmallYearAndMonth) {
  71. struct tm t;
  72. t.tm_year = 99 - 1900;
  73. t.tm_mday = 1;
  74. t.tm_mon = 0;
  75. char buf[DATE_BUF_LEN];
  76. DateToString(buf, t);
  77. const TString expectedDate = TString("00990101");
  78. UNIT_ASSERT_VALUES_EQUAL(expectedDate, ToString(buf));
  79. }
  80. Y_UNIT_TEST(FromZeroTimestamp) {
  81. const time_t timestamp = 0;
  82. char buf[DATE_BUF_LEN];
  83. DateToString(buf, timestamp);
  84. const TString expectedDate = TString("19700101");
  85. UNIT_ASSERT_VALUES_EQUAL(expectedDate, ToString(buf));
  86. }
  87. Y_UNIT_TEST(FromTimestamp) {
  88. const time_t timestamp = 1524817858;
  89. char buf[DATE_BUF_LEN];
  90. DateToString(buf, timestamp);
  91. const TString expectedDate = TString("20180427");
  92. UNIT_ASSERT_VALUES_EQUAL(expectedDate, ToString(buf));
  93. }
  94. Y_UNIT_TEST(FromTimestampAsTString) {
  95. const time_t timestamp = 1524817858;
  96. const TString expectedDate = TString("20180427");
  97. UNIT_ASSERT_VALUES_EQUAL(expectedDate, DateToString(timestamp));
  98. }
  99. Y_UNIT_TEST(YearToString) {
  100. struct tm t;
  101. t.tm_year = 99 - 1900;
  102. t.tm_mday = 1;
  103. t.tm_mon = 0;
  104. TString expectedYear = TString("0099");
  105. UNIT_ASSERT_VALUES_EQUAL(expectedYear, YearToString(t));
  106. }
  107. Y_UNIT_TEST(YearToStringBigYear) {
  108. struct tm t;
  109. t.tm_year = 123456 - 1900;
  110. t.tm_mday = 1;
  111. t.tm_mon = 0;
  112. UNIT_ASSERT_EXCEPTION(YearToString(t), yexception);
  113. }
  114. Y_UNIT_TEST(YearToStringAsTimestamp) {
  115. const time_t timestamp = 1524817858;
  116. const TString expectedYear = TString("2018");
  117. UNIT_ASSERT_VALUES_EQUAL(expectedYear, YearToString(timestamp));
  118. }
  119. }
  120. Y_UNIT_TEST_SUITE(TDateTimeTest) {
  121. Y_UNIT_TEST(Test8601) {
  122. char buf1[100];
  123. char buf2[100];
  124. for (size_t i = 0; i < 1000000; ++i) {
  125. const time_t t = RandomNumber<ui32>();
  126. OldDate8601(buf1, sizeof(buf1), t);
  127. sprint_date8601(buf2, t);
  128. UNIT_ASSERT_VALUES_EQUAL(TStringBuf(buf1), TStringBuf(buf2));
  129. }
  130. }
  131. inline bool CompareTM(const struct tm& a, const struct tm& b) {
  132. return (
  133. a.tm_sec == b.tm_sec &&
  134. a.tm_min == b.tm_min &&
  135. a.tm_hour == b.tm_hour &&
  136. a.tm_mday == b.tm_mday &&
  137. a.tm_mon == b.tm_mon &&
  138. a.tm_year == b.tm_year &&
  139. a.tm_wday == b.tm_wday &&
  140. a.tm_yday == b.tm_yday);
  141. }
  142. static inline TString Str(const struct tm& a) {
  143. return TStringBuilder() << "("
  144. << a.tm_sec << ", "
  145. << a.tm_min << ", "
  146. << a.tm_hour << ", "
  147. << a.tm_mday << ", "
  148. << a.tm_mon << ", "
  149. << a.tm_year << ", "
  150. << a.tm_wday << ", "
  151. #if !defined(_musl_) && !defined(_win_)
  152. << a.tm_yday
  153. #endif
  154. << ")";
  155. }
  156. Y_UNIT_TEST(TestBasicFuncs) {
  157. ui64 mlsecB = millisec();
  158. ui64 mcrsecB = MicroSeconds();
  159. struct timeval tvB;
  160. gettimeofday(&tvB, nullptr);
  161. usleep(100000);
  162. ui64 mlsecA = millisec();
  163. ui64 mcrsecA = MicroSeconds();
  164. struct timeval tvA;
  165. gettimeofday(&tvA, nullptr);
  166. UNIT_ASSERT(mlsecB + 90 < mlsecA);
  167. UNIT_ASSERT((mcrsecB + 90000 < mcrsecA));
  168. //UNIT_ASSERT(ToMicroSeconds(&tvB) + 90000 < ToMicroSeconds(&tvA));
  169. //UNIT_ASSERT(TVdiff(tvB, tvA) == long(ToMicroSeconds(&tvA) - ToMicroSeconds(&tvB)));
  170. }
  171. Y_UNIT_TEST(TestCompatFuncs) {
  172. struct tm t;
  173. struct tm* tret = nullptr;
  174. TTestTime e;
  175. tret = gmtime_r(&e.T_, &t);
  176. UNIT_ASSERT(tret == &t);
  177. UNIT_ASSERT(CompareTM(e.Tm_, t));
  178. /*
  179. * strptime seems to be broken on Mac OS X:
  180. *
  181. * struct tm t;
  182. * char *ret = strptime("Jul", "%b ", &t);
  183. * printf("-%s-\n", ret);
  184. *
  185. * yields "- -": ret contains a pointer to a substring of the format string,
  186. * that should never occur: function returns either NULL or pointer to buf substring.
  187. *
  188. * So this test fails on Mac OS X.
  189. */
  190. struct tm t2;
  191. Zero(t2);
  192. char* ret = strptime(e.Date_, "%a %b %d %H:%M:%S %Y\n ", &t2);
  193. UNIT_ASSERT(ret == e.Date_ + strlen(e.Date_));
  194. UNIT_ASSERT_VALUES_EQUAL(Str(e.Tm_), Str(t2));
  195. time_t t3 = timegm(&t);
  196. UNIT_ASSERT(t3 == e.T_);
  197. }
  198. Y_UNIT_TEST(TestSprintSscan) {
  199. char buf[256];
  200. long secs;
  201. TTestTime e;
  202. sprint_gm_date(buf, e.T_, &secs);
  203. UNIT_ASSERT(strcmp(buf, e.SprintDate_) == 0);
  204. UNIT_ASSERT(secs == e.SprintSecs_);
  205. struct tm t;
  206. Zero(t);
  207. bool ret = sscan_date(buf, t);
  208. UNIT_ASSERT(ret);
  209. UNIT_ASSERT(
  210. t.tm_year == e.Tm_.tm_year &&
  211. t.tm_mon == e.Tm_.tm_mon &&
  212. t.tm_mday == e.Tm_.tm_mday);
  213. buf[0] = 'a';
  214. ret = sscan_date(buf, t);
  215. UNIT_ASSERT(!ret);
  216. }
  217. Y_UNIT_TEST(TestNow) {
  218. i64 seconds = Seconds();
  219. i64 milliseconds = millisec();
  220. i64 microseconds = MicroSeconds();
  221. UNIT_ASSERT(Abs(seconds - milliseconds / 1000) <= 1);
  222. UNIT_ASSERT(Abs(milliseconds - microseconds / 1000) < 100);
  223. UNIT_ASSERT(seconds > 1243008607); // > time when test was written
  224. }
  225. Y_UNIT_TEST(TestStrftime) {
  226. struct tm tm;
  227. Zero(tm);
  228. tm.tm_year = 109;
  229. tm.tm_mon = 4;
  230. tm.tm_mday = 29;
  231. UNIT_ASSERT_STRINGS_EQUAL("2009-05-29", Strftime("%Y-%m-%d", &tm));
  232. }
  233. Y_UNIT_TEST(TestNanoSleep) {
  234. NanoSleep(0);
  235. NanoSleep(1);
  236. NanoSleep(1000);
  237. NanoSleep(1000000);
  238. }
  239. static bool TimeZoneEq(const char* zone0, const char* zone1) {
  240. if (strcmp(zone0, "GMT") == 0) {
  241. zone0 = "UTC";
  242. }
  243. if (strcmp(zone1, "GMT") == 0) {
  244. zone1 = "UTC";
  245. }
  246. return strcmp(zone0, zone1) == 0;
  247. }
  248. static bool CompareTMFull(const tm* t0, const tm* t1) {
  249. return t0 && t1 &&
  250. CompareTM(*t0, *t1) &&
  251. (t0->tm_isdst == t1->tm_isdst)
  252. #ifndef _win_
  253. && (t0->tm_gmtoff == t1->tm_gmtoff) &&
  254. TimeZoneEq(t0->tm_zone, t1->tm_zone)
  255. #endif // _win_
  256. && true;
  257. }
  258. Y_UNIT_TEST(TestGmTimeR) {
  259. time_t starttime = static_cast<time_t>(Max<i64>(-12244089600LL, Min<time_t>())); // 1-Jan-1582
  260. time_t finishtime = static_cast<time_t>(Min<i64>(0xFFFFFFFF * 20, Max<time_t>()));
  261. time_t step = (finishtime - starttime) / 25;
  262. struct tm tms0, tms1;
  263. struct tm* ptm0 = nullptr;
  264. struct tm* ptm1 = nullptr;
  265. for (time_t t = starttime; t < finishtime; t += step) {
  266. ptm0 = GmTimeR(&t, &tms0);
  267. UNIT_ASSERT_EQUAL(ptm0, &tms0);
  268. #ifdef _win_
  269. if (tms0.tm_year + 1900 > 3000) {
  270. // Windows: _MAX__TIME64_T == 23:59:59. 12/31/3000 UTC
  271. continue;
  272. }
  273. #endif
  274. ptm1 = gmtime_r(&t, &tms1);
  275. if (!ptm1) {
  276. continue;
  277. }
  278. UNIT_ASSERT_EQUAL(ptm1, &tms1);
  279. UNIT_ASSERT(CompareTMFull(ptm0, ptm1));
  280. }
  281. }
  282. }
  283. Y_UNIT_TEST_SUITE(DateTimeTest) {
  284. Y_UNIT_TEST(TestDurationFromFloat) {
  285. UNIT_ASSERT_EQUAL(TDuration::MilliSeconds(500), TDuration::Seconds(0.5));
  286. UNIT_ASSERT_EQUAL(TDuration::MilliSeconds(500), TDuration::Seconds(0.5f));
  287. }
  288. Y_UNIT_TEST(TestSecondsLargeValue) {
  289. unsigned int seconds = UINT_MAX;
  290. UNIT_ASSERT_VALUES_EQUAL(((ui64)seconds) * 1000000, TDuration::Seconds(seconds).MicroSeconds());
  291. }
  292. Y_UNIT_TEST(TestToString) {
  293. #define CHECK_CONVERTIBLE(v) \
  294. do { \
  295. UNIT_ASSERT_VALUES_EQUAL(v, ToString(TDuration::Parse(v))); \
  296. UNIT_ASSERT_VALUES_EQUAL(v, TDuration::Parse(v).ToString()); \
  297. } while (0)
  298. #if 0
  299. CHECK_CONVERTIBLE("10s");
  300. CHECK_CONVERTIBLE("1234s");
  301. CHECK_CONVERTIBLE("1234ms");
  302. CHECK_CONVERTIBLE("12ms");
  303. CHECK_CONVERTIBLE("12us");
  304. CHECK_CONVERTIBLE("1234us");
  305. #endif
  306. CHECK_CONVERTIBLE("1.000000s");
  307. CHECK_CONVERTIBLE("11234.000000s");
  308. CHECK_CONVERTIBLE("0.011122s");
  309. CHECK_CONVERTIBLE("33.011122s");
  310. }
  311. Y_UNIT_TEST(TestFromString) {
  312. static const struct T {
  313. const char* const Str;
  314. const TDuration::TValue MicroSeconds;
  315. const bool Parseable;
  316. } tests[] = {
  317. {"0", 0, true},
  318. {"1", 1000000, true},
  319. {"2s", 2000000, true},
  320. {"3ms", 3000, true},
  321. {"x3ms", 0, false},
  322. };
  323. for (const T* t = tests; t != std::end(tests); ++t) {
  324. // FromString
  325. bool parsed = false;
  326. try {
  327. TDuration time = FromString<TDuration>(t->Str);
  328. parsed = true;
  329. UNIT_ASSERT_EQUAL(t->MicroSeconds, time.MicroSeconds());
  330. } catch (const yexception&) {
  331. UNIT_ASSERT_VALUES_EQUAL(parsed, t->Parseable);
  332. }
  333. // TryFromString
  334. TDuration tryTime;
  335. UNIT_ASSERT_VALUES_EQUAL(TryFromString<TDuration>(t->Str, tryTime), t->Parseable);
  336. if (t->Parseable) {
  337. UNIT_ASSERT_EQUAL(t->MicroSeconds, tryTime.MicroSeconds());
  338. }
  339. }
  340. }
  341. Y_UNIT_TEST(TestSleep) {
  342. // check does not throw
  343. Sleep(TDuration::Seconds(0));
  344. Sleep(TDuration::MicroSeconds(1));
  345. Sleep(TDuration::MilliSeconds(1));
  346. }
  347. Y_UNIT_TEST(TestInstantToString) {
  348. UNIT_ASSERT_VALUES_EQUAL(TString("2009-08-06T15:19:06.023455Z"), ToString(TInstant::Seconds(1249571946) + TDuration::MicroSeconds(23455)));
  349. UNIT_ASSERT_VALUES_EQUAL(TString("2022-08-23T13:04:43.023455Z"), ToString(TInstant::Seconds(1661259883) + TDuration::MicroSeconds(23455)));
  350. UNIT_ASSERT_VALUES_EQUAL(TString("2122-11-23T15:12:26.023455Z"), ToString(TInstant::Seconds(4824889946) + TDuration::MicroSeconds(23455)));
  351. UNIT_ASSERT_VALUES_EQUAL(TString("2009-08-06T15:19:06.023455Z"), (TInstant::Seconds(1249571946) + TDuration::MicroSeconds(23455)).ToString());
  352. UNIT_ASSERT_VALUES_EQUAL(TString("2009-08-06T15:19:06Z"), (TInstant::Seconds(1249571946) + TDuration::MicroSeconds(23455)).ToStringUpToSeconds());
  353. }
  354. Y_UNIT_TEST(TestInstantToRfc822String) {
  355. UNIT_ASSERT_VALUES_EQUAL(TString("Thu, 06 Aug 2009 15:19:06 GMT"), (TInstant::Seconds(1249571946) + TDuration::MicroSeconds(23455)).ToRfc822String());
  356. }
  357. Y_UNIT_TEST(TestInstantMath) {
  358. UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1719), TInstant::Seconds(1700) + TDuration::Seconds(19));
  359. // overflow
  360. UNIT_ASSERT_VALUES_EQUAL(TInstant::Max(), TInstant::Max() - TDuration::Seconds(10) + TDuration::Seconds(19));
  361. // underflow
  362. UNIT_ASSERT_VALUES_EQUAL(TInstant::Zero(), TInstant::Seconds(1000) - TDuration::Seconds(2000));
  363. UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TInstant::Seconds(1000) - TInstant::Seconds(2000));
  364. }
  365. Y_UNIT_TEST(TestDurationMath) {
  366. TDuration empty;
  367. UNIT_ASSERT(!empty);
  368. // ensure that this compiles too
  369. if (empty) {
  370. UNIT_ASSERT(false);
  371. }
  372. TDuration nonEmpty = TDuration::MicroSeconds(1);
  373. UNIT_ASSERT(nonEmpty);
  374. UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(110), TDuration::Seconds(77) + TDuration::Seconds(33));
  375. // overflow
  376. UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(), TDuration::Max() - TDuration::Seconds(1) + TDuration::Seconds(10));
  377. // underflow
  378. UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TDuration::Seconds(20) - TDuration::Seconds(200));
  379. // division
  380. UNIT_ASSERT_DOUBLES_EQUAL(TDuration::Minutes(1) / TDuration::Seconds(10), 6.0, 1e-9);
  381. }
  382. Y_UNIT_TEST(TestDurationGetters) {
  383. const TDuration value = TDuration::MicroSeconds(1234567);
  384. UNIT_ASSERT_VALUES_EQUAL(value.Seconds(), 1);
  385. UNIT_ASSERT_DOUBLES_EQUAL(value.SecondsFloat(), 1.234567, 1e-9);
  386. UNIT_ASSERT_VALUES_EQUAL(value.MilliSeconds(), 1234);
  387. UNIT_ASSERT_DOUBLES_EQUAL(value.MillisecondsFloat(), 1234.567, 1e-9);
  388. UNIT_ASSERT_VALUES_EQUAL(value.MicroSeconds(), 1234567);
  389. }
  390. template <class T>
  391. void TestTimeUnits() {
  392. T withTime = T::MicroSeconds(1249571946000000L);
  393. T onlyMinutes = T::MicroSeconds(1249571940000000L);
  394. T onlyHours = T::MicroSeconds(1249570800000000L);
  395. T onlyDays = T::MicroSeconds(1249516800000000L);
  396. ui64 minutes = 20826199;
  397. ui64 hours = 347103;
  398. ui64 days = 14462;
  399. UNIT_ASSERT_VALUES_EQUAL(withTime.Minutes(), minutes);
  400. UNIT_ASSERT_VALUES_EQUAL(onlyMinutes, T::Minutes(minutes));
  401. UNIT_ASSERT_VALUES_EQUAL(onlyMinutes.Minutes(), minutes);
  402. UNIT_ASSERT_VALUES_EQUAL(withTime.Hours(), hours);
  403. UNIT_ASSERT_VALUES_EQUAL(onlyMinutes.Hours(), hours);
  404. UNIT_ASSERT_VALUES_EQUAL(onlyHours, T::Hours(hours));
  405. UNIT_ASSERT_VALUES_EQUAL(onlyHours.Hours(), hours);
  406. UNIT_ASSERT_VALUES_EQUAL(withTime.Days(), days);
  407. UNIT_ASSERT_VALUES_EQUAL(onlyHours.Days(), days);
  408. UNIT_ASSERT_VALUES_EQUAL(onlyDays, T::Days(days));
  409. UNIT_ASSERT_VALUES_EQUAL(onlyDays.Days(), days);
  410. }
  411. Y_UNIT_TEST(TestInstantUnits) {
  412. TestTimeUnits<TInstant>();
  413. }
  414. Y_UNIT_TEST(TestDurationUnits) {
  415. TestTimeUnits<TDuration>();
  416. }
  417. Y_UNIT_TEST(TestNoexceptConstruction) {
  418. UNIT_ASSERT_EXCEPTION(TDuration::MilliSeconds(FromString(TStringBuf("not a number"))), yexception);
  419. UNIT_ASSERT_EXCEPTION(TDuration::Seconds(FromString(TStringBuf("not a number"))), yexception);
  420. }
  421. Y_UNIT_TEST(TestFromValueForTDuration) {
  422. // check that FromValue creates the same TDuration
  423. TDuration d1 = TDuration::MicroSeconds(12345);
  424. TDuration d2 = TDuration::FromValue(d1.GetValue());
  425. UNIT_ASSERT_VALUES_EQUAL(d1, d2);
  426. }
  427. Y_UNIT_TEST(TestFromValueForTInstant) {
  428. // check that FromValue creates the same TInstant
  429. TInstant i1 = TInstant::MicroSeconds(12345);
  430. TInstant i2 = TInstant::FromValue(i1.GetValue());
  431. UNIT_ASSERT_VALUES_EQUAL(i1, i2);
  432. }
  433. Y_UNIT_TEST(TestTimeGmDateConversion) {
  434. tm time{};
  435. time_t timestamp = 0;
  436. // Check all days till year 2106 (max year representable if time_t is 32 bit)
  437. while (time.tm_year < 2106 - 1900) {
  438. timestamp += 86400;
  439. GmTimeR(&timestamp, &time);
  440. time_t newTimestamp = TimeGM(&time);
  441. UNIT_ASSERT_VALUES_EQUAL_C(
  442. newTimestamp,
  443. timestamp,
  444. "incorrect date " << (1900 + time.tm_year) << "-" << (time.tm_mon + 1) << "-" << time.tm_mday);
  445. }
  446. }
  447. Y_UNIT_TEST(TestTDurationConstructorFromStdChronoDuration) {
  448. UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TDuration(0ms));
  449. UNIT_ASSERT_VALUES_EQUAL(TDuration::MicroSeconds(42), TDuration(42us));
  450. UNIT_ASSERT_VALUES_EQUAL(TDuration::MicroSeconds(42000000000000L), TDuration(42000000000000us));
  451. UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(42), TDuration(42ms));
  452. UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(42.75), TDuration(42.75ms));
  453. UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(42), TDuration(42s));
  454. UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(42.25), TDuration(42.25s));
  455. UNIT_ASSERT_VALUES_EQUAL(TDuration::Minutes(42), TDuration(42min));
  456. UNIT_ASSERT_VALUES_EQUAL(TDuration::Hours(42), TDuration(42h));
  457. // TDuration doesn't support negative durations
  458. UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TDuration(-5min));
  459. UNIT_ASSERT_VALUES_EQUAL(TDuration::MilliSeconds(5), TDuration(std::chrono::duration<i8, std::milli>{5ms}));
  460. #if defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER > 17
  461. // libstdc++ does not provide std::chrono::days at the time
  462. // Consider removing this code upon OS_SDK update
  463. UNIT_ASSERT_VALUES_EQUAL(TDuration::Days(1), TDuration(std::chrono::days{1}));
  464. #endif
  465. // clump
  466. UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TDuration(std::chrono::duration<i64>{-1}));
  467. UNIT_ASSERT_VALUES_EQUAL(TDuration::Zero(), TDuration(std::chrono::duration<double>{-1}));
  468. UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(),
  469. TDuration(std::chrono::duration<ui64, std::ratio<3600>>{static_cast<ui64>(1e18)}));
  470. UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(),
  471. TDuration(std::chrono::duration<i64, std::milli>{static_cast<i64>(::Max<ui64>() / 1000)}));
  472. UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(),
  473. TDuration(std::chrono::duration<double, std::ratio<3600>>{1e18}));
  474. UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(),
  475. TDuration(std::chrono::duration<double, std::milli>{::Max<ui64>() / 1000}));
  476. UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(), TDuration(std::chrono::duration<double, std::milli>{
  477. static_cast<double>(::Max<ui64>()) / 1000 + 0.1}));
  478. UNIT_ASSERT_VALUES_EQUAL(TDuration::Max(), TDuration(std::chrono::duration<float, std::milli>{
  479. static_cast<float>(::Max<ui64>()) / 1000 + 0.1}));
  480. }
  481. Y_UNIT_TEST(TestTDurationCompareWithStdChronoDuration) {
  482. UNIT_ASSERT(TDuration::Zero() == 0ms);
  483. UNIT_ASSERT(TDuration::Seconds(42) == 42s);
  484. UNIT_ASSERT(0ms == TDuration::Zero());
  485. UNIT_ASSERT(TDuration::Zero() != 1ms);
  486. UNIT_ASSERT(TDuration::Zero() != -1ms);
  487. UNIT_ASSERT(TDuration::MilliSeconds(1) != -1ms);
  488. UNIT_ASSERT(TDuration::MilliSeconds(1) != -1ms);
  489. UNIT_ASSERT(1ms != TDuration::Zero());
  490. UNIT_ASSERT(TDuration::Seconds(2) < 3s);
  491. UNIT_ASSERT(3s > TDuration::Seconds(2));
  492. UNIT_ASSERT(!(TDuration::Seconds(2) < 1s));
  493. UNIT_ASSERT(!(TDuration::Seconds(2) < -3s));
  494. UNIT_ASSERT(!(TDuration::Seconds(2) < 2s));
  495. UNIT_ASSERT(2s < TDuration::Seconds(3));
  496. UNIT_ASSERT(TDuration::Seconds(2) <= 3s);
  497. UNIT_ASSERT(!(TDuration::Seconds(2) <= 1s));
  498. UNIT_ASSERT(!(TDuration::Seconds(2) <= -3s));
  499. UNIT_ASSERT(TDuration::Seconds(2) <= 2s);
  500. UNIT_ASSERT(2s <= TDuration::Seconds(2));
  501. UNIT_ASSERT(TDuration::Seconds(2) > -2s);
  502. UNIT_ASSERT(TDuration::Seconds(2) > 1s);
  503. UNIT_ASSERT(TDuration::Seconds(2) > 0s);
  504. UNIT_ASSERT(!(TDuration::Seconds(2) > 3s));
  505. UNIT_ASSERT(!(TDuration::Seconds(2) > 2s));
  506. UNIT_ASSERT(2s > TDuration::Seconds(1));
  507. UNIT_ASSERT(TDuration::Seconds(2) >= -2s);
  508. UNIT_ASSERT(TDuration::Seconds(2) >= 1s);
  509. UNIT_ASSERT(TDuration::Seconds(2) >= 0s);
  510. UNIT_ASSERT(!(TDuration::Seconds(2) >= 3s));
  511. UNIT_ASSERT(TDuration::Seconds(2) >= 2s);
  512. UNIT_ASSERT(2s >= TDuration::Seconds(2));
  513. static_assert(TDuration::Zero() == 0ms);
  514. static_assert(TDuration::Zero() < 1ms);
  515. }
  516. Y_UNIT_TEST(TestAdditionOfStdChronoDuration) {
  517. UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(1) + 2s, TDuration::Seconds(3));
  518. UNIT_ASSERT_VALUES_EQUAL(2s + TDuration::Seconds(1), TDuration::Seconds(3));
  519. UNIT_ASSERT_VALUES_EQUAL(-2s + TDuration::Seconds(3), TDuration::Seconds(1));
  520. UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(3) + (-2s), TDuration::Seconds(1));
  521. UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(3) - 2s, TDuration::Seconds(1));
  522. UNIT_ASSERT_VALUES_EQUAL(TDuration::Seconds(1) - (-2s), TDuration::Seconds(3));
  523. UNIT_ASSERT_VALUES_EQUAL(3s - TDuration::Seconds(2), TDuration::Seconds(1));
  524. UNIT_ASSERT_VALUES_EQUAL(3s - TDuration::Seconds(4), TDuration::Zero());
  525. UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1) + 2s, TInstant::Seconds(3));
  526. UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(3) + (-2s), TInstant::Seconds(1));
  527. UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(3) - 2s, TInstant::Seconds(1));
  528. UNIT_ASSERT_VALUES_EQUAL(TInstant::Seconds(1) - (-2s), TInstant::Seconds(3));
  529. // Operations between TDuration/TInstant and std::chrono::duration are performed
  530. // with saturation according to the rules of TDuration/TInstant
  531. UNIT_ASSERT_VALUES_EQUAL(TDuration::Max() + 1h, TDuration::Max());
  532. UNIT_ASSERT_VALUES_EQUAL(TInstant::Max() + 1h, TInstant::Max());
  533. UNIT_ASSERT_VALUES_EQUAL(1h + TDuration::Max(), TDuration::Max());
  534. UNIT_ASSERT_VALUES_EQUAL(TInstant::Max() + 1h, TInstant::Max());
  535. UNIT_ASSERT_VALUES_EQUAL(TDuration::Max() - (-1h), TDuration::Max());
  536. UNIT_ASSERT_VALUES_EQUAL(TInstant::Max() - (-1h), TInstant::Max());
  537. UNIT_ASSERT_VALUES_EQUAL(TInstant::Max() - (-1h), TInstant::Max());
  538. UNIT_ASSERT_VALUES_EQUAL(-1h - TDuration::Max(), TDuration::Zero());
  539. UNIT_ASSERT_VALUES_EQUAL(1h - TDuration::Max(), TDuration::Zero());
  540. static_assert(TDuration::Zero() + 1s == 1s);
  541. static_assert(TInstant::Seconds(1) + 1s == TInstant::Seconds(2));
  542. }
  543. }