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/internal/json_stream_parser.h>
32 
33 #include <google/protobuf/stubs/logging.h>
34 #include <google/protobuf/stubs/common.h>
35 #include <google/protobuf/stubs/time.h>
36 #include <google/protobuf/util/internal/expecting_objectwriter.h>
37 #include <google/protobuf/util/internal/object_writer.h>
38 #include <google/protobuf/stubs/strutil.h>
39 #include <gtest/gtest.h>
40 #include <google/protobuf/stubs/status.h>
41 
42 
43 namespace google {
44 namespace protobuf {
45 namespace util {
46 using util::Status;
47 namespace error {
48 using util::error::INVALID_ARGUMENT;
49 }  // namespace error
50 namespace converter {
51 
52 using util::Status;
53 
54 // Tests for the JSON Stream Parser. These tests are intended to be
55 // comprehensive and cover the following:
56 //
57 // Positive tests:
58 // - true, false, null
59 // - empty object or array.
60 // - negative and positive double and int, unsigned int
61 // - single and double quoted strings
62 // - string key, unquoted key, numeric key
63 // - array containing array, object, value
64 // - object containing array, object, value
65 // - unicode handling in strings
66 // - ascii escaping (\b, \f, \n, \r, \t, \v)
67 // - trailing commas
68 //
69 // Negative tests:
70 // - illegal literals
71 // - mismatched quotes failure on strings
72 // - unterminated string failure
73 // - unexpected end of string failure
74 // - mismatched object and array closing
75 // - Failure to close array or object
76 // - numbers too large
77 // - invalid unicode escapes.
78 // - invalid unicode sequences.
79 // - numbers as keys
80 //
81 // For each test we split the input string on every possible character to ensure
82 // the parser is able to handle arbitrarily split input for all cases. We also
83 // do a final test of the entire test case one character at a time.
84 class JsonStreamParserTest : public ::testing::Test {
85  protected:
JsonStreamParserTest()86   JsonStreamParserTest() : mock_(), ow_(&mock_) {}
~JsonStreamParserTest()87   virtual ~JsonStreamParserTest() {}
88 
RunTest(StringPiece json,int split,bool coerce_utf8=false)89   util::Status RunTest(StringPiece json, int split, bool coerce_utf8 = false) {
90     JsonStreamParser parser(&mock_);
91 
92     // Special case for split == length, test parsing one character at a time.
93     if (split == json.length()) {
94       GOOGLE_LOG(INFO) << "Testing split every char: " << json;
95       for (int i = 0; i < json.length(); ++i) {
96         StringPiece single = json.substr(i, 1);
97         util::Status result = parser.Parse(single);
98         if (!result.ok()) {
99           return result;
100         }
101       }
102       return parser.FinishParse();
103     }
104 
105     // Normal case, split at the split point and parse two substrings.
106     StringPiece first = json.substr(0, split);
107     StringPiece rest = json.substr(split);
108     GOOGLE_LOG(INFO) << "Testing split: " << first << "><" << rest;
109     util::Status result = parser.Parse(first);
110     if (result.ok()) {
111       result = parser.Parse(rest);
112       if (result.ok()) {
113         result = parser.FinishParse();
114       }
115     }
116     return result;
117   }
118 
DoTest(StringPiece json,int split,bool coerce_utf8=false)119   void DoTest(StringPiece json, int split, bool coerce_utf8 = false) {
120     util::Status result = RunTest(json, split, coerce_utf8);
121     if (!result.ok()) {
122       GOOGLE_LOG(WARNING) << result;
123     }
124     EXPECT_OK(result);
125   }
126 
DoErrorTest(StringPiece json,int split,StringPiece error_prefix,bool coerce_utf8=false)127   void DoErrorTest(StringPiece json, int split, StringPiece error_prefix,
128                    bool coerce_utf8 = false) {
129     util::Status result = RunTest(json, split, coerce_utf8);
130     EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code());
131     StringPiece error_message(result.error_message());
132     EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
133   }
134 
135 
136   MockObjectWriter mock_;
137   ExpectingObjectWriter ow_;
138 };
139 
140 
141 // Positive tests
142 
143 // - true, false, null
TEST_F(JsonStreamParserTest,SimpleTrue)144 TEST_F(JsonStreamParserTest, SimpleTrue) {
145   StringPiece str = "true";
146   for (int i = 0; i <= str.length(); ++i) {
147     ow_.RenderBool("", true);
148     DoTest(str, i);
149   }
150 }
151 
TEST_F(JsonStreamParserTest,SimpleFalse)152 TEST_F(JsonStreamParserTest, SimpleFalse) {
153   StringPiece str = "false";
154   for (int i = 0; i <= str.length(); ++i) {
155     ow_.RenderBool("", false);
156     DoTest(str, i);
157   }
158 }
159 
TEST_F(JsonStreamParserTest,SimpleNull)160 TEST_F(JsonStreamParserTest, SimpleNull) {
161   StringPiece str = "null";
162   for (int i = 0; i <= str.length(); ++i) {
163     ow_.RenderNull("");
164     DoTest(str, i);
165   }
166 }
167 
168 // - empty object and array.
TEST_F(JsonStreamParserTest,EmptyObject)169 TEST_F(JsonStreamParserTest, EmptyObject) {
170   StringPiece str = "{}";
171   for (int i = 0; i <= str.length(); ++i) {
172     ow_.StartObject("")->EndObject();
173     DoTest(str, i);
174   }
175 }
176 
TEST_F(JsonStreamParserTest,EmptyList)177 TEST_F(JsonStreamParserTest, EmptyList) {
178   StringPiece str = "[]";
179   for (int i = 0; i <= str.length(); ++i) {
180     ow_.StartList("")->EndList();
181     DoTest(str, i);
182   }
183 }
184 
185 // - negative and positive double and int, unsigned int
TEST_F(JsonStreamParserTest,SimpleDouble)186 TEST_F(JsonStreamParserTest, SimpleDouble) {
187   StringPiece str = "42.5";
188   for (int i = 0; i <= str.length(); ++i) {
189     ow_.RenderDouble("", 42.5);
190     DoTest(str, i);
191   }
192 }
193 
TEST_F(JsonStreamParserTest,ScientificDouble)194 TEST_F(JsonStreamParserTest, ScientificDouble) {
195   StringPiece str = "1.2345e-10";
196   for (int i = 0; i < str.length(); ++i) {
197     ow_.RenderDouble("", 1.2345e-10);
198     DoTest(str, i);
199   }
200 }
201 
TEST_F(JsonStreamParserTest,SimpleNegativeDouble)202 TEST_F(JsonStreamParserTest, SimpleNegativeDouble) {
203   StringPiece str = "-1045.235";
204   for (int i = 0; i <= str.length(); ++i) {
205     ow_.RenderDouble("", -1045.235);
206     DoTest(str, i);
207   }
208 }
209 
TEST_F(JsonStreamParserTest,SimpleInt)210 TEST_F(JsonStreamParserTest, SimpleInt) {
211   StringPiece str = "123456";
212   for (int i = 0; i <= str.length(); ++i) {
213     ow_.RenderUint64("", 123456);
214     DoTest(str, i);
215   }
216 }
217 
TEST_F(JsonStreamParserTest,SimpleNegativeInt)218 TEST_F(JsonStreamParserTest, SimpleNegativeInt) {
219   StringPiece str = "-79497823553162765";
220   for (int i = 0; i <= str.length(); ++i) {
221     ow_.RenderInt64("", -79497823553162765LL);
222     DoTest(str, i);
223   }
224 }
225 
TEST_F(JsonStreamParserTest,SimpleUnsignedInt)226 TEST_F(JsonStreamParserTest, SimpleUnsignedInt) {
227   StringPiece str = "11779497823553162765";
228   for (int i = 0; i <= str.length(); ++i) {
229     ow_.RenderUint64("", 11779497823553162765ULL);
230     DoTest(str, i);
231   }
232 }
233 
TEST_F(JsonStreamParserTest,OctalNumberIsInvalid)234 TEST_F(JsonStreamParserTest, OctalNumberIsInvalid) {
235   StringPiece str = "01234";
236   for (int i = 0; i <= str.length(); ++i) {
237     DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
238   }
239   str = "-01234";
240   for (int i = 0; i <= str.length(); ++i) {
241     DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
242   }
243 }
244 
TEST_F(JsonStreamParserTest,HexNumberIsInvalid)245 TEST_F(JsonStreamParserTest, HexNumberIsInvalid) {
246   StringPiece str = "0x1234";
247   for (int i = 0; i <= str.length(); ++i) {
248     DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
249   }
250   str = "-0x1234";
251   for (int i = 0; i <= str.length(); ++i) {
252     DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
253   }
254   str = "12x34";
255   for (int i = 0; i <= str.length(); ++i) {
256     DoErrorTest(str, i, "Unable to parse number.");
257   }
258 }
259 
260 // - single and double quoted strings
TEST_F(JsonStreamParserTest,EmptyDoubleQuotedString)261 TEST_F(JsonStreamParserTest, EmptyDoubleQuotedString) {
262   StringPiece str = "\"\"";
263   for (int i = 0; i <= str.length(); ++i) {
264     ow_.RenderString("", "");
265     DoTest(str, i);
266   }
267 }
268 
TEST_F(JsonStreamParserTest,EmptySingleQuotedString)269 TEST_F(JsonStreamParserTest, EmptySingleQuotedString) {
270   StringPiece str = "''";
271   for (int i = 0; i <= str.length(); ++i) {
272     ow_.RenderString("", "");
273     DoTest(str, i);
274   }
275 }
276 
TEST_F(JsonStreamParserTest,SimpleDoubleQuotedString)277 TEST_F(JsonStreamParserTest, SimpleDoubleQuotedString) {
278   StringPiece str = "\"Some String\"";
279   for (int i = 0; i <= str.length(); ++i) {
280     ow_.RenderString("", "Some String");
281     DoTest(str, i);
282   }
283 }
284 
TEST_F(JsonStreamParserTest,SimpleSingleQuotedString)285 TEST_F(JsonStreamParserTest, SimpleSingleQuotedString) {
286   StringPiece str = "'Another String'";
287   for (int i = 0; i <= str.length(); ++i) {
288     ow_.RenderString("", "Another String");
289     DoTest(str, i);
290   }
291 }
292 
293 // - string key, unquoted key, numeric key
TEST_F(JsonStreamParserTest,ObjectKeyTypes)294 TEST_F(JsonStreamParserTest, ObjectKeyTypes) {
295   StringPiece str =
296       "{'s': true, \"d\": false, key: null, snake_key: [], camelKey: {}}";
297   for (int i = 0; i <= str.length(); ++i) {
298     ow_.StartObject("")
299         ->RenderBool("s", true)
300         ->RenderBool("d", false)
301         ->RenderNull("key")
302         ->StartList("snake_key")
303         ->EndList()
304         ->StartObject("camelKey")
305         ->EndObject()
306         ->EndObject();
307     DoTest(str, i);
308   }
309 }
310 
311 // - array containing array, object, values (true, false, null, num, string)
TEST_F(JsonStreamParserTest,ArrayValues)312 TEST_F(JsonStreamParserTest, ArrayValues) {
313   StringPiece str =
314       "[true, false, null, 'a string', \"another string\", [22, -127, 45.3, "
315       "-1056.4, 11779497823553162765], {'key': true}]";
316   for (int i = 0; i <= str.length(); ++i) {
317     ow_.StartList("")
318         ->RenderBool("", true)
319         ->RenderBool("", false)
320         ->RenderNull("")
321         ->RenderString("", "a string")
322         ->RenderString("", "another string")
323         ->StartList("")
324         ->RenderUint64("", 22)
325         ->RenderInt64("", -127)
326         ->RenderDouble("", 45.3)
327         ->RenderDouble("", -1056.4)
328         ->RenderUint64("", 11779497823553162765ULL)
329         ->EndList()
330         ->StartObject("")
331         ->RenderBool("key", true)
332         ->EndObject()
333         ->EndList();
334     DoTest(str, i);
335   }
336 }
337 
338 // - object containing array, object, value (true, false, null, num, string)
TEST_F(JsonStreamParserTest,ObjectValues)339 TEST_F(JsonStreamParserTest, ObjectValues) {
340   StringPiece str =
341       "{t: true, f: false, n: null, s: 'a string', d: \"another string\", pi: "
342       "22, ni: -127, pd: 45.3, nd: -1056.4, pl: 11779497823553162765, l: [[]], "
343       "o: {'key': true}}";
344   for (int i = 0; i <= str.length(); ++i) {
345     ow_.StartObject("")
346         ->RenderBool("t", true)
347         ->RenderBool("f", false)
348         ->RenderNull("n")
349         ->RenderString("s", "a string")
350         ->RenderString("d", "another string")
351         ->RenderUint64("pi", 22)
352         ->RenderInt64("ni", -127)
353         ->RenderDouble("pd", 45.3)
354         ->RenderDouble("nd", -1056.4)
355         ->RenderUint64("pl", 11779497823553162765ULL)
356         ->StartList("l")
357         ->StartList("")
358         ->EndList()
359         ->EndList()
360         ->StartObject("o")
361         ->RenderBool("key", true)
362         ->EndObject()
363         ->EndObject();
364     DoTest(str, i);
365   }
366 }
367 
368 
TEST_F(JsonStreamParserTest,RejectNonUtf8WhenNotCoerced)369 TEST_F(JsonStreamParserTest, RejectNonUtf8WhenNotCoerced) {
370   StringPiece json = "{\"address\":\xFF\"חרושת 23, רעננה, ישראל\"}";
371   for (int i = 0; i <= json.length(); ++i) {
372     DoErrorTest(json, i, "Encountered non UTF-8 code points.");
373   }
374   json = "{\"address\": \"חרושת 23,\xFFרעננה, ישראל\"}";
375   for (int i = 0; i <= json.length(); ++i) {
376     DoErrorTest(json, i, "Encountered non UTF-8 code points.");
377   }
378   DoErrorTest("\xFF{}", 0, "Encountered non UTF-8 code points.");
379 }
380 
381 // - unicode handling in strings
TEST_F(JsonStreamParserTest,UnicodeEscaping)382 TEST_F(JsonStreamParserTest, UnicodeEscaping) {
383   StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]";
384   for (int i = 0; i <= str.length(); ++i) {
385     ow_.StartList("")
386         ->RenderString("", "\xD8\xB9\xD8\xB1\xD8\xA8\xD9\x89")
387         ->EndList();
388     DoTest(str, i);
389   }
390 }
391 
392 // - unicode UTF-16 surrogate pair handling in strings
TEST_F(JsonStreamParserTest,UnicodeSurrogatePairEscaping)393 TEST_F(JsonStreamParserTest, UnicodeSurrogatePairEscaping) {
394   StringPiece str =
395       "[\"\\u0bee\\ud800\\uddf1\\uD80C\\uDDA4\\uD83d\\udC1D\\uD83C\\uDF6F\"]";
396   for (int i = 0; i <= str.length(); ++i) {
397     ow_.StartList("")
398         ->RenderString("",
399                        "\xE0\xAF\xAE\xF0\x90\x87\xB1\xF0\x93\x86\xA4\xF0"
400                        "\x9F\x90\x9D\xF0\x9F\x8D\xAF")
401         ->EndList();
402     DoTest(str, i);
403   }
404 }
405 
406 
TEST_F(JsonStreamParserTest,UnicodeEscapingInvalidCodePointWhenNotCoerced)407 TEST_F(JsonStreamParserTest, UnicodeEscapingInvalidCodePointWhenNotCoerced) {
408   // A low surrogate alone.
409   StringPiece str = "[\"\\ude36\"]";
410   for (int i = 0; i <= str.length(); ++i) {
411     DoErrorTest(str, i, "Invalid unicode code point.");
412   }
413 }
414 
TEST_F(JsonStreamParserTest,UnicodeEscapingMissingLowSurrogateWhenNotCoerced)415 TEST_F(JsonStreamParserTest, UnicodeEscapingMissingLowSurrogateWhenNotCoerced) {
416   // A high surrogate alone.
417   StringPiece str = "[\"\\ud83d\"]";
418   for (int i = 0; i <= str.length(); ++i) {
419     DoErrorTest(str, i, "Missing low surrogate.");
420   }
421   // A high surrogate with some trailing characters.
422   str = "[\"\\ud83d|ude36\"]";
423   for (int i = 0; i <= str.length(); ++i) {
424     DoErrorTest(str, i, "Missing low surrogate.");
425   }
426   // A high surrogate with half a low surrogate.
427   str = "[\"\\ud83d\\ude--\"]";
428   for (int i = 0; i <= str.length(); ++i) {
429     DoErrorTest(str, i, "Invalid escape sequence.");
430   }
431   // Two high surrogates.
432   str = "[\"\\ud83d\\ud83d\"]";
433   for (int i = 0; i <= str.length(); ++i) {
434     DoErrorTest(str, i, "Invalid low surrogate.");
435   }
436 }
437 
438 // - ascii escaping (\b, \f, \n, \r, \t, \v)
TEST_F(JsonStreamParserTest,AsciiEscaping)439 TEST_F(JsonStreamParserTest, AsciiEscaping) {
440   StringPiece str =
441       "[\"\\b\", \"\\ning\", \"test\\f\", \"\\r\\t\", \"test\\\\\\ving\"]";
442   for (int i = 0; i <= str.length(); ++i) {
443     ow_.StartList("")
444         ->RenderString("", "\b")
445         ->RenderString("", "\ning")
446         ->RenderString("", "test\f")
447         ->RenderString("", "\r\t")
448         ->RenderString("", "test\\\ving")
449         ->EndList();
450     DoTest(str, i);
451   }
452 }
453 
454 // - trailing commas, we support a single trailing comma but no internal commas.
TEST_F(JsonStreamParserTest,TrailingCommas)455 TEST_F(JsonStreamParserTest, TrailingCommas) {
456   StringPiece str = "[['a',true,], {b: null,},]";
457   for (int i = 0; i <= str.length(); ++i) {
458     ow_.StartList("")
459         ->StartList("")
460         ->RenderString("", "a")
461         ->RenderBool("", true)
462         ->EndList()
463         ->StartObject("")
464         ->RenderNull("b")
465         ->EndObject()
466         ->EndList();
467     DoTest(str, i);
468   }
469 }
470 
471 // Negative tests
472 
473 // illegal literals
TEST_F(JsonStreamParserTest,ExtraTextAfterTrue)474 TEST_F(JsonStreamParserTest, ExtraTextAfterTrue) {
475   StringPiece str = "truee";
476   for (int i = 0; i <= str.length(); ++i) {
477     ow_.RenderBool("", true);
478     DoErrorTest(str, i, "Parsing terminated before end of input.");
479   }
480 }
481 
TEST_F(JsonStreamParserTest,InvalidNumberDashOnly)482 TEST_F(JsonStreamParserTest, InvalidNumberDashOnly) {
483   StringPiece str = "-";
484   for (int i = 0; i <= str.length(); ++i) {
485     DoErrorTest(str, i, "Unable to parse number.");
486   }
487 }
488 
TEST_F(JsonStreamParserTest,InvalidNumberDashName)489 TEST_F(JsonStreamParserTest, InvalidNumberDashName) {
490   StringPiece str = "-foo";
491   for (int i = 0; i <= str.length(); ++i) {
492     DoErrorTest(str, i, "Unable to parse number.");
493   }
494 }
495 
TEST_F(JsonStreamParserTest,InvalidLiteralInArray)496 TEST_F(JsonStreamParserTest, InvalidLiteralInArray) {
497   StringPiece str = "[nule]";
498   for (int i = 0; i <= str.length(); ++i) {
499     ow_.StartList("");
500     DoErrorTest(str, i, "Unexpected token.");
501   }
502 }
503 
TEST_F(JsonStreamParserTest,InvalidLiteralInObject)504 TEST_F(JsonStreamParserTest, InvalidLiteralInObject) {
505   StringPiece str = "{123false}";
506   for (int i = 0; i <= str.length(); ++i) {
507     ow_.StartObject("");
508     DoErrorTest(str, i, "Expected an object key or }.");
509   }
510 }
511 
512 // mismatched quotes failure on strings
TEST_F(JsonStreamParserTest,MismatchedSingleQuotedLiteral)513 TEST_F(JsonStreamParserTest, MismatchedSingleQuotedLiteral) {
514   StringPiece str = "'Some str\"";
515   for (int i = 0; i <= str.length(); ++i) {
516     DoErrorTest(str, i, "Closing quote expected in string.");
517   }
518 }
519 
TEST_F(JsonStreamParserTest,MismatchedDoubleQuotedLiteral)520 TEST_F(JsonStreamParserTest, MismatchedDoubleQuotedLiteral) {
521   StringPiece str = "\"Another string that ends poorly!'";
522   for (int i = 0; i <= str.length(); ++i) {
523     DoErrorTest(str, i, "Closing quote expected in string.");
524   }
525 }
526 
527 // unterminated strings
TEST_F(JsonStreamParserTest,UnterminatedLiteralString)528 TEST_F(JsonStreamParserTest, UnterminatedLiteralString) {
529   StringPiece str = "\"Forgot the rest of i";
530   for (int i = 0; i <= str.length(); ++i) {
531     DoErrorTest(str, i, "Closing quote expected in string.");
532   }
533 }
534 
TEST_F(JsonStreamParserTest,UnterminatedStringEscape)535 TEST_F(JsonStreamParserTest, UnterminatedStringEscape) {
536   StringPiece str = "\"Forgot the rest of \\";
537   for (int i = 0; i <= str.length(); ++i) {
538     DoErrorTest(str, i, "Closing quote expected in string.");
539   }
540 }
541 
TEST_F(JsonStreamParserTest,UnterminatedStringInArray)542 TEST_F(JsonStreamParserTest, UnterminatedStringInArray) {
543   StringPiece str = "[\"Forgot to close the string]";
544   for (int i = 0; i <= str.length(); ++i) {
545     ow_.StartList("");
546     DoErrorTest(str, i, "Closing quote expected in string.");
547   }
548 }
549 
TEST_F(JsonStreamParserTest,UnterminatedStringInObject)550 TEST_F(JsonStreamParserTest, UnterminatedStringInObject) {
551   StringPiece str = "{f: \"Forgot to close the string}";
552   for (int i = 0; i <= str.length(); ++i) {
553     ow_.StartObject("");
554     DoErrorTest(str, i, "Closing quote expected in string.");
555   }
556 }
557 
TEST_F(JsonStreamParserTest,UnterminatedObject)558 TEST_F(JsonStreamParserTest, UnterminatedObject) {
559   StringPiece str = "{";
560   for (int i = 0; i <= str.length(); ++i) {
561     ow_.StartObject("");
562     DoErrorTest(str, i, "Unexpected end of string.");
563   }
564 }
565 
566 
567 // mismatched object and array closing
TEST_F(JsonStreamParserTest,MismatchedCloseObject)568 TEST_F(JsonStreamParserTest, MismatchedCloseObject) {
569   StringPiece str = "{'key': true]";
570   for (int i = 0; i <= str.length(); ++i) {
571     ow_.StartObject("")->RenderBool("key", true);
572     DoErrorTest(str, i, "Expected , or } after key:value pair.");
573   }
574 }
575 
TEST_F(JsonStreamParserTest,MismatchedCloseArray)576 TEST_F(JsonStreamParserTest, MismatchedCloseArray) {
577   StringPiece str = "[true, null}";
578   for (int i = 0; i <= str.length(); ++i) {
579     ow_.StartList("")->RenderBool("", true)->RenderNull("");
580     DoErrorTest(str, i, "Expected , or ] after array value.");
581   }
582 }
583 
584 // Invalid object keys.
TEST_F(JsonStreamParserTest,InvalidNumericObjectKey)585 TEST_F(JsonStreamParserTest, InvalidNumericObjectKey) {
586   StringPiece str = "{42: true}";
587   for (int i = 0; i <= str.length(); ++i) {
588     ow_.StartObject("");
589     DoErrorTest(str, i, "Expected an object key or }.");
590   }
591 }
592 
TEST_F(JsonStreamParserTest,InvalidLiteralObjectInObject)593 TEST_F(JsonStreamParserTest, InvalidLiteralObjectInObject) {
594   StringPiece str = "{{bob: true}}";
595   for (int i = 0; i <= str.length(); ++i) {
596     ow_.StartObject("");
597     DoErrorTest(str, i, "Expected an object key or }.");
598   }
599 }
600 
TEST_F(JsonStreamParserTest,InvalidLiteralArrayInObject)601 TEST_F(JsonStreamParserTest, InvalidLiteralArrayInObject) {
602   StringPiece str = "{[null]}";
603   for (int i = 0; i <= str.length(); ++i) {
604     ow_.StartObject("");
605     DoErrorTest(str, i, "Expected an object key or }.");
606   }
607 }
608 
TEST_F(JsonStreamParserTest,InvalidLiteralValueInObject)609 TEST_F(JsonStreamParserTest, InvalidLiteralValueInObject) {
610   StringPiece str = "{false}";
611   for (int i = 0; i <= str.length(); ++i) {
612     ow_.StartObject("");
613     DoErrorTest(str, i, "Expected an object key or }.");
614   }
615 }
616 
TEST_F(JsonStreamParserTest,MissingColonAfterStringInObject)617 TEST_F(JsonStreamParserTest, MissingColonAfterStringInObject) {
618   StringPiece str = "{\"key\"}";
619   for (int i = 0; i <= str.length(); ++i) {
620     ow_.StartObject("");
621     DoErrorTest(str, i, "Expected : between key:value pair.");
622   }
623 }
624 
TEST_F(JsonStreamParserTest,MissingColonAfterKeyInObject)625 TEST_F(JsonStreamParserTest, MissingColonAfterKeyInObject) {
626   StringPiece str = "{key}";
627   for (int i = 0; i <= str.length(); ++i) {
628     ow_.StartObject("");
629     DoErrorTest(str, i, "Expected : between key:value pair.");
630   }
631 }
632 
TEST_F(JsonStreamParserTest,EndOfTextAfterKeyInObject)633 TEST_F(JsonStreamParserTest, EndOfTextAfterKeyInObject) {
634   StringPiece str = "{key";
635   for (int i = 0; i <= str.length(); ++i) {
636     ow_.StartObject("");
637     DoErrorTest(str, i, "Unexpected end of string.");
638   }
639 }
640 
TEST_F(JsonStreamParserTest,MissingValueAfterColonInObject)641 TEST_F(JsonStreamParserTest, MissingValueAfterColonInObject) {
642   StringPiece str = "{key:}";
643   for (int i = 0; i <= str.length(); ++i) {
644     ow_.StartObject("");
645     DoErrorTest(str, i, "Unexpected token.");
646   }
647 }
648 
TEST_F(JsonStreamParserTest,MissingCommaBetweenObjectEntries)649 TEST_F(JsonStreamParserTest, MissingCommaBetweenObjectEntries) {
650   StringPiece str = "{key:20 'hello': true}";
651   for (int i = 0; i <= str.length(); ++i) {
652     ow_.StartObject("")->RenderUint64("key", 20);
653     DoErrorTest(str, i, "Expected , or } after key:value pair.");
654   }
655 }
656 
TEST_F(JsonStreamParserTest,InvalidLiteralAsObjectKey)657 TEST_F(JsonStreamParserTest, InvalidLiteralAsObjectKey) {
658   StringPiece str = "{false: 20}";
659   for (int i = 0; i <= str.length(); ++i) {
660     ow_.StartObject("");
661     DoErrorTest(str, i, "Expected an object key or }.");
662   }
663 }
664 
TEST_F(JsonStreamParserTest,ExtraCharactersAfterObject)665 TEST_F(JsonStreamParserTest, ExtraCharactersAfterObject) {
666   StringPiece str = "{}}";
667   for (int i = 0; i <= str.length(); ++i) {
668     ow_.StartObject("")->EndObject();
669     DoErrorTest(str, i, "Parsing terminated before end of input.");
670   }
671 }
672 
673 // numbers too large
TEST_F(JsonStreamParserTest,PositiveNumberTooBig)674 TEST_F(JsonStreamParserTest, PositiveNumberTooBig) {
675   StringPiece str = "[18446744073709551616]";  // 2^64
676   for (int i = 0; i <= str.length(); ++i) {
677     ow_.StartList("");
678     DoErrorTest(str, i, "Unable to parse number.");
679   }
680 }
681 
TEST_F(JsonStreamParserTest,NegativeNumberTooBig)682 TEST_F(JsonStreamParserTest, NegativeNumberTooBig) {
683   StringPiece str = "[-18446744073709551616]";
684   for (int i = 0; i <= str.length(); ++i) {
685     ow_.StartList("");
686     DoErrorTest(str, i, "Unable to parse number.");
687   }
688 }
689 
690 /*
691 TODO(sven): Fail parsing when parsing a double that is too large.
692 
693 TEST_F(JsonStreamParserTest, DoubleTooBig) {
694   StringPiece str = "[184464073709551232321616.45]";
695   for (int i = 0; i <= str.length(); ++i) {
696     ow_.StartList("");
697     DoErrorTest(str, i, "Unable to parse number");
698   }
699 }
700 */
701 
702 // invalid bare backslash.
TEST_F(JsonStreamParserTest,UnfinishedEscape)703 TEST_F(JsonStreamParserTest, UnfinishedEscape) {
704   StringPiece str = "\"\\";
705   for (int i = 0; i <= str.length(); ++i) {
706     DoErrorTest(str, i, "Closing quote expected in string.");
707   }
708 }
709 
710 // invalid bare backslash u.
TEST_F(JsonStreamParserTest,UnfinishedUnicodeEscape)711 TEST_F(JsonStreamParserTest, UnfinishedUnicodeEscape) {
712   StringPiece str = "\"\\u";
713   for (int i = 0; i <= str.length(); ++i) {
714     DoErrorTest(str, i, "Illegal hex string.");
715   }
716 }
717 
718 // invalid unicode sequence.
TEST_F(JsonStreamParserTest,UnicodeEscapeCutOff)719 TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) {
720   StringPiece str = "\"\\u12";
721   for (int i = 0; i <= str.length(); ++i) {
722     DoErrorTest(str, i, "Illegal hex string.");
723   }
724 }
725 
726 // invalid unicode sequence (valid in modern EcmaScript but not in JSON).
TEST_F(JsonStreamParserTest,BracketedUnicodeEscape)727 TEST_F(JsonStreamParserTest, BracketedUnicodeEscape) {
728   StringPiece str = "\"\\u{1f36f}\"";
729   for (int i = 0; i <= str.length(); ++i) {
730     DoErrorTest(str, i, "Invalid escape sequence.");
731   }
732 }
733 
734 
TEST_F(JsonStreamParserTest,UnicodeEscapeInvalidCharacters)735 TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) {
736   StringPiece str = "\"\\u12$4hello";
737   for (int i = 0; i <= str.length(); ++i) {
738     DoErrorTest(str, i, "Invalid escape sequence.");
739   }
740 }
741 
742 // invalid unicode sequence in low half surrogate: g is not a hex digit.
TEST_F(JsonStreamParserTest,UnicodeEscapeLowHalfSurrogateInvalidCharacters)743 TEST_F(JsonStreamParserTest, UnicodeEscapeLowHalfSurrogateInvalidCharacters) {
744   StringPiece str = "\"\\ud800\\udcfg\"";
745   for (int i = 0; i <= str.length(); ++i) {
746     DoErrorTest(str, i, "Invalid escape sequence.");
747   }
748 }
749 
750 // Extra commas with an object or array.
TEST_F(JsonStreamParserTest,ExtraCommaInObject)751 TEST_F(JsonStreamParserTest, ExtraCommaInObject) {
752   StringPiece str = "{'k1': true,,'k2': false}";
753   for (int i = 0; i <= str.length(); ++i) {
754     ow_.StartObject("")->RenderBool("k1", true);
755     DoErrorTest(str, i, "Expected an object key or }.");
756   }
757 }
758 
TEST_F(JsonStreamParserTest,ExtraCommaInArray)759 TEST_F(JsonStreamParserTest, ExtraCommaInArray) {
760   StringPiece str = "[true,,false}";
761   for (int i = 0; i <= str.length(); ++i) {
762     ow_.StartList("")->RenderBool("", true);
763     DoErrorTest(str, i, "Unexpected token.");
764   }
765 }
766 
767 // Extra text beyond end of value.
TEST_F(JsonStreamParserTest,ExtraTextAfterLiteral)768 TEST_F(JsonStreamParserTest, ExtraTextAfterLiteral) {
769   StringPiece str = "'hello', 'world'";
770   for (int i = 0; i <= str.length(); ++i) {
771     ow_.RenderString("", "hello");
772     DoErrorTest(str, i, "Parsing terminated before end of input.");
773   }
774 }
775 
TEST_F(JsonStreamParserTest,ExtraTextAfterObject)776 TEST_F(JsonStreamParserTest, ExtraTextAfterObject) {
777   StringPiece str = "{'key': true} 'oops'";
778   for (int i = 0; i <= str.length(); ++i) {
779     ow_.StartObject("")->RenderBool("key", true)->EndObject();
780     DoErrorTest(str, i, "Parsing terminated before end of input.");
781   }
782 }
783 
TEST_F(JsonStreamParserTest,ExtraTextAfterArray)784 TEST_F(JsonStreamParserTest, ExtraTextAfterArray) {
785   StringPiece str = "[null] 'oops'";
786   for (int i = 0; i <= str.length(); ++i) {
787     ow_.StartList("")->RenderNull("")->EndList();
788     DoErrorTest(str, i, "Parsing terminated before end of input.");
789   }
790 }
791 
792 // Random unknown text in the value.
TEST_F(JsonStreamParserTest,UnknownCharactersAsValue)793 TEST_F(JsonStreamParserTest, UnknownCharactersAsValue) {
794   StringPiece str = "*&#25";
795   for (int i = 0; i <= str.length(); ++i) {
796     DoErrorTest(str, i, "Expected a value.");
797   }
798 }
799 
TEST_F(JsonStreamParserTest,UnknownCharactersInArray)800 TEST_F(JsonStreamParserTest, UnknownCharactersInArray) {
801   StringPiece str = "[*&#25]";
802   for (int i = 0; i <= str.length(); ++i) {
803     ow_.StartList("");
804     DoErrorTest(str, i, "Expected a value or ] within an array.");
805   }
806 }
807 
TEST_F(JsonStreamParserTest,UnknownCharactersInObject)808 TEST_F(JsonStreamParserTest, UnknownCharactersInObject) {
809   StringPiece str = "{'key': *&#25}";
810   for (int i = 0; i <= str.length(); ++i) {
811     ow_.StartObject("");
812     DoErrorTest(str, i, "Expected a value.");
813   }
814 }
815 
816 }  // namespace converter
817 }  // namespace util
818 }  // namespace protobuf
819 }  // namespace google
820