From 46e89dad0d973e6dbda335b7f18b599042f6ba5b Mon Sep 17 00:00:00 2001 From: thebusytypist Date: Tue, 15 Jul 2014 00:51:34 +0800 Subject: [PATCH] Add unittests for kParserErrorTermination; Fix bugs in last merge. --- include/rapidjson/reader.h | 16 ++++--- test/unittest/readertest.cpp | 88 ++++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 17 deletions(-) diff --git a/include/rapidjson/reader.h b/include/rapidjson/reader.h index 454cb6e..bdfd826 100644 --- a/include/rapidjson/reader.h +++ b/include/rapidjson/reader.h @@ -1023,7 +1023,6 @@ private: return IterativeParsingErrorState; case IterativeParsingFinishState: - is.Take(); return dst; case IterativeParsingErrorState: @@ -1031,7 +1030,6 @@ private: case IterativeParsingObjectInitialState: case IterativeParsingArrayInitialState: - is.Take(); // Push the state(Element or MemeberValue) if we are nested in another array or value of member. // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. n = src; @@ -1053,8 +1051,10 @@ private: RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); return IterativeParsingErrorState; } - else + else { + is.Take(); return dst; + } case IterativeParsingMemberKeyState: ParseString(is, handler); @@ -1095,7 +1095,6 @@ private: return dst; case IterativeParsingObjectFinishState: - is.Take(); // Get member count. c = *stack_.template Pop(1); // If the object is not empty, count the last member. @@ -1113,11 +1112,12 @@ private: RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); return IterativeParsingErrorState; } - else + else { + is.Take(); return n; + } case IterativeParsingArrayFinishState: - is.Take(); // Get element count. c = *stack_.template Pop(1); // If the array is not empty, count the last element. @@ -1135,8 +1135,10 @@ private: RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); return IterativeParsingErrorState; } - else + else { + is.Take(); return n; + } default: RAPIDJSON_ASSERT(false); diff --git a/test/unittest/readertest.cpp b/test/unittest/readertest.cpp index 45cbeaa..0bd1b13 100644 --- a/test/unittest/readertest.cpp +++ b/test/unittest/readertest.cpp @@ -707,7 +707,7 @@ TEST(Reader, Parse_IStreamWrapper_StringStream) { EXPECT_FALSE(reader.HasParseError()); } -#define TESTERRORHANDLING(text, errorCode)\ +#define TESTERRORHANDLING(text, errorCode, offset)\ {\ StringStream json(text);\ BaseReaderHandler<> handler;\ @@ -715,20 +715,21 @@ TEST(Reader, Parse_IStreamWrapper_StringStream) { reader.IterativeParse(json, handler);\ EXPECT_TRUE(reader.HasParseError());\ EXPECT_EQ(errorCode, reader.GetParseErrorCode());\ + EXPECT_EQ(offset, reader.GetErrorOffset());\ } TEST(Reader, IterativeParsing_ErrorHandling) { - TESTERRORHANDLING("{\"a\": a}", kParseErrorValueInvalid); + TESTERRORHANDLING("{\"a\": a}", kParseErrorValueInvalid, 6); - TESTERRORHANDLING("", kParseErrorDocumentEmpty); - TESTERRORHANDLING("1", kParseErrorDocumentRootNotObjectOrArray); - TESTERRORHANDLING("{}{}", kParseErrorDocumentRootNotSingular); + TESTERRORHANDLING("", kParseErrorDocumentEmpty, 0); + TESTERRORHANDLING("1", kParseErrorDocumentRootNotObjectOrArray, 0); + TESTERRORHANDLING("{}{}", kParseErrorDocumentRootNotSingular, 2); - TESTERRORHANDLING("{1}", kParseErrorObjectMissName); - TESTERRORHANDLING("{\"a\", 1}", kParseErrorObjectMissColon); - TESTERRORHANDLING("{\"a\"}", kParseErrorObjectMissColon); - TESTERRORHANDLING("{\"a\": 1", kParseErrorObjectMissCommaOrCurlyBracket); - TESTERRORHANDLING("[1 2 3]", kParseErrorArrayMissCommaOrSquareBracket); + TESTERRORHANDLING("{1}", kParseErrorObjectMissName, 1); + TESTERRORHANDLING("{\"a\", 1}", kParseErrorObjectMissColon, 4); + TESTERRORHANDLING("{\"a\"}", kParseErrorObjectMissColon, 4); + TESTERRORHANDLING("{\"a\": 1", kParseErrorObjectMissCommaOrCurlyBracket, 7); + TESTERRORHANDLING("[1 2 3]", kParseErrorArrayMissCommaOrSquareBracket, 3); } // Test iterative parsing. @@ -1220,6 +1221,73 @@ TEST(Reader, IterativeParsing_StateTransition_ElementDelimiter) { } } +// Test iterative parsing on kParseErrorTermination. +struct HandlerTerminateAtStartObject : public IterativeParsingReaderHandler<> { + bool StartObject() { return false; } +}; + +struct HandlerTerminateAtStartArray : public IterativeParsingReaderHandler<> { + bool StartArray() { return false; } +}; + +struct HandlerTerminateAtEndObject : public IterativeParsingReaderHandler<> { + bool EndObject(SizeType) { return false; } +}; + +struct HandlerTerminateAtEndArray : public IterativeParsingReaderHandler<> { + bool EndArray(SizeType) { return false; } +}; + +TEST(Reader, IterativeParsing_ShortCircuit) { + { + HandlerTerminateAtStartObject handler; + Reader reader; + StringStream is("[1, {}]"); + + ParseResult r = reader.Parse(is, handler); + + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorTermination, r.Code()); + EXPECT_EQ(4, r.Offset()); + } + + { + HandlerTerminateAtStartArray handler; + Reader reader; + StringStream is("{\"a\": []}"); + + ParseResult r = reader.Parse(is, handler); + + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorTermination, r.Code()); + EXPECT_EQ(6, r.Offset()); + } + + { + HandlerTerminateAtEndObject handler; + Reader reader; + StringStream is("[1, {}]"); + + ParseResult r = reader.Parse(is, handler); + + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorTermination, r.Code()); + EXPECT_EQ(5, r.Offset()); + } + + { + HandlerTerminateAtEndArray handler; + Reader reader; + StringStream is("{\"a\": []}"); + + ParseResult r = reader.Parse(is, handler); + + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorTermination, r.Code()); + EXPECT_EQ(7, r.Offset()); + } +} + #ifdef __GNUC__ RAPIDJSON_DIAG_POP #endif