1#include <gtest/gtest.h>
8#include <google/protobuf/dynamic_message.h>
10#include <userver/protobuf/json/convert.hpp>
11#include <userver/utest/assert_macros.hpp>
15USERVER_NAMESPACE_BEGIN
17namespace protobuf::json::tests {
19struct ValueToJsonSuccessTestParam {
21 std::string expected_json = {};
25struct ValueToJsonFailureTestParam {
28 std::string expected_path = {};
32 bool skip_native_check =
false;
35class ValueToJsonSuccessTest :
public ::testing::TestWithParam<ValueToJsonSuccessTestParam> {};
36class ValueToJsonFailureTest :
public ::testing::TestWithParam<ValueToJsonFailureTestParam> {};
38INSTANTIATE_TEST_SUITE_P(
40 ValueToJsonSuccessTest,
44 ValueToJsonSuccessTestParam{ValueMessageData{}, R"({})"},
45 ValueToJsonSuccessTestParam{ValueMessageData{ProtoValue{std::monostate{}}}, R"({})"},
46 ValueToJsonSuccessTestParam{ValueMessageData{ProtoValue{kProtoNullValue}}, R"({"field1":null})"},
47 ValueToJsonSuccessTestParam{ValueMessageData{ProtoValue{1.5}}, R"({"field1":1.5})"},
48 ValueToJsonSuccessTestParam{ValueMessageData{ProtoValue{
"hello"}}, R"({"field1":"hello"})"},
49 ValueToJsonSuccessTestParam{ValueMessageData{ProtoValue{
true}}, R"({"field1":true})"},
50 ValueToJsonSuccessTestParam{ValueMessageData{ProtoValue{std::vector<
double>{}}}, R"({"field1":[]})"},
51 ValueToJsonSuccessTestParam{
52 ValueMessageData{ProtoValue{std::vector<
double>{1.5, 1.5}}},
53 R"({"field1":[1.5, 1.5]})"
55 ValueToJsonSuccessTestParam{
56 ValueMessageData{ProtoValue{std::map<std::string, std::string>{}}},
59 ValueToJsonSuccessTestParam{
60 ValueMessageData{ProtoValue{std::map<std::string, std::string>{{
"aaa",
"hello"}, {
"bbb",
"world"}}}
62 R"({"field1":{"aaa":"hello","bbb":"world"}})"
64 ValueToJsonSuccessTestParam{
66 std::vector<ProtoValue>{},
70 ValueToJsonSuccessTestParam{
72 std::vector<ProtoValue>{std::vector<
double>{}},
76 ValueToJsonSuccessTestParam{
78 std::vector<ProtoValue>{std::vector<
double>{1.5}, std::vector<
double>{0, 1.5}},
80 R"({"field1":[[1.5],[0,1.5]]})"
82 ValueToJsonSuccessTestParam{
84 std::vector<ProtoValue>{
89 std::vector<
double>{1.5, 1.5},
90 std::map<std::string, std::string>{{
"aaa",
"hello"}, {
"bbb",
"world"}}
93 R"({"field1":[null,1.5,"hello",true,[1.5,1.5],{"aaa":"hello","bbb":"world"}]})"
95 ValueToJsonSuccessTestParam{
96 ValueMessageData{std::vector<
97 ProtoValue>{ProtoValue{1.5}, ProtoValue{std::monostate{}}, ProtoValue{
true}}},
98 R"({"field1":[1.5,true]})"
101 ValueToJsonSuccessTestParam{
103 std::map<std::string, ProtoValue>{},
107 ValueToJsonSuccessTestParam{
109 std::map<std::string, ProtoValue>{{
"aaa", ProtoValue{std::map<std::string, std::string>{}}}},
111 R"({"field1":{"aaa":{}}})"
113 ValueToJsonSuccessTestParam{
115 std::map<std::string, ProtoValue>{
116 {
"aaa", kProtoNullValue},
120 {
"eee", std::vector<
double>{1.5, 1.5}},
121 {
"", std::map<std::string, std::string>{{
"",
"hello"}, {
"bbb",
"world"}}}
124 R"({"field1":{"aaa":null,"bbb":1.5,"ccc":"hello","ddd":true,"eee":[1.5,1.5],"":{"":"hello","bbb":"world"}}})"
126 ValueToJsonSuccessTestParam{
128 std::map<std::string, ProtoValue>{
129 {
"aaa", ProtoValue{1.5}},
130 {
"bbb", ProtoValue{std::monostate{}}},
131 {
"ccc", ProtoValue{
true}}
134 R"({"field1":{"aaa":1.5,"ccc":true}})"
139INSTANTIATE_TEST_SUITE_P(
141 ValueToJsonFailureTest,
143 ValueToJsonFailureTestParam{
144 ValueMessageData{ProtoValue{std::numeric_limits<
double>::quiet_NaN()}},
145 PrintErrorCode::kInvalidValue,
146 "field1.number_value",
150 ValueToJsonFailureTestParam{
151 ValueMessageData{ProtoValue{std::numeric_limits<
double>::signaling_NaN()}},
152 PrintErrorCode::kInvalidValue,
153 "field1.number_value",
157 ValueToJsonFailureTestParam{
158 ValueMessageData{ProtoValue{std::numeric_limits<
double>::infinity()}},
159 PrintErrorCode::kInvalidValue,
160 "field1.number_value",
164 ValueToJsonFailureTestParam{
165 ValueMessageData{ProtoValue{-std::numeric_limits<
double>::infinity()}},
166 PrintErrorCode::kInvalidValue,
167 "field1.number_value",
171 ValueToJsonFailureTestParam{
172 ValueMessageData{std::vector<ProtoValue>{
174 ProtoValue{std::vector<
double>{1.5, std::numeric_limits<
double>::infinity()}},
177 PrintErrorCode::kInvalidValue,
178 "field1.list_value.values[1].list_value.values[1].number_value",
185TEST_P(ValueToJsonSuccessTest, Test) {
186 const auto& param = GetParam();
188 auto input = PrepareTestData(param.input);
194 UASSERT_NO_THROW((expected_json = PrepareJsonTestData(param.expected_json)));
197 EXPECT_EQ(json, expected_json);
198 EXPECT_EQ(expected_json, sample_json);
201TEST_P(ValueToJsonFailureTest, Test) {
202 const auto& param = GetParam();
203 auto input = PrepareTestData(param.input);
205 EXPECT_PRINT_ERROR((
void)MessageToJson(input, param.options), param.expected_errc, param.expected_path);
207 if (!param.skip_native_check) {
212TEST(ValueToJsonAdditionalTest, InlinedNonNull) {
215 auto message = PrepareTestData(data);
221 EXPECT_EQ(json, sample);
227 auto message = PrepareTestData(data);
233 EXPECT_EQ(json, sample);
235 EXPECT_EQ(json.As<
double>(), 1.5);
240 auto message = PrepareTestData(data);
246 EXPECT_EQ(json, sample);
248 EXPECT_EQ(json.As<std::string>(),
"hello");
253 auto message = PrepareTestData(data);
259 EXPECT_EQ(json, sample);
261 EXPECT_TRUE(json.As<
bool>());
266 auto message = PrepareTestData(data);
272 EXPECT_EQ(json, sample);
279 auto message = PrepareTestData(data);
285 EXPECT_EQ(json, sample);
288 EXPECT_EQ(json
[0
].As<
double>(), 1.5);
289 EXPECT_EQ(json
[1
].As<
double>(), 0);
294 auto message = PrepareTestData(data);
300 EXPECT_EQ(json, sample);
306 ValueMessageData data{std::map<std::string, std::string>{{
"aaa",
"hello"}, {
"bbb",
"world"}}};
307 auto message = PrepareTestData(data);
313 EXPECT_EQ(json, sample);
318 EXPECT_EQ(json
["aaa"].As<std::string>(),
"hello");
319 EXPECT_EQ(json
["bbb"].As<std::string>(),
"world");
323TEST(ValueToJsonAdditionalTest, InlinedNull) {
325 auto message = PrepareTestData(data);
330TEST(ValueToJsonAdditionalTest, DynamicMessage) {
331 using Message = ::google::protobuf::Value;
332 ::google::protobuf::DynamicMessageFactory factory;
335 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
336 const auto reflection = message->GetReflection();
337 const auto null_value_desc = message->GetDescriptor()->FindFieldByName(
"null_value");
339 reflection->SetEnumValue(message.get(), null_value_desc, 0);
348 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
349 const auto reflection = message->GetReflection();
350 const auto number_value_desc = message->GetDescriptor()->FindFieldByName(
"number_value");
352 reflection->SetDouble(message.get(), number_value_desc, 1.5);
358 EXPECT_EQ(json.As<
double>(), 1.5);
362 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
363 const auto reflection = message->GetReflection();
364 const auto number_value_desc = message->GetDescriptor()->FindFieldByName(
"string_value");
366 reflection->SetString(message.get(), number_value_desc,
"hello");
372 EXPECT_EQ(json.As<std::string>(),
"hello");
376 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
377 const auto reflection = message->GetReflection();
378 const auto bool_value_desc = message->GetDescriptor()->FindFieldByName(
"bool_value");
380 reflection->SetBool(message.get(), bool_value_desc,
true);
386 EXPECT_EQ(json.As<
bool>(),
true);
390 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
391 const auto reflection = message->GetReflection();
392 const auto list_value_desc = message->GetDescriptor()->FindFieldByName(
"list_value");
393 const auto list_value_message = reflection->MutableMessage(message.get(), list_value_desc, &factory);
394 const auto list_value_reflection = list_value_message->GetReflection();
395 const auto values_desc = list_value_message->GetDescriptor()->FindFieldByName(
"values");
396 const auto item_message = list_value_reflection->AddMessage(list_value_message, values_desc, &factory);
397 const auto item_reflection = item_message->GetReflection();
398 const auto number_value_desc = item_message->GetDescriptor()->FindFieldByName(
"number_value");
400 item_reflection->SetDouble(item_message, number_value_desc, 1.5);
407 EXPECT_EQ(json
[0
].As<
double>(), 1.5);
411 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
412 const auto reflection = message->GetReflection();
413 const auto struct_value_desc = message->GetDescriptor()->FindFieldByName(
"struct_value");
414 const auto struct_value_message = reflection->MutableMessage(message.get(), struct_value_desc, &factory);
415 const auto struct_value_reflection = struct_value_message->GetReflection();
416 const auto fields_desc = struct_value_message->GetDescriptor()->FindFieldByName(
"fields");
417 const auto item_message = struct_value_reflection->AddMessage(struct_value_message, fields_desc, &factory);
418 const auto item_reflection = item_message->GetReflection();
419 const auto map_key_desc = item_message->GetDescriptor()->map_key();
420 const auto map_value_desc = item_message->GetDescriptor()->map_value();
421 const auto map_value_message = item_reflection->MutableMessage(item_message, map_value_desc, &factory);
422 const auto map_value_reflection = map_value_message->GetReflection();
423 const auto number_value_desc = map_value_message->GetDescriptor()->FindFieldByName(
"number_value");
425 item_reflection->SetString(item_message, map_key_desc,
"aaa");
426 map_value_reflection->SetDouble(map_value_message, number_value_desc, 1.5);
434 EXPECT_EQ(json
["aaa"].As<
double>(), 1.5);