1#include <gtest/gtest.h>
9#include <google/protobuf/dynamic_message.h>
11#include <userver/formats/json/serialize.hpp>
12#include <userver/protobuf/datetime.hpp>
13#include <userver/protobuf/json/convert.hpp>
14#include <userver/utest/assert_macros.hpp>
18USERVER_NAMESPACE_BEGIN
20namespace protobuf::json::tests {
22using namespace std::chrono_literals;
24constexpr auto kTestSeconds = 1s + 1min + 1h + 24h + (31 * 24h) + (365 * 24h);
26struct TimestampFromJsonSuccessTestParam {
27 std::string input = {};
29 ParseOptions options = {};
32struct TimestampFromJsonFailureTestParam {
33 std::string input = {};
34 ParseErrorCode expected_errc = {};
35 std::string expected_path = {};
36 ParseOptions options = {};
41 bool skip_native_check =
false;
44void PrintTo(
const TimestampFromJsonSuccessTestParam& param, std::ostream* os) {
45 *os << fmt::format(
"{{ input = '{}' }}", param.input);
48void PrintTo(
const TimestampFromJsonFailureTestParam& param, std::ostream* os) {
49 *os << fmt::format(
"{{ input = '{}' }}", param.input);
52class TimestampFromJsonSuccessTest :
public ::testing::TestWithParam<TimestampFromJsonSuccessTestParam> {};
53class TimestampFromJsonFailureTest :
public ::testing::TestWithParam<TimestampFromJsonFailureTestParam> {};
55INSTANTIATE_TEST_SUITE_P(
57 TimestampFromJsonSuccessTest,
59 TimestampFromJsonSuccessTestParam{R"({})", TimestampMessageData{0, 0,
true}},
60 TimestampFromJsonSuccessTestParam{R"({"field1":null})", TimestampMessageData{0, 0,
true}},
61 TimestampFromJsonSuccessTestParam{R"({"field1":"1970-01-01T00:00:00Z"})", TimestampMessageData{0, 0}},
62 TimestampFromJsonSuccessTestParam{
63 R"({"field1":"1971-02-02T01:01:01.123456789Z"})",
64 TimestampMessageData{kTestSeconds.count(), 123456789}
66 TimestampFromJsonSuccessTestParam{
67 R"({"field1":"1968-11-29T22:58:59.987654321Z"})",
68 TimestampMessageData{-kTestSeconds.count(), 987654321}
70 TimestampFromJsonSuccessTestParam{
71 R"({"field1":"9999-12-31T23:59:59.999999999Z"})",
72 TimestampMessageData{kMaxTimestampSeconds, kMaxTimestampNanos}
74 TimestampFromJsonSuccessTestParam{
75 R"({"field1":"0001-01-01T00:00:00Z"})",
76 TimestampMessageData{kMinTimestampSeconds, kMinTimestampNanos}
78 TimestampFromJsonSuccessTestParam{
79 R"({"field1":"1970-01-01T00:00:00.123456780Z"})",
80 TimestampMessageData{0, 123456780}
82 TimestampFromJsonSuccessTestParam{
83 R"({"field1":"1970-01-01T00:00:00.123456Z"})",
84 TimestampMessageData{0, 123456000}
86 TimestampFromJsonSuccessTestParam{
87 R"({"field1":"1970-01-01T00:00:00.123400Z"})",
88 TimestampMessageData{0, 123400000}
90 TimestampFromJsonSuccessTestParam{
91 R"({"field1":"1970-01-01T00:00:00.100Z"})",
92 TimestampMessageData{0, 100000000}
94 TimestampFromJsonSuccessTestParam{R"({"field1":"1970-01-01T00:00:00.000000009Z"})", TimestampMessageData{0, 9}},
95 TimestampFromJsonSuccessTestParam{
96 R"({"field1":"1970-01-01T00:01:13.123+02:00"})",
97 TimestampMessageData{-(2 * 60 * 60) + 60 + 13, 123000000}
99 TimestampFromJsonSuccessTestParam{
100 R"({"field1":"1970-01-01T00:01:13.123-02:00"})",
101 TimestampMessageData{(2 * 60 * 60) + 60 + 13, 123000000}
103 TimestampFromJsonSuccessTestParam{
104 R"({"field1":"1970-01-01T00:01:13.123+02:10"})",
105 TimestampMessageData{-(2 * 60 * 60 + 10 * 60) + 60 + 13, 123000000}
107 TimestampFromJsonSuccessTestParam{
108 R"({"field1":"1970-01-01T00:01:13.123-02:10"})",
109 TimestampMessageData{(2 * 60 * 60 + 10 * 60) + 60 + 13, 123000000}
111 TimestampFromJsonSuccessTestParam{
112 R"({"field1":"1970-01-01T00:01:13.123+00:00"})",
113 TimestampMessageData{60 + 13, 123000000}
115 TimestampFromJsonSuccessTestParam{
116 R"({"field1":"1970-01-01T00:01:13.123-00:00"})",
117 TimestampMessageData{60 + 13, 123000000}
122INSTANTIATE_TEST_SUITE_P(
124 TimestampFromJsonFailureTest,
126 TimestampFromJsonFailureTestParam{R"({"field1":[]})", ParseErrorCode::kInvalidType,
"field1"},
127 TimestampFromJsonFailureTestParam{R"({"field1":{}})", ParseErrorCode::kInvalidType,
"field1", {},
true},
128 TimestampFromJsonFailureTestParam{R"({"field1":true})", ParseErrorCode::kInvalidType,
"field1"},
129 TimestampFromJsonFailureTestParam{R"({"field1":10})", ParseErrorCode::kInvalidType,
"field1"},
130 TimestampFromJsonFailureTestParam{R"({"field1":""})", ParseErrorCode::kInvalidValue,
"field1"},
131 TimestampFromJsonFailureTestParam{R"({"field1":"abc"})", ParseErrorCode::kInvalidValue,
"field1"},
132 TimestampFromJsonFailureTestParam{R"({"field1":"-"})", ParseErrorCode::kInvalidValue,
"field1"},
133 TimestampFromJsonFailureTestParam{R"({"field1":"2010"})", ParseErrorCode::kInvalidValue,
"field1"},
134 TimestampFromJsonFailureTestParam{R"({"field1":"2010-"})", ParseErrorCode::kInvalidValue,
"field1"},
135 TimestampFromJsonFailureTestParam{R"({"field1":"2010-10"})", ParseErrorCode::kInvalidValue,
"field1"},
136 TimestampFromJsonFailureTestParam{R"({"field1":"2010-10-"})", ParseErrorCode::kInvalidValue,
"field1"},
137 TimestampFromJsonFailureTestParam{R"({"field1":"2010-10-10"})", ParseErrorCode::kInvalidValue,
"field1"},
138 TimestampFromJsonFailureTestParam{R"({"field1":"2010-10-10T"})", ParseErrorCode::kInvalidValue,
"field1"},
139 TimestampFromJsonFailureTestParam{R"({"field1":"2010-10-10T10"})", ParseErrorCode::kInvalidValue,
"field1"},
140 TimestampFromJsonFailureTestParam{R"({"field1":"2010-10-10T10:10"})", ParseErrorCode::kInvalidValue,
"field1"},
141 TimestampFromJsonFailureTestParam{
142 R"({"field1":"2010-10-10T10:10:10"})",
143 ParseErrorCode::kInvalidValue,
146 TimestampFromJsonFailureTestParam{
147 R"({"field1":"2010-10-10T10:10:10z"})",
148 ParseErrorCode::kInvalidValue,
151 TimestampFromJsonFailureTestParam{
152 R"({"field1":"2010-10-10T10:10:10ZZ"})",
153 ParseErrorCode::kInvalidValue,
156 TimestampFromJsonFailureTestParam{
157 R"({"field1":"2010-10-10T10:10:10+"})",
158 ParseErrorCode::kInvalidValue,
161 TimestampFromJsonFailureTestParam{
162 R"({"field1":"2010-10-10T10:10:10+02"})",
163 ParseErrorCode::kInvalidValue,
166 TimestampFromJsonFailureTestParam{
167 R"({"field1":"2010-10-10T10:10:10-02:"})",
168 ParseErrorCode::kInvalidValue,
171 TimestampFromJsonFailureTestParam{
172 R"({"field1":"2010-10-10T10:10:10+02:00Z"})",
173 ParseErrorCode::kInvalidValue,
176 TimestampFromJsonFailureTestParam{
177 R"({"field1":"2010-10-10T10:10:10+02:0"})",
178 ParseErrorCode::kInvalidValue,
181 TimestampFromJsonFailureTestParam{
182 R"({"field1":"2010-10-10T10:10:10+2:00"})",
183 ParseErrorCode::kInvalidValue,
186 TimestampFromJsonFailureTestParam{
187 R"({"field1":"2010-10-10T10:10:10Z+02:00"})",
188 ParseErrorCode::kInvalidValue,
191 TimestampFromJsonFailureTestParam{
192 R"({"field1":"2010-10-10T10:10:1Z"})",
193 ParseErrorCode::kInvalidValue,
196 TimestampFromJsonFailureTestParam{
197 R"({"field1":"2010-10-10T10:1:10Z"})",
198 ParseErrorCode::kInvalidValue,
201 TimestampFromJsonFailureTestParam{
202 R"({"field1":"2010-10-10T1:10:10Z"})",
203 ParseErrorCode::kInvalidValue,
206 TimestampFromJsonFailureTestParam{
207 R"({"field1":"2010-10-10T1:10:10Z"})",
208 ParseErrorCode::kInvalidValue,
211 TimestampFromJsonFailureTestParam{
212 R"({"field1":"2010-10-10t10:10:10Z"})",
213 ParseErrorCode::kInvalidValue,
216 TimestampFromJsonFailureTestParam{
217 R"({"field1":"2010-10-10TT10:10:10Z"})",
218 ParseErrorCode::kInvalidValue,
221 TimestampFromJsonFailureTestParam{
222 R"({"field1":"2010-10-1T10:10:10Z"})",
223 ParseErrorCode::kInvalidValue,
226 TimestampFromJsonFailureTestParam{
227 R"({"field1":"2010-1-10T10:10:10Z"})",
228 ParseErrorCode::kInvalidValue,
231 TimestampFromJsonFailureTestParam{
232 R"({"field1":"201-10-10T10:10:10Z"})",
233 ParseErrorCode::kInvalidValue,
236 TimestampFromJsonFailureTestParam{
237 R"({"field1":"201A-10-10T10:10:10Z"})",
238 ParseErrorCode::kInvalidValue,
241 TimestampFromJsonFailureTestParam{
242 R"({"field1":"2010--10-10T10:10:10Z"})",
243 ParseErrorCode::kInvalidValue,
246 TimestampFromJsonFailureTestParam{
247 R"({"field1":"2010-1A-10T10:10:10Z"})",
248 ParseErrorCode::kInvalidValue,
251 TimestampFromJsonFailureTestParam{
252 R"({"field1":"2010-10--10T10:10:10Z"})",
253 ParseErrorCode::kInvalidValue,
256 TimestampFromJsonFailureTestParam{
257 R"({"field1":"2010-10-1AT10:10:10Z"})",
258 ParseErrorCode::kInvalidValue,
261 TimestampFromJsonFailureTestParam{
262 R"({"field1":"2010-10-10T1A:10:10Z"})",
263 ParseErrorCode::kInvalidValue,
266 TimestampFromJsonFailureTestParam{
267 R"({"field1":"2010-10-10T10-10:10Z"})",
268 ParseErrorCode::kInvalidValue,
271 TimestampFromJsonFailureTestParam{
272 R"({"field1":"2010-10-10T10:1A:10Z"})",
273 ParseErrorCode::kInvalidValue,
276 TimestampFromJsonFailureTestParam{
277 R"({"field1":"2010-10-10T10:10::10Z"})",
278 ParseErrorCode::kInvalidValue,
281 TimestampFromJsonFailureTestParam{
282 R"({"field1":"2010-10-10T10:10:1AZ"})",
283 ParseErrorCode::kInvalidValue,
286 TimestampFromJsonFailureTestParam{
287 R"({"field1":"2010-10-10T10:10:10+-02:00"})",
288 ParseErrorCode::kInvalidValue,
294TEST_P(TimestampFromJsonSuccessTest, Test) {
295 const auto& param = GetParam();
297 proto_json::messages::TimestampMessage message, expected_message, sample_message;
299 expected_message = PrepareTestData(param.expected_message);
301 message.mutable_field1()->set_seconds(100001);
303 UASSERT_NO_THROW((message = JsonToMessage<proto_json::messages::TimestampMessage>(input, param.options)));
304 UASSERT_NO_THROW(InitSampleMessage(param.input, sample_message, param.options));
306 CheckMessageEqual(message, sample_message);
307 CheckMessageEqual(message, expected_message);
310TEST_P(TimestampFromJsonFailureTest, Test) {
311 const auto& param = GetParam();
313 proto_json::messages::TimestampMessage sample_message;
317 (
void)JsonToMessage<proto_json::messages::TimestampMessage>(input, param.options),
322 if (!param.skip_native_check) {
323 UEXPECT_THROW(InitSampleMessage(param.input, sample_message, param.options), SampleError);
327TEST(TimestampFromJsonAdditionalTest, InlinedNonNull) {
328 using Message = ::google::protobuf::Timestamp;
330 const char* json_str =
"\"1970-01-01T00:02:03.000000321Z\"";
332 Message message, sample;
334 message.set_seconds(100001);
336 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
337 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
339 EXPECT_EQ(message.seconds(), 123);
340 EXPECT_EQ(message.nanos(), 321);
341 CheckMessageEqual(message, sample);
344TEST(TimestampFromJsonAdditionalTest, InlinedNull) {
345 using Message = ::google::protobuf::Timestamp;
348 Message message, sample;
350 message.set_seconds(100001);
352 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
353 UASSERT_NO_THROW(InitSampleMessage(
"null", sample));
355 EXPECT_EQ(message.seconds(), 0);
356 EXPECT_EQ(message.nanos(), 0);
357 CheckMessageEqual(message, sample);
360TEST(TimestampFromJsonAdditionalTest, DynamicMessage) {
361 using Message = ::google::protobuf::Timestamp;
363 const char* json_str =
"\"2016-02-29T00:00:00.123450Z\"";
365 ::google::protobuf::DynamicMessageFactory factory;
368 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
370 UASSERT_NO_THROW(JsonToMessage(json, *message));
372 const auto reflection = message->GetReflection();
373 const auto seconds_desc = message->GetDescriptor()->FindFieldByName(
"seconds");
374 const auto nanos_desc = message->GetDescriptor()->FindFieldByName(
"nanos");
376 EXPECT_EQ(reflection->GetInt64(*message, seconds_desc), 1456704000);
377 EXPECT_EQ(reflection->GetInt32(*message, nanos_desc), 123450000);