userver: /data/code/userver/libraries/protobuf/tests/json/timestamp_to_json_test.cpp Source File
Loading...
Searching...
No Matches
timestamp_to_json_test.cpp
1#include <gtest/gtest.h>
2
3#include <chrono>
4#include <memory>
5#include <ostream>
6#include <string>
7
8#include <fmt/format.h>
9#include <google/protobuf/dynamic_message.h>
10
11#include <userver/protobuf/datetime.hpp>
12#include <userver/protobuf/json/convert.hpp>
13#include <userver/utest/assert_macros.hpp>
14
15#include "utils.hpp"
16
17USERVER_NAMESPACE_BEGIN
18
19namespace protobuf::json::tests {
20
21using namespace std::chrono_literals;
22
23constexpr auto kTestSeconds = 1s + 1min + 1h + 24h + (31 * 24h) + (365 * 24h);
24
25struct TimestampToJsonSuccessTestParam {
26 TimestampMessageData input = {};
27 std::string expected_json = {};
28 PrintOptions options = {};
29};
30
31struct TimestampToJsonFailureTestParam {
32 TimestampMessageData input = {};
33 PrintErrorCode expected_errc = {};
34 std::string expected_path = {};
35 PrintOptions options = {};
36
37 // Older protobuf versions erroneously pass some checks, we need a way to disable them.
38 bool skip_native_check = false;
39};
40
41void PrintTo(const TimestampToJsonSuccessTestParam& param, std::ostream* os) {
42 *os << fmt::format("{{ input = {{.seconds={}, .nanos={}}} }}", param.input.seconds, param.input.nanos);
43}
44
45void PrintTo(const TimestampToJsonFailureTestParam& param, std::ostream* os) {
46 *os << fmt::format("{{ input = {{.seconds={}, .nanos={}}} }}", param.input.seconds, param.input.nanos);
47}
48
49class TimestampToJsonSuccessTest : public ::testing::TestWithParam<TimestampToJsonSuccessTestParam> {};
50class TimestampToJsonFailureTest : public ::testing::TestWithParam<TimestampToJsonFailureTestParam> {};
51
52INSTANTIATE_TEST_SUITE_P(
53 ,
54 TimestampToJsonSuccessTest,
55 ::testing::Values(
56 TimestampToJsonSuccessTestParam{TimestampMessageData{0, 0, true}, R"({})"},
57 TimestampToJsonSuccessTestParam{TimestampMessageData{0, 0}, R"({"field1": "1970-01-01T00:00:00Z"})"},
58 TimestampToJsonSuccessTestParam{
59 TimestampMessageData{kTestSeconds.count(), 123456789},
60 R"({"field1": "1971-02-02T01:01:01.123456789Z"})"
61 },
62 TimestampToJsonSuccessTestParam{
63 TimestampMessageData{-kTestSeconds.count(), 987654321},
64 R"({"field1": "1968-11-29T22:58:59.987654321Z"})"
65 },
66 TimestampToJsonSuccessTestParam{
67 TimestampMessageData{kMaxTimestampSeconds, kMaxTimestampNanos},
68 R"({"field1": "9999-12-31T23:59:59.999999999Z"})"
69 },
70 TimestampToJsonSuccessTestParam{
71 TimestampMessageData{kMinTimestampSeconds, kMinTimestampNanos},
72 R"({"field1": "0001-01-01T00:00:00Z"})"
73 },
74 TimestampToJsonSuccessTestParam{
75 TimestampMessageData{0, 123456780},
76 R"({"field1": "1970-01-01T00:00:00.123456780Z"})"
77 },
78 TimestampToJsonSuccessTestParam{
79 TimestampMessageData{0, 123456000},
80 R"({"field1": "1970-01-01T00:00:00.123456Z"})"
81 },
82 TimestampToJsonSuccessTestParam{
83 TimestampMessageData{0, 123400000},
84 R"({"field1": "1970-01-01T00:00:00.123400Z"})"
85 },
86 TimestampToJsonSuccessTestParam{
87 TimestampMessageData{0, 100000000},
88 R"({"field1": "1970-01-01T00:00:00.100Z"})"
89 },
90 TimestampToJsonSuccessTestParam{
91 TimestampMessageData{1456704000, 123450000},
92 R"({"field1": "2016-02-29T00:00:00.123450Z"})"
93 },
94 TimestampToJsonSuccessTestParam{TimestampMessageData{0, 9}, R"({"field1": "1970-01-01T00:00:00.000000009Z"})"}
95 )
96);
97
98INSTANTIATE_TEST_SUITE_P(
99 ,
100 TimestampToJsonFailureTest,
101 ::testing::Values(
102 TimestampToJsonFailureTestParam{
103 TimestampMessageData{kMaxTimestampSeconds + 1, 0},
104 PrintErrorCode::kInvalidValue,
105 "field1"
106 },
107 TimestampToJsonFailureTestParam{
108 TimestampMessageData{kMinTimestampSeconds - 1, 0},
109 PrintErrorCode::kInvalidValue,
110 "field1"
111 },
112 TimestampToJsonFailureTestParam{
113 TimestampMessageData{0, kMaxTimestampNanos + 1},
114 PrintErrorCode::kInvalidValue,
115 "field1",
116 {},
117#if GOOGLE_PROTOBUF_VERSION >= 6033000
118 false
119#else
120 true
121#endif
122 },
123 TimestampToJsonFailureTestParam{
124 TimestampMessageData{0, kMinTimestampNanos - 1},
125 PrintErrorCode::kInvalidValue,
126 "field1",
127 {},
128#if GOOGLE_PROTOBUF_VERSION >= 6033000
129 false
130#else
131 true
132#endif
133 }
134 )
135);
136
137TEST_P(TimestampToJsonSuccessTest, Test) {
138 const auto& param = GetParam();
139
140 auto input = PrepareTestData(param.input);
141 formats::json::Value json, expected_json, sample_json;
142
143 UASSERT_NO_THROW((json = MessageToJson(input, param.options)));
144 UASSERT_NO_THROW((expected_json = PrepareJsonTestData(param.expected_json)));
145 UASSERT_NO_THROW((sample_json = CreateSampleJson(input, param.options)));
146
147 EXPECT_EQ(json, expected_json);
148 EXPECT_EQ(expected_json, sample_json);
149}
150
151TEST_P(TimestampToJsonFailureTest, Test) {
152 const auto& param = GetParam();
153 auto input = PrepareTestData(param.input);
154
155 EXPECT_PRINT_ERROR((void)MessageToJson(input, param.options), param.expected_errc, param.expected_path);
156
157 if (!param.skip_native_check) {
158 UEXPECT_THROW((void)CreateSampleJson(input, param.options), SampleError);
159 }
160}
161
162TEST(TimestampToJsonAdditionalTest, InlinedNonNull) {
163 TimestampMessageData data{123, 321};
164 auto message = PrepareTestData(data);
165 formats::json::Value json, sample;
166
167 UASSERT_NO_THROW((json = MessageToJson(message.field1(), {})));
168 UASSERT_NO_THROW((sample = CreateSampleJson(message.field1())));
169 ASSERT_TRUE(json.IsString());
170 EXPECT_EQ(json, sample);
171 EXPECT_EQ(json.As<std::string>(), "1970-01-01T00:02:03.000000321Z");
172}
173
174TEST(TimestampToJsonAdditionalTest, InlinedNull) {
175 proto_json::messages::TimestampMessage message;
176 formats::json::Value json, sample;
177
178 UASSERT_NO_THROW((json = MessageToJson(message.field1(), {})));
179 UASSERT_NO_THROW((sample = CreateSampleJson(message.field1())));
180 ASSERT_TRUE(json.IsString());
181 EXPECT_EQ(json, sample);
182 EXPECT_EQ(json.As<std::string>(), "1970-01-01T00:00:00Z");
183}
184
185TEST(TimestampToJsonAdditionalTest, DynamicMessage) {
186 using Message = ::google::protobuf::Timestamp;
187 ::google::protobuf::DynamicMessageFactory factory;
188
189 {
190 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
191 const auto reflection = message->GetReflection();
192 const auto seconds_desc = message->GetDescriptor()->FindFieldByName("seconds");
193 const auto nanos_desc = message->GetDescriptor()->FindFieldByName("nanos");
194
195 reflection->SetInt64(message.get(), seconds_desc, 1456704000);
196 reflection->SetInt32(message.get(), nanos_desc, 123450000);
197
198 formats::json::Value json;
199
200 UASSERT_NO_THROW((json = MessageToJson(*message, {})));
201 ASSERT_TRUE(json.IsString());
202 EXPECT_EQ(json.As<std::string>(), "2016-02-29T00:00:00.123450Z");
203 }
204}
205
206} // namespace protobuf::json::tests
207
208USERVER_NAMESPACE_END