1#include <gtest/gtest.h>
8#include <google/protobuf/dynamic_message.h>
9#include <google/protobuf/util/json_util.h>
11#include <userver/formats/json/serialize.hpp>
12#include <userver/protobuf/json/convert.hpp>
13#include <userver/utest/assert_macros.hpp>
17USERVER_NAMESPACE_BEGIN
21struct ValueFromJsonSuccessTestParam {
22 std::string input = {};
24 ReadOptions options = {};
27struct ListValueFromJsonFailureTestParam {
28 std::string input = {};
29 ReadErrorCode expected_errc = {};
30 std::string expected_path = {};
31 ReadOptions options = {};
34 bool skip_native_check =
false;
37struct StructFromJsonFailureTestParam {
38 std::string input = {};
39 ReadErrorCode expected_errc = {};
40 std::string expected_path = {};
41 ReadOptions options = {};
44void PrintTo(
const ValueFromJsonSuccessTestParam& param, std::ostream* os) {
45 *os << fmt::format(
"{{ input = '{}' }}", param.input);
48void PrintTo(
const ListValueFromJsonFailureTestParam& param, std::ostream* os) {
49 *os << fmt::format(
"{{ input = '{}' }}", param.input);
52void PrintTo(
const StructFromJsonFailureTestParam& param, std::ostream* os) {
53 *os << fmt::format(
"{{ input = '{}' }}", param.input);
56class ValueFromJsonSuccessTest :
public ::testing::TestWithParam<ValueFromJsonSuccessTestParam> {};
57class ListValueFromJsonFailureTest :
public ::testing::TestWithParam<ListValueFromJsonFailureTestParam> {};
58class StructFromJsonFailureTest :
public ::testing::TestWithParam<StructFromJsonFailureTestParam> {};
60INSTANTIATE_TEST_SUITE_P(
62 ValueFromJsonSuccessTest,
66 ValueFromJsonSuccessTestParam{R"({})", ValueMessageData{}},
67 ValueFromJsonSuccessTestParam{R"({"field1":null})", ValueMessageData{ProtoValue{kProtoNullValue}}},
68 ValueFromJsonSuccessTestParam{
70 ValueMessageData{ProtoValue{std::map<std::string, std::string>{}}}
72 ValueFromJsonSuccessTestParam{R"({"field1":[]})", ValueMessageData{ProtoValue{std::vector<
double>{}}}},
73 ValueFromJsonSuccessTestParam{R"({"field1":1.5})", ValueMessageData{ProtoValue{1.5}}},
74 ValueFromJsonSuccessTestParam{R"({"field1":"hello"})", ValueMessageData{ProtoValue{
"hello"}}},
75 ValueFromJsonSuccessTestParam{R"({"field1":true})", ValueMessageData{ProtoValue{
true}}},
76 ValueFromJsonSuccessTestParam{
77 R"({"field1":[1.5, 1.5]})",
78 ValueMessageData{ProtoValue{std::vector<
double>{1.5, 1.5}}}
80 ValueFromJsonSuccessTestParam{
81 R"({"field1":{"aaa":"hello","bbb":"world"}})",
82 ValueMessageData{ProtoValue{std::map<std::string, std::string>{{
"aaa",
"hello"}, {
"bbb",
"world"}}}}
84 ValueFromJsonSuccessTestParam{
86 ValueMessageData{std::vector<ProtoValue>{std::vector<
double>{}}}
88 ValueFromJsonSuccessTestParam{
89 R"({"field1":[[1.5],[0,1.5]]})",
90 ValueMessageData{std::vector<ProtoValue>{std::vector<
double>{1.5}, std::vector<
double>{0, 1.5}}}
92 ValueFromJsonSuccessTestParam{
93 R"({"field1":[null,1.5,"hello",true,[1.5,1.5],{"aaa":"hello","bbb":"world"}]})",
94 ValueMessageData{std::vector<ProtoValue>{
99 std::vector<
double>{1.5, 1.5},
100 std::map<std::string, std::string>{{
"aaa",
"hello"}, {
"bbb",
"world"}}
103 ValueFromJsonSuccessTestParam{
104 R"({"field1":{"aaa":{}}})",
105 ValueMessageData{std::map<std::string, ProtoValue>{{
"aaa", std::map<std::string, std::string>{}}}}
107 ValueFromJsonSuccessTestParam{
108 R"({"field1":{"aaa":null,"bbb":1.5,"ccc":"hello","ddd":true,"eee":[1.5,1.5],"":{"":"hello","bbb":"world"}}})",
109 ValueMessageData{std::map<std::string, ProtoValue>{
110 {
"aaa", kProtoNullValue},
114 {
"eee", std::vector<
double>{1.5, 1.5}},
115 {
"", std::map<std::string, std::string>{{
"",
"hello"}, {
"bbb",
"world"}}}
121INSTANTIATE_TEST_SUITE_P(
123 ListValueFromJsonFailureTest,
125 ListValueFromJsonFailureTestParam{R"({})", ReadErrorCode::kInvalidType,
"/", {},
true},
126 ListValueFromJsonFailureTestParam{R"(true)", ReadErrorCode::kInvalidType,
"/"},
127 ListValueFromJsonFailureTestParam{R"(10)", ReadErrorCode::kInvalidType,
"/"},
128 ListValueFromJsonFailureTestParam{R"("")", ReadErrorCode::kInvalidType,
"/"}
132INSTANTIATE_TEST_SUITE_P(
134 StructFromJsonFailureTest,
136 StructFromJsonFailureTestParam{R"([])", ReadErrorCode::kInvalidType,
"/"},
137 StructFromJsonFailureTestParam{R"(true)", ReadErrorCode::kInvalidType,
"/"},
138 StructFromJsonFailureTestParam{R"(10)", ReadErrorCode::kInvalidType,
"/"},
139 StructFromJsonFailureTestParam{R"("")", ReadErrorCode::kInvalidType,
"/"}
143TEST_P(ValueFromJsonSuccessTest, Test) {
144 const auto& param = GetParam();
146 proto_json::messages::ValueMessage message, expected_message, sample_message;
147 formats::json::Value input = PrepareJsonTestData(param.input);
148 expected_message = PrepareTestData(param.expected_message);
150 message.mutable_field1()->set_number_value(100001);
152 UASSERT_NO_THROW((message = JsonToMessage<proto_json::messages::ValueMessage>(input, param.options)));
153 UASSERT_NO_THROW(InitSampleMessage(param.input, param.options, sample_message));
155 CheckMessageEqual(message, sample_message);
156 CheckMessageEqual(message, expected_message);
159TEST_P(ListValueFromJsonFailureTest, Test) {
160 using Message = ::google::protobuf::ListValue;
161 const auto& param = GetParam();
164 formats::json::Value input = PrepareJsonTestData(param.input);
166 EXPECT_READ_ERROR((
void)JsonToMessage<Message>(input, param.options), param.expected_errc, param.expected_path);
168 if (!param.skip_native_check) {
169 EXPECT_FALSE(::google::protobuf::util::JsonStringToMessage(param.input, &sample, {}).ok());
173TEST_P(StructFromJsonFailureTest, Test) {
174 using Message = ::google::protobuf::Struct;
175 const auto& param = GetParam();
178 formats::json::Value input = PrepareJsonTestData(param.input);
180 EXPECT_READ_ERROR((
void)JsonToMessage<Message>(input, param.options), param.expected_errc, param.expected_path);
181 EXPECT_FALSE(::google::protobuf::util::JsonStringToMessage(param.input, &sample, {}).ok());
184TEST(ValueFromJsonAdditionalTest, InlinedNonNullValue) {
185 using Message = ::google::protobuf::Value;
188 const char* json_str =
"1.5";
189 const auto json = formats::json::FromString(json_str);
190 Message message, sample;
192 message.set_number_value(100001);
194 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
195 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
196 EXPECT_EQ(message.number_value(), 1.5);
197 CheckMessageEqual(message, sample);
201 const char* json_str =
"\"hello\"";
202 const auto json = formats::json::FromString(json_str);
203 Message message, sample;
205 message.set_number_value(100001);
207 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
208 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
209 EXPECT_EQ(message.string_value(),
"hello");
210 CheckMessageEqual(message, sample);
214 const char* json_str =
"true";
215 const auto json = formats::json::FromString(json_str);
216 Message message, sample;
218 message.set_number_value(100001);
220 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
221 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
222 EXPECT_TRUE(message.has_bool_value());
223 EXPECT_TRUE(message.bool_value());
224 CheckMessageEqual(message, sample);
228 const char* json_str =
"[]";
229 const auto json = formats::json::FromString(json_str);
230 Message message, sample;
232 message.set_number_value(100001);
234 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
235 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
236 EXPECT_TRUE(message.has_list_value());
237 EXPECT_TRUE(message.list_value().values().empty());
238 CheckMessageEqual(message, sample);
242 const char* json_str =
"[true, false]";
243 const auto json = formats::json::FromString(json_str);
244 Message message, sample;
246 message.set_number_value(100001);
248 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
249 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
250 EXPECT_TRUE(message.has_list_value());
251 ASSERT_EQ(message.list_value().values().size(), 2);
252 EXPECT_TRUE(message.list_value().values()[0].has_bool_value());
253 EXPECT_TRUE(message.list_value().values()[0].bool_value());
254 EXPECT_TRUE(message.list_value().values()[1].has_bool_value());
255 EXPECT_FALSE(message.list_value().values()[1].bool_value());
256 CheckMessageEqual(message, sample);
260 const char* json_str =
"{}";
261 const auto json = formats::json::FromString(json_str);
262 Message message, sample;
264 message.set_number_value(100001);
266 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
267 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
268 EXPECT_TRUE(message.has_struct_value());
269 EXPECT_EQ(message.struct_value().fields().size(), std::size_t{0});
270 CheckMessageEqual(message, sample);
274 const char* json_str =
"{\"aaa\":true,\"bbb\":false}";
275 const auto json = formats::json::FromString(json_str);
276 Message message, sample;
278 message.set_number_value(100001);
280 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
281 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
282 EXPECT_TRUE(message.has_struct_value());
283 EXPECT_EQ(message.struct_value().fields().size(), std::size_t{2});
284 ASSERT_TRUE(message.struct_value().fields().contains(
"aaa"));
285 ASSERT_TRUE(message.struct_value().fields().contains(
"bbb"));
286 EXPECT_TRUE(message.struct_value().fields().at(
"aaa").has_bool_value());
287 EXPECT_TRUE(message.struct_value().fields().at(
"aaa").bool_value());
288 EXPECT_TRUE(message.struct_value().fields().at(
"bbb").has_bool_value());
289 EXPECT_FALSE(message.struct_value().fields().at(
"bbb").bool_value());
290 CheckMessageEqual(message, sample);
294TEST(ValueFromJsonAdditionalTest, InlinedNonNullListValue) {
295 using Message = ::google::protobuf::ListValue;
298 const char* json_str =
"1.5";
299 const auto json = formats::json::FromString(json_str);
302 EXPECT_READ_ERROR((
void)JsonToMessage<Message>(json), ReadErrorCode::kInvalidType,
"/");
303 UEXPECT_THROW(InitSampleMessage(json_str, {}, sample), SampleError);
307 const char* json_str =
"[]";
308 const auto json = formats::json::FromString(json_str);
309 Message message, sample;
311 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
312 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
313 EXPECT_TRUE(message.values().empty());
314 CheckMessageEqual(message, sample);
318 const char* json_str =
"[null, 1.5, \"hello\", true]";
319 const auto json = formats::json::FromString(json_str);
320 Message message, sample;
322 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
323 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
324 ASSERT_EQ(message.values().size(), 4);
325 EXPECT_TRUE(message.values()[0].has_null_value());
326 EXPECT_TRUE(message.values()[1].has_number_value());
327 EXPECT_EQ(message.values()[1].number_value(), 1.5);
328 EXPECT_TRUE(message.values()[2].has_string_value());
329 EXPECT_EQ(message.values()[2].string_value(),
"hello");
330 EXPECT_TRUE(message.values()[3].has_bool_value());
331 EXPECT_TRUE(message.values()[3].bool_value());
332 CheckMessageEqual(message, sample);
336TEST(ValueFromJsonAdditionalTest, InlinedNonNullStruct) {
337 using Message = ::google::protobuf::Struct;
340 const char* json_str =
"1.5";
341 const auto json = formats::json::FromString(json_str);
344 EXPECT_READ_ERROR((
void)JsonToMessage<Message>(json), ReadErrorCode::kInvalidType,
"/");
345 UEXPECT_THROW(InitSampleMessage(json_str, {}, sample), SampleError);
349 const char* json_str =
"{}";
350 const auto json = formats::json::FromString(json_str);
351 Message message, sample;
353 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
354 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
355 EXPECT_EQ(message.fields().size(), std::size_t{0});
356 CheckMessageEqual(message, sample);
360 const char* json_str =
"{\"aaa\":1.5,\"\":false}";
361 const auto json = formats::json::FromString(json_str);
362 Message message, sample;
364 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
365 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
366 ASSERT_EQ(message.fields().size(), std::size_t{2});
367 ASSERT_TRUE(message.fields().contains(
"aaa"));
368 EXPECT_TRUE(message.fields().at(
"aaa").has_number_value());
369 EXPECT_EQ(message.fields().at(
"aaa").number_value(), 1.5);
370 ASSERT_TRUE(message.fields().contains(
""));
371 EXPECT_TRUE(message.fields().at(
"").has_bool_value());
372 EXPECT_FALSE(message.fields().at(
"").bool_value());
373 CheckMessageEqual(message, sample);
377TEST(ValueFromJsonAdditionalTest, InlinedNullValue) {
378 using Message = ::google::protobuf::Value;
380 const char* json_str =
"null";
381 const auto json = formats::json::FromString(json_str);
382 Message message, sample;
384 message.set_number_value(100001);
386 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
387 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
388 EXPECT_TRUE(message.has_null_value());
389 CheckMessageEqual(message, sample);
392TEST(ValueFromJsonAdditionalTest, InlinedNullListValue) {
393 using Message = ::google::protobuf::ListValue;
395 const char* json_str =
"null";
396 const auto json = formats::json::FromString(json_str);
397 Message message, sample;
399 message.add_values()->set_number_value(100001);
401 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
402 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
403 EXPECT_TRUE(message.values().empty());
404 CheckMessageEqual(message, sample);
407TEST(ValueFromJsonAdditionalTest, InlinedNullStruct) {
408 using Message = ::google::protobuf::Struct;
410 const char* json_str =
"null";
411 const auto json = formats::json::FromString(json_str);
412 Message message, sample;
414 (*message.mutable_fields())[
"aaa"].set_number_value(100001);
416 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
417 UASSERT_NO_THROW(InitSampleMessage(json_str, {}, sample));
418 EXPECT_TRUE(message.fields().empty());
419 CheckMessageEqual(message, sample);
422TEST(ValueFromJsonAdditionalTest, DynamicMessage) {
423 using Message = ::google::protobuf::Value;
426 const char* json_str =
"null";
427 const auto json = formats::json::FromString(json_str);
428 ::google::protobuf::DynamicMessageFactory factory;
431 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
433 UASSERT_NO_THROW(JsonToMessage(json, {}, *message));
435 const auto reflection = message->GetReflection();
436 const auto field_desc = message->GetDescriptor()->FindFieldByName(
"null_value");
438 ASSERT_TRUE(reflection->HasField(*message, field_desc));
443 const char* json_str =
"1.5";
444 const auto json = formats::json::FromString(json_str);
445 ::google::protobuf::DynamicMessageFactory factory;
448 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
450 UASSERT_NO_THROW(JsonToMessage(json, {}, *message));
452 const auto reflection = message->GetReflection();
453 const auto field_desc = message->GetDescriptor()->FindFieldByName(
"number_value");
455 ASSERT_TRUE(reflection->HasField(*message, field_desc));
456 EXPECT_EQ(reflection->GetDouble(*message, field_desc), 1.5);
461 const char* json_str =
"\"hello\"";
462 const auto json = formats::json::FromString(json_str);
463 ::google::protobuf::DynamicMessageFactory factory;
466 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
468 UASSERT_NO_THROW(JsonToMessage(json, {}, *message));
470 const auto reflection = message->GetReflection();
471 const auto field_desc = message->GetDescriptor()->FindFieldByName(
"string_value");
473 ASSERT_TRUE(reflection->HasField(*message, field_desc));
474 EXPECT_EQ(reflection->GetString(*message, field_desc),
"hello");
479 const char* json_str =
"true";
480 const auto json = formats::json::FromString(json_str);
481 ::google::protobuf::DynamicMessageFactory factory;
484 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
486 UASSERT_NO_THROW(JsonToMessage(json, {}, *message));
488 const auto reflection = message->GetReflection();
489 const auto field_desc = message->GetDescriptor()->FindFieldByName(
"bool_value");
491 ASSERT_TRUE(reflection->HasField(*message, field_desc));
492 EXPECT_TRUE(reflection->GetBool(*message, field_desc));
497 const char* json_str =
"[1.5]";
498 const auto json = formats::json::FromString(json_str);
499 ::google::protobuf::DynamicMessageFactory factory;
502 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
504 UASSERT_NO_THROW(JsonToMessage(json, {}, *message));
506 const auto reflection = message->GetReflection();
507 const auto field_desc = message->GetDescriptor()->FindFieldByName(
"list_value");
509 ASSERT_TRUE(reflection->HasField(*message, field_desc));
511 const auto& list = reflection->GetMessage(*message, field_desc);
512 const auto list_reflection = list.GetReflection();
513 const auto values_desc = list.GetDescriptor()->FindFieldByName(
"values");
515 ASSERT_EQ(list_reflection->FieldSize(list, values_desc), 1);
517 const auto& item = list_reflection->GetRepeatedMessage(list, values_desc, 0);
518 const auto item_reflection = item.GetReflection();
519 const auto number_value_desc = item.GetDescriptor()->FindFieldByName(
"number_value");
521 EXPECT_EQ(item_reflection->GetDouble(item, number_value_desc), 1.5);
526 const char* json_str =
"{\"aaa\":\"hello\"}";
527 const auto json = formats::json::FromString(json_str);
528 ::google::protobuf::DynamicMessageFactory factory;
531 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
533 UASSERT_NO_THROW(JsonToMessage(json, {}, *message));
535 const auto reflection = message->GetReflection();
536 const auto field_desc = message->GetDescriptor()->FindFieldByName(
"struct_value");
538 ASSERT_TRUE(reflection->HasField(*message, field_desc));
540 const auto& obj = reflection->GetMessage(*message, field_desc);
541 const auto obj_reflection = obj.GetReflection();
542 const auto fields_desc = obj.GetDescriptor()->FindFieldByName(
"fields");
544 ASSERT_EQ(obj_reflection->FieldSize(obj, fields_desc), 1);
546 const auto& item = obj_reflection->GetRepeatedMessage(obj, fields_desc, 0);
547 const auto item_reflection = item.GetReflection();
548 const auto map_key_desc = item.GetDescriptor()->map_key();
549 const auto map_value_desc = item.GetDescriptor()->map_value();
550 const auto& map_value = item_reflection->GetMessage(item, map_value_desc);
551 const auto map_value_reflection = map_value.GetReflection();
552 const auto string_value_desc = map_value.GetDescriptor()->FindFieldByName(
"string_value");
554 EXPECT_EQ(item_reflection->GetString(item, map_key_desc),
"aaa");
555 EXPECT_EQ(map_value_reflection->GetString(map_value, string_value_desc),
"hello");