123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578 |
- #include "unittest.h"
- #define private public // For testing private members
- #include "rapidjson/reader.h"
- using namespace rapidjson;
- template<bool expect>
- struct ParseBoolHandler : BaseReaderHandler<> {
- ParseBoolHandler() : step_(0) {}
- void Default() { FAIL(); }
- void Bool(bool b) { EXPECT_EQ(expect, b); ++step_; }
- unsigned step_;
- };
- TEST(Reader, ParseTrue) {
- StringStream s("true");
- ParseBoolHandler<true> h;
- Reader reader;
- reader.ParseTrue<0>(s, h);
- EXPECT_EQ(1u, h.step_);
- }
- TEST(Reader, ParseFalse) {
- StringStream s("false");
- ParseBoolHandler<false> h;
- Reader reader;
- reader.ParseFalse<0>(s, h);
- EXPECT_EQ(1u, h.step_);
- }
- struct ParseIntHandler : BaseReaderHandler<> {
- ParseIntHandler() : step_(0) {}
- void Default() { FAIL(); }
- void Int(int i) { actual_ = i; step_++; }
- unsigned step_;
- int actual_;
- };
- struct ParseUintHandler : BaseReaderHandler<> {
- ParseUintHandler() : step_(0) {}
- void Default() { FAIL(); }
- void Uint(unsigned i) { actual_ = i; step_++; }
- unsigned step_;
- unsigned actual_;
- };
- struct ParseInt64Handler : BaseReaderHandler<> {
- ParseInt64Handler() : step_(0) {}
- void Default() { FAIL(); }
- void Int64(int64_t i) { actual_ = i; step_++; }
- unsigned step_;
- int64_t actual_;
- };
- struct ParseUint64Handler : BaseReaderHandler<> {
- ParseUint64Handler() : step_(0) {}
- void Default() { FAIL(); }
- void Uint64(uint64_t i) { actual_ = i; step_++; }
- unsigned step_;
- uint64_t actual_;
- };
- struct ParseDoubleHandler : BaseReaderHandler<> {
- ParseDoubleHandler() : step_(0) {}
- void Default() { FAIL(); }
- void Double(double d) { actual_ = d; step_++; }
- unsigned step_;
- double actual_;
- };
- TEST(Reader, ParseNumberHandler) {
- #define TEST_NUMBER(Handler, str, x) \
- { \
- StringStream s(str); \
- Handler h; \
- Reader reader; \
- reader.ParseNumber<0>(s, h); \
- EXPECT_EQ(1u, h.step_); \
- EXPECT_EQ(double(x), h.actual_); \
- }
- #define TEST_DOUBLE(str, x) \
- { \
- StringStream s(str); \
- ParseDoubleHandler h; \
- Reader reader; \
- reader.ParseNumber<0>(s, h); \
- EXPECT_EQ(1u, h.step_); \
- EXPECT_DOUBLE_EQ(x, h.actual_); \
- }
- TEST_NUMBER(ParseUintHandler, "0", 0);
- TEST_NUMBER(ParseUintHandler, "123", 123);
- TEST_NUMBER(ParseUintHandler, "2147483648", 2147483648u); // 2^31 - 1 (cannot be stored in int)
- TEST_NUMBER(ParseUintHandler, "4294967295", 4294967295u);
- TEST_NUMBER(ParseIntHandler, "-123", -123);
- TEST_NUMBER(ParseIntHandler, "-2147483648", -2147483648LL); // -2^31 (min of int)
- TEST_NUMBER(ParseUint64Handler, "4294967296", 4294967296ULL); // 2^32 (max of unsigned + 1, force to use uint64_t)
- TEST_NUMBER(ParseUint64Handler, "18446744073709551615", 18446744073709551615ULL); // 2^64 - 1 (max of uint64_t)
- TEST_NUMBER(ParseInt64Handler, "-2147483649", -2147483649LL); // -2^31 -1 (min of int - 1, force to use int64_t)
- TEST_NUMBER(ParseInt64Handler, "-9223372036854775808", (-9223372036854775807LL - 1)); // -2^63 (min of int64_t)
- TEST_DOUBLE("0.0", 0.0);
- TEST_DOUBLE("1.0", 1.0);
- TEST_DOUBLE("-1.0", -1.0);
- TEST_DOUBLE("1.5", 1.5);
- TEST_DOUBLE("-1.5", -1.5);
- TEST_DOUBLE("3.1416", 3.1416);
- TEST_DOUBLE("1E10", 1E10);
- TEST_DOUBLE("1e10", 1e10);
- TEST_DOUBLE("1E+10", 1E+10);
- TEST_DOUBLE("1E-10", 1E-10);
- TEST_DOUBLE("-1E10", -1E10);
- TEST_DOUBLE("-1e10", -1e10);
- TEST_DOUBLE("-1E+10", -1E+10);
- TEST_DOUBLE("-1E-10", -1E-10);
- TEST_DOUBLE("1.234E+10", 1.234E+10);
- TEST_DOUBLE("1.234E-10", 1.234E-10);
- TEST_DOUBLE("1.79769e+308", 1.79769e+308);
- //TEST_DOUBLE("2.22507e-308", 2.22507e-308); // TODO: underflow
- TEST_DOUBLE("-1.79769e+308", -1.79769e+308);
- //TEST_DOUBLE("-2.22507e-308", -2.22507e-308); // TODO: underflow
- TEST_DOUBLE("18446744073709551616", 18446744073709551616.0); // 2^64 (max of uint64_t + 1, force to use double)
- TEST_DOUBLE("-9223372036854775809", -9223372036854775809.0); // -2^63 - 1(min of int64_t + 1, force to use double)
- {
- char n1e308[310]; // '1' followed by 308 '0'
- n1e308[0] = '1';
- for (int i = 1; i < 309; i++)
- n1e308[i] = '0';
- n1e308[309] = '\0';
- TEST_DOUBLE(n1e308, 1E308);
- }
- #undef TEST_NUMBER
- #undef TEST_DOUBLE
- }
- TEST(Reader, ParseNumberHandler_Error) {
- #define TEST_NUMBER_ERROR(str) \
- { \
- char buffer[1001]; \
- sprintf(buffer, "[%s]", str); \
- InsituStringStream s(buffer); \
- BaseReaderHandler<> h; \
- Reader reader; \
- EXPECT_FALSE(reader.Parse<0>(s, h)); \
- }
- TEST_NUMBER_ERROR("a"); // At least one digit in integer part
- TEST_NUMBER_ERROR(".1"); // At least one digit in integer part
-
- {
- char n1e309[311]; // '1' followed by 309 '0'
- n1e309[0] = '1';
- for (int i = 1; i < 310; i++)
- n1e309[i] = '0';
- n1e309[310] = '\0';
- TEST_NUMBER_ERROR(n1e309); // Number too big to store in double
- }
- TEST_NUMBER_ERROR("1."); // At least one digit in fraction part
- TEST_NUMBER_ERROR("1e309"); // Number too big to store in double
- TEST_NUMBER_ERROR("1e_"); // At least one digit in exponent
- #undef TEST_NUMBER_ERROR
- }
- template <typename Encoding>
- struct ParseStringHandler : BaseReaderHandler<Encoding> {
- ParseStringHandler() : str_(0), length_(0) {}
- ~ParseStringHandler() { EXPECT_TRUE(str_ != 0); if (copy_) free(const_cast<typename Encoding::Ch*>(str_)); }
- void Default() { FAIL(); }
- void String(const typename Encoding::Ch* str, size_t length, bool copy) {
- EXPECT_EQ(0, str_);
- if (copy) {
- str_ = (typename Encoding::Ch*)malloc((length + 1) * sizeof(typename Encoding::Ch));
- memcpy((void*)str_, str, (length + 1) * sizeof(typename Encoding::Ch));
- }
- else
- str_ = str;
- length_ = length;
- copy_ = copy;
- }
- const typename Encoding::Ch* str_;
- size_t length_;
- bool copy_;
- };
- TEST(Reader, ParseString) {
- #define TEST_STRING(Encoding, e, x) \
- { \
- Encoding::Ch* buffer = StrDup(x); \
- GenericInsituStringStream<Encoding> is(buffer); \
- ParseStringHandler<Encoding> h; \
- GenericReader<Encoding, Encoding> reader; \
- reader.ParseString<kParseInsituFlag | kParseValidateEncodingFlag>(is, h); \
- EXPECT_EQ(0, StrCmp<Encoding::Ch>(e, h.str_)); \
- EXPECT_EQ(StrLen(e), h.length_); \
- free(buffer); \
- GenericStringStream<Encoding> s(x); \
- ParseStringHandler<Encoding> h2; \
- GenericReader<Encoding, Encoding> reader2; \
- reader2.ParseString<0>(s, h2); \
- EXPECT_EQ(0, StrCmp<Encoding::Ch>(e, h2.str_)); \
- EXPECT_EQ(StrLen(e), h2.length_); \
- }
- // 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.
- #define ARRAY(...) { __VA_ARGS__ }
- #define TEST_STRINGARRAY(Encoding, array, x) \
- { \
- static const Encoding::Ch e[] = array; \
- TEST_STRING(Encoding, e, x); \
- }
- #define TEST_STRINGARRAY2(Encoding, earray, xarray) \
- { \
- static const Encoding::Ch e[] = earray; \
- static const Encoding::Ch x[] = xarray; \
- TEST_STRING(Encoding, e, x); \
- }
- TEST_STRING(UTF8<>, "", "\"\"");
- TEST_STRING(UTF8<>, "Hello", "\"Hello\"");
- TEST_STRING(UTF8<>, "Hello\nWorld", "\"Hello\\nWorld\"");
- TEST_STRING(UTF8<>, "\"\\/\b\f\n\r\t", "\"\\\"\\\\/\\b\\f\\n\\r\\t\"");
- TEST_STRING(UTF8<>, "\x24", "\"\\u0024\""); // Dollar sign U+0024
- TEST_STRING(UTF8<>, "\xC2\xA2", "\"\\u00A2\""); // Cents sign U+00A2
- TEST_STRING(UTF8<>, "\xE2\x82\xAC", "\"\\u20AC\""); // Euro sign U+20AC
- TEST_STRING(UTF8<>, "\xF0\x9D\x84\x9E", "\"\\uD834\\uDD1E\""); // G clef sign U+1D11E
- // UTF16
- TEST_STRING(UTF16<>, L"", L"\"\"");
- TEST_STRING(UTF16<>, L"Hello", L"\"Hello\"");
- TEST_STRING(UTF16<>, L"Hello\nWorld", L"\"Hello\\nWorld\"");
- TEST_STRING(UTF16<>, L"\"\\/\b\f\n\r\t", L"\"\\\"\\\\/\\b\\f\\n\\r\\t\"");
- TEST_STRINGARRAY(UTF16<>, ARRAY(0x0024, 0x0000), L"\"\\u0024\"");
- TEST_STRINGARRAY(UTF16<>, ARRAY(0x00A2, 0x0000), L"\"\\u00A2\""); // Cents sign U+00A2
- TEST_STRINGARRAY(UTF16<>, ARRAY(0x20AC, 0x0000), L"\"\\u20AC\""); // Euro sign U+20AC
- TEST_STRINGARRAY(UTF16<>, ARRAY(0xD834, 0xDD1E, 0x0000), L"\"\\uD834\\uDD1E\""); // G clef sign U+1D11E
- // UTF32
- TEST_STRINGARRAY2(UTF32<>, ARRAY('\0'), ARRAY('\"', '\"', '\0'));
- TEST_STRINGARRAY2(UTF32<>, ARRAY('H', 'e', 'l', 'l', 'o', '\0'), ARRAY('\"', 'H', 'e', 'l', 'l', 'o', '\"', '\0'));
- TEST_STRINGARRAY2(UTF32<>, ARRAY('H', 'e', 'l', 'l', 'o', '\n', 'W', 'o', 'r', 'l', 'd', '\0'), ARRAY('\"', 'H', 'e', 'l', 'l', 'o', '\\', 'n', 'W', 'o', 'r', 'l', 'd', '\"', '\0'));
- TEST_STRINGARRAY2(UTF32<>, ARRAY('\"', '\\', '/', '\b', '\f', '\n', '\r', '\t', '\0'), ARRAY('\"', '\\', '\"', '\\', '\\', '/', '\\', 'b', '\\', 'f', '\\', 'n', '\\', 'r', '\\', 't', '\"', '\0'));
- TEST_STRINGARRAY2(UTF32<>, ARRAY(0x00024, 0x0000), ARRAY('\"', '\\', 'u', '0', '0', '2', '4', '\"', '\0'));
- TEST_STRINGARRAY2(UTF32<>, ARRAY(0x000A2, 0x0000), ARRAY('\"', '\\', 'u', '0', '0', 'A', '2', '\"', '\0')); // Cents sign U+00A2
- TEST_STRINGARRAY2(UTF32<>, ARRAY(0x020AC, 0x0000), ARRAY('\"', '\\', 'u', '2', '0', 'A', 'C', '\"', '\0')); // Euro sign U+20AC
- TEST_STRINGARRAY2(UTF32<>, ARRAY(0x1D11E, 0x0000), ARRAY('\"', '\\', 'u', 'D', '8', '3', '4', '\\', 'u', 'D', 'D', '1', 'E', '\"', '\0')); // G clef sign U+1D11E
- #undef TEST_STRINGARRAY
- #undef ARRAY
- #undef TEST_STRING
- // Support of null character in string
- {
- StringStream s("\"Hello\\u0000World\"");
- const char e[] = "Hello\0World";
- ParseStringHandler<UTF8<> > h;
- Reader reader;
- reader.ParseString<0>(s, h);
- EXPECT_EQ(0, memcmp(e, h.str_, h.length_ + 1));
- EXPECT_EQ(11u, h.length_);
- }
- }
- TEST(Reader, ParseString_Transcoding) {
- const char* x = "\"Hello\"";
- const wchar_t* e = L"Hello";
- GenericStringStream<UTF8<> > is(x);
- GenericReader<UTF8<>, UTF16<> > reader;
- ParseStringHandler<UTF16<> > h;
- reader.ParseString<0>(is, h);
- EXPECT_EQ(0, StrCmp<UTF16<>::Ch>(e, h.str_));
- EXPECT_EQ(StrLen(e), h.length_);
- }
- TEST(Reader, ParseString_NonDestructive) {
- StringStream s("\"Hello\\nWorld\"");
- ParseStringHandler<UTF8<> > h;
- Reader reader;
- reader.ParseString<0>(s, h);
- EXPECT_EQ(0, StrCmp("Hello\nWorld", h.str_));
- EXPECT_EQ(11u, h.length_);
- }
- bool TestString(const char* str) {
- StringStream s(str);
- BaseReaderHandler<> h;
- Reader reader;
- return reader.Parse<kParseValidateEncodingFlag>(s, h);
- }
- TEST(Reader, ParseString_Error) {
- #define ARRAY(...) { __VA_ARGS__ }
- #define TEST_STRINGARRAY_ERROR(Encoding, array) \
- { \
- static const Encoding::Ch e[] = array; \
- EXPECT_FALSE(TestString(e)); \
- }
- EXPECT_FALSE(TestString("[\"\\a\"]")); // Unknown escape character
- EXPECT_FALSE(TestString("[\"\\uABCG\"]")); // Incorrect hex digit after \\u escape
- EXPECT_FALSE(TestString("[\"\\uD800X\"]")); // Missing the second \\u in surrogate pair
- EXPECT_FALSE(TestString("[\"\\uD800\\uFFFF\"]")); // The second \\u in surrogate pair is invalid
- EXPECT_FALSE(TestString("[\"Test]")); // lacks ending quotation before the end of string
- // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
- // 3 Malformed sequences
- // 3.1 Unexpected continuation bytes
- {
- char e[] = { '[', '\"', 0, '\"', ']', '\0' };
- for (unsigned char c = 0x80u; c <= 0xBFu; c++) {
- e[2] = c;
- bool b = TestString(e);
- EXPECT_FALSE(b);
- if (b)
- std::cout << (unsigned)(unsigned char)c << std::endl;
- }
- }
- // 3.2 Lonely start characters, 3.5 Impossible bytes
- {
- char e[] = { '[', '\"', 0, ' ', '\"', ']', '\0' };
- for (unsigned c = 0xC0u; c <= 0xFFu; c++) {
- e[2] = (char)c;
- EXPECT_FALSE(TestString(e));
- }
- }
- // 4 Overlong sequences
- // 4.1 Examples of an overlong ASCII character
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xC0u, 0xAFu, '\"', ']', '\0'));
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xE0u, 0x80u, 0xAFu, '\"', ']', '\0'));
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0xAFu, '\"', ']', '\0'));
- // 4.2 Maximum overlong sequences
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xC1u, 0xBFu, '\"', ']', '\0'));
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xE0u, 0x9Fu, 0xBFu, '\"', ']', '\0'));
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xF0u, 0x8Fu, 0xBFu, 0xBFu, '\"', ']', '\0'));
- // 4.3 Overlong representation of the NUL character
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xC0u, 0x80u, '\"', ']', '\0'));
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xE0u, 0x80u, 0x80u, '\"', ']', '\0'));
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0x80u, '\"', ']', '\0'));
- // 5 Illegal code positions
- // 5.1 Single UTF-16 surrogates
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xEDu, 0xA0u, 0x80u, '\"', ']', '\0'));
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xEDu, 0xADu, 0xBFu, '\"', ']', '\0'));
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xEDu, 0xAEu, 0x80u, '\"', ']', '\0'));
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xEDu, 0xAFu, 0xBFu, '\"', ']', '\0'));
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xEDu, 0xB0u, 0x80u, '\"', ']', '\0'));
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xEDu, 0xBEu, 0x80u, '\"', ']', '\0'));
- TEST_STRINGARRAY_ERROR(UTF8<>, ARRAY('[', '\"', 0xEDu, 0xBFu, 0xBFu, '\"', ']', '\0'));
- #undef ARRAY
- #undef TEST_STRINGARRAY_ERROR
- }
- template <unsigned count>
- struct ParseArrayHandler : BaseReaderHandler<> {
- ParseArrayHandler() : step_(0) {}
- void Default() { FAIL(); }
- void Uint(unsigned i) { EXPECT_EQ(step_, i); step_++; }
- void StartArray() { EXPECT_EQ(0u, step_); step_++; }
- void EndArray(SizeType) { step_++; }
- unsigned step_;
- };
- TEST(Reader, ParseEmptyArray) {
- char *json = StrDup("[ ] ");
- InsituStringStream s(json);
- ParseArrayHandler<0> h;
- Reader reader;
- reader.ParseArray<0>(s, h);
- EXPECT_EQ(2u, h.step_);
- free(json);
- }
- TEST(Reader, ParseArray) {
- char *json = StrDup("[1, 2, 3, 4]");
- InsituStringStream s(json);
- ParseArrayHandler<4> h;
- Reader reader;
- reader.ParseArray<0>(s, h);
- EXPECT_EQ(6u, h.step_);
- free(json);
- }
- TEST(Reader, ParseArray_Error) {
- #define TEST_ARRAY_ERROR(str) \
- { \
- char buffer[1001]; \
- strncpy(buffer, str, 1000); \
- InsituStringStream s(buffer); \
- BaseReaderHandler<> h; \
- GenericReader<UTF8<>, UTF8<>, CrtAllocator> reader; \
- EXPECT_FALSE(reader.Parse<0>(s, h)); \
- }
- // Must be a comma or ']' after an array element.
- TEST_ARRAY_ERROR("[");
- TEST_ARRAY_ERROR("[}");
- TEST_ARRAY_ERROR("[1 2]");
- #undef TEST_ARRAY_ERROR
- }
- struct ParseObjectHandler : BaseReaderHandler<> {
- ParseObjectHandler() : step_(0) {}
- void Null() { EXPECT_EQ(8u, step_); step_++; }
- void Bool(bool b) {
- switch(step_) {
- case 4: EXPECT_TRUE(b); step_++; break;
- case 6: EXPECT_FALSE(b); step_++; break;
- default: FAIL();
- }
- }
- void Int(int i) {
- switch(step_) {
- case 10: EXPECT_EQ(123, i); step_++; break;
- case 15: EXPECT_EQ(1, i); step_++; break;
- case 16: EXPECT_EQ(2, i); step_++; break;
- case 17: EXPECT_EQ(3, i); step_++; break;
- default: FAIL();
- }
- }
- void Uint(unsigned i) { Int(i); }
- void Double(double d) { EXPECT_EQ(12u, step_); EXPECT_EQ(3.1416, d); step_++; }
- void String(const char* str, size_t, bool) {
- switch(step_) {
- case 1: EXPECT_STREQ("hello", str); step_++; break;
- case 2: EXPECT_STREQ("world", str); step_++; break;
- case 3: EXPECT_STREQ("t", str); step_++; break;
- case 5: EXPECT_STREQ("f", str); step_++; break;
- case 7: EXPECT_STREQ("n", str); step_++; break;
- case 9: EXPECT_STREQ("i", str); step_++; break;
- case 11: EXPECT_STREQ("pi", str); step_++; break;
- case 13: EXPECT_STREQ("a", str); step_++; break;
- default: FAIL();
- }
- }
- void StartObject() { EXPECT_EQ(0u, step_); step_++; }
- void EndObject(SizeType memberCount) { EXPECT_EQ(19u, step_); EXPECT_EQ(7u, memberCount); step_++;}
- void StartArray() { EXPECT_EQ(14u, step_); step_++; }
- void EndArray(SizeType elementCount) { EXPECT_EQ(18u, step_); EXPECT_EQ(3u, elementCount); step_++;}
- unsigned step_;
- };
- TEST(Reader, ParseObject) {
- const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } ";
- // Insitu
- {
- char* json2 = StrDup(json);
- InsituStringStream s(json2);
- ParseObjectHandler h;
- Reader reader;
- reader.ParseObject<kParseInsituFlag>(s, h);
- EXPECT_EQ(20u, h.step_);
- free(json2);
- }
- // Normal
- {
- StringStream s(json);
- ParseObjectHandler h;
- Reader reader;
- reader.ParseObject<0>(s, h);
- EXPECT_EQ(20u, h.step_);
- }
- }
- struct ParseEmptyObjectHandler : BaseReaderHandler<> {
- ParseEmptyObjectHandler() : step_(0) {}
- void Default() { FAIL(); }
- void StartObject() { EXPECT_EQ(0u, step_); step_++; }
- void EndObject(SizeType) { EXPECT_EQ(1u, step_); step_++; }
- unsigned step_;
- };
- TEST(Reader, Parse_EmptyObject) {
- StringStream s("{ } ");
- ParseEmptyObjectHandler h;
- Reader reader;
- reader.ParseObject<0>(s, h);
- EXPECT_EQ(2u, h.step_);
- }
- TEST(Reader, ParseObject_Error) {
- #define TEST_OBJECT_ERROR(str) \
- { \
- char buffer[1001]; \
- strncpy(buffer, str, 1000); \
- InsituStringStream s(buffer); \
- BaseReaderHandler<> h; \
- GenericReader<UTF8<>, UTF8<>, CrtAllocator> reader; \
- EXPECT_FALSE(reader.Parse<0>(s, h)); \
- }
- // Name of an object member must be a string
- TEST_OBJECT_ERROR("{null:1}");
- TEST_OBJECT_ERROR("{true:1}");
- TEST_OBJECT_ERROR("{false:1}");
- TEST_OBJECT_ERROR("{1:1}");
- TEST_OBJECT_ERROR("{[]:1}");
- TEST_OBJECT_ERROR("{{}:1}");
- TEST_OBJECT_ERROR("{xyz:1}");
- // There must be a colon after the name of object member
- TEST_OBJECT_ERROR("{\"a\" 1}");
- TEST_OBJECT_ERROR("{\"a\",1}");
- // Must be a comma or '}' after an object member
- TEST_OBJECT_ERROR("{]");
- TEST_OBJECT_ERROR("{\"a\":1]");
- #undef TEST_OBJECT_ERROR
- }
- TEST(Reader, Parse_Error) {
- #define TEST_ERROR(str) \
- { \
- char buffer[1001]; \
- strncpy(buffer, str, 1000); \
- InsituStringStream s(buffer); \
- BaseReaderHandler<> h; \
- Reader reader; \
- EXPECT_FALSE(reader.Parse<0>(s, h)); \
- }
- // Text only contains white space(s)
- TEST_ERROR("");
- TEST_ERROR(" ");
- TEST_ERROR(" \n");
- // Expect either an object or array at root
- TEST_ERROR("null");
- TEST_ERROR("true");
- TEST_ERROR("false");
- TEST_ERROR("\"s\"");
- TEST_ERROR("0");
- // Nothing should follow the root object or array
- TEST_ERROR("[] 0");
- TEST_ERROR("{} 0");
- // Invalid value
- TEST_ERROR("nulL");
- TEST_ERROR("truE");
- TEST_ERROR("falsE");
- #undef TEST_ERROR
- }
|