userver: /data/code/userver/libraries/proto-structs/tests/timestamp_test.cpp Source File
Loading...
Searching...
No Matches
timestamp_test.cpp
1#include <gtest/gtest.h>
2
3#include <limits>
4
5#include <userver/proto-structs/exceptions.hpp>
6#include <userver/proto-structs/timestamp.hpp>
7#include <userver/utest/assert_macros.hpp>
8#include <userver/utils/impl/internal_tag.hpp>
9
10using namespace std::literals::chrono_literals;
11
12USERVER_NAMESPACE_BEGIN
13
14namespace proto_structs::tests {
15
16TEST(TimestampTest, IsValid) {
17 using OverflowingDuration = std::chrono::duration<std::chrono::seconds::rep, std::chrono::hours::period>;
18 constexpr auto kMaxSystemClockDuration = std::chrono::system_clock::time_point::max().time_since_epoch();
19
20 EXPECT_FALSE(Timestamp::IsValid(Timestamp::kMinSeconds - 1s, 0ns));
21 EXPECT_FALSE(Timestamp::IsValid(Timestamp::kMaxSeconds + 1s, 0ns));
22 EXPECT_FALSE(Timestamp::IsValid(0s, 1'000'000'000ns));
23 EXPECT_FALSE(Timestamp::IsValid(0s, -1ns));
24 EXPECT_FALSE(Timestamp::IsValid(1s, -1ns));
25 EXPECT_FALSE(Timestamp::IsValid(-1s, -1ns));
26
27 EXPECT_THROW(Timestamp(Timestamp::kMinSeconds - 1s, 0ns), ValueError);
28 EXPECT_THROW(Timestamp{Duration::Min()}, ValueError);
29 EXPECT_THROW(Timestamp{Duration::Max()}, ValueError);
30 EXPECT_THROW(Timestamp(Timestamp::kMinSeconds - 1s), ValueError);
31 EXPECT_THROW(Timestamp(Timestamp::kMaxSeconds + 1s), ValueError);
32
33 if constexpr (std::chrono::duration_cast<std::chrono::seconds>(kMaxSystemClockDuration) > Timestamp::kMaxSeconds) {
34 EXPECT_THROW(Timestamp{std::chrono::system_clock::time_point::max()}, ValueError);
35 }
36
37 EXPECT_THROW(
38 Timestamp(utils::impl::InternalTag{}, std::numeric_limits<int64_t>::max(), std::numeric_limits<int32_t>::max()),
39 ValueError
40 );
41 EXPECT_THROW(
42 Timestamp(utils::impl::InternalTag{}, std::numeric_limits<int64_t>::min(), std::numeric_limits<int32_t>::min()),
43 ValueError
44 );
45
46 UEXPECT_THROW_MSG(Timestamp(-100'654'321'000s, 123'456'789ns), ValueError, "-100654321000s.123456789ns");
47 UEXPECT_THROW_MSG((Timestamp{OverflowingDuration::max()}), ValueError, "will overflow");
48
49 EXPECT_TRUE(Timestamp::IsValid(0s, 0ns));
50 EXPECT_TRUE(Timestamp::IsValid(0s, 1ns));
51 EXPECT_TRUE(Timestamp::IsValid(1s, 1ns));
52 EXPECT_TRUE(Timestamp::IsValid(Timestamp::Min().Seconds(), Timestamp::Min().Nanos()));
53 EXPECT_TRUE(Timestamp::IsValid(Timestamp::Max().Seconds(), Timestamp::Max().Nanos()));
54}
55
56TEST(TimestampTest, MinMax) {
57 EXPECT_EQ(Timestamp::Min().Seconds(), Timestamp::kMinSeconds);
58 EXPECT_EQ(Timestamp::Min().Nanos(), 0ns);
59 EXPECT_EQ(Timestamp::Min().GetTimeSinceEpoch().Seconds(), Timestamp::kMinSeconds);
60 EXPECT_EQ(Timestamp::Min().GetTimeSinceEpoch().Nanos(), 0ns);
61 EXPECT_EQ(Timestamp::Max().Seconds(), Timestamp::kMaxSeconds);
62 EXPECT_EQ(Timestamp::Max().Nanos(), 999'999'999ns);
63 EXPECT_EQ(Timestamp::Max().GetTimeSinceEpoch().Seconds(), Timestamp::kMaxSeconds);
64 EXPECT_EQ(Timestamp::Max().GetTimeSinceEpoch().Nanos(), 999'999'999ns);
65}
66
67TEST(TimestampTest, Conversions) {
68 using SysClockDuration = std::chrono::system_clock::time_point::duration;
69
70 Timestamp t;
71
72 EXPECT_EQ(t.Seconds(), 0s);
73 EXPECT_EQ(t.Nanos(), 0ns);
74 ASSERT_TRUE(t.FitsInChronoTimePoint());
75 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(0ns));
76 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), 0s);
77 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), 0ns);
78
79 t = Timestamp(123s, 987'654'321ns);
80
81 EXPECT_EQ(t.Seconds(), 123s);
82 EXPECT_EQ(t.Nanos(), 987'654'321ns);
83 ASSERT_TRUE(t.FitsInChronoTimePoint());
84 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(123s + 987'654'321ns));
85 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), 123s);
86 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), 987'654'321ns);
87
88 t = Timestamp{Duration(333s, 123'456'789ns)};
89
90 EXPECT_EQ(t.Seconds(), 333s);
91 EXPECT_EQ(t.Nanos(), 123'456'789ns);
92 ASSERT_TRUE(t.FitsInChronoTimePoint());
93 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(333s + 123'456'789ns));
94 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), 333s);
95 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), 123'456'789ns);
96
97 t = Timestamp{Duration(-333s, -123'456'789ns)};
98
99 EXPECT_EQ(t.Seconds(), -334s);
100 EXPECT_EQ(t.Nanos(), -123'456'789ns + 1s);
101 ASSERT_TRUE(t.FitsInChronoTimePoint());
102 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(-333s - 123'456'789ns));
103 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), -333s);
104 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), -123'456'789ns);
105
106 t = Timestamp{555'987'654'321ns};
107
108 EXPECT_EQ(t.Seconds(), 555s);
109 EXPECT_EQ(t.Nanos(), 987'654'321ns);
110 ASSERT_TRUE(t.FitsInChronoTimePoint());
111 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(555s + 987'654'321ns));
112 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), 555s);
113 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), 987'654'321ns);
114
115 t = Timestamp{-555'987'654'321ns};
116
117 EXPECT_EQ(t.Seconds(), -556s);
118 EXPECT_EQ(t.Nanos(), -987'654'321ns + 1s);
119 ASSERT_TRUE(t.FitsInChronoTimePoint());
120 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), -555s);
121 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), -987'654'321ns);
122
123 std::chrono::system_clock::time_point point{std::chrono::duration_cast<SysClockDuration>(777'111'222'333ns)};
124 t = point;
125
126 EXPECT_EQ(t.Seconds(), 777s);
127 EXPECT_EQ(t.Nanos(), std::chrono::duration_cast<SysClockDuration>(111'222'333ns));
128 ASSERT_TRUE(t.FitsInChronoTimePoint());
129 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(777s + 111'222'333ns));
130 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), 777s);
131 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), std::chrono::duration_cast<SysClockDuration>(111'222'333ns));
132
133 t = Timestamp{utils::impl::InternalTag{}, 1001, 333'555'777};
134
135 EXPECT_EQ(t.Seconds(), 1001s);
136 EXPECT_EQ(t.Nanos(), 333'555'777ns);
137 ASSERT_TRUE(t.FitsInChronoTimePoint());
138 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(1001s + 333'555'777ns));
139 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), 1001s);
140 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), 333'555'777ns);
141}
142
143TEST(TimestampTest, SaturateCast) {
144 if constexpr (!Timestamp::Min().GetTimeSinceEpoch().FitsInChronoDuration<std::chrono::system_clock::duration>()) {
145 EXPECT_EQ(Timestamp::Min().ToTimePoint(), std::chrono::system_clock::time_point::min());
146 }
147
148 if constexpr (!Timestamp::Max().GetTimeSinceEpoch().FitsInChronoDuration<std::chrono::system_clock::duration>()) {
149 EXPECT_EQ(Timestamp::Max().ToTimePoint(), std::chrono::system_clock::time_point::max());
150 }
151}
152
153} // namespace proto_structs::tests
154
155USERVER_NAMESPACE_END