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/io/zero_copy_stream_impl.h>
38 #include <google/protobuf/descriptor_database.h>
39 #include <google/protobuf/dynamic_message.h>
40 #include <google/protobuf/util/internal/testdata/maps.pb.h>
41 #include <google/protobuf/util/json_format.pb.h>
42 #include <google/protobuf/util/json_format_proto3.pb.h>
43 #include <google/protobuf/util/type_resolver.h>
44 #include <google/protobuf/util/type_resolver_util.h>
45 #include <gtest/gtest.h>
46
47 namespace google {
48 namespace protobuf {
49 namespace util {
50 namespace {
51
52 using proto3::BAR;
53 using proto3::FOO;
54 using proto3::TestAny;
55 using proto3::TestEnumValue;
56 using proto3::TestMap;
57 using proto3::TestMessage;
58 using proto3::TestOneof;
59 using proto_util_converter::testing::MapIn;
60
61 // As functions defined in json_util.h are just thin wrappers around the
62 // JSON conversion code in //net/proto2/util/converter, in this test we
63 // only cover some very basic cases to make sure the wrappers have forwarded
64 // parameters to the underlying implementation correctly. More detailed
65 // tests are contained in the //net/proto2/util/converter directory.
66 class JsonUtilTest : public ::testing::Test {
67 protected:
JsonUtilTest()68 JsonUtilTest() {}
69
ToJson(const Message & message,const JsonPrintOptions & options)70 std::string ToJson(const Message& message, const JsonPrintOptions& options) {
71 std::string result;
72 GOOGLE_CHECK_OK(MessageToJsonString(message, &result, options));
73 return result;
74 }
75
FromJson(const std::string & json,Message * message,const JsonParseOptions & options)76 bool FromJson(const std::string& json, Message* message,
77 const JsonParseOptions& options) {
78 return JsonStringToMessage(json, message, options).ok();
79 }
80
FromJson(const std::string & json,Message * message)81 bool FromJson(const std::string& json, Message* message) {
82 return FromJson(json, message, JsonParseOptions());
83 }
84
85 std::unique_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 options.always_print_primitive_fields = true;
133 m.set_string_value("i am a test string value");
134 m.set_bytes_value("i am a test bytes value");
135 EXPECT_EQ(
136 "{\"boolValue\":false,"
137 "\"int32Value\":0,"
138 "\"int64Value\":\"0\","
139 "\"uint32Value\":0,"
140 "\"uint64Value\":\"0\","
141 "\"floatValue\":0,"
142 "\"doubleValue\":0,"
143 "\"stringValue\":\"i am a test string value\","
144 "\"bytesValue\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
145 "\"enumValue\":\"FOO\","
146 "\"repeatedBoolValue\":[],"
147 "\"repeatedInt32Value\":[],"
148 "\"repeatedInt64Value\":[],"
149 "\"repeatedUint32Value\":[],"
150 "\"repeatedUint64Value\":[],"
151 "\"repeatedFloatValue\":[],"
152 "\"repeatedDoubleValue\":[],"
153 "\"repeatedStringValue\":[],"
154 "\"repeatedBytesValue\":[],"
155 "\"repeatedEnumValue\":[],"
156 "\"repeatedMessageValue\":[]"
157 "}",
158 ToJson(m, options));
159
160 options.preserve_proto_field_names = true;
161 m.set_string_value("i am a test string value");
162 m.set_bytes_value("i am a test bytes value");
163 EXPECT_EQ(
164 "{\"bool_value\":false,"
165 "\"int32_value\":0,"
166 "\"int64_value\":\"0\","
167 "\"uint32_value\":0,"
168 "\"uint64_value\":\"0\","
169 "\"float_value\":0,"
170 "\"double_value\":0,"
171 "\"string_value\":\"i am a test string value\","
172 "\"bytes_value\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
173 "\"enum_value\":\"FOO\","
174 "\"repeated_bool_value\":[],"
175 "\"repeated_int32_value\":[],"
176 "\"repeated_int64_value\":[],"
177 "\"repeated_uint32_value\":[],"
178 "\"repeated_uint64_value\":[],"
179 "\"repeated_float_value\":[],"
180 "\"repeated_double_value\":[],"
181 "\"repeated_string_value\":[],"
182 "\"repeated_bytes_value\":[],"
183 "\"repeated_enum_value\":[],"
184 "\"repeated_message_value\":[]"
185 "}",
186 ToJson(m, options));
187 }
188
TEST_F(JsonUtilTest,TestPreserveProtoFieldNames)189 TEST_F(JsonUtilTest, TestPreserveProtoFieldNames) {
190 TestMessage m;
191 m.mutable_message_value();
192
193 JsonPrintOptions options;
194 options.preserve_proto_field_names = true;
195 EXPECT_EQ("{\"message_value\":{}}", ToJson(m, options));
196 }
197
TEST_F(JsonUtilTest,TestAlwaysPrintEnumsAsInts)198 TEST_F(JsonUtilTest, TestAlwaysPrintEnumsAsInts) {
199 TestMessage orig;
200 orig.set_enum_value(proto3::BAR);
201 orig.add_repeated_enum_value(proto3::FOO);
202 orig.add_repeated_enum_value(proto3::BAR);
203
204 JsonPrintOptions print_options;
205 print_options.always_print_enums_as_ints = true;
206
207 std::string expected_json = "{\"enumValue\":1,\"repeatedEnumValue\":[0,1]}";
208 EXPECT_EQ(expected_json, ToJson(orig, print_options));
209
210 TestMessage parsed;
211 JsonParseOptions parse_options;
212 ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
213
214 EXPECT_EQ(proto3::BAR, parsed.enum_value());
215 EXPECT_EQ(2, parsed.repeated_enum_value_size());
216 EXPECT_EQ(proto3::FOO, parsed.repeated_enum_value(0));
217 EXPECT_EQ(proto3::BAR, parsed.repeated_enum_value(1));
218 }
219
TEST_F(JsonUtilTest,TestPrintEnumsAsIntsWithDefaultValue)220 TEST_F(JsonUtilTest, TestPrintEnumsAsIntsWithDefaultValue) {
221 TestEnumValue orig;
222 // orig.set_enum_value1(proto3::FOO)
223 orig.set_enum_value2(proto3::FOO);
224 orig.set_enum_value3(proto3::BAR);
225
226 JsonPrintOptions print_options;
227 print_options.always_print_enums_as_ints = true;
228 print_options.always_print_primitive_fields = true;
229
230 std::string expected_json =
231 "{\"enumValue1\":0,\"enumValue2\":0,\"enumValue3\":1}";
232 EXPECT_EQ(expected_json, ToJson(orig, print_options));
233
234 TestEnumValue parsed;
235 JsonParseOptions parse_options;
236 ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
237
238 EXPECT_EQ(proto3::FOO, parsed.enum_value1());
239 EXPECT_EQ(proto3::FOO, parsed.enum_value2());
240 EXPECT_EQ(proto3::BAR, parsed.enum_value3());
241 }
242
TEST_F(JsonUtilTest,ParseMessage)243 TEST_F(JsonUtilTest, ParseMessage) {
244 // Some random message but good enough to verify that the parsing warpper
245 // functions are working properly.
246 std::string input =
247 "{\n"
248 " \"int32Value\": 1024,\n"
249 " \"repeatedInt32Value\": [1, 2],\n"
250 " \"messageValue\": {\n"
251 " \"value\": 2048\n"
252 " },\n"
253 " \"repeatedMessageValue\": [\n"
254 " {\"value\": 40}, {\"value\": 96}\n"
255 " ]\n"
256 "}\n";
257 JsonParseOptions options;
258 TestMessage m;
259 ASSERT_TRUE(FromJson(input, &m, options));
260 EXPECT_EQ(1024, m.int32_value());
261 ASSERT_EQ(2, m.repeated_int32_value_size());
262 EXPECT_EQ(1, m.repeated_int32_value(0));
263 EXPECT_EQ(2, m.repeated_int32_value(1));
264 EXPECT_EQ(2048, m.message_value().value());
265 ASSERT_EQ(2, m.repeated_message_value_size());
266 EXPECT_EQ(40, m.repeated_message_value(0).value());
267 EXPECT_EQ(96, m.repeated_message_value(1).value());
268 }
269
TEST_F(JsonUtilTest,ParseMap)270 TEST_F(JsonUtilTest, ParseMap) {
271 TestMap message;
272 (*message.mutable_string_map())["hello"] = 1234;
273 JsonPrintOptions print_options;
274 JsonParseOptions parse_options;
275 EXPECT_EQ("{\"stringMap\":{\"hello\":1234}}", ToJson(message, print_options));
276 TestMap other;
277 ASSERT_TRUE(FromJson(ToJson(message, print_options), &other, parse_options));
278 EXPECT_EQ(message.DebugString(), other.DebugString());
279 }
280
TEST_F(JsonUtilTest,ParsePrimitiveMapIn)281 TEST_F(JsonUtilTest, ParsePrimitiveMapIn) {
282 MapIn message;
283 JsonPrintOptions print_options;
284 print_options.always_print_primitive_fields = true;
285 JsonParseOptions parse_options;
286 EXPECT_EQ("{\"other\":\"\",\"things\":[],\"mapInput\":{},\"mapAny\":{}}",
287 ToJson(message, print_options));
288 MapIn other;
289 ASSERT_TRUE(FromJson(ToJson(message, print_options), &other, parse_options));
290 EXPECT_EQ(message.DebugString(), other.DebugString());
291 }
292
TEST_F(JsonUtilTest,PrintPrimitiveOneof)293 TEST_F(JsonUtilTest, PrintPrimitiveOneof) {
294 TestOneof message;
295 JsonPrintOptions options;
296 options.always_print_primitive_fields = true;
297 message.mutable_oneof_message_value();
298 EXPECT_EQ("{\"oneofMessageValue\":{\"value\":0}}", ToJson(message, options));
299
300 message.set_oneof_int32_value(1);
301 EXPECT_EQ("{\"oneofInt32Value\":1}", ToJson(message, options));
302 }
303
TEST_F(JsonUtilTest,TestParseIgnoreUnknownFields)304 TEST_F(JsonUtilTest, TestParseIgnoreUnknownFields) {
305 TestMessage m;
306 JsonParseOptions options;
307 options.ignore_unknown_fields = true;
308 EXPECT_TRUE(FromJson("{\"unknownName\":0}", &m, options));
309 }
310
TEST_F(JsonUtilTest,TestParseErrors)311 TEST_F(JsonUtilTest, TestParseErrors) {
312 TestMessage m;
313 JsonParseOptions options;
314 // Parsing should fail if the field name can not be recognized.
315 EXPECT_FALSE(FromJson("{\"unknownName\":0}", &m, options));
316 // Parsing should fail if the value is invalid.
317 EXPECT_FALSE(FromJson("{\"int32Value\":2147483648}", &m, options));
318 }
319
TEST_F(JsonUtilTest,TestDynamicMessage)320 TEST_F(JsonUtilTest, TestDynamicMessage) {
321 // Some random message but good enough to test the wrapper functions.
322 std::string input =
323 "{\n"
324 " \"int32Value\": 1024,\n"
325 " \"repeatedInt32Value\": [1, 2],\n"
326 " \"messageValue\": {\n"
327 " \"value\": 2048\n"
328 " },\n"
329 " \"repeatedMessageValue\": [\n"
330 " {\"value\": 40}, {\"value\": 96}\n"
331 " ]\n"
332 "}\n";
333
334 // Create a new DescriptorPool with the same protos as the generated one.
335 DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
336 DescriptorPool pool(&database);
337 // A dynamic version of the test proto.
338 DynamicMessageFactory factory;
339 std::unique_ptr<Message> message(
340 factory.GetPrototype(pool.FindMessageTypeByName("proto3.TestMessage"))
341 ->New());
342 EXPECT_TRUE(FromJson(input, message.get()));
343
344 // Convert to generated message for easy inspection.
345 TestMessage generated;
346 EXPECT_TRUE(generated.ParseFromString(message->SerializeAsString()));
347 EXPECT_EQ(1024, generated.int32_value());
348 ASSERT_EQ(2, generated.repeated_int32_value_size());
349 EXPECT_EQ(1, generated.repeated_int32_value(0));
350 EXPECT_EQ(2, generated.repeated_int32_value(1));
351 EXPECT_EQ(2048, generated.message_value().value());
352 ASSERT_EQ(2, generated.repeated_message_value_size());
353 EXPECT_EQ(40, generated.repeated_message_value(0).value());
354 EXPECT_EQ(96, generated.repeated_message_value(1).value());
355
356 JsonOptions options;
357 EXPECT_EQ(ToJson(generated, options), ToJson(*message, options));
358 }
359
TEST_F(JsonUtilTest,TestParsingUnknownAnyFields)360 TEST_F(JsonUtilTest, TestParsingUnknownAnyFields) {
361 std::string input =
362 "{\n"
363 " \"value\": {\n"
364 " \"@type\": \"type.googleapis.com/proto3.TestMessage\",\n"
365 " \"unknown_field\": \"UNKNOWN_VALUE\",\n"
366 " \"string_value\": \"expected_value\"\n"
367 " }\n"
368 "}";
369
370 TestAny m;
371 JsonParseOptions options;
372 EXPECT_FALSE(FromJson(input, &m, options));
373
374 options.ignore_unknown_fields = true;
375 EXPECT_TRUE(FromJson(input, &m, options));
376
377 TestMessage t;
378 EXPECT_TRUE(m.value().UnpackTo(&t));
379 EXPECT_EQ("expected_value", t.string_value());
380 }
381
TEST_F(JsonUtilTest,TestParsingUnknownEnumsProto2)382 TEST_F(JsonUtilTest, TestParsingUnknownEnumsProto2) {
383 std::string input =
384 "{\n"
385 " \"a\": \"UNKNOWN_VALUE\"\n"
386 "}";
387 protobuf_unittest::TestNumbers m;
388 JsonParseOptions options;
389 EXPECT_FALSE(FromJson(input, &m, options));
390
391 options.ignore_unknown_fields = true;
392 EXPECT_TRUE(FromJson(input, &m, options));
393 EXPECT_FALSE(m.has_a());
394 }
395
TEST_F(JsonUtilTest,TestParsingUnknownEnumsProto3)396 TEST_F(JsonUtilTest, TestParsingUnknownEnumsProto3) {
397 TestMessage m;
398 {
399 JsonParseOptions options;
400 ASSERT_FALSE(options.ignore_unknown_fields);
401 std::string input =
402 "{\n"
403 " \"enum_value\":\"UNKNOWN_VALUE\"\n"
404 "}";
405 m.set_enum_value(proto3::BAR);
406 EXPECT_FALSE(FromJson(input, &m, options));
407 ASSERT_EQ(proto3::BAR, m.enum_value()); // Keep previous value
408
409 options.ignore_unknown_fields = true;
410 EXPECT_TRUE(FromJson(input, &m, options));
411 EXPECT_EQ(0, m.enum_value()); // Unknown enum value must be decoded as 0
412 }
413 // Integer values are read as usual
414 {
415 JsonParseOptions options;
416 std::string input =
417 "{\n"
418 " \"enum_value\":12345\n"
419 "}";
420 m.set_enum_value(proto3::BAR);
421 EXPECT_TRUE(FromJson(input, &m, options));
422 ASSERT_EQ(12345, m.enum_value());
423
424 options.ignore_unknown_fields = true;
425 EXPECT_TRUE(FromJson(input, &m, options));
426 EXPECT_EQ(12345, m.enum_value());
427 }
428
429 // Trying to pass an object as an enum field value is always treated as an
430 // error
431 {
432 JsonParseOptions options;
433 std::string input =
434 "{\n"
435 " \"enum_value\":{}\n"
436 "}";
437 options.ignore_unknown_fields = true;
438 EXPECT_FALSE(FromJson(input, &m, options));
439 options.ignore_unknown_fields = false;
440 EXPECT_FALSE(FromJson(input, &m, options));
441 }
442 // Trying to pass an array as an enum field value is always treated as an
443 // error
444 {
445 JsonParseOptions options;
446 std::string input =
447 "{\n"
448 " \"enum_value\":[]\n"
449 "}";
450 EXPECT_FALSE(FromJson(input, &m, options));
451 options.ignore_unknown_fields = true;
452 EXPECT_FALSE(FromJson(input, &m, options));
453 }
454 }
455
TEST_F(JsonUtilTest,TestParsingEnumIgnoreCase)456 TEST_F(JsonUtilTest, TestParsingEnumIgnoreCase) {
457 TestMessage m;
458 {
459 JsonParseOptions options;
460 std::string input =
461 "{\n"
462 " \"enum_value\":\"bar\"\n"
463 "}";
464 m.set_enum_value(proto3::FOO);
465 EXPECT_FALSE(FromJson(input, &m, options));
466 // Default behavior is case-sensitive, so keep previous value.
467 ASSERT_EQ(proto3::FOO, m.enum_value());
468 }
469 {
470 JsonParseOptions options;
471 options.case_insensitive_enum_parsing = false;
472 std::string input =
473 "{\n"
474 " \"enum_value\":\"bar\"\n"
475 "}";
476 m.set_enum_value(proto3::FOO);
477 EXPECT_FALSE(FromJson(input, &m, options));
478 ASSERT_EQ(proto3::FOO, m.enum_value()); // Keep previous value
479 }
480 {
481 JsonParseOptions options;
482 options.case_insensitive_enum_parsing = true;
483 std::string input =
484 "{\n"
485 " \"enum_value\":\"bar\"\n"
486 "}";
487 m.set_enum_value(proto3::FOO);
488 EXPECT_TRUE(FromJson(input, &m, options));
489 ASSERT_EQ(proto3::BAR, m.enum_value());
490 }
491 }
492
493 typedef std::pair<char*, int> Segment;
494 // A ZeroCopyOutputStream that writes to multiple buffers.
495 class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
496 public:
SegmentedZeroCopyOutputStream(std::list<Segment> segments)497 explicit SegmentedZeroCopyOutputStream(std::list<Segment> segments)
498 : segments_(segments),
499 last_segment_(static_cast<char*>(NULL), 0),
500 byte_count_(0) {}
501
Next(void ** buffer,int * length)502 virtual bool Next(void** buffer, int* length) {
503 if (segments_.empty()) {
504 return false;
505 }
506 last_segment_ = segments_.front();
507 segments_.pop_front();
508 *buffer = last_segment_.first;
509 *length = last_segment_.second;
510 byte_count_ += *length;
511 return true;
512 }
513
BackUp(int length)514 virtual void BackUp(int length) {
515 GOOGLE_CHECK(length <= last_segment_.second);
516 segments_.push_front(
517 Segment(last_segment_.first + last_segment_.second - length, length));
518 last_segment_ = Segment(last_segment_.first, last_segment_.second - length);
519 byte_count_ -= length;
520 }
521
ByteCount() const522 virtual int64 ByteCount() const { return byte_count_; }
523
524 private:
525 std::list<Segment> segments_;
526 Segment last_segment_;
527 int64 byte_count_;
528 };
529
530 // This test splits the output buffer and also the input data into multiple
531 // segments and checks that the implementation of ZeroCopyStreamByteSink
532 // handles all possible cases correctly.
TEST(ZeroCopyStreamByteSinkTest,TestAllInputOutputPatterns)533 TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) {
534 static const int kOutputBufferLength = 10;
535 // An exhaustive test takes too long, skip some combinations to make the test
536 // run faster.
537 static const int kSkippedPatternCount = 7;
538
539 char buffer[kOutputBufferLength];
540 for (int split_pattern = 0; split_pattern < (1 << (kOutputBufferLength - 1));
541 split_pattern += kSkippedPatternCount) {
542 // Split the buffer into small segments according to the split_pattern.
543 std::list<Segment> segments;
544 int segment_start = 0;
545 for (int i = 0; i < kOutputBufferLength - 1; ++i) {
546 if (split_pattern & (1 << i)) {
547 segments.push_back(
548 Segment(buffer + segment_start, i - segment_start + 1));
549 segment_start = i + 1;
550 }
551 }
552 segments.push_back(
553 Segment(buffer + segment_start, kOutputBufferLength - segment_start));
554
555 // Write exactly 10 bytes through the ByteSink.
556 std::string input_data = "0123456789";
557 for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
558 input_pattern += kSkippedPatternCount) {
559 memset(buffer, 0, sizeof(buffer));
560 {
561 SegmentedZeroCopyOutputStream output_stream(segments);
562 internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
563 int start = 0;
564 for (int j = 0; j < input_data.length() - 1; ++j) {
565 if (input_pattern & (1 << j)) {
566 byte_sink.Append(&input_data[start], j - start + 1);
567 start = j + 1;
568 }
569 }
570 byte_sink.Append(&input_data[start], input_data.length() - start);
571 }
572 EXPECT_EQ(input_data, std::string(buffer, input_data.length()));
573 }
574
575 // Write only 9 bytes through the ByteSink.
576 input_data = "012345678";
577 for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
578 input_pattern += kSkippedPatternCount) {
579 memset(buffer, 0, sizeof(buffer));
580 {
581 SegmentedZeroCopyOutputStream output_stream(segments);
582 internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
583 int start = 0;
584 for (int j = 0; j < input_data.length() - 1; ++j) {
585 if (input_pattern & (1 << j)) {
586 byte_sink.Append(&input_data[start], j - start + 1);
587 start = j + 1;
588 }
589 }
590 byte_sink.Append(&input_data[start], input_data.length() - start);
591 }
592 EXPECT_EQ(input_data, std::string(buffer, input_data.length()));
593 EXPECT_EQ(0, buffer[input_data.length()]);
594 }
595
596 // Write 11 bytes through the ByteSink. The extra byte will just
597 // be ignored.
598 input_data = "0123456789A";
599 for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
600 input_pattern += kSkippedPatternCount) {
601 memset(buffer, 0, sizeof(buffer));
602 {
603 SegmentedZeroCopyOutputStream output_stream(segments);
604 internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
605 int start = 0;
606 for (int j = 0; j < input_data.length() - 1; ++j) {
607 if (input_pattern & (1 << j)) {
608 byte_sink.Append(&input_data[start], j - start + 1);
609 start = j + 1;
610 }
611 }
612 byte_sink.Append(&input_data[start], input_data.length() - start);
613 }
614 EXPECT_EQ(input_data.substr(0, kOutputBufferLength),
615 std::string(buffer, kOutputBufferLength));
616 }
617 }
618 }
619
TEST_F(JsonUtilTest,TestWrongJsonInput)620 TEST_F(JsonUtilTest, TestWrongJsonInput) {
621 const char json[] = "{\"unknown_field\":\"some_value\"}";
622 io::ArrayInputStream input_stream(json, strlen(json));
623 char proto_buffer[10000];
624 io::ArrayOutputStream output_stream(proto_buffer, sizeof(proto_buffer));
625 std::string message_type = "type.googleapis.com/proto3.TestMessage";
626 TypeResolver* resolver = NewTypeResolverForDescriptorPool(
627 "type.googleapis.com", DescriptorPool::generated_pool());
628
629 auto result_status = util::JsonToBinaryStream(resolver, message_type,
630 &input_stream, &output_stream);
631
632 delete resolver;
633
634 EXPECT_FALSE(result_status.ok());
635 EXPECT_EQ(result_status.code(),
636 util::error::INVALID_ARGUMENT);
637 }
638
TEST_F(JsonUtilTest,HtmlEscape)639 TEST_F(JsonUtilTest, HtmlEscape) {
640 TestMessage m;
641 m.set_string_value("</script>");
642 JsonPrintOptions options;
643 EXPECT_EQ("{\"stringValue\":\"\\u003c/script\\u003e\"}", ToJson(m, options));
644 }
645
646 } // namespace
647 } // namespace util
648 } // namespace protobuf
649 } // namespace google
650