1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
6#include <userver/proto-structs/exceptions.hpp>
7#include <userver/proto-structs/timestamp.hpp>
8#include "userver/proto-structs/duration.hpp"
9#include "userver/utils/impl/internal_tag.hpp"
11using namespace std::literals::chrono_literals;
13USERVER_NAMESPACE_BEGIN
15namespace proto_structs::tests {
17TEST(TimestampTest, IsValid) {
18 using OverflowingDuration = std::chrono::duration<std::chrono::seconds::rep, std::chrono::hours::period>;
19 constexpr auto kMaxSystemClockDuration = std::chrono::system_clock::time_point::max().time_since_epoch();
21 EXPECT_FALSE(Timestamp::IsValid(Timestamp::kMinSeconds - 1s, 0ns));
22 EXPECT_FALSE(Timestamp::IsValid(Timestamp::kMaxSeconds + 1s, 0ns));
23 EXPECT_FALSE(Timestamp::IsValid(0s, 1'000'000'000ns));
24 EXPECT_FALSE(Timestamp::IsValid(0s, -1ns));
25 EXPECT_FALSE(Timestamp::IsValid(1s, -1ns));
26 EXPECT_FALSE(Timestamp::IsValid(-1s, -1ns));
28 EXPECT_THROW(Timestamp(Timestamp::kMinSeconds - 1s, 0ns), ValueError);
29 EXPECT_THROW(Timestamp{Duration::Min()}, ValueError);
30 EXPECT_THROW(Timestamp{Duration::Max()}, ValueError);
31 EXPECT_THROW(Timestamp(Timestamp::kMinSeconds - 1s), ValueError);
32 EXPECT_THROW(Timestamp(Timestamp::kMaxSeconds + 1s), ValueError);
34 if constexpr (std::chrono::duration_cast<std::chrono::seconds>(kMaxSystemClockDuration) > Timestamp::kMaxSeconds) {
35 EXPECT_THROW(Timestamp{std::chrono::system_clock::time_point::max()}, ValueError);
39 Timestamp(
utils::impl::InternalTag{}, std::numeric_limits<int64_t>::max(), std::numeric_limits<int32_t>::max()),
43 Timestamp(
utils::impl::InternalTag{}, std::numeric_limits<int64_t>::min(), std::numeric_limits<int32_t>::min()),
48 []() { [[maybe_unused]] Timestamp t(-100'654'321'000s, 123'456'789ns); },
49 ::testing::ThrowsMessage<ValueError>(::testing::HasSubstr(
"-100654321000s.123456789ns"))
52 []() { [[maybe_unused]] Timestamp t(OverflowingDuration::max()); },
53 ::testing::ThrowsMessage<ValueError>(::testing::HasSubstr(
"will overflow"))
56 EXPECT_TRUE(Timestamp::IsValid(0s, 0ns));
57 EXPECT_TRUE(Timestamp::IsValid(0s, 1ns));
58 EXPECT_TRUE(Timestamp::IsValid(1s, 1ns));
59 EXPECT_TRUE(Timestamp::IsValid(Timestamp::Min().Seconds(), Timestamp::Min().Nanos()));
60 EXPECT_TRUE(Timestamp::IsValid(Timestamp::Max().Seconds(), Timestamp::Max().Nanos()));
63TEST(TimestampTest, MinMax) {
64 EXPECT_EQ(Timestamp::Min().Seconds(), Timestamp::kMinSeconds);
65 EXPECT_EQ(Timestamp::Min().Nanos(), 0ns);
66 EXPECT_EQ(Timestamp::Min().GetTimeSinceEpoch().Seconds(), Timestamp::kMinSeconds);
67 EXPECT_EQ(Timestamp::Min().GetTimeSinceEpoch().Nanos(), 0ns);
68 EXPECT_EQ(Timestamp::Max().Seconds(), Timestamp::kMaxSeconds);
69 EXPECT_EQ(Timestamp::Max().Nanos(), 999'999'999ns);
70 EXPECT_EQ(Timestamp::Max().GetTimeSinceEpoch().Seconds(), Timestamp::kMaxSeconds);
71 EXPECT_EQ(Timestamp::Max().GetTimeSinceEpoch().Nanos(), 999'999'999ns);
74TEST(TimestampTest, Conversions) {
75 using SysClockDuration = std::chrono::system_clock::time_point::duration;
79 EXPECT_EQ(t.Seconds(), 0s);
80 EXPECT_EQ(t.Nanos(), 0ns);
81 ASSERT_TRUE(t.FitsInChronoTimePoint());
82 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(0ns));
83 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), 0s);
84 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), 0ns);
86 t = Timestamp(123s, 987'654'321ns);
88 EXPECT_EQ(t.Seconds(), 123s);
89 EXPECT_EQ(t.Nanos(), 987'654'321ns);
90 ASSERT_TRUE(t.FitsInChronoTimePoint());
91 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(123s + 987'654'321ns));
92 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), 123s);
93 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), 987'654'321ns);
95 t = Timestamp{Duration(333s, 123'456'789ns)};
97 EXPECT_EQ(t.Seconds(), 333s);
98 EXPECT_EQ(t.Nanos(), 123'456'789ns);
99 ASSERT_TRUE(t.FitsInChronoTimePoint());
100 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(333s + 123'456'789ns));
101 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), 333s);
102 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), 123'456'789ns);
104 t = Timestamp{Duration(-333s, -123'456'789ns)};
106 EXPECT_EQ(t.Seconds(), -334s);
107 EXPECT_EQ(t.Nanos(), -123'456'789ns + 1s);
108 ASSERT_TRUE(t.FitsInChronoTimePoint());
109 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(-333s - 123'456'789ns));
110 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), -333s);
111 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), -123'456'789ns);
113 t = Timestamp{555'987'654'321ns};
115 EXPECT_EQ(t.Seconds(), 555s);
116 EXPECT_EQ(t.Nanos(), 987'654'321ns);
117 ASSERT_TRUE(t.FitsInChronoTimePoint());
118 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(555s + 987'654'321ns));
119 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), 555s);
120 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), 987'654'321ns);
122 t = Timestamp{-555'987'654'321ns};
124 EXPECT_EQ(t.Seconds(), -556s);
125 EXPECT_EQ(t.Nanos(), -987'654'321ns + 1s);
126 ASSERT_TRUE(t.FitsInChronoTimePoint());
127 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), -555s);
128 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), -987'654'321ns);
130 std::chrono::system_clock::time_point point{std::chrono::duration_cast<SysClockDuration>(777'111'222'333ns)};
133 EXPECT_EQ(t.Seconds(), 777s);
134 EXPECT_EQ(t.Nanos(), std::chrono::duration_cast<SysClockDuration>(111'222'333ns));
135 ASSERT_TRUE(t.FitsInChronoTimePoint());
136 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(777s + 111'222'333ns));
137 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), 777s);
138 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), std::chrono::duration_cast<SysClockDuration>(111'222'333ns));
140 t = Timestamp{utils::impl::InternalTag{}, 1001, 333'555'777};
142 EXPECT_EQ(t.Seconds(), 1001s);
143 EXPECT_EQ(t.Nanos(), 333'555'777ns);
144 ASSERT_TRUE(t.FitsInChronoTimePoint());
145 EXPECT_EQ(t.ToTimePoint().time_since_epoch(), std::chrono::duration_cast<SysClockDuration>(1001s + 333'555'777ns));
146 EXPECT_EQ(t.GetTimeSinceEpoch().Seconds(), 1001s);
147 EXPECT_EQ(t.GetTimeSinceEpoch().Nanos(), 333'555'777ns);
150TEST(TimestampTest, SaturateCast) {
151 if constexpr (!Timestamp::Min().GetTimeSinceEpoch().FitsInChronoDuration<std::chrono::system_clock::duration>()) {
152 EXPECT_EQ(Timestamp::Min().ToTimePoint(), std::chrono::system_clock::time_point::min());
155 if constexpr (!Timestamp::Max().GetTimeSinceEpoch().FitsInChronoDuration<std::chrono::system_clock::duration>()) {
156 EXPECT_EQ(Timestamp::Max().ToTimePoint(), std::chrono::system_clock::time_point::max());