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. |
84 class JsonStreamParserTest : public ::testing::Test { | 86 class JsonStreamParserTest : public ::testing::Test { |
85 protected: | 87 protected: |
86 JsonStreamParserTest() : mock_(), ow_(&mock_) {} | 88 JsonStreamParserTest() : mock_(), ow_(&mock_) {} |
87 virtual ~JsonStreamParserTest() {} | 89 virtual ~JsonStreamParserTest() {} |
88 | 90 |
89 util::Status RunTest(StringPiece json, int split, bool coerce_utf8 = false) { | 91 util::Status RunTest(StringPiece json, int split, bool coerce_utf8 = false, |
| 92 bool allow_empty_null = false, |
| 93 bool loose_float_number_conversion = false) { |
90 JsonStreamParser parser(&mock_); | 94 JsonStreamParser parser(&mock_); |
91 | 95 |
92 // Special case for split == length, test parsing one character at a time. | 96 // Special case for split == length, test parsing one character at a time. |
93 if (split == json.length()) { | 97 if (split == json.length()) { |
94 GOOGLE_LOG(INFO) << "Testing split every char: " << json; | 98 GOOGLE_LOG(INFO) << "Testing split every char: " << json; |
95 for (int i = 0; i < json.length(); ++i) { | 99 for (int i = 0; i < json.length(); ++i) { |
96 StringPiece single = json.substr(i, 1); | 100 StringPiece single = json.substr(i, 1); |
97 util::Status result = parser.Parse(single); | 101 util::Status result = parser.Parse(single); |
98 if (!result.ok()) { | 102 if (!result.ok()) { |
99 return result; | 103 return result; |
100 } | 104 } |
101 } | 105 } |
102 return parser.FinishParse(); | 106 return parser.FinishParse(); |
103 } | 107 } |
104 | 108 |
105 // Normal case, split at the split point and parse two substrings. | 109 // Normal case, split at the split point and parse two substrings. |
106 StringPiece first = json.substr(0, split); | 110 StringPiece first = json.substr(0, split); |
107 StringPiece rest = json.substr(split); | 111 StringPiece rest = json.substr(split); |
108 GOOGLE_LOG(INFO) << "Testing split: " << first << "><" << rest; | 112 GOOGLE_LOG(INFO) << "Testing split: " << first << "><" << rest; |
109 util::Status result = parser.Parse(first); | 113 util::Status result = parser.Parse(first); |
110 if (result.ok()) { | 114 if (result.ok()) { |
111 result = parser.Parse(rest); | 115 result = parser.Parse(rest); |
112 if (result.ok()) { | 116 if (result.ok()) { |
113 result = parser.FinishParse(); | 117 result = parser.FinishParse(); |
114 } | 118 } |
115 } | 119 } |
116 return result; | 120 return result; |
117 } | 121 } |
118 | 122 |
119 void DoTest(StringPiece json, int split, bool coerce_utf8 = false) { | 123 void DoTest(StringPiece json, int split, bool coerce_utf8 = false, |
120 util::Status result = RunTest(json, split, coerce_utf8); | 124 bool allow_empty_null = false, |
| 125 bool loose_float_number_conversion = false) { |
| 126 util::Status result = RunTest(json, split, coerce_utf8, allow_empty_null, |
| 127 loose_float_number_conversion); |
121 if (!result.ok()) { | 128 if (!result.ok()) { |
122 GOOGLE_LOG(WARNING) << result; | 129 GOOGLE_LOG(WARNING) << result; |
123 } | 130 } |
124 EXPECT_OK(result); | 131 EXPECT_OK(result); |
125 } | 132 } |
126 | 133 |
127 void DoErrorTest(StringPiece json, int split, StringPiece error_prefix, | 134 void DoErrorTest(StringPiece json, int split, StringPiece error_prefix, |
128 bool coerce_utf8 = false) { | 135 bool coerce_utf8 = false, bool allow_empty_null = false) { |
129 util::Status result = RunTest(json, split, coerce_utf8); | 136 util::Status result = |
| 137 RunTest(json, split, coerce_utf8, allow_empty_null); |
130 EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code()); | 138 EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code()); |
131 StringPiece error_message(result.error_message()); | 139 StringPiece error_message(result.error_message()); |
132 EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size())); | 140 EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size())); |
133 } | 141 } |
134 | 142 |
135 | 143 |
| 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 |
136 MockObjectWriter mock_; | 150 MockObjectWriter mock_; |
137 ExpectingObjectWriter ow_; | 151 ExpectingObjectWriter ow_; |
138 }; | 152 }; |
139 | 153 |
140 | 154 |
141 // Positive tests | 155 // Positive tests |
142 | 156 |
143 // - true, false, null | 157 // - true, false, null |
144 TEST_F(JsonStreamParserTest, SimpleTrue) { | 158 TEST_F(JsonStreamParserTest, SimpleTrue) { |
145 StringPiece str = "true"; | 159 StringPiece str = "true"; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 ->RenderNull("key") | 315 ->RenderNull("key") |
302 ->StartList("snake_key") | 316 ->StartList("snake_key") |
303 ->EndList() | 317 ->EndList() |
304 ->StartObject("camelKey") | 318 ->StartObject("camelKey") |
305 ->EndObject() | 319 ->EndObject() |
306 ->EndObject(); | 320 ->EndObject(); |
307 DoTest(str, i); | 321 DoTest(str, i); |
308 } | 322 } |
309 } | 323 } |
310 | 324 |
311 // - array containing array, object, values (true, false, null, num, string) | 325 // - array containing primitive values (true, false, null, num, string) |
312 TEST_F(JsonStreamParserTest, ArrayValues) { | 326 TEST_F(JsonStreamParserTest, ArrayPrimitiveValues) { |
313 StringPiece str = | 327 StringPiece str = "[true, false, null, 'one', \"two\"]"; |
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) { | 328 for (int i = 0; i <= str.length(); ++i) { |
317 ow_.StartList("") | 329 ow_.StartList("") |
318 ->RenderBool("", true) | 330 ->RenderBool("", true) |
319 ->RenderBool("", false) | 331 ->RenderBool("", false) |
320 ->RenderNull("") | 332 ->RenderNull("") |
321 ->RenderString("", "a string") | 333 ->RenderString("", "one") |
322 ->RenderString("", "another string") | 334 ->RenderString("", "two") |
| 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("") |
323 ->StartList("") | 346 ->StartList("") |
324 ->RenderUint64("", 22) | 347 ->RenderUint64("", 22) |
325 ->RenderInt64("", -127) | 348 ->RenderInt64("", -127) |
326 ->RenderDouble("", 45.3) | 349 ->RenderDouble("", 45.3) |
327 ->RenderDouble("", -1056.4) | 350 ->RenderDouble("", -1056.4) |
328 ->RenderUint64("", 11779497823553162765ULL) | 351 ->RenderUint64("", 11779497823553162765ULL) |
329 ->EndList() | 352 ->EndList() |
330 ->StartObject("") | 353 ->StartObject("") |
331 ->RenderBool("key", true) | 354 ->RenderBool("key", true) |
332 ->EndObject() | 355 ->EndObject() |
333 ->EndList(); | 356 ->EndList(); |
334 DoTest(str, i); | 357 DoTest(str, i); |
335 } | 358 } |
336 } | 359 } |
337 | 360 |
| 361 |
338 // - object containing array, object, value (true, false, null, num, string) | 362 // - object containing array, object, value (true, false, null, num, string) |
339 TEST_F(JsonStreamParserTest, ObjectValues) { | 363 TEST_F(JsonStreamParserTest, ObjectValues) { |
340 StringPiece str = | 364 StringPiece str = |
341 "{t: true, f: false, n: null, s: 'a string', d: \"another string\", pi: " | 365 "{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: [[]], " | 366 "22, ni: -127, pd: 45.3, nd: -1056.4, pl: 11779497823553162765, l: [[]], " |
343 "o: {'key': true}}"; | 367 "o: {'key': true}}"; |
344 for (int i = 0; i <= str.length(); ++i) { | 368 for (int i = 0; i <= str.length(); ++i) { |
345 ow_.StartObject("") | 369 ow_.StartObject("") |
346 ->RenderBool("t", true) | 370 ->RenderBool("t", true) |
347 ->RenderBool("f", false) | 371 ->RenderBool("f", false) |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
680 } | 704 } |
681 | 705 |
682 TEST_F(JsonStreamParserTest, NegativeNumberTooBig) { | 706 TEST_F(JsonStreamParserTest, NegativeNumberTooBig) { |
683 StringPiece str = "[-18446744073709551616]"; | 707 StringPiece str = "[-18446744073709551616]"; |
684 for (int i = 0; i <= str.length(); ++i) { | 708 for (int i = 0; i <= str.length(); ++i) { |
685 ow_.StartList(""); | 709 ow_.StartList(""); |
686 DoErrorTest(str, i, "Unable to parse number."); | 710 DoErrorTest(str, i, "Unable to parse number."); |
687 } | 711 } |
688 } | 712 } |
689 | 713 |
690 /* | |
691 TODO(sven): Fail parsing when parsing a double that is too large. | |
692 | |
693 TEST_F(JsonStreamParserTest, DoubleTooBig) { | 714 TEST_F(JsonStreamParserTest, DoubleTooBig) { |
694 StringPiece str = "[184464073709551232321616.45]"; | 715 StringPiece str = "[1.89769e+308]"; |
695 for (int i = 0; i <= str.length(); ++i) { | 716 for (int i = 0; i <= str.length(); ++i) { |
696 ow_.StartList(""); | 717 ow_.StartList(""); |
697 DoErrorTest(str, i, "Unable to parse number"); | 718 DoErrorTest(str, i, "Number exceeds the range of double."); |
| 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."); |
698 } | 724 } |
699 } | 725 } |
700 */ | 726 |
701 | 727 |
702 // invalid bare backslash. | 728 // invalid bare backslash. |
703 TEST_F(JsonStreamParserTest, UnfinishedEscape) { | 729 TEST_F(JsonStreamParserTest, UnfinishedEscape) { |
704 StringPiece str = "\"\\"; | 730 StringPiece str = "\"\\"; |
705 for (int i = 0; i <= str.length(); ++i) { | 731 for (int i = 0; i <= str.length(); ++i) { |
706 DoErrorTest(str, i, "Closing quote expected in string."); | 732 DoErrorTest(str, i, "Closing quote expected in string."); |
707 } | 733 } |
708 } | 734 } |
709 | 735 |
710 // invalid bare backslash u. | 736 // invalid bare backslash u. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
810 for (int i = 0; i <= str.length(); ++i) { | 836 for (int i = 0; i <= str.length(); ++i) { |
811 ow_.StartObject(""); | 837 ow_.StartObject(""); |
812 DoErrorTest(str, i, "Expected a value."); | 838 DoErrorTest(str, i, "Expected a value."); |
813 } | 839 } |
814 } | 840 } |
815 | 841 |
816 } // namespace converter | 842 } // namespace converter |
817 } // namespace util | 843 } // namespace util |
818 } // namespace protobuf | 844 } // namespace protobuf |
819 } // namespace google | 845 } // namespace google |
OLD | NEW |