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, expected_message, sample_message;
104 expected_message = PrepareTestData(param.expected_message);
106 message.mutable_field1()->add_paths(
"dump");
108 UASSERT_NO_THROW((message = JsonToMessage<proto_json::messages::FieldMaskMessage>(input, param.options)));
109 UASSERT_NO_THROW(InitSampleMessage(param.input, sample_message, param.options));
111 CheckMessageEqual(message, sample_message);
112 CheckMessageEqual(message, expected_message);
115TEST_P(FieldMaskFromJsonFailureTest, Test) {
116 const auto& param = GetParam();
118 proto_json::messages::FieldMaskMessage sample_message;
122 (
void)JsonToMessage<proto_json::messages::FieldMaskMessage>(input, param.options),
127 if (!param.skip_native_check) {
128 UEXPECT_THROW(InitSampleMessage(param.input, sample_message, param.options), SampleError);
132TEST(FieldMaskFromJsonAdditionalTest, InlinedNonNull) {
133 using Message = ::google::protobuf::FieldMask;
135 const char* json_str =
"\"someField.anotherField,oneMore\"";
137 Message message, sample;
139 message.add_paths(
"dump");
141 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
142 UASSERT_NO_THROW(InitSampleMessage(json_str, sample));
144 CheckMessageEqual(message, sample);
147TEST(FieldMaskFromJsonAdditionalTest, InlinedNull) {
148 using Message = ::google::protobuf::FieldMask;
154 EXPECT_PARSE_ERROR((message = JsonToMessage<Message>(json)), ParseErrorCode::kInvalidType,
"/");
155 UEXPECT_THROW(InitSampleMessage(
"null", message), SampleError);
160 Message message, sample;
162 message.add_paths(
"dump");
164 UASSERT_NO_THROW((message = JsonToMessage<Message>(json)));
165 UASSERT_NO_THROW(InitSampleMessage(
"{}", sample));
167 EXPECT_TRUE(message.paths().empty());
168 CheckMessageEqual(message, sample);
172TEST(FieldMaskFromJsonAdditionalTest, DynamicMessage) {
173 using Message = ::google::protobuf::FieldMask;
175 const char* json_str =
"\"someField.anotherField,oneMore\"";
177 ::google::protobuf::DynamicMessageFactory factory;
180 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
182 UASSERT_NO_THROW(JsonToMessage(json, *message));
184 const auto reflection = message->GetReflection();
185 const auto paths_desc = message->GetDescriptor()->FindFieldByName(
"paths");
186 std::unordered_multiset<std::string> paths;
188 for (
int i = 0; i < reflection->FieldSize(*message, paths_desc); ++i) {
189 paths.insert(reflection->GetRepeatedString(*message, paths_desc, i));
192 EXPECT_EQ(paths, (std::unordered_multiset<std::string>{
"some_field.another_field",
"one_more"}));