1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
6#include <userver/proto-structs/duration.hpp>
7#include <userver/proto-structs/exceptions.hpp>
8#include <userver/utils/impl/internal_tag.hpp>
10using namespace std::literals::chrono_literals;
12USERVER_NAMESPACE_BEGIN
14namespace proto_structs::tests {
16TEST(DurationTest, IsValid) {
17 using OverflowingDuration = std::chrono::duration<std::chrono::seconds::rep, std::chrono::hours::period>;
19 EXPECT_FALSE(Duration::IsValid(Duration::kMinSeconds - 1s, 0ns));
20 EXPECT_FALSE(Duration::IsValid(Duration::kMaxSeconds + 1s, 0ns));
21 EXPECT_FALSE(Duration::IsValid(0s, 1'000'000'000ns));
22 EXPECT_FALSE(Duration::IsValid(0s, -1'000'000'000ns));
23 EXPECT_FALSE(Duration::IsValid(1s, -1ns));
24 EXPECT_FALSE(Duration::IsValid(-1s, 1ns));
26 EXPECT_THROW(Duration(Duration::kMinSeconds - 1s, 0ns), ValueError);
27 EXPECT_THROW(Duration(Duration::kMinSeconds - 1s), ValueError);
28 EXPECT_THROW(Duration{OverflowingDuration::max()}, ValueError);
29 EXPECT_THROW(Duration{OverflowingDuration::min()}, ValueError);
31 Duration(
utils::impl::InternalTag{}, std::numeric_limits<int64_t>::max(), std::numeric_limits<int32_t>::max()),
35 Duration(
utils::impl::InternalTag{}, std::numeric_limits<int64_t>::min(), std::numeric_limits<int32_t>::min()),
39 []() { [[maybe_unused]] Duration d(987'654'321'000s, 123'456'789ns); },
40 ::testing::ThrowsMessage<ValueError>(::testing::HasSubstr(
"987654321000s.123456789ns"))
43 []() { [[maybe_unused]] Duration d(OverflowingDuration::max()); },
44 ::testing::ThrowsMessage<ValueError>(::testing::HasSubstr(
"will overflow"))
47 EXPECT_TRUE(Duration::IsValid(0s, 0ns));
48 EXPECT_TRUE(Duration::IsValid(0s, 1ns));
49 EXPECT_TRUE(Duration::IsValid(0s, -1ns));
50 EXPECT_TRUE(Duration::IsValid(1s, 1ns));
51 EXPECT_TRUE(Duration::IsValid(-1s, -1ns));
52 EXPECT_TRUE(Duration::IsValid(Duration::Min().Seconds(), Duration::Min().Nanos()));
53 EXPECT_TRUE(Duration::IsValid(Duration::Max().Seconds(), Duration::Max().Nanos()));
56TEST(DurationTest, MinMax) {
57 EXPECT_EQ(Duration::Min().Seconds(), Duration::kMinSeconds);
58 EXPECT_EQ(Duration::Min().Nanos(), -999'999'999ns);
59 EXPECT_EQ(Duration::Max().Seconds(), Duration::kMaxSeconds);
60 EXPECT_EQ(Duration::Max().Nanos(), 999'999'999ns);
63TEST(DurationTest, Conversions) {
66 EXPECT_EQ(d.Seconds(), 0s);
67 EXPECT_EQ(d.Nanos(), 0ns);
69 d = Duration(123s, 987'654'321ns);
71 EXPECT_EQ(d.Seconds(), 123s);
72 EXPECT_EQ(d.Nanos(), 987'654'321ns);
73 ASSERT_TRUE(d.FitsInChronoDuration<std::chrono::minutes>());
74 EXPECT_EQ(d.ToChronoDuration<std::chrono::minutes>(), 2min);
75 EXPECT_EQ(
static_cast<std::chrono::minutes>(d), 2min);
76 EXPECT_EQ(d.ToNanos(), 123'987'654'321ns);
77 EXPECT_EQ(d.ToMicros(), 123'987'654us);
78 EXPECT_EQ(d.ToMillis(), 123'987ms);
80 d = -123'987'654'321ns;
82 EXPECT_EQ(d.Seconds(), -123s);
83 EXPECT_EQ(d.Nanos(), -987'654'321ns);
84 ASSERT_TRUE(d.FitsInChronoDuration<std::chrono::minutes>());
85 EXPECT_EQ(d.ToChronoDuration<std::chrono::minutes>(), -2min);
86 EXPECT_EQ(
static_cast<std::chrono::minutes>(d), -2min);
87 EXPECT_EQ(d.ToNanos(), -123'987'654'321ns);
88 EXPECT_EQ(d.ToMicros(), -123'987'654us);
89 EXPECT_EQ(d.ToMillis(), -123'987ms);
91 d = Duration(
utils::impl::InternalTag{}, 10, 987);
93 EXPECT_EQ(d.Seconds(), 10s);
94 EXPECT_EQ(d.Nanos(), 987ns);
97TEST(DurationTest, SaturateCast) {
98 constexpr auto kMaxSeconds = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::nanoseconds::max());
99 constexpr auto kMinSeconds = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::nanoseconds::min());
100 static_assert(kMaxSeconds < Duration::kMaxSeconds && kMinSeconds > Duration::kMinSeconds);
104 ASSERT_NO_THROW(d = std::chrono::nanoseconds::max());
105 EXPECT_TRUE(d.FitsInChronoDuration<std::chrono::nanoseconds>());
106 EXPECT_EQ(d.ToChronoDuration<std::chrono::nanoseconds>(), std::chrono::nanoseconds::max());
107 EXPECT_EQ(
static_cast<std::chrono::nanoseconds>(d), std::chrono::nanoseconds::max());
108 EXPECT_EQ(d.ToNanos(), std::chrono::nanoseconds::max());
110 ASSERT_NO_THROW(d = std::chrono::nanoseconds::min());
111 EXPECT_TRUE(d.FitsInChronoDuration<std::chrono::nanoseconds>());
112 EXPECT_EQ(d.ToChronoDuration<std::chrono::nanoseconds>(), std::chrono::nanoseconds::min());
113 EXPECT_EQ(
static_cast<std::chrono::nanoseconds>(d), std::chrono::nanoseconds::min());
114 EXPECT_EQ(d.ToNanos(), std::chrono::nanoseconds::min());
116 ASSERT_NO_THROW(d = Duration(kMaxSeconds + 1s, 0ns));
117 EXPECT_FALSE(d.FitsInChronoDuration<std::chrono::nanoseconds>());
118 EXPECT_EQ(d.ToChronoDuration<std::chrono::nanoseconds>(), std::chrono::nanoseconds::max());
119 EXPECT_EQ(
static_cast<std::chrono::nanoseconds>(d), std::chrono::nanoseconds::max());
120 EXPECT_EQ(d.ToNanos(), std::chrono::nanoseconds::max());
122 ASSERT_NO_THROW(d = Duration(kMinSeconds - 1s, 0ns));
123 EXPECT_FALSE(d.FitsInChronoDuration<std::chrono::nanoseconds>());
124 EXPECT_EQ(d.ToChronoDuration<std::chrono::nanoseconds>(), std::chrono::nanoseconds::min());
125 EXPECT_EQ(
static_cast<std::chrono::nanoseconds>(d), std::chrono::nanoseconds::min());
126 EXPECT_EQ(d.ToNanos(), std::chrono::nanoseconds::min());
128 ASSERT_NO_THROW(d = Duration(kMaxSeconds + 1s, 123'456'789ns));
129 EXPECT_FALSE(d.FitsInChronoDuration<std::chrono::nanoseconds>());
130 EXPECT_TRUE(d.FitsInChronoDuration<std::chrono::milliseconds>());
131 EXPECT_EQ(d.ToChronoDuration<std::chrono::milliseconds>(), kMaxSeconds + 1s + 123ms);
132 EXPECT_EQ(
static_cast<std::chrono::milliseconds>(d), kMaxSeconds + 1s + 123ms);
133 EXPECT_EQ(d.ToNanos(), std::chrono::nanoseconds::max());
134 EXPECT_EQ(d.ToMillis(), kMaxSeconds + 1s + 123ms);
136 ASSERT_NO_THROW(d = Duration(kMinSeconds - 1s, -123'456'789ns));
137 EXPECT_FALSE(d.FitsInChronoDuration<std::chrono::nanoseconds>());
138 EXPECT_TRUE(d.FitsInChronoDuration<std::chrono::milliseconds>());
139 EXPECT_EQ(d.ToChronoDuration<std::chrono::milliseconds>(), kMinSeconds - 1s - 123ms);
140 EXPECT_EQ(
static_cast<std::chrono::milliseconds>(d), kMinSeconds - 1s - 123ms);
141 EXPECT_EQ(d.ToNanos(), std::chrono::nanoseconds::min());
142 EXPECT_EQ(d.ToMillis(), kMinSeconds - 1s - 123ms);
145 using TestDuration = std::chrono::duration<std::int16_t, std::pico>;
148 ASSERT_NO_THROW(d = Duration::Min());
149 EXPECT_FALSE(d.FitsInChronoDuration<TestDuration>());
150 EXPECT_EQ(d.ToChronoDuration<TestDuration>(), TestDuration::min());
151 EXPECT_EQ(
static_cast<TestDuration>(d), TestDuration::min());
153 ASSERT_NO_THROW(d = Duration::Max());
154 EXPECT_FALSE(d.FitsInChronoDuration<TestDuration>());
155 EXPECT_EQ(d.ToChronoDuration<TestDuration>(), TestDuration::max());
156 EXPECT_EQ(
static_cast<TestDuration>(d), TestDuration::max());
158 ASSERT_NO_THROW(d = TestDuration::min());
159 EXPECT_TRUE(d.FitsInChronoDuration<TestDuration>());
160 EXPECT_EQ(d.Seconds(), 0s);
161 EXPECT_EQ(d.Nanos(), -32ns);
162 EXPECT_EQ(d.ToChronoDuration<TestDuration>().count(), -32'000);
163 EXPECT_EQ(
static_cast<TestDuration>(d).count(), -32'000);
165 ASSERT_NO_THROW(d = TestDuration::max());
166 EXPECT_TRUE(d.FitsInChronoDuration<TestDuration>());
167 EXPECT_EQ(d.Seconds(), 0s);
168 EXPECT_EQ(d.Nanos(), 32ns);
169 EXPECT_EQ(d.ToChronoDuration<TestDuration>().count(), 32'000);
170 EXPECT_EQ(
static_cast<TestDuration>(d).count(), 32'000);
174 using TestDuration = std::chrono::duration<std::int16_t, std::chrono::weeks::period>;
177 ASSERT_NO_THROW(d = Duration::Min());
178 EXPECT_FALSE(d.FitsInChronoDuration<TestDuration>());
179 EXPECT_EQ(d.ToChronoDuration<TestDuration>(), TestDuration::min());
180 EXPECT_EQ(
static_cast<TestDuration>(d), TestDuration::min());
182 ASSERT_NO_THROW(d = Duration::Max());
183 EXPECT_FALSE(d.FitsInChronoDuration<TestDuration>());
184 EXPECT_EQ(d.ToChronoDuration<TestDuration>(), TestDuration::max());
185 EXPECT_EQ(
static_cast<TestDuration>(d), TestDuration::max());
187 ASSERT_NO_THROW(d = TestDuration::min());
188 EXPECT_TRUE(d.FitsInChronoDuration<TestDuration>());
189 EXPECT_EQ(d.ToChronoDuration<TestDuration>(), TestDuration::min());
190 EXPECT_EQ(
static_cast<TestDuration>(d), TestDuration::min());
192 ASSERT_NO_THROW(d = TestDuration::max());
193 EXPECT_TRUE(d.FitsInChronoDuration<TestDuration>());
194 EXPECT_EQ(d.ToChronoDuration<TestDuration>(), TestDuration::max());
195 EXPECT_EQ(
static_cast<TestDuration>(d), TestDuration::max());