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
19namespace protobuf::json::tests {
21struct ValueFromJsonSuccessTestParam {
22 std::string input = {};
24 ParseOptions options = {};
27struct ListValueFromJsonFailureTestParam {
28 std::string input = {};
29 ParseErrorCode expected_errc = {};
30 std::string expected_path = {};
31 ParseOptions options = {};
34 bool skip_native_check =
false;
37struct StructFromJsonFailureTestParam {
38 std::string input = {};
39 ParseErrorCode expected_errc = {};
40 std::string expected_path = {};
41 ParseOptions 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"({})", ParseErrorCode::kInvalidType,
"/", {},
true},
126 ListValueFromJsonFailureTestParam{R"(true)", ParseErrorCode::kInvalidType,
"/"},
127 ListValueFromJsonFailureTestParam{R"(10)", ParseErrorCode::kInvalidType,
"/"},
128 ListValueFromJsonFailureTestParam{R"("")", ParseErrorCode::kInvalidType,
"/"}
132INSTANTIATE_TEST_SUITE_P(
134 StructFromJsonFailureTest,
136 StructFromJsonFailureTestParam{R"([])", ParseErrorCode::kInvalidType,
"/"},
137 StructFromJsonFailureTestParam{R"(true)", ParseErrorCode::kInvalidType,
"/"},
138 StructFromJsonFailureTestParam{R"(10)", ParseErrorCode::kInvalidType,
"/"},
139 StructFromJsonFailureTestParam{R"("")", ParseErrorCode::kInvalidType,
"/"}
143TEST_P(ValueFromJsonSuccessTest, Test) {
144 const auto& param = GetParam();
146 proto_json::messages::ValueMessage message;
147 proto_json::messages::ValueMessage expected_message;
148 proto_json::messages::ValueMessage sample_message;
149 formats::json::
Value input = PrepareJsonTestData(param.input);
150 expected_message = PrepareTestData(param.expected_message);
152 message.mutable_field1()->set_number_value(100001);
154 UASSERT_NO_THROW((message = JsonToMessage<proto_json::messages::ValueMessage>(input, param.options)));
155 UASSERT_NO_THROW(InitSampleMessage(param.input, sample_message, param.options));
157 CheckMessageEqual(message, sample_message);
158 CheckMessageEqual(message, expected_message);
161TEST_P(ListValueFromJsonFailureTest, Test) {
162 using Message = ::google::protobuf::ListValue;
163 const auto& param = GetParam();
166 formats::json::
Value input = PrepareJsonTestData(param.input);
168 EXPECT_PARSE_ERROR((
void)JsonToMessage<Message>(input, param.options), param.expected_errc, param.expected_path);
170 if (!param.skip_native_check) {
171 EXPECT_FALSE(::google::protobuf::util::JsonStringToMessage(param.input, &sample, {}).ok());
175TEST_P(StructFromJsonFailureTest, Test) {
176 using Message = ::google::protobuf::Struct;
177 const auto& param = GetParam();
180 formats::json::
Value input = PrepareJsonTestData(param.input);
182 EXPECT_PARSE_ERROR((
void)JsonToMessage<Message>(input, param.options), param.expected_errc, param.expected_path);
183 EXPECT_FALSE(::google::protobuf::util::JsonStringToMessage(param.input, &sample, {}).ok());
186TEST(ValueFromJsonAdditionalTest, InlinedNonNullValue) {
187 using Message = ::google::protobuf::Value;
190 const char* json_str =
"1.5";
195 message.set_number_value(100001);
197 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
198 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
199 EXPECT_EQ(message.number_value(), 1.5);
200 CheckMessageEqual(message, sample);
204 const char* json_str = R"("hello")";
209 message.set_number_value(100001);
211 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
212 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
213 EXPECT_EQ(message.string_value(),
"hello");
214 CheckMessageEqual(message, sample);
218 const char* json_str =
"true";
223 message.set_number_value(100001);
225 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
226 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
227 EXPECT_TRUE(message.has_bool_value());
228 EXPECT_TRUE(message.bool_value());
229 CheckMessageEqual(message, sample);
233 const char* json_str =
"[]";
238 message.set_number_value(100001);
240 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
241 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
242 EXPECT_TRUE(message.has_list_value());
243 EXPECT_TRUE(message.list_value().values().empty());
244 CheckMessageEqual(message, sample);
248 const char* json_str =
"[true, false]";
253 message.set_number_value(100001);
255 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
256 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
257 EXPECT_TRUE(message.has_list_value());
258 ASSERT_EQ(message.list_value().values().size(), 2);
259 EXPECT_TRUE(message.list_value().values()[0].has_bool_value());
260 EXPECT_TRUE(message.list_value().values()[0].bool_value());
261 EXPECT_TRUE(message.list_value().values()[1].has_bool_value());
262 EXPECT_FALSE(message.list_value().values()[1].bool_value());
263 CheckMessageEqual(message, sample);
267 const char* json_str =
"{}";
272 message.set_number_value(100001);
274 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
275 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
276 EXPECT_TRUE(message.has_struct_value());
277 EXPECT_EQ(message.struct_value().fields().size(), std::size_t{0});
278 CheckMessageEqual(message, sample);
282 const char* json_str = R"({"aaa":true,"bbb":false})";
287 message.set_number_value(100001);
289 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
290 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
291 EXPECT_TRUE(message.has_struct_value());
292 EXPECT_EQ(message.struct_value().fields().size(), std::size_t{2});
293 ASSERT_TRUE(message.struct_value().fields().contains(
"aaa"));
294 ASSERT_TRUE(message.struct_value().fields().contains(
"bbb"));
295 EXPECT_TRUE(message.struct_value().fields().at(
"aaa").has_bool_value());
296 EXPECT_TRUE(message.struct_value().fields().at(
"aaa").bool_value());
297 EXPECT_TRUE(message.struct_value().fields().at(
"bbb").has_bool_value());
298 EXPECT_FALSE(message.struct_value().fields().at(
"bbb").bool_value());
299 CheckMessageEqual(message, sample);
303TEST(ValueFromJsonAdditionalTest, InlinedNonNullListValue) {
304 using Message = ::google::protobuf::ListValue;
307 const char* json_str =
"1.5";
311 EXPECT_PARSE_ERROR((
void)JsonToMessage<Message>(json), ParseErrorCode::kInvalidType,
"/");
312 UEXPECT_THROW(InitSampleMessage(json_str, sample), SampleError);
316 const char* json_str =
"[]";
321 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
322 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
323 EXPECT_TRUE(message.values().empty());
324 CheckMessageEqual(message, sample);
328 const char* json_str = R"([null, 1.5, "hello", true])";
333 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
334 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
335 ASSERT_EQ(message.values().size(), 4);
336 EXPECT_TRUE(message.values()[0].has_null_value());
337 EXPECT_TRUE(message.values()[1].has_number_value());
338 EXPECT_EQ(message.values()[1].number_value(), 1.5);
339 EXPECT_TRUE(message.values()[2].has_string_value());
340 EXPECT_EQ(message.values()[2].string_value(),
"hello");
341 EXPECT_TRUE(message.values()[3].has_bool_value());
342 EXPECT_TRUE(message.values()[3].bool_value());
343 CheckMessageEqual(message, sample);
347TEST(ValueFromJsonAdditionalTest, InlinedNonNullStruct) {
348 using Message = ::google::protobuf::Struct;
351 const char* json_str =
"1.5";
355 EXPECT_PARSE_ERROR((
void)JsonToMessage<Message>(json), ParseErrorCode::kInvalidType,
"/");
356 UEXPECT_THROW(InitSampleMessage(json_str, sample), SampleError);
360 const char* json_str =
"{}";
365 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
366 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
367 EXPECT_EQ(message.fields().size(), std::size_t{0});
368 CheckMessageEqual(message, sample);
372 const char* json_str = R"({"aaa":1.5,"":false})";
377 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
378 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
379 ASSERT_EQ(message.fields().size(), std::size_t{2});
380 ASSERT_TRUE(message.fields().contains(
"aaa"));
381 EXPECT_TRUE(message.fields().at(
"aaa").has_number_value());
382 EXPECT_EQ(message.fields().at(
"aaa").number_value(), 1.5);
383 ASSERT_TRUE(message.fields().contains(
""));
384 EXPECT_TRUE(message.fields().at(
"").has_bool_value());
385 EXPECT_FALSE(message.fields().at(
"").bool_value());
386 CheckMessageEqual(message, sample);
390TEST(ValueFromJsonAdditionalTest, InlinedNullValue) {
391 using Message = ::google::protobuf::Value;
393 const char* json_str =
"null";
398 message.set_number_value(100001);
400 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
401 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
402 EXPECT_TRUE(message.has_null_value());
403 CheckMessageEqual(message, sample);
406TEST(ValueFromJsonAdditionalTest, InlinedNullListValue) {
407 using Message = ::google::protobuf::ListValue;
409 const char* json_str =
"null";
414 message.add_values()->set_number_value(100001);
416 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
417 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
418 EXPECT_TRUE(message.values().empty());
419 CheckMessageEqual(message, sample);
422TEST(ValueFromJsonAdditionalTest, InlinedNullStruct) {
423 using Message = ::google::protobuf::Struct;
425 const char* json_str =
"null";
430 (*message.mutable_fields())[
"aaa"].set_number_value(100001);
432 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
433 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
434 EXPECT_TRUE(message.fields().empty());
435 CheckMessageEqual(message, sample);
438TEST(ValueFromJsonAdditionalTest, DynamicMessage) {
439 using Message = ::google::protobuf::Value;
442 const char* json_str =
"null";
444 ::google::protobuf::DynamicMessageFactory factory;
447 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
449 UASSERT_NO_THROW(JsonToMessage(json, *message));
451 const auto reflection = message->GetReflection();
452 const auto field_desc = message->GetDescriptor()->FindFieldByName(
"null_value");
454 ASSERT_TRUE(reflection->HasField(*message, field_desc));
459 const char* json_str =
"1.5";
461 ::google::protobuf::DynamicMessageFactory factory;
464 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
466 UASSERT_NO_THROW(JsonToMessage(json, *message));
468 const auto reflection = message->GetReflection();
469 const auto field_desc = message->GetDescriptor()->FindFieldByName(
"number_value");
471 ASSERT_TRUE(reflection->HasField(*message, field_desc));
472 EXPECT_EQ(reflection->GetDouble(*message, field_desc), 1.5);
477 const char* json_str = R"("hello")";
479 ::google::protobuf::DynamicMessageFactory factory;
482 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
484 UASSERT_NO_THROW(JsonToMessage(json, *message));
486 const auto reflection = message->GetReflection();
487 const auto field_desc = message->GetDescriptor()->FindFieldByName(
"string_value");
489 ASSERT_TRUE(reflection->HasField(*message, field_desc));
490 EXPECT_EQ(reflection->GetString(*message, field_desc),
"hello");
495 const char* json_str =
"true";
497 ::google::protobuf::DynamicMessageFactory factory;
500 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
502 UASSERT_NO_THROW(JsonToMessage(json, *message));
504 const auto reflection = message->GetReflection();
505 const auto field_desc = message->GetDescriptor()->FindFieldByName(
"bool_value");
507 ASSERT_TRUE(reflection->HasField(*message, field_desc));
508 EXPECT_TRUE(reflection->GetBool(*message, field_desc));
513 const char* json_str =
"[1.5]";
515 ::google::protobuf::DynamicMessageFactory factory;
518 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
520 UASSERT_NO_THROW(JsonToMessage(json, *message));
522 const auto reflection = message->GetReflection();
523 const auto field_desc = message->GetDescriptor()->FindFieldByName(
"list_value");
525 ASSERT_TRUE(reflection->HasField(*message, field_desc));
527 const auto& list = reflection->GetMessage(*message, field_desc);
528 const auto list_reflection = list.GetReflection();
529 const auto values_desc = list.GetDescriptor()->FindFieldByName(
"values");
531 ASSERT_EQ(list_reflection->FieldSize(list, values_desc), 1);
533 const auto& item = list_reflection->GetRepeatedMessage(list, values_desc, 0);
534 const auto item_reflection = item.GetReflection();
535 const auto number_value_desc = item.GetDescriptor()->FindFieldByName(
"number_value");
537 EXPECT_EQ(item_reflection->GetDouble(item, number_value_desc), 1.5);
542 const char* json_str = R"({"aaa":"hello"})";
544 ::google::protobuf::DynamicMessageFactory factory;
547 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
549 UASSERT_NO_THROW(JsonToMessage(json, *message));
551 const auto reflection = message->GetReflection();
552 const auto field_desc = message->GetDescriptor()->FindFieldByName(
"struct_value");
554 ASSERT_TRUE(reflection->HasField(*message, field_desc));
556 const auto& obj = reflection->GetMessage(*message, field_desc);
557 const auto obj_reflection = obj.GetReflection();
558 const auto fields_desc = obj.GetDescriptor()->FindFieldByName(
"fields");
560 ASSERT_EQ(obj_reflection->FieldSize(obj, fields_desc), 1);
562 const auto& item = obj_reflection->GetRepeatedMessage(obj, fields_desc, 0);
563 const auto item_reflection = item.GetReflection();
564 const auto map_key_desc = item.GetDescriptor()->map_key();
565 const auto map_value_desc = item.GetDescriptor()->map_value();
566 const auto& map_value = item_reflection->GetMessage(item, map_value_desc);
567 const auto map_value_reflection = map_value.GetReflection();
568 const auto string_value_desc = map_value.GetDescriptor()->FindFieldByName(
"string_value");
570 EXPECT_EQ(item_reflection->GetString(item, map_key_desc),
"aaa");
571 EXPECT_EQ(map_value_reflection->GetString(map_value, string_value_desc),
"hello");