1#include <gtest/gtest.h>
9#include <google/protobuf/dynamic_message.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 {
22T GetWrappedValue(
const ::google::protobuf::Message& msg) {
23 const auto reflection = msg.GetReflection();
24 const auto value_desc = msg.GetDescriptor()->FindFieldByName(
"value");
27 throw std::runtime_error(
"Field 'value' is not found in wrapper message");
30 if constexpr (std::is_same_v<T,
double>) {
31 return reflection->GetDouble(msg, value_desc);
32 }
else if constexpr (std::is_same_v<T,
float>) {
33 return reflection->GetFloat(msg, value_desc);
34 }
else if constexpr (std::is_same_v<T, std::int64_t>) {
35 return reflection->GetInt64(msg, value_desc);
36 }
else if constexpr (std::is_same_v<T, std::uint64_t>) {
37 return reflection->GetUInt64(msg, value_desc);
38 }
else if constexpr (std::is_same_v<T, std::int32_t>) {
39 return reflection->GetInt32(msg, value_desc);
40 }
else if constexpr (std::is_same_v<T, std::uint32_t>) {
41 return reflection->GetUInt32(msg, value_desc);
42 }
else if constexpr (std::is_same_v<T,
bool>) {
43 return reflection->GetBool(msg, value_desc);
44 }
else if constexpr (std::is_same_v<T, std::string>) {
45 return reflection->GetString(msg, value_desc);
47 static_assert(
sizeof(T) &&
false,
"unexpected type");
51struct WrapperFromJsonSuccessTestParam {
52 std::string input = {};
54 ParseOptions options = {};
57struct WrapperFromJsonFailureTestParam {
58 std::string input = {};
59 ParseErrorCode expected_errc = {};
60 std::string expected_path = {};
61 ParseOptions options = {};
67 bool skip_native_check =
false;
70void PrintTo(
const WrapperFromJsonFailureTestParam& param, std::ostream* os) {
71 *os << fmt::format(
"{{ input = '{}' }}", param.input);
74class WrapperFromJsonSuccessTest :
public ::testing::TestWithParam<WrapperFromJsonSuccessTestParam> {};
75class WrapperFromJsonFailureTest :
public ::testing::TestWithParam<WrapperFromJsonFailureTestParam> {};
77INSTANTIATE_TEST_SUITE_P(
79 WrapperFromJsonSuccessTest,
81 WrapperFromJsonSuccessTestParam{R"({})", WrapperMessageData{}},
82 WrapperFromJsonSuccessTestParam{
84 "field1":null,
85 "field2":null,
86 "field3":null,
87 "field4":null,
88 "field5":null,
89 "field6":null,
90 "field7":null,
91 "field8":null,
92 "field9":null
93 })",
96 WrapperFromJsonSuccessTestParam{
98 "field1":0,
99 "field2":0,
100 "field3":"0",
101 "field4":"0",
102 "field5":0,
103 "field6":0,
104 "field7":false,
105 "field8":"",
106 "field9":""
107 })",
108 WrapperMessageData{0, 0, 0, 0, 0, 0,
false,
"",
""},
110 WrapperFromJsonSuccessTestParam{
113 "field1":1.5,
114 "field2":1.5,
115 "field3":"-123",
116 "field4":"123",
117 "field5":-321,
118 "field6":321,
119 "field7":true,
120 "field8":"hello",
121 "field9":"d29ybGQ="
122 })",
123 WrapperMessageData{1.5, 1.5, -123, 123, -321, 321,
true,
"hello",
"world"},
125 WrapperFromJsonSuccessTestParam{
128 "field3":"-123",
129 "field5":-321,
130 "field7":true,
131 "field9":"d29ybGQ="
132 })",
148INSTANTIATE_TEST_SUITE_P(
150 WrapperFromJsonFailureTest,
152 WrapperFromJsonFailureTestParam{R"({"field1":[]})", ParseErrorCode::kInvalidType,
"field1"},
153 WrapperFromJsonFailureTestParam{R"({"field2":{}})", ParseErrorCode::kInvalidType,
"field2", {},
true},
154 WrapperFromJsonFailureTestParam{R"({"field3":true})", ParseErrorCode::kInvalidType,
"field3"},
155 WrapperFromJsonFailureTestParam{R"({"field4":"hello"})", ParseErrorCode::kInvalidValue,
"field4"},
156 WrapperFromJsonFailureTestParam{R"({"field5":1.5})", ParseErrorCode::kInvalidValue,
"field5"}
160TEST_P(WrapperFromJsonSuccessTest, Test) {
161 const auto& param = GetParam();
163 proto_json::messages::WrapperMessage message;
164 proto_json::messages::WrapperMessage expected_message;
165 proto_json::messages::WrapperMessage sample_message;
166 formats::json::
Value input = PrepareJsonTestData(param.input);
167 expected_message = PrepareTestData(param.expected_message);
169 message.mutable_field1()->set_value(100001);
170 message.mutable_field2()->set_value(200002);
171 message.mutable_field3()->set_value(300003);
172 message.mutable_field4()->set_value(400004);
173 message.mutable_field5()->set_value(500005);
174 message.mutable_field6()->set_value(600006);
175 message.mutable_field7()->set_value(
true);
176 message.mutable_field8()->set_value(
"dump1");
177 message.mutable_field9()->set_value(
"dump2");
179 UASSERT_NO_THROW((message = JsonToMessage<proto_json::messages::WrapperMessage>(input, param.options)));
180 UASSERT_NO_THROW(InitSampleMessage(param.input, sample_message, param.options));
182 CheckMessageEqual(message, sample_message);
183 CheckMessageEqual(message, expected_message);
186TEST_P(WrapperFromJsonFailureTest, Test) {
187 const auto& param = GetParam();
189 proto_json::messages::WrapperMessage sample_message;
190 formats::json::
Value input = PrepareJsonTestData(param.input);
193 (
void)JsonToMessage<proto_json::messages::WrapperMessage>(input, param.options),
198 if (!param.skip_native_check) {
199 UEXPECT_THROW(InitSampleMessage(param.input, sample_message, param.options), SampleError);
204class WrapperFromJsonAdditionalTest :
public ::testing::Test {
209using WrapperTypes = ::testing::Types<
220TYPED_TEST_SUITE(WrapperFromJsonAdditionalTest, WrapperTypes);
222TYPED_TEST(WrapperFromJsonAdditionalTest, InlinedNonNull) {
223 using Param =
typename TestFixture::Param;
224 using Message =
typename Param::Message;
230 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
231 UASSERT_NO_THROW(InitSampleMessage(Param::kJson, sample));
232 EXPECT_EQ(message.value(), sample.value());
233 EXPECT_EQ(message.value(), Param::kValue);
236TYPED_TEST(WrapperFromJsonAdditionalTest, InlinedNull) {
237 using Param =
typename TestFixture::Param;
238 using Message =
typename Param::Message;
239 using Value = std::remove_const_t<
decltype(Param::kValue)>;
245 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
246 UASSERT_NO_THROW(InitSampleMessage(
"null", sample));
247 EXPECT_EQ(message.value(), sample.value());
248 EXPECT_EQ(message.value(), Value{});
251TYPED_TEST(WrapperFromJsonAdditionalTest, DynamicMessage) {
252 using Param =
typename TestFixture::Param;
253 using Message =
typename Param::Message;
256 ::google::protobuf::DynamicMessageFactory factory;
259 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
261 UASSERT_NO_THROW(JsonToMessage(json, *message));
262 EXPECT_EQ(GetWrappedValue<WrappedType<Param>>(*message), Param::kValue);