timestamp_test.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * Copyright 2018 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "Firestore/core/include/firebase/firestore/timestamp.h"
  17. #include <cmath>
  18. #include <limits>
  19. #include <utility>
  20. #include <vector>
  21. #include "Firestore/core/src/util/warnings.h"
  22. #include "gtest/gtest.h"
  23. SUPPRESS_COMMA_WARNINGS_BEGIN()
  24. #include "absl/time/clock.h"
  25. #include "absl/time/time.h"
  26. SUPPRESS_END()
  27. namespace firebase {
  28. namespace {
  29. using TimePoint = std::chrono::time_point<std::chrono::system_clock>;
  30. using Sec = std::chrono::seconds;
  31. using Ms = std::chrono::milliseconds;
  32. const auto kUpperBound = 253402300800L - 1;
  33. const auto kLowerBound = -62135596800L;
  34. constexpr int32_t kNanosPerSecond = 1000 * 1000 * 1000;
  35. // For near-bounds tests that use <chrono>, it's important to only run them if
  36. // system_clock::duration can represent values this large (e.g., on Linux, it's
  37. // system_clock::duration uses nanoseconds precision and thus would overflow
  38. // trying to represent very large numbers).
  39. bool CanSystemClockDurationHold(const Sec seconds) {
  40. namespace chr = std::chrono;
  41. if (seconds.count() >= 0) {
  42. const auto max_seconds =
  43. chr::duration_cast<chr::seconds>(TimePoint::duration::max()).count();
  44. return max_seconds >= seconds.count();
  45. } else {
  46. const auto min_seconds =
  47. chr::duration_cast<chr::seconds>(TimePoint::duration::min()).count();
  48. return min_seconds <= seconds.count();
  49. }
  50. }
  51. } // namespace
  52. TEST(Timestamp, Constructors) {
  53. const Timestamp zero;
  54. EXPECT_EQ(0, zero.seconds());
  55. EXPECT_EQ(0, zero.nanoseconds());
  56. const Timestamp positive(100, 200);
  57. EXPECT_EQ(100, positive.seconds());
  58. EXPECT_EQ(200, positive.nanoseconds());
  59. const Timestamp negative(-100, 200);
  60. EXPECT_EQ(-100, negative.seconds());
  61. EXPECT_EQ(200, negative.nanoseconds());
  62. const Timestamp now = Timestamp::Now();
  63. EXPECT_LT(0, now.seconds());
  64. EXPECT_LE(0, now.nanoseconds());
  65. Timestamp copy_now = now;
  66. EXPECT_EQ(now, copy_now);
  67. EXPECT_EQ(now.seconds(), copy_now.seconds());
  68. EXPECT_EQ(now.nanoseconds(), copy_now.nanoseconds());
  69. const Timestamp move_now = std::move(copy_now);
  70. EXPECT_EQ(now, move_now);
  71. }
  72. TEST(Timestamp, Now) {
  73. Timestamp now = Timestamp::Now();
  74. timespec spec = absl::ToTimespec(absl::Now());
  75. int64_t seconds_diff = spec.tv_sec - now.seconds();
  76. int64_t nanos_diff = spec.tv_nsec - now.nanoseconds();
  77. nanos_diff = std::abs(seconds_diff * kNanosPerSecond + nanos_diff);
  78. // Assert that time produced by Timestamp and Abseil are within 10ms of each
  79. // other. In practice these are only a few microseconds apart, but the
  80. // larger goal here is to verify that the seconds value is being properly
  81. // adjusted to be relative to the UNIX epoch.
  82. ASSERT_LT(nanos_diff, 10E6);
  83. }
  84. TEST(Timestamp, Bounds) {
  85. const Timestamp max_timestamp{kUpperBound, 999999999};
  86. EXPECT_EQ(kUpperBound, max_timestamp.seconds());
  87. EXPECT_EQ(999999999, max_timestamp.nanoseconds());
  88. const Timestamp min_timestamp{kLowerBound, 0};
  89. EXPECT_EQ(kLowerBound, min_timestamp.seconds());
  90. EXPECT_EQ(0, min_timestamp.nanoseconds());
  91. }
  92. TEST(Timestamp, FromTimeT) {
  93. const Timestamp zero = Timestamp::FromTimeT(std::time_t{});
  94. EXPECT_EQ(0, zero.seconds());
  95. EXPECT_EQ(0, zero.nanoseconds());
  96. const Timestamp positive = Timestamp::FromTimeT(std::time_t{123456});
  97. EXPECT_EQ(123456, positive.seconds());
  98. EXPECT_EQ(0, positive.nanoseconds());
  99. const Timestamp negative = Timestamp::FromTimeT(std::time_t{-123456});
  100. EXPECT_EQ(-123456, negative.seconds());
  101. EXPECT_EQ(0, negative.nanoseconds());
  102. }
  103. TEST(Timestamp, FromChrono) {
  104. const auto zero = Timestamp::FromTimePoint(TimePoint{});
  105. EXPECT_EQ(0, zero.seconds());
  106. EXPECT_EQ(0, zero.nanoseconds());
  107. const auto sec = Timestamp::FromTimePoint(TimePoint{Sec(123)});
  108. EXPECT_EQ(123, sec.seconds());
  109. EXPECT_EQ(0, sec.nanoseconds());
  110. const auto ms = Timestamp::FromTimePoint(TimePoint{Sec(123) + Ms(456)});
  111. EXPECT_EQ(123, ms.seconds());
  112. EXPECT_EQ(456000000, ms.nanoseconds());
  113. }
  114. TEST(Timestamp, FromChronoNegativeTime) {
  115. const auto no_fraction = Timestamp::FromTimePoint(TimePoint{Sec(-123)});
  116. EXPECT_EQ(-123, no_fraction.seconds());
  117. EXPECT_EQ(0, no_fraction.nanoseconds());
  118. const auto with_positive_fraction =
  119. Timestamp::FromTimePoint(TimePoint{Sec(-123) + Ms(456)});
  120. EXPECT_EQ(-123, with_positive_fraction.seconds());
  121. EXPECT_EQ(456000000, with_positive_fraction.nanoseconds());
  122. const auto with_negative_fraction =
  123. Timestamp::FromTimePoint(TimePoint{Sec(-122) + Ms(-544)});
  124. EXPECT_EQ(-123, with_negative_fraction.seconds());
  125. EXPECT_EQ(456000000, with_negative_fraction.nanoseconds());
  126. const auto with_large_negative_fraction =
  127. Timestamp::FromTimePoint(TimePoint{Sec(-122) + Ms(-100544)});
  128. EXPECT_EQ(-223, with_large_negative_fraction.seconds());
  129. EXPECT_EQ(456000000, with_large_negative_fraction.nanoseconds());
  130. const auto only_negative_fraction =
  131. Timestamp::FromTimePoint(TimePoint{Ms(-544)});
  132. EXPECT_EQ(-1, only_negative_fraction.seconds());
  133. EXPECT_EQ(456000000, only_negative_fraction.nanoseconds());
  134. const auto positive_time_negative_fraction =
  135. Timestamp::FromTimePoint(TimePoint{Sec(1) + Ms(-544)});
  136. EXPECT_EQ(0, positive_time_negative_fraction.seconds());
  137. EXPECT_EQ(456000000, positive_time_negative_fraction.nanoseconds());
  138. if (CanSystemClockDurationHold(Sec(kUpperBound + 1))) {
  139. const auto near_bounds =
  140. Timestamp::FromTimePoint(TimePoint{Sec(kUpperBound + 1) + Ms(-544)});
  141. EXPECT_EQ(kUpperBound, near_bounds.seconds());
  142. EXPECT_EQ(456000000, near_bounds.nanoseconds());
  143. }
  144. }
  145. TEST(Timestamp, ToChrono) {
  146. namespace chr = std::chrono;
  147. // Note: this line is outside the inner block because otherwise clang-format
  148. // gets confused about namespace alias on the line above.
  149. const Timestamp positive{123, 456789000};
  150. {
  151. const auto micros = positive.ToTimePoint().time_since_epoch();
  152. EXPECT_EQ(123456789, chr::duration_cast<chr::microseconds>(micros).count());
  153. const auto millis =
  154. positive.ToTimePoint<chr::system_clock, chr::milliseconds>()
  155. .time_since_epoch();
  156. EXPECT_EQ(123456000, chr::duration_cast<chr::microseconds>(millis).count());
  157. const auto nanos =
  158. positive.ToTimePoint<chr::system_clock, chr::nanoseconds>()
  159. .time_since_epoch();
  160. EXPECT_EQ(123456789000,
  161. chr::duration_cast<chr::nanoseconds>(nanos).count());
  162. }
  163. {
  164. const Timestamp negative{-123, 456000000};
  165. const auto millis =
  166. negative.ToTimePoint<chr::system_clock, chr::milliseconds>()
  167. .time_since_epoch();
  168. const auto seconds = chr::duration_cast<chr::seconds>(millis);
  169. EXPECT_EQ(-122, seconds.count());
  170. EXPECT_EQ(-544,
  171. chr::duration_cast<chr::milliseconds>(millis - seconds).count());
  172. }
  173. // Bounds
  174. {
  175. const Timestamp max{kUpperBound, 999999999};
  176. const auto max_micros = max.ToTimePoint().time_since_epoch();
  177. EXPECT_EQ(kUpperBound * 1000 * 1000 + 999999,
  178. chr::duration_cast<chr::microseconds>(max_micros).count());
  179. const Timestamp min{kLowerBound, 0};
  180. const auto min_micros = min.ToTimePoint().time_since_epoch();
  181. EXPECT_EQ(kLowerBound * 1000 * 1000,
  182. chr::duration_cast<chr::microseconds>(min_micros).count());
  183. }
  184. // Overflow
  185. {
  186. const Timestamp max{kUpperBound, 999999999};
  187. const auto max_nanos =
  188. max.ToTimePoint<chr::system_clock, chr::nanoseconds>()
  189. .time_since_epoch();
  190. EXPECT_EQ(std::numeric_limits<chr::nanoseconds::rep>::max(),
  191. chr::duration_cast<chr::nanoseconds>(max_nanos).count());
  192. const Timestamp min{kLowerBound, 0};
  193. const auto min_nanos =
  194. min.ToTimePoint<chr::system_clock, chr::nanoseconds>()
  195. .time_since_epoch();
  196. EXPECT_EQ(std::numeric_limits<chr::nanoseconds::rep>::min(),
  197. chr::duration_cast<chr::nanoseconds>(min_nanos).count());
  198. }
  199. }
  200. TEST(Timestamp, Comparison) {
  201. EXPECT_LT(Timestamp(), Timestamp(1, 2));
  202. EXPECT_LT(Timestamp(1, 2), Timestamp(2, 1));
  203. EXPECT_LT(Timestamp(2, 1), Timestamp(2, 2));
  204. EXPECT_GT(Timestamp(1, 1), Timestamp());
  205. EXPECT_GT(Timestamp(2, 1), Timestamp(1, 2));
  206. EXPECT_GT(Timestamp(2, 2), Timestamp(2, 1));
  207. EXPECT_LE(Timestamp(), Timestamp());
  208. EXPECT_LE(Timestamp(), Timestamp(1, 2));
  209. EXPECT_LE(Timestamp(1, 2), Timestamp(2, 1));
  210. EXPECT_LE(Timestamp(2, 1), Timestamp(2, 1));
  211. EXPECT_LE(Timestamp(2, 1), Timestamp(2, 2));
  212. EXPECT_GE(Timestamp(), Timestamp());
  213. EXPECT_GE(Timestamp(1, 1), Timestamp());
  214. EXPECT_GE(Timestamp(1, 1), Timestamp(1, 1));
  215. EXPECT_GE(Timestamp(2, 1), Timestamp(1, 2));
  216. EXPECT_GE(Timestamp(2, 1), Timestamp(2, 1));
  217. EXPECT_GE(Timestamp(2, 2), Timestamp(2, 1));
  218. EXPECT_EQ(Timestamp(), Timestamp());
  219. EXPECT_EQ(Timestamp(), Timestamp(0, 0));
  220. EXPECT_EQ(Timestamp(123, 123456789), Timestamp(123, 123456789));
  221. EXPECT_NE(Timestamp(), Timestamp(0, 1));
  222. EXPECT_NE(Timestamp(), Timestamp(1, 0));
  223. EXPECT_NE(Timestamp(123, 123456789), Timestamp(123, 123456780));
  224. }
  225. TEST(Timestamp, InvalidArguments) {
  226. // Negative nanoseconds.
  227. ASSERT_ANY_THROW(Timestamp(0, -1));
  228. ASSERT_ANY_THROW(Timestamp(100, -1));
  229. ASSERT_ANY_THROW(Timestamp(100, -12346789));
  230. // Nanoseconds that are more than one second.
  231. ASSERT_ANY_THROW(Timestamp(0, 999999999 + 1));
  232. // Seconds beyond supported range.
  233. ASSERT_ANY_THROW(Timestamp(kLowerBound - 1, 0));
  234. ASSERT_ANY_THROW(Timestamp(kUpperBound + 1, 0));
  235. }
  236. TEST(Timestamp, InvalidArgumentsChrono) {
  237. // Make sure Timestamp doesn't accept values beyond the supported range, if
  238. // system clock-based time_point on this platform can represent values this
  239. // large.
  240. if (CanSystemClockDurationHold(Sec(kUpperBound + 1))) {
  241. ASSERT_ANY_THROW(Timestamp::FromTimePoint(TimePoint{Sec(kUpperBound + 1)}));
  242. }
  243. if (CanSystemClockDurationHold(Sec(kLowerBound - 1))) {
  244. ASSERT_ANY_THROW(Timestamp::FromTimePoint(TimePoint{Sec(kLowerBound - 1)}));
  245. }
  246. }
  247. TEST(Timestamp, ToString) {
  248. EXPECT_EQ(Timestamp().ToString(), "Timestamp(seconds=0, nanoseconds=0)");
  249. EXPECT_EQ(Timestamp(123, 123456789).ToString(),
  250. "Timestamp(seconds=123, nanoseconds=123456789)");
  251. EXPECT_EQ(Timestamp(-123, 123456789).ToString(),
  252. "Timestamp(seconds=-123, nanoseconds=123456789)");
  253. }
  254. } // namespace firebase