Commit ab250d21 authored by Milo Yip's avatar Milo Yip

Rectify parsing error offsets

parent 37711887
This diff is collapsed.
...@@ -418,7 +418,7 @@ TEST(Reader, ParseNumber_NormalPrecisionError) { ...@@ -418,7 +418,7 @@ TEST(Reader, ParseNumber_NormalPrecisionError) {
} }
TEST(Reader, ParseNumber_Error) { TEST(Reader, ParseNumber_Error) {
#define TEST_NUMBER_ERROR(errorCode, str) \ #define TEST_NUMBER_ERROR(errorCode, str, errorOffset) \
{ \ { \
char buffer[1001]; \ char buffer[1001]; \
sprintf(buffer, "%s", str); \ sprintf(buffer, "%s", str); \
...@@ -427,6 +427,7 @@ TEST(Reader, ParseNumber_Error) { ...@@ -427,6 +427,7 @@ TEST(Reader, ParseNumber_Error) {
Reader reader; \ Reader reader; \
EXPECT_FALSE(reader.Parse(s, h)); \ EXPECT_FALSE(reader.Parse(s, h)); \
EXPECT_EQ(errorCode, reader.GetParseErrorCode());\ EXPECT_EQ(errorCode, reader.GetParseErrorCode());\
EXPECT_EQ(errorOffset, reader.GetErrorOffset());\
} }
// Number too big to be stored in double. // Number too big to be stored in double.
...@@ -436,17 +437,17 @@ TEST(Reader, ParseNumber_Error) { ...@@ -436,17 +437,17 @@ TEST(Reader, ParseNumber_Error) {
for (int i = 1; i < 310; i++) for (int i = 1; i < 310; i++)
n1e309[i] = '0'; n1e309[i] = '0';
n1e309[310] = '\0'; n1e309[310] = '\0';
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, n1e309); TEST_NUMBER_ERROR(kParseErrorNumberTooBig, n1e309, 0);
} }
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e309"); TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e309", 0);
// Miss fraction part in number. // Miss fraction part in number.
TEST_NUMBER_ERROR(kParseErrorNumberMissFraction, "1."); TEST_NUMBER_ERROR(kParseErrorNumberMissFraction, "1.", 2);
TEST_NUMBER_ERROR(kParseErrorNumberMissFraction, "1.a"); TEST_NUMBER_ERROR(kParseErrorNumberMissFraction, "1.a", 2);
// Miss exponent in number. // Miss exponent in number.
TEST_NUMBER_ERROR(kParseErrorNumberMissExponent, "1e"); TEST_NUMBER_ERROR(kParseErrorNumberMissExponent, "1e", 2);
TEST_NUMBER_ERROR(kParseErrorNumberMissExponent, "1e_"); TEST_NUMBER_ERROR(kParseErrorNumberMissExponent, "1e_", 2);
#undef TEST_NUMBER_ERROR #undef TEST_NUMBER_ERROR
} }
...@@ -604,8 +605,15 @@ ParseErrorCode TestString(const typename Encoding::Ch* str) { ...@@ -604,8 +605,15 @@ ParseErrorCode TestString(const typename Encoding::Ch* str) {
} }
TEST(Reader, ParseString_Error) { TEST(Reader, ParseString_Error) {
#define TEST_STRING_ERROR(errorCode, str)\ #define TEST_STRING_ERROR(errorCode, str, errorOffset)\
EXPECT_EQ(errorCode, TestString<UTF8<> >(str)) {\
GenericStringStream<UTF8<> > s(str);\
BaseReaderHandler<UTF8<> > h;\
GenericReader<UTF8<> , UTF8<> > reader;\
reader.template Parse<kParseValidateEncodingFlag>(s, h);\
EXPECT_EQ(errorCode, reader.GetParseErrorCode());\
EXPECT_EQ(errorOffset, reader.GetErrorOffset());\
}
#define ARRAY(...) { __VA_ARGS__ } #define ARRAY(...) { __VA_ARGS__ }
#define TEST_STRINGENCODING_ERROR(Encoding, TargetEncoding, utype, array) \ #define TEST_STRINGENCODING_ERROR(Encoding, TargetEncoding, utype, array) \
...@@ -622,21 +630,21 @@ TEST(Reader, ParseString_Error) { ...@@ -622,21 +630,21 @@ TEST(Reader, ParseString_Error) {
} }
// Invalid escape character in string. // Invalid escape character in string.
TEST_STRING_ERROR(kParseErrorStringEscapeInvalid, "[\"\\a\"]"); TEST_STRING_ERROR(kParseErrorStringEscapeInvalid, "[\"\\a\"]", 2);
// Incorrect hex digit after \\u escape in string. // Incorrect hex digit after \\u escape in string.
TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uABCG\"]"); TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uABCG\"]", 2);
// Quotation in \\u escape in string (Issue #288) // Quotation in \\u escape in string (Issue #288)
TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uaaa\"]"); TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uaaa\"]", 2);
TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uD800\\uFFF\"]"); TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uD800\\uFFF\"]", 2);
// The surrogate pair in string is invalid. // The surrogate pair in string is invalid.
TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800X\"]"); TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800X\"]", 2);
TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800\\uFFFF\"]"); TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800\\uFFFF\"]", 2);
// Missing a closing quotation mark in string. // Missing a closing quotation mark in string.
TEST_STRING_ERROR(kParseErrorStringMissQuotationMark, "[\"Test]"); TEST_STRING_ERROR(kParseErrorStringMissQuotationMark, "[\"Test]", 7);
// http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
...@@ -659,7 +667,7 @@ TEST(Reader, ParseString_Error) { ...@@ -659,7 +667,7 @@ TEST(Reader, ParseString_Error) {
char e[] = { '[', '\"', 0, ' ', '\"', ']', '\0' }; char e[] = { '[', '\"', 0, ' ', '\"', ']', '\0' };
for (unsigned c = 0xC0u; c <= 0xFFu; c++) { for (unsigned c = 0xC0u; c <= 0xFFu; c++) {
e[2] = static_cast<char>(c); e[2] = static_cast<char>(c);
TEST_STRING_ERROR(kParseErrorStringInvalidEncoding, e); TEST_STRING_ERROR(kParseErrorStringInvalidEncoding, e, 2);
} }
} }
...@@ -738,7 +746,7 @@ TEST(Reader, ParseArray) { ...@@ -738,7 +746,7 @@ TEST(Reader, ParseArray) {
} }
TEST(Reader, ParseArray_Error) { TEST(Reader, ParseArray_Error) {
#define TEST_ARRAY_ERROR(errorCode, str) \ #define TEST_ARRAY_ERROR(errorCode, str, errorOffset) \
{ \ { \
char buffer[1001]; \ char buffer[1001]; \
strncpy(buffer, str, 1000); \ strncpy(buffer, str, 1000); \
...@@ -747,12 +755,13 @@ TEST(Reader, ParseArray_Error) { ...@@ -747,12 +755,13 @@ TEST(Reader, ParseArray_Error) {
GenericReader<UTF8<>, UTF8<>, CrtAllocator> reader; \ GenericReader<UTF8<>, UTF8<>, CrtAllocator> reader; \
EXPECT_FALSE(reader.Parse(s, h)); \ EXPECT_FALSE(reader.Parse(s, h)); \
EXPECT_EQ(errorCode, reader.GetParseErrorCode());\ EXPECT_EQ(errorCode, reader.GetParseErrorCode());\
EXPECT_EQ(errorOffset, reader.GetErrorOffset());\
} }
// Missing a comma or ']' after an array element. // Missing a comma or ']' after an array element.
TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1"); TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1", 2);
TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1}"); TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1}", 2);
TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1 2]"); TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1 2]", 3);
#undef TEST_ARRAY_ERROR #undef TEST_ARRAY_ERROR
} }
...@@ -899,7 +908,7 @@ TEST(Reader, ParseInsituIterative_MultipleRoot) { ...@@ -899,7 +908,7 @@ TEST(Reader, ParseInsituIterative_MultipleRoot) {
TestInsituMultipleRoot<kParseIterativeFlag | kParseStopWhenDoneFlag>(); TestInsituMultipleRoot<kParseIterativeFlag | kParseStopWhenDoneFlag>();
} }
#define TEST_ERROR(errorCode, str) \ #define TEST_ERROR(errorCode, str, errorOffset) \
{ \ { \
char buffer[1001]; \ char buffer[1001]; \
strncpy(buffer, str, 1000); \ strncpy(buffer, str, 1000); \
...@@ -908,48 +917,49 @@ TEST(Reader, ParseInsituIterative_MultipleRoot) { ...@@ -908,48 +917,49 @@ TEST(Reader, ParseInsituIterative_MultipleRoot) {
Reader reader; \ Reader reader; \
EXPECT_FALSE(reader.Parse(s, h)); \ EXPECT_FALSE(reader.Parse(s, h)); \
EXPECT_EQ(errorCode, reader.GetParseErrorCode());\ EXPECT_EQ(errorCode, reader.GetParseErrorCode());\
EXPECT_EQ(errorOffset, reader.GetErrorOffset());\
} }
TEST(Reader, ParseDocument_Error) { TEST(Reader, ParseDocument_Error) {
// The document is empty. // The document is empty.
TEST_ERROR(kParseErrorDocumentEmpty, ""); TEST_ERROR(kParseErrorDocumentEmpty, "", 0);
TEST_ERROR(kParseErrorDocumentEmpty, " "); TEST_ERROR(kParseErrorDocumentEmpty, " ", 1);
TEST_ERROR(kParseErrorDocumentEmpty, " \n"); TEST_ERROR(kParseErrorDocumentEmpty, " \n", 2);
// The document root must not follow by other values. // The document root must not follow by other values.
TEST_ERROR(kParseErrorDocumentRootNotSingular, "[] 0"); TEST_ERROR(kParseErrorDocumentRootNotSingular, "[] 0", 3);
TEST_ERROR(kParseErrorDocumentRootNotSingular, "{} 0"); TEST_ERROR(kParseErrorDocumentRootNotSingular, "{} 0", 3);
TEST_ERROR(kParseErrorDocumentRootNotSingular, "null []"); TEST_ERROR(kParseErrorDocumentRootNotSingular, "null []", 5);
TEST_ERROR(kParseErrorDocumentRootNotSingular, "0 {}"); TEST_ERROR(kParseErrorDocumentRootNotSingular, "0 {}", 2);
} }
TEST(Reader, ParseValue_Error) { TEST(Reader, ParseValue_Error) {
// Invalid value. // Invalid value.
TEST_ERROR(kParseErrorValueInvalid, "nulL"); TEST_ERROR(kParseErrorValueInvalid, "nulL", 3);
TEST_ERROR(kParseErrorValueInvalid, "truE"); TEST_ERROR(kParseErrorValueInvalid, "truE", 3);
TEST_ERROR(kParseErrorValueInvalid, "falsE"); TEST_ERROR(kParseErrorValueInvalid, "falsE", 4);
TEST_ERROR(kParseErrorValueInvalid, "a]"); TEST_ERROR(kParseErrorValueInvalid, "a]", 0);
TEST_ERROR(kParseErrorValueInvalid, ".1"); TEST_ERROR(kParseErrorValueInvalid, ".1", 0);
} }
TEST(Reader, ParseObject_Error) { TEST(Reader, ParseObject_Error) {
// Missing a name for object member. // Missing a name for object member.
TEST_ERROR(kParseErrorObjectMissName, "{1}"); TEST_ERROR(kParseErrorObjectMissName, "{1}", 1);
TEST_ERROR(kParseErrorObjectMissName, "{:1}"); TEST_ERROR(kParseErrorObjectMissName, "{:1}", 1);
TEST_ERROR(kParseErrorObjectMissName, "{null:1}"); TEST_ERROR(kParseErrorObjectMissName, "{null:1}", 1);
TEST_ERROR(kParseErrorObjectMissName, "{true:1}"); TEST_ERROR(kParseErrorObjectMissName, "{true:1}", 1);
TEST_ERROR(kParseErrorObjectMissName, "{false:1}"); TEST_ERROR(kParseErrorObjectMissName, "{false:1}", 1);
TEST_ERROR(kParseErrorObjectMissName, "{1:1}"); TEST_ERROR(kParseErrorObjectMissName, "{1:1}", 1);
TEST_ERROR(kParseErrorObjectMissName, "{[]:1}"); TEST_ERROR(kParseErrorObjectMissName, "{[]:1}", 1);
TEST_ERROR(kParseErrorObjectMissName, "{{}:1}"); TEST_ERROR(kParseErrorObjectMissName, "{{}:1}", 1);
TEST_ERROR(kParseErrorObjectMissName, "{xyz:1}"); TEST_ERROR(kParseErrorObjectMissName, "{xyz:1}", 1);
// Missing a colon after a name of object member. // Missing a colon after a name of object member.
TEST_ERROR(kParseErrorObjectMissColon, "{\"a\" 1}"); TEST_ERROR(kParseErrorObjectMissColon, "{\"a\" 1}", 5);
TEST_ERROR(kParseErrorObjectMissColon, "{\"a\",1}"); TEST_ERROR(kParseErrorObjectMissColon, "{\"a\",1}", 4);
// Must be a comma or '}' after an object member // Must be a comma or '}' after an object member
TEST_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, "{\"a\":1]"); TEST_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, "{\"a\":1]", 6);
// This tests that MemoryStream is checking the length in Peek(). // This tests that MemoryStream is checking the length in Peek().
{ {
...@@ -1089,10 +1099,10 @@ TEST(Reader, IterativeParsing_ErrorHandling) { ...@@ -1089,10 +1099,10 @@ TEST(Reader, IterativeParsing_ErrorHandling) {
TESTERRORHANDLING("{\"a\"}", kParseErrorObjectMissColon, 4u); TESTERRORHANDLING("{\"a\"}", kParseErrorObjectMissColon, 4u);
TESTERRORHANDLING("{\"a\": 1", kParseErrorObjectMissCommaOrCurlyBracket, 7u); TESTERRORHANDLING("{\"a\": 1", kParseErrorObjectMissCommaOrCurlyBracket, 7u);
TESTERRORHANDLING("[1 2 3]", kParseErrorArrayMissCommaOrSquareBracket, 3u); TESTERRORHANDLING("[1 2 3]", kParseErrorArrayMissCommaOrSquareBracket, 3u);
TESTERRORHANDLING("{\"a: 1", kParseErrorStringMissQuotationMark, 5u); TESTERRORHANDLING("{\"a: 1", kParseErrorStringMissQuotationMark, 6u);
// Any JSON value can be a valid root element in RFC7159. // Any JSON value can be a valid root element in RFC7159.
TESTERRORHANDLING("\"ab", kParseErrorStringMissQuotationMark, 2u); TESTERRORHANDLING("\"ab", kParseErrorStringMissQuotationMark, 3u);
TESTERRORHANDLING("truE", kParseErrorValueInvalid, 3u); TESTERRORHANDLING("truE", kParseErrorValueInvalid, 3u);
TESTERRORHANDLING("False", kParseErrorValueInvalid, 0u); TESTERRORHANDLING("False", kParseErrorValueInvalid, 0u);
TESTERRORHANDLING("true, false", kParseErrorDocumentRootNotSingular, 4u); TESTERRORHANDLING("true, false", kParseErrorDocumentRootNotSingular, 4u);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment