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
19struct ValueToJsonSuccessTestParam {
21 std::string expected_json = {};
22 WriteOptions options = {};
25struct ValueToJsonFailureTestParam {
27 WriteErrorCode expected_errc = {};
28 std::string expected_path = {};
29 WriteOptions options = {};
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{kProtoNullValue}}, R"({"field1":null})"},
46 ValueToJsonSuccessTestParam{ValueMessageData{ProtoValue{1.5}}, R"({"field1":1.5})"},
47 ValueToJsonSuccessTestParam{ValueMessageData{ProtoValue{
"hello"}}, R"({"field1":"hello"})"},
48 ValueToJsonSuccessTestParam{ValueMessageData{ProtoValue{
true}}, R"({"field1":true})"},
49 ValueToJsonSuccessTestParam{ValueMessageData{ProtoValue{std::vector<
double>{}}}, R"({"field1":[]})"},
50 ValueToJsonSuccessTestParam{
51 ValueMessageData{ProtoValue{std::vector<
double>{1.5, 1.5}}},
52 R"({"field1":[1.5, 1.5]})"
54 ValueToJsonSuccessTestParam{
55 ValueMessageData{ProtoValue{std::map<std::string, std::string>{}}},
58 ValueToJsonSuccessTestParam{
59 ValueMessageData{ProtoValue{std::map<std::string, std::string>{{
"aaa",
"hello"}, {
"bbb",
"world"}}}
61 R"({"field1":{"aaa":"hello","bbb":"world"}})"
63 ValueToJsonSuccessTestParam{
65 std::vector<ProtoValue>{},
69 ValueToJsonSuccessTestParam{
71 std::vector<ProtoValue>{std::vector<
double>{}},
75 ValueToJsonSuccessTestParam{
77 std::vector<ProtoValue>{std::vector<
double>{1.5}, std::vector<
double>{0, 1.5}},
79 R"({"field1":[[1.5],[0,1.5]]})"
81 ValueToJsonSuccessTestParam{
83 std::vector<ProtoValue>{
88 std::vector<
double>{1.5, 1.5},
89 std::map<std::string, std::string>{{
"aaa",
"hello"}, {
"bbb",
"world"}}
92 R"({"field1":[null,1.5,"hello",true,[1.5,1.5],{"aaa":"hello","bbb":"world"}]})"
94 ValueToJsonSuccessTestParam{
96 std::map<std::string, ProtoValue>{},
100 ValueToJsonSuccessTestParam{
102 std::map<std::string, ProtoValue>{{
"aaa", ProtoValue{std::map<std::string, std::string>{}}}},
104 R"({"field1":{"aaa":{}}})"
106 ValueToJsonSuccessTestParam{
108 std::map<std::string, ProtoValue>{
109 {
"aaa", kProtoNullValue},
113 {
"eee", std::vector<
double>{1.5, 1.5}},
114 {
"", std::map<std::string, std::string>{{
"",
"hello"}, {
"bbb",
"world"}}}
117 R"({"field1":{"aaa":null,"bbb":1.5,"ccc":"hello","ddd":true,"eee":[1.5,1.5],"":{"":"hello","bbb":"world"}}})"
122INSTANTIATE_TEST_SUITE_P(
124 ValueToJsonFailureTest,
126 ValueToJsonFailureTestParam{
127 ValueMessageData{ProtoValue{std::monostate{}}},
128 WriteErrorCode::kInvalidValue,
133 ValueToJsonFailureTestParam{
134 ValueMessageData{ProtoValue{std::numeric_limits<
double>::quiet_NaN()}},
135 WriteErrorCode::kInvalidValue,
136 "field1.number_value"
138 ValueToJsonFailureTestParam{
139 ValueMessageData{ProtoValue{std::numeric_limits<
double>::signaling_NaN()}},
140 WriteErrorCode::kInvalidValue,
141 "field1.number_value"
143 ValueToJsonFailureTestParam{
144 ValueMessageData{ProtoValue{std::numeric_limits<
double>::infinity()}},
145 WriteErrorCode::kInvalidValue,
146 "field1.number_value"
148 ValueToJsonFailureTestParam{
149 ValueMessageData{ProtoValue{-std::numeric_limits<
double>::infinity()}},
150 WriteErrorCode::kInvalidValue,
151 "field1.number_value"
153 ValueToJsonFailureTestParam{
154 ValueMessageData{std::vector<ProtoValue>{ProtoValue{1.5}, ProtoValue{std::monostate{}}, ProtoValue{
true}}},
155 WriteErrorCode::kInvalidValue,
156 "field1.list_value.values[1]",
160 ValueToJsonFailureTestParam{
161 ValueMessageData{std::vector<ProtoValue>{
163 ProtoValue{std::vector<
double>{1.5, std::numeric_limits<
double>::infinity()}},
166 WriteErrorCode::kInvalidValue,
167 "field1.list_value.values[1].list_value.values[1].number_value"
169 ValueToJsonFailureTestParam{
170 ValueMessageData{std::map<
172 ProtoValue>{{
"aaa", ProtoValue{1.5}}, {
"bbb", ProtoValue{std::monostate{}}}, {
"ccc", ProtoValue{
true}}}
174 WriteErrorCode::kInvalidValue,
175 "field1.struct_value.fields['bbb']",
182TEST_P(ValueToJsonSuccessTest, Test) {
183 const auto& param = GetParam();
185 auto input = PrepareTestData(param.input);
186 formats::json::Value json, expected_json, sample_json;
188 UASSERT_NO_THROW((json = MessageToJson(input, param.options)));
189 UASSERT_NO_THROW((expected_json = PrepareJsonTestData(param.expected_json)));
190 UASSERT_NO_THROW((sample_json = CreateSampleJson(input, param.options)));
192 EXPECT_EQ(json, expected_json);
193 EXPECT_EQ(expected_json, sample_json);
196TEST_P(ValueToJsonFailureTest, Test) {
197 const auto& param = GetParam();
198 auto input = PrepareTestData(param.input);
200 EXPECT_WRITE_ERROR((
void)MessageToJson(input, param.options), param.expected_errc, param.expected_path);
202 if (!param.skip_native_check) {
203 UEXPECT_THROW((
void)CreateSampleJson(input, param.options), SampleError);
207TEST(ValueToJsonAdditionalTest, InlinedNonNull) {
210 auto message = PrepareTestData(data);
211 formats::json::Value json, sample;
213 UASSERT_NO_THROW((json = MessageToJson(message.field1())));
214 UASSERT_NO_THROW((sample = CreateSampleJson(message.field1())));
215 EXPECT_EQ(json, sample);
216 EXPECT_TRUE(json.IsNull());
221 auto message = PrepareTestData(data);
222 formats::json::Value json, sample;
224 UASSERT_NO_THROW((json = MessageToJson(message.field1())));
225 UASSERT_NO_THROW((sample = CreateSampleJson(message.field1())));
226 EXPECT_EQ(json, sample);
227 ASSERT_TRUE(json.IsNumber());
228 EXPECT_EQ(json.As<
double>(), 1.5);
233 auto message = PrepareTestData(data);
234 formats::json::Value json, sample;
236 UASSERT_NO_THROW((json = MessageToJson(message.field1())));
237 UASSERT_NO_THROW((sample = CreateSampleJson(message.field1())));
238 EXPECT_EQ(json, sample);
239 EXPECT_TRUE(json.IsString());
240 EXPECT_EQ(json.As<std::string>(),
"hello");
245 auto message = PrepareTestData(data);
246 formats::json::Value json, sample;
248 UASSERT_NO_THROW((json = MessageToJson(message.field1())));
249 UASSERT_NO_THROW((sample = CreateSampleJson(message.field1())));
250 EXPECT_EQ(json, sample);
251 EXPECT_TRUE(json.IsBool());
252 EXPECT_TRUE(json.As<
bool>());
257 auto message = PrepareTestData(data);
258 formats::json::Value json, sample;
260 UASSERT_NO_THROW((json = MessageToJson(message.field1())));
261 UASSERT_NO_THROW((sample = CreateSampleJson(message.field1())));
262 EXPECT_EQ(json, sample);
263 EXPECT_TRUE(json.IsArray());
264 ASSERT_EQ(json.GetSize(), std::size_t{0});
269 auto message = PrepareTestData(data);
270 formats::json::Value json, sample;
272 UASSERT_NO_THROW((json = MessageToJson(message.field1())));
273 UASSERT_NO_THROW((sample = CreateSampleJson(message.field1())));
274 EXPECT_EQ(json, sample);
275 EXPECT_TRUE(json.IsArray());
276 ASSERT_EQ(json.GetSize(), std::size_t{2});
277 EXPECT_EQ(json[0].As<
double>(), 1.5);
278 EXPECT_EQ(json[1].As<
double>(), 0);
283 auto message = PrepareTestData(data);
284 formats::json::Value json, sample;
286 UASSERT_NO_THROW((json = MessageToJson(message.field1())));
287 UASSERT_NO_THROW((sample = CreateSampleJson(message.field1())));
288 EXPECT_EQ(json, sample);
289 EXPECT_TRUE(json.IsObject());
290 ASSERT_EQ(json.GetSize(), std::size_t{0});
294 ValueMessageData data{std::map<std::string, std::string>{{
"aaa",
"hello"}, {
"bbb",
"world"}}};
295 auto message = PrepareTestData(data);
296 formats::json::Value json, sample;
298 UASSERT_NO_THROW((json = MessageToJson(message.field1())));
299 UASSERT_NO_THROW((sample = CreateSampleJson(message.field1())));
300 EXPECT_EQ(json, sample);
301 EXPECT_TRUE(json.IsObject());
302 ASSERT_EQ(json.GetSize(), std::size_t{2});
303 ASSERT_TRUE(json.HasMember(
"aaa"));
304 ASSERT_TRUE(json.HasMember(
"bbb"));
305 EXPECT_EQ(json[
"aaa"].As<std::string>(),
"hello");
306 EXPECT_EQ(json[
"bbb"].As<std::string>(),
"world");
310TEST(ValueToJsonAdditionalTest, InlinedNull) {
312 auto message = PrepareTestData(data);
314 EXPECT_WRITE_ERROR((
void)MessageToJson(message.field1()), WriteErrorCode::kInvalidValue,
"/");
317TEST(ValueToJsonAdditionalTest, DynamicMessage) {
318 using Message = ::google::protobuf::Value;
319 ::google::protobuf::DynamicMessageFactory factory;
322 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
323 const auto reflection = message->GetReflection();
324 const auto null_value_desc = message->GetDescriptor()->FindFieldByName(
"null_value");
326 reflection->SetEnumValue(message.get(), null_value_desc, 0);
328 formats::json::Value json;
330 UASSERT_NO_THROW((json = MessageToJson(*message)));
331 ASSERT_TRUE(json.IsNull());
335 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
336 const auto reflection = message->GetReflection();
337 const auto number_value_desc = message->GetDescriptor()->FindFieldByName(
"number_value");
339 reflection->SetDouble(message.get(), number_value_desc, 1.5);
341 formats::json::Value json;
343 UASSERT_NO_THROW((json = MessageToJson(*message)));
344 ASSERT_TRUE(json.IsNumber());
345 EXPECT_EQ(json.As<
double>(), 1.5);
349 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
350 const auto reflection = message->GetReflection();
351 const auto number_value_desc = message->GetDescriptor()->FindFieldByName(
"string_value");
353 reflection->SetString(message.get(), number_value_desc,
"hello");
355 formats::json::Value json;
357 UASSERT_NO_THROW((json = MessageToJson(*message)));
358 ASSERT_TRUE(json.IsString());
359 EXPECT_EQ(json.As<std::string>(),
"hello");
363 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
364 const auto reflection = message->GetReflection();
365 const auto bool_value_desc = message->GetDescriptor()->FindFieldByName(
"bool_value");
367 reflection->SetBool(message.get(), bool_value_desc,
true);
369 formats::json::Value json;
371 UASSERT_NO_THROW((json = MessageToJson(*message)));
372 ASSERT_TRUE(json.IsBool());
373 EXPECT_EQ(json.As<
bool>(),
true);
377 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
378 const auto reflection = message->GetReflection();
379 const auto list_value_desc = message->GetDescriptor()->FindFieldByName(
"list_value");
380 const auto list_value_message = reflection->MutableMessage(message.get(), list_value_desc, &factory);
381 const auto list_value_reflection = list_value_message->GetReflection();
382 const auto values_desc = list_value_message->GetDescriptor()->FindFieldByName(
"values");
383 const auto item_message = list_value_reflection->AddMessage(list_value_message, values_desc, &factory);
384 const auto item_reflection = item_message->GetReflection();
385 const auto number_value_desc = item_message->GetDescriptor()->FindFieldByName(
"number_value");
387 item_reflection->SetDouble(item_message, number_value_desc, 1.5);
389 formats::json::Value json;
391 UASSERT_NO_THROW((json = MessageToJson(*message)));
392 ASSERT_TRUE(json.IsArray());
393 ASSERT_EQ(json.GetSize(), std::size_t{1});
394 EXPECT_EQ(json[0].As<
double>(), 1.5);
398 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
399 const auto reflection = message->GetReflection();
400 const auto struct_value_desc = message->GetDescriptor()->FindFieldByName(
"struct_value");
401 const auto struct_value_message = reflection->MutableMessage(message.get(), struct_value_desc, &factory);
402 const auto struct_value_reflection = struct_value_message->GetReflection();
403 const auto fields_desc = struct_value_message->GetDescriptor()->FindFieldByName(
"fields");
404 const auto item_message = struct_value_reflection->AddMessage(struct_value_message, fields_desc, &factory);
405 const auto item_reflection = item_message->GetReflection();
406 const auto map_key_desc = item_message->GetDescriptor()->map_key();
407 const auto map_value_desc = item_message->GetDescriptor()->map_value();
408 const auto map_value_message = item_reflection->MutableMessage(item_message, map_value_desc, &factory);
409 const auto map_value_reflection = map_value_message->GetReflection();
410 const auto number_value_desc = map_value_message->GetDescriptor()->FindFieldByName(
"number_value");
412 item_reflection->SetString(item_message, map_key_desc,
"aaa");
413 map_value_reflection->SetDouble(map_value_message, number_value_desc, 1.5);
415 formats::json::Value json;
417 UASSERT_NO_THROW((json = MessageToJson(*message)));
418 ASSERT_TRUE(json.IsObject());
419 ASSERT_EQ(json.GetSize(), std::size_t{1});
420 ASSERT_TRUE(json.HasMember(
"aaa"));
421 EXPECT_EQ(json[
"aaa"].As<
double>(), 1.5);