diff options
author | 2016-03-31 20:40:36 +0200 | |
---|---|---|
committer | 2016-03-31 20:40:36 +0200 | |
commit | bd2e14349beb065b7124d89d9d415d5cfb8b83d1 (patch) | |
tree | bc837234de77eccdfd46c26e7f2efcd9a07cdb49 /3rdparty/rapidjson/test/unittest/readertest.cpp | |
parent | 4172b54d844e4c1ff5626a8f22bf3f56e6c9dd94 (diff) |
Update rapidjson (nw)
Diffstat (limited to '3rdparty/rapidjson/test/unittest/readertest.cpp')
-rw-r--r-- | 3rdparty/rapidjson/test/unittest/readertest.cpp | 304 |
1 files changed, 263 insertions, 41 deletions
diff --git a/3rdparty/rapidjson/test/unittest/readertest.cpp b/3rdparty/rapidjson/test/unittest/readertest.cpp index 32af8a86eec..3f11fec8be3 100644 --- a/3rdparty/rapidjson/test/unittest/readertest.cpp +++ b/3rdparty/rapidjson/test/unittest/readertest.cpp @@ -1,5 +1,5 @@ // Tencent is pleased to support the open source community by making RapidJSON available. -// +// // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // // Licensed under the MIT License (the "License"); you may not use this file except @@ -7,9 +7,9 @@ // // http://opensource.org/licenses/MIT // -// Unless required by applicable law or agreed to in writing, software distributed -// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. #include "unittest.h" @@ -241,13 +241,13 @@ static void TestParseDouble() { TEST_DOUBLE(fullPrecision, "0.017976931348623157e+310", 1.7976931348623157e+308); // Max double in another form // Since - // abs((2^-1022 - 2^-1074) - 2.2250738585072012e-308) = 3.109754131239141401123495768877590405345064751974375599... ¡Á 10^-324 - // abs((2^-1022) - 2.2250738585072012e-308) = 1.830902327173324040642192159804623318305533274168872044... ¡Á 10 ^ -324 + // abs((2^-1022 - 2^-1074) - 2.2250738585072012e-308) = 3.109754131239141401123495768877590405345064751974375599... �� 10^-324 + // abs((2^-1022) - 2.2250738585072012e-308) = 1.830902327173324040642192159804623318305533274168872044... �� 10 ^ -324 // So 2.2250738585072012e-308 should round to 2^-1022 = 2.2250738585072014e-308 TEST_DOUBLE(fullPrecision, "2.2250738585072012e-308", 2.2250738585072014e-308); // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ // More closer to normal/subnormal boundary - // boundary = 2^-1022 - 2^-1075 = 2.225073858507201136057409796709131975934819546351645648... ¡Á 10^-308 + // boundary = 2^-1022 - 2^-1075 = 2.225073858507201136057409796709131975934819546351645648... �� 10^-308 TEST_DOUBLE(fullPrecision, "2.22507385850720113605740979670913197593481954635164564e-308", 2.2250738585072009e-308); TEST_DOUBLE(fullPrecision, "2.22507385850720113605740979670913197593481954635164565e-308", 2.2250738585072014e-308); @@ -297,7 +297,7 @@ static void TestParseDouble() { } // Cover trimming - TEST_DOUBLE(fullPrecision, + TEST_DOUBLE(fullPrecision, "2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508" "7914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012" "9811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306" @@ -306,7 +306,7 @@ static void TestParseDouble() { "5722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844" "2390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042" "7567186443383770486037861622771738545623065874679014086723327636718751234567890123456789012345678901" -"e-308", +"e-308", 2.2250738585072014e-308); { @@ -457,12 +457,12 @@ template <typename Encoding> struct ParseStringHandler : BaseReaderHandler<Encoding, ParseStringHandler<Encoding> > { ParseStringHandler() : str_(0), length_(0), copy_() {} ~ParseStringHandler() { EXPECT_TRUE(str_ != 0); if (copy_) free(const_cast<typename Encoding::Ch*>(str_)); } - + ParseStringHandler(const ParseStringHandler&); ParseStringHandler& operator=(const ParseStringHandler&); bool Default() { ADD_FAILURE(); return false; } - bool String(const typename Encoding::Ch* str, size_t length, bool copy) { + bool String(const typename Encoding::Ch* str, size_t length, bool copy) { EXPECT_EQ(0, str_); if (copy) { str_ = static_cast<typename Encoding::Ch*>(malloc((length + 1) * sizeof(typename Encoding::Ch))); @@ -470,7 +470,7 @@ struct ParseStringHandler : BaseReaderHandler<Encoding, ParseStringHandler<Encod } else str_ = str; - length_ = length; + length_ = length; copy_ = copy; return true; } @@ -499,7 +499,7 @@ TEST(Reader, ParseString) { EXPECT_EQ(StrLen(e), h2.length_); \ } - // String constant L"\xXX" can only specify character code in bytes, which is not endianness-neutral. + // String constant L"\xXX" can only specify character code in bytes, which is not endianness-neutral. // And old compiler does not support u"" and U"" string literal. So here specify string literal by array of Ch. // In addition, GCC 4.8 generates -Wnarrowing warnings when character code >= 128 are assigned to signed integer types. // Therefore, utype is added for declaring unsigned array, and then cast it to Encoding::Ch. @@ -650,7 +650,7 @@ TEST(Reader, ParseString_Error) { // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt - // 3 Malformed sequences + // 3 Malformed sequences // 3.1 Unexpected continuation bytes { @@ -684,19 +684,19 @@ TEST(Reader, ParseString_Error) { } } - // 4 Overlong sequences + // 4 Overlong sequences // 4.1 Examples of an overlong ASCII character TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0xAFu, '\"', ']', '\0')); TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0xAFu, '\"', ']', '\0')); TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0xAFu, '\"', ']', '\0')); - // 4.2 Maximum overlong sequences + // 4.2 Maximum overlong sequences TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC1u, 0xBFu, '\"', ']', '\0')); TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x9Fu, 0xBFu, '\"', ']', '\0')); TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x8Fu, 0xBFu, 0xBFu, '\"', ']', '\0')); - // 4.3 Overlong representation of the NUL character + // 4.3 Overlong representation of the NUL character TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0x80u, '\"', ']', '\0')); TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0x80u, '\"', ']', '\0')); TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0x80u, '\"', ']', '\0')); @@ -778,6 +778,10 @@ TEST(Reader, ParseArray_Error) { TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1}", 2); TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1 2]", 3); + // Array cannot have a trailing comma (without kParseTrailingCommasFlag); + // a value must follow a comma + TEST_ARRAY_ERROR(kParseErrorValueInvalid, "[1,]", 3); + #undef TEST_ARRAY_ERROR } @@ -786,14 +790,14 @@ struct ParseObjectHandler : BaseReaderHandler<UTF8<>, ParseObjectHandler> { bool Default() { ADD_FAILURE(); return false; } bool Null() { EXPECT_EQ(8u, step_); step_++; return true; } - bool Bool(bool b) { + bool Bool(bool b) { switch(step_) { case 4: EXPECT_TRUE(b); step_++; return true; case 6: EXPECT_FALSE(b); step_++; return true; default: ADD_FAILURE(); return false; } } - bool Int(int i) { + bool Int(int i) { switch(step_) { case 10: EXPECT_EQ(123, i); step_++; return true; case 15: EXPECT_EQ(1, i); step_++; return true; @@ -804,7 +808,7 @@ struct ParseObjectHandler : BaseReaderHandler<UTF8<>, ParseObjectHandler> { } bool Uint(unsigned i) { return Int(static_cast<int>(i)); } bool Double(double d) { EXPECT_EQ(12u, step_); EXPECT_DOUBLE_EQ(3.1416, d); step_++; return true; } - bool String(const char* str, size_t, bool) { + bool String(const char* str, size_t, bool) { switch(step_) { case 1: EXPECT_STREQ("hello", str); step_++; return true; case 2: EXPECT_STREQ("world", str); step_++; return true; @@ -978,6 +982,10 @@ TEST(Reader, ParseObject_Error) { // Must be a comma or '}' after an object member TEST_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, "{\"a\":1]", 6); + // Object cannot have a trailing comma (without kParseTrailingCommasFlag); + // an object member name must follow a comma + TEST_ERROR(kParseErrorObjectMissName, "{\"a\":1,}", 7); + // This tests that MemoryStream is checking the length in Peek(). { MemoryStream ms("{\"a\"", 1); @@ -1037,7 +1045,7 @@ struct StreamTraits<CustomStringStream<Encoding> > { }; } // namespace rapidjson -#endif +#endif TEST(Reader, CustomStringStream) { const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } "; @@ -1061,7 +1069,7 @@ public: return c == std::char_traits<char>::eof() ? '\0' : static_cast<Ch>(c); } - Ch Take() { + Ch Take() { int c = is_.get(); return c == std::char_traits<char>::eof() ? '\0' : static_cast<Ch>(c); } @@ -1089,7 +1097,7 @@ TEST(Reader, Parse_IStreamWrapper_StringStream) { Reader reader; ParseArrayHandler<4> h; reader.Parse(is, h); - EXPECT_FALSE(reader.HasParseError()); + EXPECT_FALSE(reader.HasParseError()); } // Test iterative parsing. @@ -1119,6 +1127,16 @@ TEST(Reader, IterativeParsing_ErrorHandling) { TESTERRORHANDLING("{\"a\": 1", kParseErrorObjectMissCommaOrCurlyBracket, 7u); TESTERRORHANDLING("[1 2 3]", kParseErrorArrayMissCommaOrSquareBracket, 3u); TESTERRORHANDLING("{\"a: 1", kParseErrorStringMissQuotationMark, 6u); + TESTERRORHANDLING("{\"a\":}", kParseErrorValueInvalid, 5u); + TESTERRORHANDLING("{\"a\":]", kParseErrorValueInvalid, 5u); + TESTERRORHANDLING("[1,2,}", kParseErrorValueInvalid, 5u); + TESTERRORHANDLING("[}]", kParseErrorValueInvalid, 1u); + TESTERRORHANDLING("[,]", kParseErrorValueInvalid, 1u); + TESTERRORHANDLING("[1,,]", kParseErrorValueInvalid, 3u); + + // Trailing commas are not allowed without kParseTrailingCommasFlag + TESTERRORHANDLING("{\"a\": 1,}", kParseErrorObjectMissName, 8u); + TESTERRORHANDLING("[1,2,3,]", kParseErrorValueInvalid, 7u); // Any JSON value can be a valid root element in RFC7159. TESTERRORHANDLING("\"ab", kParseErrorStringMissQuotationMark, 3u); @@ -1177,7 +1195,7 @@ struct IterativeParsingReaderHandler { bool StartObject() { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STARTOBJECT; return true; } bool Key (const Ch*, SizeType, bool) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_KEY; return true; } - + bool EndObject(SizeType c) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_ENDOBJECT; @@ -1428,7 +1446,7 @@ TEST(Reader, ParseEmptyOnelineComment) { } TEST(Reader, ParseMultipleCommentsInARow) { - const char* json = + const char* json = "{/* first comment *//* second */\n" "/* third */ /*fourth*/// last one\n" "\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; @@ -1523,7 +1541,8 @@ struct NumbersAsStringsHandler { // 'str' is not null-terminated bool RawNumber(const char* str, SizeType length, bool) { EXPECT_TRUE(str != 0); - EXPECT_TRUE(strncmp(str, "3.1416", length) == 0); + EXPECT_TRUE(expected_len_ == length); + EXPECT_TRUE(strncmp(str, expected_, length) == 0); return true; } bool String(const char*, SizeType, bool) { return true; } @@ -1532,24 +1551,227 @@ struct NumbersAsStringsHandler { bool EndObject(SizeType) { return true; } bool StartArray() { return true; } bool EndArray(SizeType) { return true; } + + NumbersAsStringsHandler(const char* expected) + : expected_(expected) + , expected_len_(strlen(expected)) {} + + const char* expected_; + size_t expected_len_; }; TEST(Reader, NumbersAsStrings) { - { - const char* json = "{ \"pi\": 3.1416 } "; - StringStream s(json); - NumbersAsStringsHandler h; - Reader reader; - EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h)); - } - { - char* json = StrDup("{ \"pi\": 3.1416 } "); - InsituStringStream s(json); - NumbersAsStringsHandler h; - Reader reader; - EXPECT_TRUE(reader.Parse<kParseInsituFlag|kParseNumbersAsStringsFlag>(s, h)); - free(json); - } + { + const char* json = "{ \"pi\": 3.1416 } "; + StringStream s(json); + NumbersAsStringsHandler h("3.1416"); + Reader reader; + EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h)); + } + { + char* json = StrDup("{ \"pi\": 3.1416 } "); + InsituStringStream s(json); + NumbersAsStringsHandler h("3.1416"); + Reader reader; + EXPECT_TRUE(reader.Parse<kParseInsituFlag|kParseNumbersAsStringsFlag>(s, h)); + free(json); + } + { + const char* json = "{ \"gigabyte\": 1.0e9 } "; + StringStream s(json); + NumbersAsStringsHandler h("1.0e9"); + Reader reader; + EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h)); + } + { + char* json = StrDup("{ \"gigabyte\": 1.0e9 } "); + InsituStringStream s(json); + NumbersAsStringsHandler h("1.0e9"); + Reader reader; + EXPECT_TRUE(reader.Parse<kParseInsituFlag|kParseNumbersAsStringsFlag>(s, h)); + free(json); + } + { + const char* json = "{ \"pi\": 314.159e-2 } "; + StringStream s(json); + NumbersAsStringsHandler h("314.159e-2"); + Reader reader; + EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h)); + } + { + char* json = StrDup("{ \"gigabyte\": 314.159e-2 } "); + InsituStringStream s(json); + NumbersAsStringsHandler h("314.159e-2"); + Reader reader; + EXPECT_TRUE(reader.Parse<kParseInsituFlag|kParseNumbersAsStringsFlag>(s, h)); + free(json); + } + { + const char* json = "{ \"negative\": -1.54321 } "; + StringStream s(json); + NumbersAsStringsHandler h("-1.54321"); + Reader reader; + EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h)); + } + { + char* json = StrDup("{ \"negative\": -1.54321 } "); + InsituStringStream s(json); + NumbersAsStringsHandler h("-1.54321"); + Reader reader; + EXPECT_TRUE(reader.Parse<kParseInsituFlag|kParseNumbersAsStringsFlag>(s, h)); + free(json); + } + { + const char* json = "{ \"pi\": 314.159e-2 } "; + std::stringstream ss(json); + IStreamWrapper s(ss); + NumbersAsStringsHandler h("314.159e-2"); + Reader reader; + EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h)); + } +} + +template <unsigned extraFlags> +void TestTrailingCommas() { + { + StringStream s("[1,2,3,]"); + ParseArrayHandler<3> h; + Reader reader; + EXPECT_TRUE(reader.Parse<extraFlags|kParseTrailingCommasFlag>(s, h)); + EXPECT_EQ(5u, h.step_); + } + { + const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false," + "\"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3],}"; + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse<extraFlags|kParseTrailingCommasFlag>(s, h)); + EXPECT_EQ(20u, h.step_); + } + { + // whitespace around trailing commas + const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false," + "\"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3\n,\n]\n,\n} "; + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse<extraFlags|kParseTrailingCommasFlag>(s, h)); + EXPECT_EQ(20u, h.step_); + } + { + // comments around trailing commas + const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null," + "\"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3/*test*/,/*test*/]/*test*/,/*test*/}"; + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse<extraFlags|kParseTrailingCommasFlag|kParseCommentsFlag>(s, h)); + EXPECT_EQ(20u, h.step_); + } +} + +TEST(Reader, TrailingCommas) { + TestTrailingCommas<kParseNoFlags>(); +} + +TEST(Reader, TrailingCommasIterative) { + TestTrailingCommas<kParseIterativeFlag>(); +} + +template <unsigned extraFlags> +void TestMultipleTrailingCommaErrors() { + // only a single trailing comma is allowed. + { + StringStream s("[1,2,3,,]"); + ParseArrayHandler<3> h; + Reader reader; + ParseResult r = reader.Parse<extraFlags|kParseTrailingCommasFlag>(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorValueInvalid, r.Code()); + EXPECT_EQ(7u, r.Offset()); + } + { + const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false," + "\"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3,],,}"; + StringStream s(json); + ParseObjectHandler h; + Reader reader; + ParseResult r = reader.Parse<extraFlags|kParseTrailingCommasFlag>(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorObjectMissName, r.Code()); + EXPECT_EQ(95u, r.Offset()); + } +} + +TEST(Reader, MultipleTrailingCommaErrors) { + TestMultipleTrailingCommaErrors<kParseNoFlags>(); +} + +TEST(Reader, MultipleTrailingCommaErrorsIterative) { + TestMultipleTrailingCommaErrors<kParseIterativeFlag>(); +} + +template <unsigned extraFlags> +void TestEmptyExceptForCommaErrors() { + // not allowed even with trailing commas enabled; the + // trailing comma must follow a value. + { + StringStream s("[,]"); + ParseArrayHandler<3> h; + Reader reader; + ParseResult r = reader.Parse<extraFlags|kParseTrailingCommasFlag>(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorValueInvalid, r.Code()); + EXPECT_EQ(1u, r.Offset()); + } + { + StringStream s("{,}"); + ParseObjectHandler h; + Reader reader; + ParseResult r = reader.Parse<extraFlags|kParseTrailingCommasFlag>(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorObjectMissName, r.Code()); + EXPECT_EQ(1u, r.Offset()); + } +} + +TEST(Reader, EmptyExceptForCommaErrors) { + TestEmptyExceptForCommaErrors<kParseNoFlags>(); +} + +TEST(Reader, EmptyExceptForCommaErrorsIterative) { + TestEmptyExceptForCommaErrors<kParseIterativeFlag>(); +} + +template <unsigned extraFlags> +void TestTrailingCommaHandlerTermination() { + { + HandlerTerminateAtEndArray h; + Reader reader; + StringStream s("[1,2,3,]"); + ParseResult r = reader.Parse<extraFlags|kParseTrailingCommasFlag>(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorTermination, r.Code()); + EXPECT_EQ(7u, r.Offset()); + } + { + HandlerTerminateAtEndObject h; + Reader reader; + StringStream s("{\"t\": true, \"f\": false,}"); + ParseResult r = reader.Parse<extraFlags|kParseTrailingCommasFlag>(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorTermination, r.Code()); + EXPECT_EQ(23u, r.Offset()); + } +} + +TEST(Reader, TrailingCommaHandlerTermination) { + TestTrailingCommaHandlerTermination<kParseNoFlags>(); +} + +TEST(Reader, TrailingCommaHandlerTerminationIterative) { + TestTrailingCommaHandlerTermination<kParseIterativeFlag>(); } #ifdef __GNUC__ |