summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/rapidjson/test
diff options
context:
space:
mode:
author ImJezze <jezze@gmx.net>2016-03-12 12:31:13 +0100
committer ImJezze <jezze@gmx.net>2016-03-12 12:31:13 +0100
commita026a582f1a0ea8c1ede3acaddacef506ef3f3b0 (patch)
treee31573822f2359677de519f9f3b600d98e8764cd /3rdparty/rapidjson/test
parent477d2abd43984f076b7e45f5527591fa8fd0d241 (diff)
parentdcab55bf53b94713a6f72e9633f5101c8dd6c08c (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.txt9
-rw-r--r--3rdparty/rapidjson/test/perftest/perftest.h2
-rw-r--r--3rdparty/rapidjson/test/perftest/rapidjsontest.cpp19
-rw-r--r--3rdparty/rapidjson/test/unittest/CMakeLists.txt9
-rw-r--r--3rdparty/rapidjson/test/unittest/documenttest.cpp63
-rw-r--r--3rdparty/rapidjson/test/unittest/dtoatest.cpp6
-rw-r--r--3rdparty/rapidjson/test/unittest/readertest.cpp72
-rw-r--r--3rdparty/rapidjson/test/unittest/schematest.cpp18
-rw-r--r--3rdparty/rapidjson/test/unittest/simdtest.cpp22
-rw-r--r--3rdparty/rapidjson/test/unittest/valuetest.cpp370
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 {