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 = {};
25 ParseOptions options = {};
28struct FieldMaskFromJsonFailureTestParam {
29 std::string input = {};
30 ParseErrorCode expected_errc = {};
31 std::string expected_path = {};
32 ParseOptions options = {};
37 bool skip_native_check =
false;
40void PrintTo(
const FieldMaskFromJsonSuccessTestParam& param, std::ostream* os) {
41 *os << fmt::format(
"{{ input = '{}' }}", param.input);
44void PrintTo(
const FieldMaskFromJsonFailureTestParam& param, std::ostream* os) {
45 *os << fmt::format(
"{{ input = '{}' }}", param.input);
48class FieldMaskFromJsonSuccessTest :
public ::testing::TestWithParam<FieldMaskFromJsonSuccessTestParam> {};
49class FieldMaskFromJsonFailureTest :
public ::testing::TestWithParam<FieldMaskFromJsonFailureTestParam> {};
51INSTANTIATE_TEST_SUITE_P(
53 FieldMaskFromJsonSuccessTest,
55 FieldMaskFromJsonSuccessTestParam{R"({})", FieldMaskMessageData{}},
56 FieldMaskFromJsonSuccessTestParam{R"({"field1":null})", FieldMaskMessageData{}},
57 FieldMaskFromJsonSuccessTestParam{R"({"field1":""})", FieldMaskMessageData{std::vector<std::string>{}}},
58 FieldMaskFromJsonSuccessTestParam{R"({"field1":","})", FieldMaskMessageData{std::vector<std::string>{
"",
""}}},
59 FieldMaskFromJsonSuccessTestParam{
60 R"({"field1":",,,aaa,"})",
61 FieldMaskMessageData{std::vector<std::string>{
"",
"",
"",
"aaa",
""}}
63 FieldMaskFromJsonSuccessTestParam{
64 R"({"field1":"someField.anotherField"})",
65 FieldMaskMessageData{std::vector<std::string>{
"some_field.another_field"}}
67 FieldMaskFromJsonSuccessTestParam{
68 R"({"field1":"someField.anotherField..oneMore,AB0C"})",
69 FieldMaskMessageData{std::vector<std::string>{
"some_field.another_field..one_more",
"_a_b0_c"}}
74INSTANTIATE_TEST_SUITE_P(
76 FieldMaskFromJsonFailureTest,
78 FieldMaskFromJsonFailureTestParam{R"({"field1":[]})", ParseErrorCode::kInvalidType,
"field1"},
79 FieldMaskFromJsonFailureTestParam{R"({"field1":{}})", ParseErrorCode::kInvalidType,
"field1", {},
true},
80 FieldMaskFromJsonFailureTestParam{R"({"field1":true})", ParseErrorCode::kInvalidType,
"field1"},
81 FieldMaskFromJsonFailureTestParam{R"({"field1":1})", ParseErrorCode::kInvalidType,
"field1"},
82 FieldMaskFromJsonFailureTestParam{
83 R"({"field1":"some_field"})",
84 ParseErrorCode::kInvalidValue,
89 FieldMaskFromJsonFailureTestParam{
90 R"({"field1":"someF!ield"})",
91 ParseErrorCode::kInvalidValue,
99TEST_P(FieldMaskFromJsonSuccessTest, Test) {
100 const auto& param = GetParam();
102 proto_json::messages::FieldMaskMessage message;
103 proto_json::messages::FieldMaskMessage expected_message;
104 proto_json::messages::FieldMaskMessage sample_message;
105 formats::json::
Value input = PrepareJsonTestData(param.input);
106 expected_message = PrepareTestData(param.expected_message);
108 message.mutable_field1()->add_paths(
"dump");
110 UASSERT_NO_THROW((message = JsonToMessage<proto_json::messages::FieldMaskMessage>(input, param.options)));
111 UASSERT_NO_THROW(InitSampleMessage(param.input, sample_message, param.options));
113 CheckMessageEqual(message, sample_message);
114 CheckMessageEqual(message, expected_message);
117TEST_P(FieldMaskFromJsonFailureTest, Test) {
118 const auto& param = GetParam();
120 proto_json::messages::FieldMaskMessage sample_message;
121 formats::json::
Value input = PrepareJsonTestData(param.input);
124 (
void)JsonToMessage<proto_json::messages::FieldMaskMessage>(input, param.options),
129 if (!param.skip_native_check) {
130 UEXPECT_THROW(InitSampleMessage(param.input, sample_message, param.options), SampleError);
134TEST(FieldMaskFromJsonAdditionalTest, InlinedNonNull) {
135 using Message = ::google::protobuf::FieldMask;
137 const char* json_str =
"\"someField.anotherField,oneMore\"";
142 message.add_paths(
"dump");
144 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
145 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
147 CheckMessageEqual(message, sample);
150TEST(FieldMaskFromJsonAdditionalTest, InlinedNull) {
151 using Message = ::google::protobuf::FieldMask;
157 EXPECT_PARSE_ERROR((message = JsonToMessage<Message>(json)), ParseErrorCode::kInvalidType,
"/");
158 UEXPECT_THROW(InitSampleMessage(
"null", message), SampleError);
166 message.add_paths(
"dump");
168 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
169 UASSERT_NO_THROW(InitSampleMessage(
"{}", sample));
171 EXPECT_TRUE(message.paths().empty());
172 CheckMessageEqual(message, sample);
176TEST(FieldMaskFromJsonAdditionalTest, DynamicMessage) {
177 using Message = ::google::protobuf::FieldMask;
179 const char* json_str =
"\"someField.anotherField,oneMore\"";
181 ::google::protobuf::DynamicMessageFactory factory;
184 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
186 UASSERT_NO_THROW(JsonToMessage(json, *message));
188 const auto reflection = message->GetReflection();
189 const auto paths_desc = message->GetDescriptor()->FindFieldByName(
"paths");
190 std::unordered_multiset<std::string> paths;
192 for (
int i = 0; i < reflection->FieldSize(*message, paths_desc); ++i) {
193 paths.insert(reflection->GetRepeatedString(*message, paths_desc, i));
196 EXPECT_EQ(paths, (std::unordered_multiset<std::string>{
"some_field.another_field",
"one_more"}));