userver: /data/code/userver/libraries/protobuf/tests/json/repeated_from_json_test.cpp Source File
Loading...
Searching...
No Matches
repeated_from_json_test.cpp
1#include <gtest/gtest.h>
2
3#include <ostream>
4#include <string>
5
6#include <fmt/format.h>
7
8#include <userver/protobuf/json/convert.hpp>
9#include <userver/utest/assert_macros.hpp>
10
11#include "utils.hpp"
12
13USERVER_NAMESPACE_BEGIN
14
15namespace protobuf::json::tests {
16
17struct RepeatedFromJsonSuccessTestParam {
18 std::string input = {};
19 RepeatedMessageData expected_message = {};
20 ParseOptions options = {};
21};
22
23struct RepeatedFromJsonFailureTestParam {
24 std::string input = {};
25 ParseErrorCode expected_errc = {};
26 std::string expected_path = {};
27 ParseOptions options = {};
28
29 // Protobuf ProtoJSON legacy syntax supports some features which we want to prohibit (because
30 // we do not want our clients to use syntax that may break in the newer protobuf versions). This
31 // variable is used disable some checks that will fail for legacy syntax.
32 bool skip_native_check = false;
33};
34
35void PrintTo(const RepeatedFromJsonSuccessTestParam& param, std::ostream* os) {
36 *os << fmt::format("{{ input = '{}' }}", param.input);
37}
38
39void PrintTo(const RepeatedFromJsonFailureTestParam& param, std::ostream* os) {
40 *os << fmt::format("{{ input = '{}' }}", param.input);
41}
42
43class RepeatedFromJsonSuccessTest : public ::testing::TestWithParam<RepeatedFromJsonSuccessTestParam> {};
44class RepeatedFromJsonFailureTest : public ::testing::TestWithParam<RepeatedFromJsonFailureTestParam> {};
45
46INSTANTIATE_TEST_SUITE_P(
47 ,
48 RepeatedFromJsonSuccessTest,
49 ::testing::Values(
50 RepeatedFromJsonSuccessTestParam{R"({})", RepeatedMessageData{}},
51 RepeatedFromJsonSuccessTestParam{
52 R"({
53 "field1":[],"field2":[],"field3":[],"field4":[],"field5":[],"field6":[],"field7":[],
54 "field8":[],"field9":[],"field10":[],"field11":[],"field12":[]
55 })",
56 RepeatedMessageData{}
57 },
58 RepeatedFromJsonSuccessTestParam{
59 R"({
60 "field1":null,"field2":null,"field3":null,"field5":null,"field6":null,"field7":null,"field8":null,
61 "field9":null,"field10":null,"field11":null,"field12":null
62 })",// can't use "field4:null" because native legacy parser treats this as a single item array
63 RepeatedMessageData{}
64 },
65 RepeatedFromJsonSuccessTestParam{
66 R"({
67 "field1":[100],
68 "field2":[{"field1":true}],
69 "field3":["123.987s"],
70 "field4":[null],
71 "field5":[1],
72 "field6":["-1"],
73 "field7":["1"],
74 "field8":["-1.5"],
75 "field9":[1.5],
76 "field10":[false],
77 "field11":["hello"],
78 "field12":["TEST_VALUE1"]
79 })",
80 RepeatedMessageData{
81 {100},
82 {{true}},
83 {{.seconds = 123, .nanos = 987'000'000}},
84 {ProtoValue{ProtoNullValue{}}},
85 {1},
86 {-1},
87 {1},
88 {-1.5},
89 {1.5},
90 {false},
91 {"hello"},
92 {proto_json::messages::RepeatedMessage::TEST_VALUE1}
93 }
94 },
95 RepeatedFromJsonSuccessTestParam{
96 R"({
97 "field1":[100,0,200],
98 "field2":[{"field1":true},{"field1":false}],
99 "field3":["123.987s","0s","-987s"]
100 })",
101 RepeatedMessageData{
102 {100, 0, 200},
103 {{true}, {false}},
104 {{.seconds = 123, .nanos = 987'000'000}, {}, {.seconds = -987}}
105 }
106 }
107 )
108);
109
110INSTANTIATE_TEST_SUITE_P(
111 ,
112 RepeatedFromJsonFailureTest,
113 ::testing::Values(
114 RepeatedFromJsonFailureTestParam{R"({"field1":{}})", ParseErrorCode::kInvalidType, "field1"},
115 RepeatedFromJsonFailureTestParam{
116 R"({"field1":1})",
117 ParseErrorCode::kInvalidType,
118 "field1",
119 {},
120 true // legacy implementation treats single value as array of one item
121 },
122 RepeatedFromJsonFailureTestParam{R"({"field2":true})", ParseErrorCode::kInvalidType, "field2", {}, true},
123 RepeatedFromJsonFailureTestParam{R"({"field3":"test"})", ParseErrorCode::kInvalidType, "field3", {}, true},
124 RepeatedFromJsonFailureTestParam{
125 R"({"field1":[1, null, 2]})",
126 ParseErrorCode::kInvalidValue,
127 "field1[1]",
128 {},
129 true // legacy implementation ignores null as items
130 },
131 RepeatedFromJsonFailureTestParam{R"({"field2":[null]})", ParseErrorCode::kInvalidValue, "field2[0]", {}, true},
132 RepeatedFromJsonFailureTestParam{
133 R"({"field3":["123.100s", "-123.100s", null]})",
134 ParseErrorCode::kInvalidValue,
135 "field3[2]",
136 {},
137 true // legacy implementation ignores null as items
138 },
139 RepeatedFromJsonFailureTestParam{
140 R"({"field1":[[1,2,3]]})",
141 ParseErrorCode::kInvalidType,
142 "field1[0]",
143 {},
144 true // legacy implementation flattens array in this case
145 },
146 RepeatedFromJsonFailureTestParam{
147 R"({"field2":[[{"field1":true}]]})",
148 ParseErrorCode::kInvalidType,
149 "field2[0]",
150 {},
151 true // legacy implementation flattens array in this case
152 },
153 RepeatedFromJsonFailureTestParam{
154 R"({"field2":[{"field1":true},"oops"]})",
155 ParseErrorCode::kInvalidType,
156 "field2[1]"
157 },
158 RepeatedFromJsonFailureTestParam{
159 R"({"field3":["123.100s", "oops"]})",
160 ParseErrorCode::kInvalidValue,
161 "field3[1]"
162 }
163 )
164);
165
166TEST_P(RepeatedFromJsonSuccessTest, Test) {
167 using Message = proto_json::messages::RepeatedMessage;
168 const auto& param = GetParam();
169
170 Message message;
171 Message expected_message;
172 Message sample_message;
173 formats::json::Value input = PrepareJsonTestData(param.input);
174 expected_message = PrepareTestData(param.expected_message);
175
176 UASSERT_NO_THROW((message = JsonToMessage<Message>(input, param.options)));
177 UASSERT_NO_THROW(InitSampleMessage(param.input, sample_message, param.options));
178
179 CheckMessageEqual(message, sample_message);
180 CheckMessageEqual(message, expected_message);
181}
182
183TEST_P(RepeatedFromJsonFailureTest, Test) {
184 using Message = proto_json::messages::RepeatedMessage;
185 const auto& param = GetParam();
186
187 Message sample;
188 formats::json::Value input = PrepareJsonTestData(param.input);
189
190 EXPECT_PARSE_ERROR((void)JsonToMessage<Message>(input, param.options), param.expected_errc, param.expected_path);
191
192 if (!param.skip_native_check) {
193 UEXPECT_THROW(InitSampleMessage(param.input, sample, param.options), SampleError);
194 }
195}
196
197} // namespace protobuf::json::tests
198
199USERVER_NAMESPACE_END