diff options
author | 2016-03-12 12:31:13 +0100 | |
---|---|---|
committer | 2016-03-12 12:31:13 +0100 | |
commit | a026a582f1a0ea8c1ede3acaddacef506ef3f3b0 (patch) | |
tree | e31573822f2359677de519f9f3b600d98e8764cd /3rdparty/rapidjson/test | |
parent | 477d2abd43984f076b7e45f5527591fa8fd0d241 (diff) | |
parent | dcab55bf53b94713a6f72e9633f5101c8dd6c08c (diff) |
Merge pull request #15 from mamedev/master
Sync to base master
Diffstat (limited to '3rdparty/rapidjson/test')
-rw-r--r-- | 3rdparty/rapidjson/test/perftest/CMakeLists.txt | 9 | ||||
-rw-r--r-- | 3rdparty/rapidjson/test/perftest/perftest.h | 2 | ||||
-rw-r--r-- | 3rdparty/rapidjson/test/perftest/rapidjsontest.cpp | 19 | ||||
-rw-r--r-- | 3rdparty/rapidjson/test/unittest/CMakeLists.txt | 9 | ||||
-rw-r--r-- | 3rdparty/rapidjson/test/unittest/documenttest.cpp | 63 | ||||
-rw-r--r-- | 3rdparty/rapidjson/test/unittest/dtoatest.cpp | 6 | ||||
-rw-r--r-- | 3rdparty/rapidjson/test/unittest/readertest.cpp | 72 | ||||
-rw-r--r-- | 3rdparty/rapidjson/test/unittest/schematest.cpp | 18 | ||||
-rw-r--r-- | 3rdparty/rapidjson/test/unittest/simdtest.cpp | 22 | ||||
-rw-r--r-- | 3rdparty/rapidjson/test/unittest/valuetest.cpp | 370 |
10 files changed, 527 insertions, 63 deletions
diff --git a/3rdparty/rapidjson/test/perftest/CMakeLists.txt b/3rdparty/rapidjson/test/perftest/CMakeLists.txt index c88cf707451..c33aae469a3 100644 --- a/3rdparty/rapidjson/test/perftest/CMakeLists.txt +++ b/3rdparty/rapidjson/test/perftest/CMakeLists.txt @@ -10,6 +10,15 @@ target_link_libraries(perftest ${TEST_LIBRARIES}) add_dependencies(tests perftest) +find_program(CCACHE_FOUND ccache) +if(CCACHE_FOUND) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fcolor-diagnostics") + endif() +endif(CCACHE_FOUND) + IF(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug")) add_test(NAME perftest COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/perftest diff --git a/3rdparty/rapidjson/test/perftest/perftest.h b/3rdparty/rapidjson/test/perftest/perftest.h index 029940934c7..b098e414720 100644 --- a/3rdparty/rapidjson/test/perftest/perftest.h +++ b/3rdparty/rapidjson/test/perftest/perftest.h @@ -30,6 +30,8 @@ # define RAPIDJSON_SSE2 #endif +#define RAPIDJSON_HAS_STDSTRING 1 + //////////////////////////////////////////////////////////////////////////////// // Google Test diff --git a/3rdparty/rapidjson/test/perftest/rapidjsontest.cpp b/3rdparty/rapidjson/test/perftest/rapidjsontest.cpp index 74424ac332b..675db3182a5 100644 --- a/3rdparty/rapidjson/test/perftest/rapidjsontest.cpp +++ b/3rdparty/rapidjson/test/perftest/rapidjsontest.cpp @@ -187,6 +187,25 @@ TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_MemoryPoolAllocator)) { } } +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseLength_MemoryPoolAllocator)) { + for (size_t i = 0; i < kTrialCount; i++) { + Document doc; + doc.Parse(json_, length_); + ASSERT_TRUE(doc.IsObject()); + } +} + +#if RAPIDJSON_HAS_STDSTRING +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseStdString_MemoryPoolAllocator)) { + const std::string s(json_, length_); + for (size_t i = 0; i < kTrialCount; i++) { + Document doc; + doc.Parse(s); + ASSERT_TRUE(doc.IsObject()); + } +} +#endif + TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterative_MemoryPoolAllocator)) { for (size_t i = 0; i < kTrialCount; i++) { Document doc; diff --git a/3rdparty/rapidjson/test/unittest/CMakeLists.txt b/3rdparty/rapidjson/test/unittest/CMakeLists.txt index 0ae166282e5..02c15327e6b 100644 --- a/3rdparty/rapidjson/test/unittest/CMakeLists.txt +++ b/3rdparty/rapidjson/test/unittest/CMakeLists.txt @@ -25,6 +25,15 @@ set(UNITTEST_SOURCES valuetest.cpp writertest.cpp) +find_program(CCACHE_FOUND ccache) +if(CCACHE_FOUND) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fcolor-diagnostics") + endif() +endif(CCACHE_FOUND) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal") elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") diff --git a/3rdparty/rapidjson/test/unittest/documenttest.cpp b/3rdparty/rapidjson/test/unittest/documenttest.cpp index afe696a1e21..0c9ffaba442 100644 --- a/3rdparty/rapidjson/test/unittest/documenttest.cpp +++ b/3rdparty/rapidjson/test/unittest/documenttest.cpp @@ -34,6 +34,8 @@ void ParseCheck(DocumentType& doc) { typedef typename DocumentType::ValueType ValueType; EXPECT_FALSE(doc.HasParseError()); + if (doc.HasParseError()) + printf("Error: %d at %zu\n", static_cast<int>(doc.GetParseError()), doc.GetErrorOffset()); EXPECT_TRUE(static_cast<ParseResult>(doc)); EXPECT_TRUE(doc.IsObject()); @@ -93,6 +95,26 @@ void ParseTest() { doc.ParseInsitu(buffer); ParseCheck(doc); free(buffer); + + // Parse(const Ch*, size_t) + size_t length = strlen(json); + buffer = reinterpret_cast<char*>(malloc(length * 2)); + memcpy(buffer, json, length); + memset(buffer + length, 'X', length); +#if RAPIDJSON_HAS_STDSTRING + std::string s2(buffer, length); // backup buffer +#endif + doc.SetNull(); + doc.Parse(buffer, length); + free(buffer); + ParseCheck(doc); + +#if RAPIDJSON_HAS_STDSTRING + // Parse(std::string) + doc.SetNull(); + doc.Parse(s2); + ParseCheck(doc); +#endif } TEST(Document, Parse) { @@ -140,6 +162,47 @@ static FILE* OpenEncodedFile(const char* filename) { return 0; } +TEST(Document, Parse_Encoding) { + const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "; + + typedef GenericDocument<UTF16<> > DocumentType; + DocumentType doc; + + // Parse<unsigned, SourceEncoding>(const SourceEncoding::Ch*) + // doc.Parse<kParseDefaultFlags, UTF8<> >(json); + // EXPECT_FALSE(doc.HasParseError()); + // EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world")); + + // Parse<unsigned, SourceEncoding>(const SourceEncoding::Ch*, size_t) + size_t length = strlen(json); + char* buffer = reinterpret_cast<char*>(malloc(length * 2)); + memcpy(buffer, json, length); + memset(buffer + length, 'X', length); +#if RAPIDJSON_HAS_STDSTRING + std::string s2(buffer, length); // backup buffer +#endif + doc.SetNull(); + doc.Parse<kParseDefaultFlags, UTF8<> >(buffer, length); + free(buffer); + EXPECT_FALSE(doc.HasParseError()); + if (doc.HasParseError()) + printf("Error: %d at %zu\n", static_cast<int>(doc.GetParseError()), doc.GetErrorOffset()); + EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world")); + +#if RAPIDJSON_HAS_STDSTRING + // Parse<unsigned, SourceEncoding>(std::string) + doc.SetNull(); + +#if defined(_MSC_VER) && _MSC_VER < 1800 + doc.Parse<kParseDefaultFlags, UTF8<> >(s2.c_str()); // VS2010 or below cannot handle templated function overloading. Use const char* instead. +#else + doc.Parse<kParseDefaultFlags, UTF8<> >(s2); +#endif + EXPECT_FALSE(doc.HasParseError()); + EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world")); +#endif +} + TEST(Document, ParseStream_EncodedInputStream) { // UTF8 -> UTF16 FILE* fp = OpenEncodedFile("utf8.json"); diff --git a/3rdparty/rapidjson/test/unittest/dtoatest.cpp b/3rdparty/rapidjson/test/unittest/dtoatest.cpp index da020957211..fe28271f976 100644 --- a/3rdparty/rapidjson/test/unittest/dtoatest.cpp +++ b/3rdparty/rapidjson/test/unittest/dtoatest.cpp @@ -81,6 +81,12 @@ TEST(dtoa, maxDecimalPlaces) { TEST_DTOA(3, 2.225073858507201e-308, "0.0"); // Max subnormal positive double TEST_DTOA(3, 2.2250738585072014e-308, "0.0"); // Min normal positive double TEST_DTOA(3, 1.7976931348623157e308, "1.7976931348623157e308"); // Max double + TEST_DTOA(5, -0.14000000000000001, "-0.14"); + TEST_DTOA(4, -0.14000000000000001, "-0.14"); + TEST_DTOA(3, -0.14000000000000001, "-0.14"); + TEST_DTOA(3, -0.10000000000000001, "-0.1"); + TEST_DTOA(2, -0.10000000000000001, "-0.1"); + TEST_DTOA(1, -0.10000000000000001, "-0.1"); #undef TEST_DTOA } diff --git a/3rdparty/rapidjson/test/unittest/readertest.cpp b/3rdparty/rapidjson/test/unittest/readertest.cpp index a07e59a6c9f..32af8a86eec 100644 --- a/3rdparty/rapidjson/test/unittest/readertest.cpp +++ b/3rdparty/rapidjson/test/unittest/readertest.cpp @@ -1170,6 +1170,8 @@ struct IterativeParsingReaderHandler { bool Double(double) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_DOUBLE; return true; } + bool RawNumber(const Ch*, SizeType, bool) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STRING; return true; } + bool String(const Ch*, SizeType, bool) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STRING; return true; } bool StartObject() { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STARTOBJECT; return true; } @@ -1349,12 +1351,13 @@ struct TerminateHandler { bool Int64(int64_t) { return e != 4; } bool Uint64(uint64_t) { return e != 5; } bool Double(double) { return e != 6; } - bool String(const char*, SizeType, bool) { return e != 7; } - bool StartObject() { return e != 8; } - bool Key(const char*, SizeType, bool) { return e != 9; } - bool EndObject(SizeType) { return e != 10; } - bool StartArray() { return e != 11; } - bool EndArray(SizeType) { return e != 12; } + bool RawNumber(const char*, SizeType, bool) { return e != 7; } + bool String(const char*, SizeType, bool) { return e != 8; } + bool StartObject() { return e != 9; } + bool Key(const char*, SizeType, bool) { return e != 10; } + bool EndObject(SizeType) { return e != 11; } + bool StartArray() { return e != 12; } + bool EndArray(SizeType) { return e != 13; } }; #define TEST_TERMINATION(e, json)\ @@ -1375,14 +1378,15 @@ TEST(Reader, ParseTerminationByHandler) { TEST_TERMINATION(4, "[-1234567890123456789"); TEST_TERMINATION(5, "[1234567890123456789"); TEST_TERMINATION(6, "[0.5]"); - TEST_TERMINATION(7, "[\"a\""); - TEST_TERMINATION(8, "[{"); - TEST_TERMINATION(9, "[{\"a\""); - TEST_TERMINATION(10, "[{}"); - TEST_TERMINATION(10, "[{\"a\":1}"); // non-empty object - TEST_TERMINATION(11, "{\"a\":["); - TEST_TERMINATION(12, "{\"a\":[]"); - TEST_TERMINATION(12, "{\"a\":[1]"); // non-empty array + // RawNumber() is never called + TEST_TERMINATION(8, "[\"a\""); + TEST_TERMINATION(9, "[{"); + TEST_TERMINATION(10, "[{\"a\""); + TEST_TERMINATION(11, "[{}"); + TEST_TERMINATION(11, "[{\"a\":1}"); // non-empty object + TEST_TERMINATION(12, "{\"a\":["); + TEST_TERMINATION(13, "{\"a\":[]"); + TEST_TERMINATION(13, "{\"a\":[1]"); // non-empty array } TEST(Reader, ParseComments) { @@ -1508,6 +1512,46 @@ TEST(Reader, UnrecognizedComment) { EXPECT_EQ(kParseErrorUnspecificSyntaxError, reader.GetParseErrorCode()); } +struct NumbersAsStringsHandler { + bool Null() { return true; } + bool Bool(bool) { return true; } + bool Int(int) { return true; } + bool Uint(unsigned) { return true; } + bool Int64(int64_t) { return true; } + bool Uint64(uint64_t) { return true; } + bool Double(double) { return true; } + // '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); + return true; + } + bool String(const char*, SizeType, bool) { return true; } + bool StartObject() { return true; } + bool Key(const char*, SizeType, bool) { return true; } + bool EndObject(SizeType) { return true; } + bool StartArray() { return true; } + bool EndArray(SizeType) { return true; } +}; + +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); + } +} + #ifdef __GNUC__ RAPIDJSON_DIAG_POP #endif diff --git a/3rdparty/rapidjson/test/unittest/schematest.cpp b/3rdparty/rapidjson/test/unittest/schematest.cpp index 623c65ac61e..7182ad29426 100644 --- a/3rdparty/rapidjson/test/unittest/schematest.cpp +++ b/3rdparty/rapidjson/test/unittest/schematest.cpp @@ -1152,6 +1152,24 @@ TEST(SchemaValidatingWriter, Simple) { EXPECT_TRUE(validator.GetInvalidDocumentPointer() == SchemaDocument::PointerType("")); } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + +static SchemaDocument ReturnSchemaDocument() { + Document sd; + sd.Parse("{ \"type\": [\"number\", \"string\"] }"); + SchemaDocument s(sd); + return s; +} + +TEST(Schema, Issue552) { + SchemaDocument s = ReturnSchemaDocument(); + VALIDATE(s, "42", true); + VALIDATE(s, "\"Life, the universe, and everything\"", true); + INVALIDATE(s, "[\"Life\", \"the universe\", \"and everything\"]", "", "type", ""); +} + +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + #ifdef __clang__ RAPIDJSON_DIAG_POP #endif diff --git a/3rdparty/rapidjson/test/unittest/simdtest.cpp b/3rdparty/rapidjson/test/unittest/simdtest.cpp index 6ded7402fbf..1b6fcef3a48 100644 --- a/3rdparty/rapidjson/test/unittest/simdtest.cpp +++ b/3rdparty/rapidjson/test/unittest/simdtest.cpp @@ -73,6 +73,28 @@ TEST(SIMD, SIMD_SUFFIX(SkipWhitespace)) { TestSkipWhitespace<InsituStringStream>(); } +TEST(SIMD, SIMD_SUFFIX(SkipWhitespace_EncodedMemoryStream)) { + for (size_t step = 1; step < 32; step++) { + char buffer[1024]; + for (size_t i = 0; i < 1024; i++) + buffer[i] = " \t\r\n"[i % 4]; + for (size_t i = 0; i < 1024; i += step) + buffer[i] = 'X'; + + MemoryStream ms(buffer, 1024); + EncodedInputStream<UTF8<>, MemoryStream> s(ms); + size_t i = 0; + for (;;) { + SkipWhitespace(s); + if (s.Peek() == '\0') + break; + //EXPECT_EQ(i, s.Tell()); + EXPECT_EQ('X', s.Take()); + i += step; + } + } +} + struct ScanCopyUnescapedStringHandler : BaseReaderHandler<UTF8<>, ScanCopyUnescapedStringHandler> { bool String(const char* str, size_t length, bool) { memcpy(buffer, str, length + 1); diff --git a/3rdparty/rapidjson/test/unittest/valuetest.cpp b/3rdparty/rapidjson/test/unittest/valuetest.cpp index 5e88a77e3a3..d6c7492deae 100644 --- a/3rdparty/rapidjson/test/unittest/valuetest.cpp +++ b/3rdparty/rapidjson/test/unittest/valuetest.cpp @@ -23,6 +23,18 @@ RAPIDJSON_DIAG_OFF(c++98-compat) using namespace rapidjson; +TEST(Value, Size) { + if (sizeof(SizeType) == 4) { +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION + EXPECT_EQ(16, sizeof(Value)); +#elif RAPIDJSON_64BIT + EXPECT_EQ(24, sizeof(Value)); +#else + EXPECT_EQ(16, sizeof(Value)); +#endif + } +} + TEST(Value, DefaultConstructor) { Value x; EXPECT_EQ(kNullType, x.GetType()); @@ -335,6 +347,12 @@ TEST(Value, True) { Value z; z.SetBool(true); EXPECT_TRUE(z.IsTrue()); + + // Templated functions + EXPECT_TRUE(z.Is<bool>()); + EXPECT_TRUE(z.Get<bool>()); + EXPECT_FALSE(z.Set<bool>(false).Get<bool>()); + EXPECT_TRUE(z.Set(true).Get<bool>()); } TEST(Value, False) { @@ -414,6 +432,12 @@ TEST(Value, Int) { // operator=(int) z = 5678; EXPECT_EQ(5678, z.GetInt()); + + // Templated functions + EXPECT_TRUE(z.Is<int>()); + EXPECT_EQ(5678, z.Get<int>()); + EXPECT_EQ(5679, z.Set(5679).Get<int>()); + EXPECT_EQ(5680, z.Set<int>(5680).Get<int>()); } TEST(Value, Uint) { @@ -453,6 +477,12 @@ TEST(Value, Uint) { EXPECT_EQ(2147483648u, z.GetUint()); EXPECT_FALSE(z.IsInt()); EXPECT_TRUE(z.IsInt64()); // Issue 41: Incorrect parsing of unsigned int number types + + // Templated functions + EXPECT_TRUE(z.Is<unsigned>()); + EXPECT_EQ(2147483648u, z.Get<unsigned>()); + EXPECT_EQ(2147483649u, z.Set(2147483649u).Get<unsigned>()); + EXPECT_EQ(2147483650u, z.Set<unsigned>(2147483650u).Get<unsigned>()); } TEST(Value, Int64) { @@ -505,8 +535,15 @@ TEST(Value, Int64) { EXPECT_FALSE(z.IsInt()); EXPECT_NEAR(-2147483649.0, z.GetDouble(), 0.0); - z.SetInt64(static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 00000000))); + int64_t i = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 00000000)); + z.SetInt64(i); EXPECT_DOUBLE_EQ(-9223372036854775808.0, z.GetDouble()); + + // Templated functions + EXPECT_TRUE(z.Is<int64_t>()); + EXPECT_EQ(i, z.Get<int64_t>()); + EXPECT_EQ(i - 1, z.Set(i - 1).Get<int64_t>()); + EXPECT_EQ(i - 2, z.Set<int64_t>(i - 2).Get<int64_t>()); } TEST(Value, Uint64) { @@ -547,10 +584,17 @@ TEST(Value, Uint64) { EXPECT_FALSE(z.IsUint()); EXPECT_TRUE(z.IsInt64()); - z.SetUint64(RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)); // 2^63 cannot cast as int64 + uint64_t u = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); + z.SetUint64(u); // 2^63 cannot cast as int64 EXPECT_FALSE(z.IsInt64()); - EXPECT_EQ(RAPIDJSON_UINT64_C2(0x80000000, 0x00000000), z.GetUint64()); // Issue 48 + EXPECT_EQ(u, z.GetUint64()); // Issue 48 EXPECT_DOUBLE_EQ(9223372036854775808.0, z.GetDouble()); + + // Templated functions + EXPECT_TRUE(z.Is<uint64_t>()); + EXPECT_EQ(u, z.Get<uint64_t>()); + EXPECT_EQ(u + 1, z.Set(u + 1).Get<uint64_t>()); + EXPECT_EQ(u + 2, z.Set<uint64_t>(u + 2).Get<uint64_t>()); } TEST(Value, Double) { @@ -577,6 +621,12 @@ TEST(Value, Double) { z = 56.78; EXPECT_NEAR(56.78, z.GetDouble(), 0.0); + + // Templated functions + EXPECT_TRUE(z.Is<double>()); + EXPECT_EQ(56.78, z.Get<double>()); + EXPECT_EQ(57.78, z.Set(57.78).Get<double>()); + EXPECT_EQ(58.78, z.Set<double>(58.78).Get<double>()); } TEST(Value, Float) { @@ -602,18 +652,30 @@ TEST(Value, Float) { z.SetFloat(12.34f); EXPECT_NEAR(12.34f, z.GetFloat(), 0.0f); + // Issue 573 + z.SetInt(0); + EXPECT_EQ(0.0f, z.GetFloat()); + z = 56.78f; EXPECT_NEAR(56.78f, z.GetFloat(), 0.0f); + + // Templated functions + EXPECT_TRUE(z.Is<float>()); + EXPECT_EQ(56.78f, z.Get<float>()); + EXPECT_EQ(57.78f, z.Set(57.78f).Get<float>()); + EXPECT_EQ(58.78f, z.Set<float>(58.78f).Get<float>()); } TEST(Value, IsLosslessDouble) { EXPECT_TRUE(Value(12.34).IsLosslessDouble()); EXPECT_TRUE(Value(-123).IsLosslessDouble()); EXPECT_TRUE(Value(2147483648u).IsLosslessDouble()); - EXPECT_TRUE(Value(static_cast<int64_t>(-RAPIDJSON_UINT64_C2(0x40000000, 0x00000000))).IsLosslessDouble()); + EXPECT_TRUE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x40000000, 0x00000000))).IsLosslessDouble()); +#if !(defined(_MSC_VER) && _MSC_VER < 1800) // VC2010 has problem EXPECT_TRUE(Value(RAPIDJSON_UINT64_C2(0xA0000000, 0x00000000)).IsLosslessDouble()); +#endif - EXPECT_FALSE(Value(static_cast<int64_t>(-RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble()); + EXPECT_FALSE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble()); EXPECT_FALSE(Value(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)).IsLosslessDouble()); } @@ -724,6 +786,11 @@ TEST(Value, String) { EXPECT_STREQ("World", w.GetString()); EXPECT_EQ(5u, w.GetStringLength()); + // templated functions + EXPECT_TRUE(z.Is<const char*>()); + EXPECT_STREQ(cstr, z.Get<const char*>()); + EXPECT_STREQ("Apple", z.Set<const char*>("Apple").Get<const char*>()); + #if RAPIDJSON_HAS_STDSTRING { std::string str = "Hello World"; @@ -759,6 +826,14 @@ TEST(Value, String) { vs1 = StringRef(str); TestEqual(str, vs1); TestEqual(vs0, vs1); + + // Templated function. + EXPECT_TRUE(vs0.Is<std::string>()); + EXPECT_EQ(str, vs0.Get<std::string>()); + vs0.Set<std::string>(std::string("Apple"), allocator); + EXPECT_EQ(std::string("Apple"), vs0.Get<std::string>()); + vs0.Set(std::string("Orange"), allocator); + EXPECT_EQ(std::string("Orange"), vs0.Get<std::string>()); } #endif // RAPIDJSON_HAS_STDSTRING } @@ -769,25 +844,9 @@ TEST(Value, SetStringNullException) { EXPECT_THROW(v.SetString(0, 0), AssertException); } -TEST(Value, Array) { - Value x(kArrayType); - const Value& y = x; - Value::AllocatorType allocator; - - EXPECT_EQ(kArrayType, x.GetType()); - EXPECT_TRUE(x.IsArray()); - EXPECT_TRUE(x.Empty()); - EXPECT_EQ(0u, x.Size()); - EXPECT_TRUE(y.IsArray()); - EXPECT_TRUE(y.Empty()); - EXPECT_EQ(0u, y.Size()); - - EXPECT_FALSE(x.IsNull()); - EXPECT_FALSE(x.IsBool()); - EXPECT_FALSE(x.IsFalse()); - EXPECT_FALSE(x.IsTrue()); - EXPECT_FALSE(x.IsString()); - EXPECT_FALSE(x.IsObject()); +template <typename T, typename Allocator> +static void TestArray(T& x, Allocator& allocator) { + const T& y = x; // PushBack() Value v; @@ -834,7 +893,7 @@ TEST(Value, Array) { #endif // iterator - Value::ValueIterator itr = x.Begin(); + typename T::ValueIterator itr = x.Begin(); EXPECT_TRUE(itr != x.End()); EXPECT_TRUE(itr->IsNull()); ++itr; @@ -853,7 +912,7 @@ TEST(Value, Array) { EXPECT_STREQ("foo", itr->GetString()); // const iterator - Value::ConstValueIterator citr = y.Begin(); + typename T::ConstValueIterator citr = y.Begin(); EXPECT_TRUE(citr != y.End()); EXPECT_TRUE(citr->IsNull()); ++citr; @@ -939,6 +998,29 @@ TEST(Value, Array) { EXPECT_EQ(i + removeCount, x[static_cast<SizeType>(i)][0].GetUint()); } } +} + +TEST(Value, Array) { + Value x(kArrayType); + const Value& y = x; + Value::AllocatorType allocator; + + EXPECT_EQ(kArrayType, x.GetType()); + EXPECT_TRUE(x.IsArray()); + EXPECT_TRUE(x.Empty()); + EXPECT_EQ(0u, x.Size()); + EXPECT_TRUE(y.IsArray()); + EXPECT_TRUE(y.Empty()); + EXPECT_EQ(0u, y.Size()); + + EXPECT_FALSE(x.IsNull()); + EXPECT_FALSE(x.IsBool()); + EXPECT_FALSE(x.IsFalse()); + EXPECT_FALSE(x.IsTrue()); + EXPECT_FALSE(x.IsString()); + EXPECT_FALSE(x.IsObject()); + + TestArray(x, allocator); // Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed. // http://en.wikipedia.org/wiki/Erase-remove_idiom @@ -962,19 +1044,96 @@ TEST(Value, Array) { EXPECT_TRUE(z.Empty()); } -TEST(Value, Object) { - Value x(kObjectType); - const Value& y = x; // const version +TEST(Value, ArrayHelper) { Value::AllocatorType allocator; + { + Value x(kArrayType); + Value::Array a = x.GetArray(); + TestArray(a, allocator); + } - EXPECT_EQ(kObjectType, x.GetType()); - EXPECT_TRUE(x.IsObject()); - EXPECT_TRUE(x.ObjectEmpty()); - EXPECT_EQ(0u, x.MemberCount()); - EXPECT_EQ(kObjectType, y.GetType()); - EXPECT_TRUE(y.IsObject()); - EXPECT_TRUE(y.ObjectEmpty()); - EXPECT_EQ(0u, y.MemberCount()); + { + Value x(kArrayType); + Value::Array a = x.GetArray(); + a.PushBack(1, allocator); + + Value::Array a2(a); // copy constructor + EXPECT_EQ(1, a2.Size()); + + Value::Array a3 = a; + EXPECT_EQ(1, a3.Size()); + + Value::ConstArray y = static_cast<const Value&>(x).GetArray(); + (void)y; + // y.PushBack(1, allocator); // should not compile + + // Templated functions + x.Clear(); + EXPECT_TRUE(x.Is<Value::Array>()); + EXPECT_TRUE(x.Is<Value::ConstArray>()); + a.PushBack(1, allocator); + EXPECT_EQ(1, x.Get<Value::Array>()[0].GetInt()); + EXPECT_EQ(1, x.Get<Value::ConstArray>()[0].GetInt()); + + Value x2; + x2.Set<Value::Array>(a); + EXPECT_TRUE(x.IsArray()); // IsArray() is invariant after moving. + EXPECT_EQ(1, x2.Get<Value::Array>()[0].GetInt()); + } + + { + Value y(kArrayType); + y.PushBack(123, allocator); + + Value x(y.GetArray()); // Construct value form array. + EXPECT_TRUE(x.IsArray()); + EXPECT_EQ(123, x[0].GetInt()); + EXPECT_TRUE(y.IsArray()); // Invariant + EXPECT_TRUE(y.Empty()); + } + + { + Value x(kArrayType); + Value y(kArrayType); + y.PushBack(123, allocator); + x.PushBack(y.GetArray(), allocator); // Implicit constructor to convert Array to GenericValue + + EXPECT_EQ(1, x.Size()); + EXPECT_EQ(123, x[0][0].GetInt()); + EXPECT_TRUE(y.IsArray()); + EXPECT_TRUE(y.Empty()); + } +} + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR +TEST(Value, ArrayHelperRangeFor) { + Value::AllocatorType allocator; + Value x(kArrayType); + + for (int i = 0; i < 10; i++) + x.PushBack(i, allocator); + + { + int i = 0; + for (auto& v : x.GetArray()) + EXPECT_EQ(i++, v.GetInt()); + EXPECT_EQ(i, 10); + } + { + int i = 0; + for (const auto& v : const_cast<const Value&>(x).GetArray()) + EXPECT_EQ(i++, v.GetInt()); + EXPECT_EQ(i, 10); + } + + // Array a = x.GetArray(); + // Array ca = const_cast<const Value&>(x).GetArray(); +} +#endif + +template <typename T, typename Allocator> +static void TestObject(T& x, Allocator& allocator) { + const T& y = x; // const version // AddMember() x.AddMember("A", "Apple", allocator); @@ -1215,7 +1374,7 @@ TEST(Value, Object) { const unsigned n = 10; for (unsigned first = 0; first < n; first++) { for (unsigned last = first; last <= n; last++) { - Value(kObjectType).Swap(x); + x.RemoveAllMembers(); for (unsigned i = 0; i < n; i++) x.AddMember(keys[i], Value(kArrayType).PushBack(i, allocator), allocator); @@ -1238,6 +1397,23 @@ TEST(Value, Object) { x.RemoveAllMembers(); EXPECT_TRUE(x.ObjectEmpty()); EXPECT_EQ(0u, x.MemberCount()); +} + +TEST(Value, Object) { + Value x(kObjectType); + const Value& y = x; // const version + Value::AllocatorType allocator; + + EXPECT_EQ(kObjectType, x.GetType()); + EXPECT_TRUE(x.IsObject()); + EXPECT_TRUE(x.ObjectEmpty()); + EXPECT_EQ(0u, x.MemberCount()); + EXPECT_EQ(kObjectType, y.GetType()); + EXPECT_TRUE(y.IsObject()); + EXPECT_TRUE(y.ObjectEmpty()); + EXPECT_EQ(0u, y.MemberCount()); + + TestObject(x, allocator); // SetObject() Value z; @@ -1245,6 +1421,100 @@ TEST(Value, Object) { EXPECT_TRUE(z.IsObject()); } +TEST(Value, ObjectHelper) { + Value::AllocatorType allocator; + { + Value x(kObjectType); + Value::Object o = x.GetObject(); + TestObject(o, allocator); + } + + { + Value x(kObjectType); + Value::Object o = x.GetObject(); + o.AddMember("1", 1, allocator); + + Value::Object o2(o); // copy constructor + EXPECT_EQ(1, o2.MemberCount()); + + Value::Object o3 = o; + EXPECT_EQ(1, o3.MemberCount()); + + Value::ConstObject y = static_cast<const Value&>(x).GetObject(); + (void)y; + // y.AddMember("1", 1, allocator); // should not compile + + // Templated functions + x.RemoveAllMembers(); + EXPECT_TRUE(x.Is<Value::Object>()); + EXPECT_TRUE(x.Is<Value::ConstObject>()); + o.AddMember("1", 1, allocator); + EXPECT_EQ(1, x.Get<Value::Object>()["1"].GetInt()); + EXPECT_EQ(1, x.Get<Value::ConstObject>()["1"].GetInt()); + + Value x2; + x2.Set<Value::Object>(o); + EXPECT_TRUE(x.IsObject()); // IsObject() is invariant after moving + EXPECT_EQ(1, x2.Get<Value::Object>()["1"].GetInt()); + } + + { + Value x(kObjectType); + x.AddMember("a", "apple", allocator); + Value y(x.GetObject()); + EXPECT_STREQ("apple", y["a"].GetString()); + EXPECT_TRUE(x.IsObject()); // Invariant + } + + { + Value x(kObjectType); + x.AddMember("a", "apple", allocator); + Value y(kObjectType); + y.AddMember("fruits", x.GetObject(), allocator); + EXPECT_STREQ("apple", y["fruits"]["a"].GetString()); + EXPECT_TRUE(x.IsObject()); // Invariant + } +} + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR +TEST(Value, ObjectHelperRangeFor) { + Value::AllocatorType allocator; + Value x(kObjectType); + + for (int i = 0; i < 10; i++) { + char name[10]; + Value n(name, static_cast<SizeType>(sprintf(name, "%d", i)), allocator); + x.AddMember(n, i, allocator); + } + + { + int i = 0; + for (auto& m : x.GetObject()) { + char name[10]; + sprintf(name, "%d", i); + EXPECT_STREQ(name, m.name.GetString()); + EXPECT_EQ(i, m.value.GetInt()); + i++; + } + EXPECT_EQ(i, 10); + } + { + int i = 0; + for (const auto& m : const_cast<const Value&>(x).GetObject()) { + char name[10]; + sprintf(name, "%d", i); + EXPECT_STREQ(name, m.name.GetString()); + EXPECT_EQ(i, m.value.GetInt()); + i++; + } + EXPECT_EQ(i, 10); + } + + // Object a = x.GetObject(); + // Object ca = const_cast<const Value&>(x).GetObject(); +} +#endif + TEST(Value, EraseMember_String) { Value::AllocatorType allocator; Value x(kObjectType); @@ -1378,12 +1648,13 @@ struct TerminateHandler { bool Int64(int64_t) { return e != 4; } bool Uint64(uint64_t) { return e != 5; } bool Double(double) { return e != 6; } - bool String(const char*, SizeType, bool) { return e != 7; } - bool StartObject() { return e != 8; } - bool Key(const char*, SizeType, bool) { return e != 9; } - bool EndObject(SizeType) { return e != 10; } - bool StartArray() { return e != 11; } - bool EndArray(SizeType) { return e != 12; } + bool RawNumber(const char*, SizeType, bool) { return e != 7; } + bool String(const char*, SizeType, bool) { return e != 8; } + bool StartObject() { return e != 9; } + bool Key(const char*, SizeType, bool) { return e != 10; } + bool EndObject(SizeType) { return e != 11; } + bool StartArray() { return e != 12; } + bool EndArray(SizeType) { return e != 13; } }; #define TEST_TERMINATION(e, json)\ @@ -1404,12 +1675,13 @@ TEST(Value, AcceptTerminationByHandler) { TEST_TERMINATION(4, "[-1234567890123456789]"); TEST_TERMINATION(5, "[9223372036854775808]"); TEST_TERMINATION(6, "[0.5]"); - TEST_TERMINATION(7, "[\"a\"]"); - TEST_TERMINATION(8, "[{}]"); - TEST_TERMINATION(9, "[{\"a\":1}]"); - TEST_TERMINATION(10, "[{}]"); - TEST_TERMINATION(11, "{\"a\":[]}"); + // RawNumber() is never called + TEST_TERMINATION(8, "[\"a\"]"); + TEST_TERMINATION(9, "[{}]"); + TEST_TERMINATION(10, "[{\"a\":1}]"); + TEST_TERMINATION(11, "[{}]"); TEST_TERMINATION(12, "{\"a\":[]}"); + TEST_TERMINATION(13, "{\"a\":[]}"); } struct ValueIntComparer { |