• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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