1#include <gtest/gtest.h>
6#include <unordered_set>
10#include <google/protobuf/dynamic_message.h>
12#include <userver/formats/json/serialize.hpp>
13#include <userver/protobuf/json/convert.hpp>
14#include <userver/utest/assert_macros.hpp>
18USERVER_NAMESPACE_BEGIN
20namespace protobuf::json::tests {
22struct FieldMaskFromJsonSuccessTestParam {
23 std::string input = {};
28 bool skip_native_check =
false;
31struct FieldMaskFromJsonFailureTestParam {
32 std::string input = {};
34 std::string expected_path = {};
40 bool skip_native_check =
false;
43void PrintTo(
const FieldMaskFromJsonSuccessTestParam& param, std::ostream* os) {
44 *os << fmt::format(
"{{ input = '{}' }}", param.input);
47void PrintTo(
const FieldMaskFromJsonFailureTestParam& param, std::ostream* os) {
48 *os << fmt::format(
"{{ input = '{}' }}", param.input);
51class FieldMaskFromJsonSuccessTest :
public ::testing::TestWithParam<FieldMaskFromJsonSuccessTestParam> {};
52class FieldMaskFromJsonFailureTest :
public ::testing::TestWithParam<FieldMaskFromJsonFailureTestParam> {};
54INSTANTIATE_TEST_SUITE_P(
56 FieldMaskFromJsonSuccessTest,
58 FieldMaskFromJsonSuccessTestParam{R"({})", FieldMaskMessageData{}},
59 FieldMaskFromJsonSuccessTestParam{R"({"field1":null})", FieldMaskMessageData{}},
60 FieldMaskFromJsonSuccessTestParam{R"({"field1":""})", FieldMaskMessageData{std::vector<std::string>{}}},
61 FieldMaskFromJsonSuccessTestParam{
63 FieldMaskMessageData{std::vector<std::string>{
"",
""}},
67 FieldMaskFromJsonSuccessTestParam{
68 R"({"field1":",,,aaa,"})",
69 FieldMaskMessageData{std::vector<std::string>{
"",
"",
"",
"aaa",
""}},
73 FieldMaskFromJsonSuccessTestParam{
74 R"({"field1":"someField.anotherField"})",
75 FieldMaskMessageData{std::vector<std::string>{
"some_field.another_field"}}
77 FieldMaskFromJsonSuccessTestParam{
78 R"({"field1":"someField.anotherField..oneMore,AB0C"})",
79 FieldMaskMessageData{std::vector<std::string>{
"some_field.another_field..one_more",
"_a_b0_c"}},
86INSTANTIATE_TEST_SUITE_P(
88 FieldMaskFromJsonFailureTest,
94 FieldMaskFromJsonFailureTestParam{
95 R"({"field1":"some_field"})",
101 FieldMaskFromJsonFailureTestParam{
102 R"({"field1":"someF!ield"})",
111TEST_P(FieldMaskFromJsonSuccessTest, Test) {
112 const auto& param = GetParam();
114 proto_json::messages::FieldMaskMessage message;
115 proto_json::messages::FieldMaskMessage expected_message;
116 proto_json::messages::FieldMaskMessage sample_message;
117 formats::
json::
Value input = PrepareJsonTestData(param.input);
118 expected_message = PrepareTestData(param.expected_message);
120 message.mutable_field1()->add_paths(
"dump");
122 UASSERT_NO_THROW((message = JsonToMessage<proto_json::messages::FieldMaskMessage>(input, param.options)));
124 if (!param.skip_native_check) {
125 UASSERT_NO_THROW(InitSampleMessage(param.input, sample_message, param.options));
126 CheckMessageEqual(message, sample_message);
129 CheckMessageEqual(message, expected_message);
132TEST_P(FieldMaskFromJsonFailureTest, Test) {
133 const auto& param = GetParam();
135 proto_json::messages::FieldMaskMessage sample_message;
136 formats::
json::
Value input = PrepareJsonTestData(param.input);
139 (
void)JsonToMessage<proto_json::messages::FieldMaskMessage>(input, param.options),
144 if (!param.skip_native_check) {
149TEST(FieldMaskFromJsonAdditionalTest, InlinedNonNull) {
150 using Message = ::google::protobuf::FieldMask;
152 const char* json_str =
"\"someField.anotherField,oneMore\"";
157 message.add_paths(
"dump");
162 CheckMessageEqual(message, sample);
165TEST(FieldMaskFromJsonAdditionalTest, InlinedNull) {
166 using Message = ::google::protobuf::FieldMask;
173 if (kIsModernProtoJson) {
183 message.add_paths(
"dump");
188 EXPECT_TRUE(message.paths().empty());
189 CheckMessageEqual(message, sample);
193TEST(FieldMaskFromJsonAdditionalTest, DynamicMessage) {
194 using Message = ::google::protobuf::FieldMask;
196 const char* json_str =
"\"someField.anotherField,oneMore\"";
198 ::google::protobuf::DynamicMessageFactory factory;
201 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
205 const auto reflection = message->GetReflection();
206 const auto paths_desc = message->GetDescriptor()->FindFieldByName(
"paths");
207 std::unordered_multiset<std::string> paths;
209 for (
int i = 0; i < reflection->FieldSize(*message, paths_desc); ++i) {
210 paths.insert(reflection->GetRepeatedString(*message, paths_desc, i));
213 EXPECT_EQ(paths, (std::unordered_multiset<std::string>{
"some_field.another_field",
"one_more"}));