1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 #include <google/protobuf/util/json_util.h>
32
33 #include <list>
34 #include <string>
35
36 #include <google/protobuf/io/zero_copy_stream.h>
37 #include <google/protobuf/descriptor_database.h>
38 #include <google/protobuf/dynamic_message.h>
39 #include <google/protobuf/util/json_format_proto3.pb.h>
40 #include <google/protobuf/util/type_resolver.h>
41 #include <google/protobuf/util/type_resolver_util.h>
42 #include <gtest/gtest.h>
43
44 namespace google {
45 namespace protobuf {
46 namespace util {
47 namespace {
48
49 using proto3::FOO;
50 using proto3::BAR;
51 using proto3::TestMessage;
52 using proto3::TestMap;
53
54 static const char kTypeUrlPrefix[] = "type.googleapis.com";
55
GetTypeUrl(const Descriptor * message)56 static string GetTypeUrl(const Descriptor* message) {
57 return string(kTypeUrlPrefix) + "/" + message->full_name();
58 }
59
60 // As functions defined in json_util.h are just thin wrappers around the
61 // JSON conversion code in //net/proto2/util/converter, in this test we
62 // only cover some very basic cases to make sure the wrappers have forwarded
63 // parameters to the underlying implementation correctly. More detailed
64 // tests are contained in the //net/proto2/util/converter directory.
65 class JsonUtilTest : public testing::Test {
66 protected:
JsonUtilTest()67 JsonUtilTest() {
68 }
69
ToJson(const Message & message,const JsonPrintOptions & options)70 string ToJson(const Message& message, const JsonPrintOptions& options) {
71 string result;
72 GOOGLE_CHECK_OK(MessageToJsonString(message, &result, options));
73 return result;
74 }
75
FromJson(const string & json,Message * message,const JsonParseOptions & options)76 bool FromJson(const string& json, Message* message,
77 const JsonParseOptions& options) {
78 return JsonStringToMessage(json, message, options).ok();
79 }
80
FromJson(const string & json,Message * message)81 bool FromJson(const string& json, Message* message) {
82 return FromJson(json, message, JsonParseOptions());
83 }
84
85 google::protobuf::scoped_ptr<TypeResolver> resolver_;
86 };
87
TEST_F(JsonUtilTest,TestWhitespaces)88 TEST_F(JsonUtilTest, TestWhitespaces) {
89 TestMessage m;
90 m.mutable_message_value();
91
92 JsonPrintOptions options;
93 EXPECT_EQ("{\"messageValue\":{}}", ToJson(m, options));
94 options.add_whitespace = true;
95 EXPECT_EQ(
96 "{\n"
97 " \"messageValue\": {}\n"
98 "}\n",
99 ToJson(m, options));
100 }
101
TEST_F(JsonUtilTest,TestDefaultValues)102 TEST_F(JsonUtilTest, TestDefaultValues) {
103 TestMessage m;
104 JsonPrintOptions options;
105 EXPECT_EQ("{}", ToJson(m, options));
106 options.always_print_primitive_fields = true;
107 EXPECT_EQ(
108 "{\"boolValue\":false,"
109 "\"int32Value\":0,"
110 "\"int64Value\":\"0\","
111 "\"uint32Value\":0,"
112 "\"uint64Value\":\"0\","
113 "\"floatValue\":0,"
114 "\"doubleValue\":0,"
115 "\"stringValue\":\"\","
116 "\"bytesValue\":\"\","
117 "\"enumValue\":\"FOO\","
118 "\"repeatedBoolValue\":[],"
119 "\"repeatedInt32Value\":[],"
120 "\"repeatedInt64Value\":[],"
121 "\"repeatedUint32Value\":[],"
122 "\"repeatedUint64Value\":[],"
123 "\"repeatedFloatValue\":[],"
124 "\"repeatedDoubleValue\":[],"
125 "\"repeatedStringValue\":[],"
126 "\"repeatedBytesValue\":[],"
127 "\"repeatedEnumValue\":[],"
128 "\"repeatedMessageValue\":[]"
129 "}",
130 ToJson(m, options));
131 }
132
TEST_F(JsonUtilTest,ParseMessage)133 TEST_F(JsonUtilTest, ParseMessage) {
134 // Some random message but good enough to verify that the parsing warpper
135 // functions are working properly.
136 string input =
137 "{\n"
138 " \"int32Value\": 1024,\n"
139 " \"repeatedInt32Value\": [1, 2],\n"
140 " \"messageValue\": {\n"
141 " \"value\": 2048\n"
142 " },\n"
143 " \"repeatedMessageValue\": [\n"
144 " {\"value\": 40}, {\"value\": 96}\n"
145 " ]\n"
146 "}\n";
147 JsonParseOptions options;
148 TestMessage m;
149 ASSERT_TRUE(FromJson(input, &m, options));
150 EXPECT_EQ(1024, m.int32_value());
151 ASSERT_EQ(2, m.repeated_int32_value_size());
152 EXPECT_EQ(1, m.repeated_int32_value(0));
153 EXPECT_EQ(2, m.repeated_int32_value(1));
154 EXPECT_EQ(2048, m.message_value().value());
155 ASSERT_EQ(2, m.repeated_message_value_size());
156 EXPECT_EQ(40, m.repeated_message_value(0).value());
157 EXPECT_EQ(96, m.repeated_message_value(1).value());
158 }
159
TEST_F(JsonUtilTest,ParseMap)160 TEST_F(JsonUtilTest, ParseMap) {
161 TestMap message;
162 (*message.mutable_string_map())["hello"] = 1234;
163 JsonPrintOptions print_options;
164 JsonParseOptions parse_options;
165 EXPECT_EQ("{\"stringMap\":{\"hello\":1234}}", ToJson(message, print_options));
166 TestMap other;
167 ASSERT_TRUE(FromJson(ToJson(message, print_options), &other, parse_options));
168 EXPECT_EQ(message.DebugString(), other.DebugString());
169 }
170
TEST_F(JsonUtilTest,TestParseIgnoreUnknownFields)171 TEST_F(JsonUtilTest, TestParseIgnoreUnknownFields) {
172 TestMessage m;
173 JsonParseOptions options;
174 options.ignore_unknown_fields = true;
175 EXPECT_TRUE(FromJson("{\"unknownName\":0}", &m, options));
176 }
177
TEST_F(JsonUtilTest,TestParseErrors)178 TEST_F(JsonUtilTest, TestParseErrors) {
179 TestMessage m;
180 JsonParseOptions options;
181 // Parsing should fail if the field name can not be recognized.
182 EXPECT_FALSE(FromJson("{\"unknownName\":0}", &m, options));
183 // Parsing should fail if the value is invalid.
184 EXPECT_FALSE(FromJson("{\"int32Value\":2147483648}", &m, options));
185 }
186
TEST_F(JsonUtilTest,TestDynamicMessage)187 TEST_F(JsonUtilTest, TestDynamicMessage) {
188 // Some random message but good enough to test the wrapper functions.
189 string input =
190 "{\n"
191 " \"int32Value\": 1024,\n"
192 " \"repeatedInt32Value\": [1, 2],\n"
193 " \"messageValue\": {\n"
194 " \"value\": 2048\n"
195 " },\n"
196 " \"repeatedMessageValue\": [\n"
197 " {\"value\": 40}, {\"value\": 96}\n"
198 " ]\n"
199 "}\n";
200
201 // Create a new DescriptorPool with the same protos as the generated one.
202 DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
203 DescriptorPool pool(&database);
204 // A dynamic version of the test proto.
205 DynamicMessageFactory factory;
206 google::protobuf::scoped_ptr<Message> message(factory.GetPrototype(
207 pool.FindMessageTypeByName("proto3.TestMessage"))->New());
208 EXPECT_TRUE(FromJson(input, message.get()));
209
210 // Convert to generated message for easy inspection.
211 TestMessage generated;
212 EXPECT_TRUE(generated.ParseFromString(message->SerializeAsString()));
213 EXPECT_EQ(1024, generated.int32_value());
214 ASSERT_EQ(2, generated.repeated_int32_value_size());
215 EXPECT_EQ(1, generated.repeated_int32_value(0));
216 EXPECT_EQ(2, generated.repeated_int32_value(1));
217 EXPECT_EQ(2048, generated.message_value().value());
218 ASSERT_EQ(2, generated.repeated_message_value_size());
219 EXPECT_EQ(40, generated.repeated_message_value(0).value());
220 EXPECT_EQ(96, generated.repeated_message_value(1).value());
221
222 JsonOptions options;
223 EXPECT_EQ(ToJson(generated, options), ToJson(*message, options));
224 }
225
226 typedef pair<char*, int> Segment;
227 // A ZeroCopyOutputStream that writes to multiple buffers.
228 class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
229 public:
SegmentedZeroCopyOutputStream(list<Segment> segments)230 explicit SegmentedZeroCopyOutputStream(list<Segment> segments)
231 : segments_(segments), last_segment_(static_cast<char*>(NULL), 0), byte_count_(0) {}
232
Next(void ** buffer,int * length)233 virtual bool Next(void** buffer, int* length) {
234 if (segments_.empty()) {
235 return false;
236 }
237 last_segment_ = segments_.front();
238 segments_.pop_front();
239 *buffer = last_segment_.first;
240 *length = last_segment_.second;
241 byte_count_ += *length;
242 return true;
243 }
244
BackUp(int length)245 virtual void BackUp(int length) {
246 GOOGLE_CHECK(length <= last_segment_.second);
247 segments_.push_front(
248 Segment(last_segment_.first + last_segment_.second - length, length));
249 last_segment_ = Segment(last_segment_.first, last_segment_.second - length);
250 byte_count_ -= length;
251 }
252
ByteCount() const253 virtual int64 ByteCount() const { return byte_count_; }
254
255 private:
256 list<Segment> segments_;
257 Segment last_segment_;
258 int64 byte_count_;
259 };
260
261 // This test splits the output buffer and also the input data into multiple
262 // segments and checks that the implementation of ZeroCopyStreamByteSink
263 // handles all possible cases correctly.
TEST(ZeroCopyStreamByteSinkTest,TestAllInputOutputPatterns)264 TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) {
265 static const int kOutputBufferLength = 10;
266 // An exhaustive test takes too long, skip some combinations to make the test
267 // run faster.
268 static const int kSkippedPatternCount = 7;
269
270 char buffer[kOutputBufferLength];
271 for (int split_pattern = 0; split_pattern < (1 << (kOutputBufferLength - 1));
272 split_pattern += kSkippedPatternCount) {
273 // Split the buffer into small segments according to the split_pattern.
274 list<Segment> segments;
275 int segment_start = 0;
276 for (int i = 0; i < kOutputBufferLength - 1; ++i) {
277 if (split_pattern & (1 << i)) {
278 segments.push_back(
279 Segment(buffer + segment_start, i - segment_start + 1));
280 segment_start = i + 1;
281 }
282 }
283 segments.push_back(
284 Segment(buffer + segment_start, kOutputBufferLength - segment_start));
285
286 // Write exactly 10 bytes through the ByteSink.
287 string input_data = "0123456789";
288 for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
289 input_pattern += kSkippedPatternCount) {
290 memset(buffer, 0, sizeof(buffer));
291 {
292 SegmentedZeroCopyOutputStream output_stream(segments);
293 internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
294 int start = 0;
295 for (int j = 0; j < input_data.length() - 1; ++j) {
296 if (input_pattern & (1 << j)) {
297 byte_sink.Append(&input_data[start], j - start + 1);
298 start = j + 1;
299 }
300 }
301 byte_sink.Append(&input_data[start], input_data.length() - start);
302 }
303 EXPECT_EQ(input_data, string(buffer, input_data.length()));
304 }
305
306 // Write only 9 bytes through the ByteSink.
307 input_data = "012345678";
308 for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
309 input_pattern += kSkippedPatternCount) {
310 memset(buffer, 0, sizeof(buffer));
311 {
312 SegmentedZeroCopyOutputStream output_stream(segments);
313 internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
314 int start = 0;
315 for (int j = 0; j < input_data.length() - 1; ++j) {
316 if (input_pattern & (1 << j)) {
317 byte_sink.Append(&input_data[start], j - start + 1);
318 start = j + 1;
319 }
320 }
321 byte_sink.Append(&input_data[start], input_data.length() - start);
322 }
323 EXPECT_EQ(input_data, string(buffer, input_data.length()));
324 EXPECT_EQ(0, buffer[input_data.length()]);
325 }
326
327 // Write 11 bytes through the ByteSink. The extra byte will just
328 // be ignored.
329 input_data = "0123456789A";
330 for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
331 input_pattern += kSkippedPatternCount) {
332 memset(buffer, 0, sizeof(buffer));
333 {
334 SegmentedZeroCopyOutputStream output_stream(segments);
335 internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
336 int start = 0;
337 for (int j = 0; j < input_data.length() - 1; ++j) {
338 if (input_pattern & (1 << j)) {
339 byte_sink.Append(&input_data[start], j - start + 1);
340 start = j + 1;
341 }
342 }
343 byte_sink.Append(&input_data[start], input_data.length() - start);
344 }
345 EXPECT_EQ(input_data.substr(0, kOutputBufferLength),
346 string(buffer, kOutputBufferLength));
347 }
348 }
349 }
350
351 } // namespace
352 } // namespace util
353 } // namespace protobuf
354 } // namespace google
355