OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 // - mismatched object and array closing | 74 // - mismatched object and array closing |
75 // - Failure to close array or object | 75 // - Failure to close array or object |
76 // - numbers too large | 76 // - numbers too large |
77 // - invalid unicode escapes. | 77 // - invalid unicode escapes. |
78 // - invalid unicode sequences. | 78 // - invalid unicode sequences. |
79 // - numbers as keys | 79 // - numbers as keys |
80 // | 80 // |
81 // For each test we split the input string on every possible character to ensure | 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 | 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. | 83 // do a final test of the entire test case one character at a time. |
84 // | |
85 // It is verified that expected calls to the mocked objects are in sequence. | |
86 class JsonStreamParserTest : public ::testing::Test { | 84 class JsonStreamParserTest : public ::testing::Test { |
87 protected: | 85 protected: |
88 JsonStreamParserTest() : mock_(), ow_(&mock_) {} | 86 JsonStreamParserTest() : mock_(), ow_(&mock_) {} |
89 virtual ~JsonStreamParserTest() {} | 87 virtual ~JsonStreamParserTest() {} |
90 | 88 |
91 util::Status RunTest(StringPiece json, int split, bool coerce_utf8 = false, | 89 util::Status RunTest(StringPiece json, int split, bool coerce_utf8 = false) { |
92 bool allow_empty_null = false, | |
93 bool loose_float_number_conversion = false) { | |
94 JsonStreamParser parser(&mock_); | 90 JsonStreamParser parser(&mock_); |
95 | 91 |
96 // Special case for split == length, test parsing one character at a time. | 92 // Special case for split == length, test parsing one character at a time. |
97 if (split == json.length()) { | 93 if (split == json.length()) { |
98 GOOGLE_LOG(INFO) << "Testing split every char: " << json; | 94 GOOGLE_LOG(INFO) << "Testing split every char: " << json; |
99 for (int i = 0; i < json.length(); ++i) { | 95 for (int i = 0; i < json.length(); ++i) { |
100 StringPiece single = json.substr(i, 1); | 96 StringPiece single = json.substr(i, 1); |
101 util::Status result = parser.Parse(single); | 97 util::Status result = parser.Parse(single); |
102 if (!result.ok()) { | 98 if (!result.ok()) { |
103 return result; | 99 return result; |
104 } | 100 } |
105 } | 101 } |
106 return parser.FinishParse(); | 102 return parser.FinishParse(); |
107 } | 103 } |
108 | 104 |
109 // Normal case, split at the split point and parse two substrings. | 105 // Normal case, split at the split point and parse two substrings. |
110 StringPiece first = json.substr(0, split); | 106 StringPiece first = json.substr(0, split); |
111 StringPiece rest = json.substr(split); | 107 StringPiece rest = json.substr(split); |
112 GOOGLE_LOG(INFO) << "Testing split: " << first << "><" << rest; | 108 GOOGLE_LOG(INFO) << "Testing split: " << first << "><" << rest; |
113 util::Status result = parser.Parse(first); | 109 util::Status result = parser.Parse(first); |
114 if (result.ok()) { | 110 if (result.ok()) { |
115 result = parser.Parse(rest); | 111 result = parser.Parse(rest); |
116 if (result.ok()) { | 112 if (result.ok()) { |
117 result = parser.FinishParse(); | 113 result = parser.FinishParse(); |
118 } | 114 } |
119 } | 115 } |
120 return result; | 116 return result; |
121 } | 117 } |
122 | 118 |
123 void DoTest(StringPiece json, int split, bool coerce_utf8 = false, | 119 void DoTest(StringPiece json, int split, bool coerce_utf8 = false) { |
124 bool allow_empty_null = false, | 120 util::Status result = RunTest(json, split, coerce_utf8); |
125 bool loose_float_number_conversion = false) { | |
126 util::Status result = RunTest(json, split, coerce_utf8, allow_empty_null, | |
127 loose_float_number_conversion); | |
128 if (!result.ok()) { | 121 if (!result.ok()) { |
129 GOOGLE_LOG(WARNING) << result; | 122 GOOGLE_LOG(WARNING) << result; |
130 } | 123 } |
131 EXPECT_OK(result); | 124 EXPECT_OK(result); |
132 } | 125 } |
133 | 126 |
134 void DoErrorTest(StringPiece json, int split, StringPiece error_prefix, | 127 void DoErrorTest(StringPiece json, int split, StringPiece error_prefix, |
135 bool coerce_utf8 = false, bool allow_empty_null = false) { | 128 bool coerce_utf8 = false) { |
136 util::Status result = | 129 util::Status result = RunTest(json, split, coerce_utf8); |
137 RunTest(json, split, coerce_utf8, allow_empty_null); | |
138 EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code()); | 130 EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code()); |
139 StringPiece error_message(result.error_message()); | 131 StringPiece error_message(result.error_message()); |
140 EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size())); | 132 EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size())); |
141 } | 133 } |
142 | 134 |
143 | 135 |
144 #ifndef _MSC_VER | |
145 // TODO(xiaofeng): We have to disable InSequence check for MSVC because it | |
146 // causes stack overflow due to its use of a linked list that is desctructed | |
147 // recursively. | |
148 ::testing::InSequence in_sequence_; | |
149 #endif // !_MSC_VER | |
150 MockObjectWriter mock_; | 136 MockObjectWriter mock_; |
151 ExpectingObjectWriter ow_; | 137 ExpectingObjectWriter ow_; |
152 }; | 138 }; |
153 | 139 |
154 | 140 |
155 // Positive tests | 141 // Positive tests |
156 | 142 |
157 // - true, false, null | 143 // - true, false, null |
158 TEST_F(JsonStreamParserTest, SimpleTrue) { | 144 TEST_F(JsonStreamParserTest, SimpleTrue) { |
159 StringPiece str = "true"; | 145 StringPiece str = "true"; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 ->RenderNull("key") | 301 ->RenderNull("key") |
316 ->StartList("snake_key") | 302 ->StartList("snake_key") |
317 ->EndList() | 303 ->EndList() |
318 ->StartObject("camelKey") | 304 ->StartObject("camelKey") |
319 ->EndObject() | 305 ->EndObject() |
320 ->EndObject(); | 306 ->EndObject(); |
321 DoTest(str, i); | 307 DoTest(str, i); |
322 } | 308 } |
323 } | 309 } |
324 | 310 |
325 // - array containing primitive values (true, false, null, num, string) | 311 // - array containing array, object, values (true, false, null, num, string) |
326 TEST_F(JsonStreamParserTest, ArrayPrimitiveValues) { | 312 TEST_F(JsonStreamParserTest, ArrayValues) { |
327 StringPiece str = "[true, false, null, 'one', \"two\"]"; | 313 StringPiece str = |
| 314 "[true, false, null, 'a string', \"another string\", [22, -127, 45.3, " |
| 315 "-1056.4, 11779497823553162765], {'key': true}]"; |
328 for (int i = 0; i <= str.length(); ++i) { | 316 for (int i = 0; i <= str.length(); ++i) { |
329 ow_.StartList("") | 317 ow_.StartList("") |
330 ->RenderBool("", true) | 318 ->RenderBool("", true) |
331 ->RenderBool("", false) | 319 ->RenderBool("", false) |
332 ->RenderNull("") | 320 ->RenderNull("") |
333 ->RenderString("", "one") | 321 ->RenderString("", "a string") |
334 ->RenderString("", "two") | 322 ->RenderString("", "another string") |
335 ->EndList(); | |
336 DoTest(str, i); | |
337 } | |
338 } | |
339 | |
340 // - array containing array, object | |
341 TEST_F(JsonStreamParserTest, ArrayComplexValues) { | |
342 StringPiece str = | |
343 "[[22, -127, 45.3, -1056.4, 11779497823553162765], {'key': true}]"; | |
344 for (int i = 0; i <= str.length(); ++i) { | |
345 ow_.StartList("") | |
346 ->StartList("") | 323 ->StartList("") |
347 ->RenderUint64("", 22) | 324 ->RenderUint64("", 22) |
348 ->RenderInt64("", -127) | 325 ->RenderInt64("", -127) |
349 ->RenderDouble("", 45.3) | 326 ->RenderDouble("", 45.3) |
350 ->RenderDouble("", -1056.4) | 327 ->RenderDouble("", -1056.4) |
351 ->RenderUint64("", 11779497823553162765ULL) | 328 ->RenderUint64("", 11779497823553162765ULL) |
352 ->EndList() | 329 ->EndList() |
353 ->StartObject("") | 330 ->StartObject("") |
354 ->RenderBool("key", true) | 331 ->RenderBool("key", true) |
355 ->EndObject() | 332 ->EndObject() |
356 ->EndList(); | 333 ->EndList(); |
357 DoTest(str, i); | 334 DoTest(str, i); |
358 } | 335 } |
359 } | 336 } |
360 | 337 |
361 | |
362 // - object containing array, object, value (true, false, null, num, string) | 338 // - object containing array, object, value (true, false, null, num, string) |
363 TEST_F(JsonStreamParserTest, ObjectValues) { | 339 TEST_F(JsonStreamParserTest, ObjectValues) { |
364 StringPiece str = | 340 StringPiece str = |
365 "{t: true, f: false, n: null, s: 'a string', d: \"another string\", pi: " | 341 "{t: true, f: false, n: null, s: 'a string', d: \"another string\", pi: " |
366 "22, ni: -127, pd: 45.3, nd: -1056.4, pl: 11779497823553162765, l: [[]], " | 342 "22, ni: -127, pd: 45.3, nd: -1056.4, pl: 11779497823553162765, l: [[]], " |
367 "o: {'key': true}}"; | 343 "o: {'key': true}}"; |
368 for (int i = 0; i <= str.length(); ++i) { | 344 for (int i = 0; i <= str.length(); ++i) { |
369 ow_.StartObject("") | 345 ow_.StartObject("") |
370 ->RenderBool("t", true) | 346 ->RenderBool("t", true) |
371 ->RenderBool("f", false) | 347 ->RenderBool("f", false) |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
704 } | 680 } |
705 | 681 |
706 TEST_F(JsonStreamParserTest, NegativeNumberTooBig) { | 682 TEST_F(JsonStreamParserTest, NegativeNumberTooBig) { |
707 StringPiece str = "[-18446744073709551616]"; | 683 StringPiece str = "[-18446744073709551616]"; |
708 for (int i = 0; i <= str.length(); ++i) { | 684 for (int i = 0; i <= str.length(); ++i) { |
709 ow_.StartList(""); | 685 ow_.StartList(""); |
710 DoErrorTest(str, i, "Unable to parse number."); | 686 DoErrorTest(str, i, "Unable to parse number."); |
711 } | 687 } |
712 } | 688 } |
713 | 689 |
| 690 /* |
| 691 TODO(sven): Fail parsing when parsing a double that is too large. |
| 692 |
714 TEST_F(JsonStreamParserTest, DoubleTooBig) { | 693 TEST_F(JsonStreamParserTest, DoubleTooBig) { |
715 StringPiece str = "[1.89769e+308]"; | 694 StringPiece str = "[184464073709551232321616.45]"; |
716 for (int i = 0; i <= str.length(); ++i) { | 695 for (int i = 0; i <= str.length(); ++i) { |
717 ow_.StartList(""); | 696 ow_.StartList(""); |
718 DoErrorTest(str, i, "Number exceeds the range of double."); | 697 DoErrorTest(str, i, "Unable to parse number"); |
719 } | |
720 str = "[-1.89769e+308]"; | |
721 for (int i = 0; i <= str.length(); ++i) { | |
722 ow_.StartList(""); | |
723 DoErrorTest(str, i, "Number exceeds the range of double."); | |
724 } | 698 } |
725 } | 699 } |
726 | 700 */ |
727 | 701 |
728 // invalid bare backslash. | 702 // invalid bare backslash. |
729 TEST_F(JsonStreamParserTest, UnfinishedEscape) { | 703 TEST_F(JsonStreamParserTest, UnfinishedEscape) { |
730 StringPiece str = "\"\\"; | 704 StringPiece str = "\"\\"; |
731 for (int i = 0; i <= str.length(); ++i) { | 705 for (int i = 0; i <= str.length(); ++i) { |
732 DoErrorTest(str, i, "Closing quote expected in string."); | 706 DoErrorTest(str, i, "Closing quote expected in string."); |
733 } | 707 } |
734 } | 708 } |
735 | 709 |
736 // invalid bare backslash u. | 710 // invalid bare backslash u. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
836 for (int i = 0; i <= str.length(); ++i) { | 810 for (int i = 0; i <= str.length(); ++i) { |
837 ow_.StartObject(""); | 811 ow_.StartObject(""); |
838 DoErrorTest(str, i, "Expected a value."); | 812 DoErrorTest(str, i, "Expected a value."); |
839 } | 813 } |
840 } | 814 } |
841 | 815 |
842 } // namespace converter | 816 } // namespace converter |
843 } // namespace util | 817 } // namespace util |
844 } // namespace protobuf | 818 } // namespace protobuf |
845 } // namespace google | 819 } // namespace google |
OLD | NEW |