1#include <gtest/gtest.h>
8#include <google/protobuf/dynamic_message.h>
10#include <userver/formats/json/serialize.hpp>
11#include <userver/protobuf/json/convert.hpp>
12#include <userver/utest/assert_macros.hpp>
16USERVER_NAMESPACE_BEGIN
18namespace protobuf::json::tests {
20struct AnyFromJsonSuccessTestParam {
21 std::string input = {};
26 bool skip_native_check =
false;
29struct AnyFromJsonFailureTestParam {
30 std::string input = {};
32 std::string expected_path = {};
36void PrintTo(
const AnyFromJsonSuccessTestParam& param, std::ostream* os) {
37 *os << fmt::format(
"{{ input = '{}' }}", param.input);
40void PrintTo(
const AnyFromJsonFailureTestParam& param, std::ostream* os) {
41 *os << fmt::format(
"{{ input = '{}' }}", param.input);
44class AnyFromJsonSuccessTest :
public ::testing::TestWithParam<AnyFromJsonSuccessTestParam> {};
45class AnyFromJsonFailureTest :
public ::testing::TestWithParam<AnyFromJsonFailureTestParam> {};
47INSTANTIATE_TEST_SUITE_P(
49 AnyFromJsonSuccessTest,
51 AnyFromJsonSuccessTestParam{R"({})", AnyMessageData{}},
52 AnyFromJsonSuccessTestParam{R"({"field1":null})", AnyMessageData{}},
53 AnyFromJsonSuccessTestParam{R"({"field1":{}})", AnyMessageData{RawAnyData{
"",
""}}},
54 AnyFromJsonSuccessTestParam{
56 "field1": {
57 "@type":"type.googleapis.com/proto_json.messages.Int32Message"
58 }
59 })",
60 AnyMessageData{Int32MessageData{}}
62 AnyFromJsonSuccessTestParam{
64 "field1": {
65 "@type":"type.googleapis.com/proto_json.messages.Int32Message",
66 "field1":0,"field2":0,"field3":0
67 }
68 })",
69 AnyMessageData{Int32MessageData{0, 0, 0}}
71 AnyFromJsonSuccessTestParam{
73 "field1": {
74 "@type":"type.googleapis.com/proto_json.messages.Int32Message",
75 "field1":null,"field2":null,"field3":1
76 }
77 })",
78 AnyMessageData{Int32MessageData{0, 0, 1}}
80 AnyFromJsonSuccessTestParam{
82 "field1": {
83 "@type":"type.googleapis.com/proto_json.messages.Int32Message",
84 "field1":10,"field2":20,"field3":30
85 }
86 })",
87 AnyMessageData{Int32MessageData{10, 20, 30}}
89 AnyFromJsonSuccessTestParam{
91 "field1": {
92 "@type":"type.googleapis.com/proto_json.messages.Int32Message",
93 "field1":10,"field2":20,"field3":30,"unknown_field":true
94 }
95 })",
96 AnyMessageData{Int32MessageData{10, 20, 30}},
97 {.ignore_unknown_fields =
true}
99 AnyFromJsonSuccessTestParam{
101 "field1": {
102 "@type":"type.googleapis.com/google.protobuf.Duration",
103 "value":"123.000000987s"
104 }
105 })",
106 AnyMessageData{DurationMessageData{123, 987}}
108 AnyFromJsonSuccessTestParam{
110 "field1": {
111 "@type":"type.googleapis.com/google.protobuf.Duration",
112 "value":"123.000000987s",
113 "unknown_field":true
114 }
115 })",
116 AnyMessageData{DurationMessageData{123, 987}},
117 {.ignore_unknown_fields =
true},
121 AnyFromJsonSuccessTestParam{
123 "field1": {
124 "@type":"type.googleapis.com/google.protobuf.Duration"
125 }
126 })",
127 AnyMessageData{DurationMessageData{0, 0}}
129 AnyFromJsonSuccessTestParam{
131 "field1": {
132 "@type":"type.googleapis.com/google.protobuf.Duration",
133 "value":null
134 }
135 })",
136 AnyMessageData{DurationMessageData{0, 0}}
138 AnyFromJsonSuccessTestParam{
140 "field1": {
141 "@type":"type.googleapis.com/google.protobuf.Value",
142 "value":null
143 }
144 })",
145 AnyMessageData{ValueMessageData{kProtoNullValue}}
147 AnyFromJsonSuccessTestParam{
149 "field1": {
150 "@type":"type.googleapis.com/google.protobuf.Value",
151 "value":"hello"
152 }
153 })",
154 AnyMessageData{ValueMessageData{
"hello"}}
156 AnyFromJsonSuccessTestParam{
158 "field1": {
159 "@type":"type.googleapis.com/google.protobuf.Value",
160 "value":[1.5,1.5]
161 }
162 })",
163 AnyMessageData{ValueMessageData{std::vector<
double>{1.5, 1.5}}}
165 AnyFromJsonSuccessTestParam{
167 "field1": {
168 "@type":"type.googleapis.com/google.protobuf.Value",
169 "value":{"aaa":"hello","bbb":"world"}
170 }
171 })",
172 AnyMessageData{ValueMessageData{std::map<std::string, std::string>{{
"aaa",
"hello"}, {
"bbb",
"world"}}}}
175 AnyFromJsonSuccessTestParam{
176 R"({"field1":{"type_url":"type.googleapis.com/proto_json.messages.Int32Message","value":"CAoQFBge"}})",
178 RawAnyData{
"type.googleapis.com/proto_json.messages.Int32Message",
"\x08\x0a\x10\x14\x18\x1e"}
180 {.nonportable_raw_any =
true},
184 AnyFromJsonSuccessTestParam{
185 R"({"field1":{"typeUrl":"type.googleapis.com/proto_json.messages.Int32Message","value":"CAoQFBge"}})",
187 RawAnyData{
"type.googleapis.com/proto_json.messages.Int32Message",
"\x08\x0a\x10\x14\x18\x1e"}
189 {.nonportable_raw_any =
true},
193 AnyFromJsonSuccessTestParam{
194 R"({"field1":{"type_url":"type.googleapis.com/proto_json.messages.NonExistent","value":"CAE="}})",
195 AnyMessageData{RawAnyData{
"type.googleapis.com/proto_json.messages.NonExistent",
"\x08\x01"}},
196 {.nonportable_raw_any =
true},
200 AnyFromJsonSuccessTestParam{
201 R"({"field1":{"type_url":"","value":""}})",
202 AnyMessageData{RawAnyData{
"",
""}},
203 {.nonportable_raw_any =
true},
210INSTANTIATE_TEST_SUITE_P(
212 AnyFromJsonFailureTest,
218 AnyFromJsonFailureTestParam{
220 "field1": {
221 "@type":"oops"
222 }
223 })",
227 AnyFromJsonFailureTestParam{
229 "field1": {
230 "@type":"type.googleapis.com/proto_json.messages.NonExistent"
231 }
232 })",
236 AnyFromJsonFailureTestParam{
238 "field1": {
239 "@type":true
240 }
241 })",
245 AnyFromJsonFailureTestParam{
247 "field1": {
248 "value":"123.000000987s"
249 }
250 })",
254 AnyFromJsonFailureTestParam{
256 "field1": {
257 "field1":1
258 }
259 })",
263 AnyFromJsonFailureTestParam{
265 "field1": {
266 "@type":"type.googleapis.com/proto_json.messages.Int32Message",
267 "field1":10,"field2":20,"field3":30,"unknown_field":true
268 }
269 })",
271 "field1.unknown_field",
274 AnyFromJsonFailureTestParam{
276 "field1": {
277 "@type":"type.googleapis.com/google.protobuf.Duration",
278 "value":"123.000000987s",
279 "unknown_field":true
280 }
281 })",
283 "field1.unknown_field",
287 AnyFromJsonFailureTestParam{
288 R"({"field1":{"type_url":"type.googleapis.com/some.Type"}})",
294 AnyFromJsonFailureTestParam{
295 R"({"field1":{"value":""}})",
301 AnyFromJsonFailureTestParam{
302 R"({"field1":{"type_url":123,"value":""}})",
310TEST_P(AnyFromJsonSuccessTest, Test) {
311 const auto& param = GetParam();
313 proto_json::messages::AnyMessage message;
314 proto_json::messages::AnyMessage expected_message;
315 proto_json::messages::AnyMessage sample_message;
316 formats::
json::
Value input = PrepareJsonTestData(param.input);
317 expected_message = PrepareTestData(param.expected_message);
319 message.mutable_field1()->set_type_url(
"dump");
321 UASSERT_NO_THROW((message = JsonToMessage<proto_json::messages::AnyMessage>(input, param.options)));
323 if (!param.skip_native_check) {
324 UASSERT_NO_THROW(InitSampleMessage(param.input, sample_message, param.options));
325 CheckMessageEqual(message, sample_message);
328 CheckMessageEqual(message, expected_message);
331TEST_P(AnyFromJsonFailureTest, Test) {
332 const auto& param = GetParam();
334 proto_json::messages::AnyMessage sample_message;
335 formats::
json::
Value input = PrepareJsonTestData(param.input);
338 (
void)JsonToMessage<proto_json::messages::AnyMessage>(input, param.options),
345TEST(AnyFromJsonAdditionalTest, InlinedNonNull) {
346 using Message = ::google::protobuf::Any;
348 const char* json_str =
350 "@type":"type.googleapis.com/proto_json.messages.Int32Message",
351 "field1":1,"field2":2,"field3":3
352 })";
356 proto_json::messages::Int32Message payload;
358 message.set_type_url(
"dump");
362 ASSERT_TRUE(message.Is<proto_json::messages::Int32Message>());
363 ASSERT_TRUE(message.UnpackTo(&payload));
365 EXPECT_EQ(payload.field1(), 1);
366 EXPECT_EQ(payload.field2(), 2);
367 EXPECT_EQ(payload.field3(), 3);
368 CheckMessageEqual(message, sample);
371TEST(AnyFromJsonAdditionalTest, InlinedNull) {
372 using Message = ::google::protobuf::Any;
387 message.set_type_url(
"dump");
392 EXPECT_TRUE(message.type_url().empty());
393 EXPECT_TRUE(message.value().empty());
394 CheckMessageEqual(message, sample);
398TEST(AnyFromJsonAdditionalTest, DynamicMessage) {
399 using Message = ::google::protobuf::Any;
401 const char* json_str =
403 "@type":"type.googleapis.com/proto_json.messages.Int32Message",
404 "field1":1,"field2":2,"field3":3
405 })";
408 proto_json::messages::Int32Message payload;
409 ::google::protobuf::DynamicMessageFactory factory;
412 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
416 const auto reflection = message->GetReflection();
417 const auto type_url_desc = message->GetDescriptor()->FindFieldByName(
"type_url");
418 const auto value_desc = message->GetDescriptor()->FindFieldByName(
"value");
421 reflection->GetString(*message, type_url_desc),
422 "type.googleapis.com/proto_json.messages.Int32Message"
424 ASSERT_TRUE(payload.ParseFromString(reflection->GetString(*message, value_desc)));
425 EXPECT_EQ(payload.field1(), 1);
426 EXPECT_EQ(payload.field2(), 2);
427 EXPECT_EQ(payload.field3(), 3);