userver: /data/code/userver/libraries/protobuf/tests/json/map_from_json_test.cpp Source File
Loading...
Searching...
No Matches
map_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 MapFromJsonSuccessTestParam {
18 std::string input = {};
19 MapMessageData expected_message = {};
20 ParseOptions options = {};
21};
22
23struct MapFromJsonFailureTestParam {
24 std::string input = {};
25 ParseErrorCode expected_errc = {};
26 std::string expected_path = {};
27 ParseOptions options = {};
28
29 // This variable is used to disable some checks that fail in the native protobuf implementation.
30 bool skip_native_check = false;
31};
32
33void PrintTo(const MapFromJsonSuccessTestParam& param, std::ostream* os) {
34 *os << fmt::format("{{ input = '{}' }}", param.input);
35}
36
37void PrintTo(const MapFromJsonFailureTestParam& param, std::ostream* os) {
38 *os << fmt::format("{{ input = '{}' }}", param.input);
39}
40
41class MapFromJsonSuccessTest : public ::testing::TestWithParam<MapFromJsonSuccessTestParam> {};
42class MapFromJsonFailureTest : public ::testing::TestWithParam<MapFromJsonFailureTestParam> {};
43
44INSTANTIATE_TEST_SUITE_P(
45 ,
46 MapFromJsonSuccessTest,
47 ::testing::Values(
48 MapFromJsonSuccessTestParam{R"({})", MapMessageData{}},
49 MapFromJsonSuccessTestParam{
50 R"({"field1":{},"field2":{},"field3":{},"field4":{},"field5":{},"field6":{},"field7":{}})",
51 MapMessageData{}
52 },
53 MapFromJsonSuccessTestParam{
54 R"({
55 "field1":{"1":2,"3":4,"5":6},
56 "field2":{"10":1.5,"20":1.5},
57 "field3":{"100":true,"200":false},
58 "field4":{"1000":"hello","2000":"world"},
59 "field5":{"true":"TEST_ENUM_VALUE1","false":"TEST_ENUM_VALUE0"},
60 "field6":{"aaa":{"field1":true},"bbb":{}},
61 "field7":{"ccc":"10.000000999s"}
62 })",
63 MapMessageData{
64 .field1 = {{1, 2}, {3, 4}, {5, 6}},
65 .field2 = {{10, 1.5}, {20, 1.5}},
66 .field3 = {{100, true}, {200, false}},
67 .field4 = {{1000, "hello"}, {2000, "world"}},
68 .field5 =
69 {{true, proto_json::messages::MapMessage::TEST_ENUM_VALUE1},
70 {false, proto_json::messages::MapMessage::TEST_ENUM_VALUE0}},
71 .field6 = {{"aaa", {true}}, {"bbb", {false}}},
72 .field7 = {{"ccc", {.seconds = 10, .nanos = 999}}}
73 }
74 },
75 MapFromJsonSuccessTestParam{
76 R"({"field5":{"true":0,"false":1}})",
77 MapMessageData{
78 .field5 =
79 {{true, proto_json::messages::MapMessage::TEST_ENUM_VALUE0},
80 {false, proto_json::messages::MapMessage::TEST_ENUM_VALUE1}}
81 }
82 }
83 )
84);
85
86INSTANTIATE_TEST_SUITE_P(
87 ,
88 MapFromJsonFailureTest,
89 ::testing::Values(
90 MapFromJsonFailureTestParam{R"({"field1":[]})", ParseErrorCode::kInvalidType, "field1"},
91 MapFromJsonFailureTestParam{R"({"field2":1})", ParseErrorCode::kInvalidType, "field2"},
92 MapFromJsonFailureTestParam{R"({"field3":true})", ParseErrorCode::kInvalidType, "field3"},
93 MapFromJsonFailureTestParam{R"({"field7":"test"})", ParseErrorCode::kInvalidType, "field7"},
94 MapFromJsonFailureTestParam{R"({"field1":{"":1}})", ParseErrorCode::kInvalidValue, "field1.''"},
95 MapFromJsonFailureTestParam{
96 R"({"field2":{"10":1.5,"-10":0,"0":0}})",
98 "field2.-10"
99 },
100 MapFromJsonFailureTestParam{
101 R"({"field3":{"10":true,"10x":false}})",
103 "field3.10x"
104 },
105 MapFromJsonFailureTestParam{R"({"field4":{"1.5":"hello"}})", ParseErrorCode::kInvalidValue, "field4.'1.5'"},
106 MapFromJsonFailureTestParam{
107 R"({"field5":{"TRUE":0}})",
109 "field5.TRUE",
110 {},
111 // Old protobuf versions use case-insensitive comparison for bool value.
112 !kIsModernProtoJson
113 },
114 MapFromJsonFailureTestParam{R"({"field7":{"aaa":"oops"}})", ParseErrorCode::kInvalidValue, "field7.aaa"}
115 )
116);
117
118TEST_P(MapFromJsonSuccessTest, Test) {
119 using Message = proto_json::messages::MapMessage;
120 const auto& param = GetParam();
121
122 Message message;
123 Message expected_message;
124 Message sample_message;
125 formats::json::Value input = PrepareJsonTestData(param.input);
126 expected_message = PrepareTestData(param.expected_message);
127
128 UASSERT_NO_THROW((message = JsonToMessage<Message>(input, param.options)));
129 UASSERT_NO_THROW(InitSampleMessage(param.input, sample_message, param.options));
130
131 CheckMessageEqual(message, sample_message);
132 CheckMessageEqual(message, expected_message);
133}
134
135TEST_P(MapFromJsonFailureTest, Test) {
136 using Message = proto_json::messages::MapMessage;
137 const auto& param = GetParam();
138
139 Message sample;
140 formats::json::Value input = PrepareJsonTestData(param.input);
141
142 EXPECT_PARSE_ERROR((void)JsonToMessage<Message>(input, param.options), param.expected_errc, param.expected_path);
143
144 if (!param.skip_native_check) {
145 UEXPECT_THROW(InitSampleMessage(param.input, sample, param.options), SampleError);
146 }
147}
148
149} // namespace protobuf::json::tests
150
151USERVER_NAMESPACE_END