diff options
Diffstat (limited to '3rdparty/jsoncpp/src/test_lib_json')
-rw-r--r-- | 3rdparty/jsoncpp/src/test_lib_json/CMakeLists.txt | 22 | ||||
-rw-r--r-- | 3rdparty/jsoncpp/src/test_lib_json/jsontest.cpp | 443 | ||||
-rw-r--r-- | 3rdparty/jsoncpp/src/test_lib_json/jsontest.h | 280 | ||||
-rw-r--r-- | 3rdparty/jsoncpp/src/test_lib_json/main.cpp | 1637 | ||||
-rw-r--r-- | 3rdparty/jsoncpp/src/test_lib_json/sconscript | 10 |
5 files changed, 2392 insertions, 0 deletions
diff --git a/3rdparty/jsoncpp/src/test_lib_json/CMakeLists.txt b/3rdparty/jsoncpp/src/test_lib_json/CMakeLists.txt new file mode 100644 index 00000000000..420d659968c --- /dev/null +++ b/3rdparty/jsoncpp/src/test_lib_json/CMakeLists.txt @@ -0,0 +1,22 @@ + +IF(JSONCPP_LIB_BUILD_SHARED) + ADD_DEFINITIONS( -DJSON_DLL ) +ENDIF(JSONCPP_LIB_BUILD_SHARED) + +ADD_EXECUTABLE( jsoncpp_test + jsontest.cpp + jsontest.h + main.cpp + ) + +TARGET_LINK_LIBRARIES(jsoncpp_test jsoncpp_lib) + +# Run unit tests in post-build +# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?) +IF(JSONCPP_WITH_POST_BUILD_UNITTEST) + ADD_CUSTOM_COMMAND( TARGET jsoncpp_test + POST_BUILD + COMMAND $<TARGET_FILE:jsoncpp_test>) +ENDIF(JSONCPP_WITH_POST_BUILD_UNITTEST) + +SET_TARGET_PROPERTIES(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test) diff --git a/3rdparty/jsoncpp/src/test_lib_json/jsontest.cpp b/3rdparty/jsoncpp/src/test_lib_json/jsontest.cpp new file mode 100644 index 00000000000..ef9c543fa47 --- /dev/null +++ b/3rdparty/jsoncpp/src/test_lib_json/jsontest.cpp @@ -0,0 +1,443 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#define _CRT_SECURE_NO_WARNINGS 1 // Prevents deprecation warning with MSVC +#include "jsontest.h" +#include <stdio.h> +#include <string> + +#if defined(_MSC_VER) +// Used to install a report hook that prevent dialog on assertion and error. +#include <crtdbg.h> +#endif // if defined(_MSC_VER) + +#if defined(_WIN32) +// Used to prevent dialog on memory fault. +// Limits headers included by Windows.h +#define WIN32_LEAN_AND_MEAN +#define NOSERVICE +#define NOMCX +#define NOIME +#define NOSOUND +#define NOCOMM +#define NORPC +#define NOGDI +#define NOUSER +#define NODRIVERS +#define NOLOGERROR +#define NOPROFILER +#define NOMEMMGR +#define NOLFILEIO +#define NOOPENFILE +#define NORESOURCE +#define NOATOM +#define NOLANGUAGE +#define NOLSTRING +#define NODBCS +#define NOKEYBOARDINFO +#define NOGDICAPMASKS +#define NOCOLOR +#define NOGDIOBJ +#define NODRAWTEXT +#define NOTEXTMETRIC +#define NOSCALABLEFONT +#define NOBITMAP +#define NORASTEROPS +#define NOMETAFILE +#define NOSYSMETRICS +#define NOSYSTEMPARAMSINFO +#define NOMSG +#define NOWINSTYLES +#define NOWINOFFSETS +#define NOSHOWWINDOW +#define NODEFERWINDOWPOS +#define NOVIRTUALKEYCODES +#define NOKEYSTATES +#define NOWH +#define NOMENUS +#define NOSCROLL +#define NOCLIPBOARD +#define NOICONS +#define NOMB +#define NOSYSCOMMANDS +#define NOMDI +#define NOCTLMGR +#define NOWINMESSAGES +#include <windows.h> +#endif // if defined(_WIN32) + +namespace JsonTest { + +// class TestResult +// ////////////////////////////////////////////////////////////////// + +TestResult::TestResult() + : predicateId_(1), lastUsedPredicateId_(0), messageTarget_(0) { + // The root predicate has id 0 + rootPredicateNode_.id_ = 0; + rootPredicateNode_.next_ = 0; + predicateStackTail_ = &rootPredicateNode_; +} + +void TestResult::setTestName(const std::string& name) { name_ = name; } + +TestResult& +TestResult::addFailure(const char* file, unsigned int line, const char* expr) { + /// Walks the PredicateContext stack adding them to failures_ if not already + /// added. + unsigned int nestingLevel = 0; + PredicateContext* lastNode = rootPredicateNode_.next_; + for (; lastNode != 0; lastNode = lastNode->next_) { + if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext + { + lastUsedPredicateId_ = lastNode->id_; + addFailureInfo( + lastNode->file_, lastNode->line_, lastNode->expr_, nestingLevel); + // Link the PredicateContext to the failure for message target when + // popping the PredicateContext. + lastNode->failure_ = &(failures_.back()); + } + ++nestingLevel; + } + + // Adds the failed assertion + addFailureInfo(file, line, expr, nestingLevel); + messageTarget_ = &(failures_.back()); + return *this; +} + +void TestResult::addFailureInfo(const char* file, + unsigned int line, + const char* expr, + unsigned int nestingLevel) { + Failure failure; + failure.file_ = file; + failure.line_ = line; + if (expr) { + failure.expr_ = expr; + } + failure.nestingLevel_ = nestingLevel; + failures_.push_back(failure); +} + +TestResult& TestResult::popPredicateContext() { + PredicateContext* lastNode = &rootPredicateNode_; + while (lastNode->next_ != 0 && lastNode->next_->next_ != 0) { + lastNode = lastNode->next_; + } + // Set message target to popped failure + PredicateContext* tail = lastNode->next_; + if (tail != 0 && tail->failure_ != 0) { + messageTarget_ = tail->failure_; + } + // Remove tail from list + predicateStackTail_ = lastNode; + lastNode->next_ = 0; + return *this; +} + +bool TestResult::failed() const { return !failures_.empty(); } + +unsigned int TestResult::getAssertionNestingLevel() const { + unsigned int level = 0; + const PredicateContext* lastNode = &rootPredicateNode_; + while (lastNode->next_ != 0) { + lastNode = lastNode->next_; + ++level; + } + return level; +} + +void TestResult::printFailure(bool printTestName) const { + if (failures_.empty()) { + return; + } + + if (printTestName) { + printf("* Detail of %s test failure:\n", name_.c_str()); + } + + // Print in reverse to display the callstack in the right order + Failures::const_iterator itEnd = failures_.end(); + for (Failures::const_iterator it = failures_.begin(); it != itEnd; ++it) { + const Failure& failure = *it; + std::string indent(failure.nestingLevel_ * 2, ' '); + if (failure.file_) { + printf("%s%s(%d): ", indent.c_str(), failure.file_, failure.line_); + } + if (!failure.expr_.empty()) { + printf("%s\n", failure.expr_.c_str()); + } else if (failure.file_) { + printf("\n"); + } + if (!failure.message_.empty()) { + std::string reindented = indentText(failure.message_, indent + " "); + printf("%s\n", reindented.c_str()); + } + } +} + +std::string TestResult::indentText(const std::string& text, + const std::string& indent) { + std::string reindented; + std::string::size_type lastIndex = 0; + while (lastIndex < text.size()) { + std::string::size_type nextIndex = text.find('\n', lastIndex); + if (nextIndex == std::string::npos) { + nextIndex = text.size() - 1; + } + reindented += indent; + reindented += text.substr(lastIndex, nextIndex - lastIndex + 1); + lastIndex = nextIndex + 1; + } + return reindented; +} + +TestResult& TestResult::addToLastFailure(const std::string& message) { + if (messageTarget_ != 0) { + messageTarget_->message_ += message; + } + return *this; +} + +TestResult& TestResult::operator<<(Json::Int64 value) { + return addToLastFailure(Json::valueToString(value)); +} + +TestResult& TestResult::operator<<(Json::UInt64 value) { + return addToLastFailure(Json::valueToString(value)); +} + +TestResult& TestResult::operator<<(bool value) { + return addToLastFailure(value ? "true" : "false"); +} + +// class TestCase +// ////////////////////////////////////////////////////////////////// + +TestCase::TestCase() : result_(0) {} + +TestCase::~TestCase() {} + +void TestCase::run(TestResult& result) { + result_ = &result; + runTestCase(); +} + +// class Runner +// ////////////////////////////////////////////////////////////////// + +Runner::Runner() {} + +Runner& Runner::add(TestCaseFactory factory) { + tests_.push_back(factory); + return *this; +} + +unsigned int Runner::testCount() const { + return static_cast<unsigned int>(tests_.size()); +} + +std::string Runner::testNameAt(unsigned int index) const { + TestCase* test = tests_[index](); + std::string name = test->testName(); + delete test; + return name; +} + +void Runner::runTestAt(unsigned int index, TestResult& result) const { + TestCase* test = tests_[index](); + result.setTestName(test->testName()); + printf("Testing %s: ", test->testName()); + fflush(stdout); +#if JSON_USE_EXCEPTION + try { +#endif // if JSON_USE_EXCEPTION + test->run(result); +#if JSON_USE_EXCEPTION + } + catch (const std::exception& e) { + result.addFailure(__FILE__, __LINE__, "Unexpected exception caught:") + << e.what(); + } +#endif // if JSON_USE_EXCEPTION + delete test; + const char* status = result.failed() ? "FAILED" : "OK"; + printf("%s\n", status); + fflush(stdout); +} + +bool Runner::runAllTest(bool printSummary) const { + unsigned int count = testCount(); + std::deque<TestResult> failures; + for (unsigned int index = 0; index < count; ++index) { + TestResult result; + runTestAt(index, result); + if (result.failed()) { + failures.push_back(result); + } + } + + if (failures.empty()) { + if (printSummary) { + printf("All %d tests passed\n", count); + } + return true; + } else { + for (unsigned int index = 0; index < failures.size(); ++index) { + TestResult& result = failures[index]; + result.printFailure(count > 1); + } + + if (printSummary) { + unsigned int failedCount = static_cast<unsigned int>(failures.size()); + unsigned int passedCount = count - failedCount; + printf("%d/%d tests passed (%d failure(s))\n", + passedCount, + count, + failedCount); + } + return false; + } +} + +bool Runner::testIndex(const std::string& testName, + unsigned int& indexOut) const { + unsigned int count = testCount(); + for (unsigned int index = 0; index < count; ++index) { + if (testNameAt(index) == testName) { + indexOut = index; + return true; + } + } + return false; +} + +void Runner::listTests() const { + unsigned int count = testCount(); + for (unsigned int index = 0; index < count; ++index) { + printf("%s\n", testNameAt(index).c_str()); + } +} + +int Runner::runCommandLine(int argc, const char* argv[]) const { + typedef std::deque<std::string> TestNames; + Runner subrunner; + for (int index = 1; index < argc; ++index) { + std::string opt = argv[index]; + if (opt == "--list-tests") { + listTests(); + return 0; + } else if (opt == "--test-auto") { + preventDialogOnCrash(); + } else if (opt == "--test") { + ++index; + if (index < argc) { + unsigned int testNameIndex; + if (testIndex(argv[index], testNameIndex)) { + subrunner.add(tests_[testNameIndex]); + } else { + fprintf(stderr, "Test '%s' does not exist!\n", argv[index]); + return 2; + } + } else { + printUsage(argv[0]); + return 2; + } + } else { + printUsage(argv[0]); + return 2; + } + } + bool succeeded; + if (subrunner.testCount() > 0) { + succeeded = subrunner.runAllTest(subrunner.testCount() > 1); + } else { + succeeded = runAllTest(true); + } + return succeeded ? 0 : 1; +} + +#if defined(_MSC_VER) && defined(_DEBUG) +// Hook MSVCRT assertions to prevent dialog from appearing +static int +msvcrtSilentReportHook(int reportType, char* message, int* /*returnValue*/) { + // The default CRT handling of error and assertion is to display + // an error dialog to the user. + // Instead, when an error or an assertion occurs, we force the + // application to terminate using abort() after display + // the message on stderr. + if (reportType == _CRT_ERROR || reportType == _CRT_ASSERT) { + // calling abort() cause the ReportHook to be called + // The following is used to detect this case and let's the + // error handler fallback on its default behaviour ( + // display a warning message) + static volatile bool isAborting = false; + if (isAborting) { + return TRUE; + } + isAborting = true; + + fprintf(stderr, "CRT Error/Assert:\n%s\n", message); + fflush(stderr); + abort(); + } + // Let's other reportType (_CRT_WARNING) be handled as they would by default + return FALSE; +} +#endif // if defined(_MSC_VER) + +void Runner::preventDialogOnCrash() { +#if defined(_MSC_VER) && defined(_DEBUG) + // Install a hook to prevent MSVCRT error and assertion from + // popping a dialog + // This function a NO-OP in release configuration + // (which cause warning since msvcrtSilentReportHook is not referenced) + _CrtSetReportHook(&msvcrtSilentReportHook); +#endif // if defined(_MSC_VER) + +// @todo investiguate this handler (for buffer overflow) +// _set_security_error_handler + +#if defined(_WIN32) + // Prevents the system from popping a dialog for debugging if the + // application fails due to invalid memory access. + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | + SEM_NOOPENFILEERRORBOX); +#endif // if defined(_WIN32) +} + +void Runner::printUsage(const char* appName) { + printf("Usage: %s [options]\n" + "\n" + "If --test is not specified, then all the test cases be run.\n" + "\n" + "Valid options:\n" + "--list-tests: print the name of all test cases on the standard\n" + " output and exit.\n" + "--test TESTNAME: executes the test case with the specified name.\n" + " May be repeated.\n" + "--test-auto: prevent dialog prompting for debugging on crash.\n", + appName); +} + +// Assertion functions +// ////////////////////////////////////////////////////////////////// + +TestResult& checkStringEqual(TestResult& result, + const std::string& expected, + const std::string& actual, + const char* file, + unsigned int line, + const char* expr) { + if (expected != actual) { + result.addFailure(file, line, expr); + result << "Expected: '" << expected << "'\n"; + result << "Actual : '" << actual << "'"; + } + return result; +} + +} // namespace JsonTest diff --git a/3rdparty/jsoncpp/src/test_lib_json/jsontest.h b/3rdparty/jsoncpp/src/test_lib_json/jsontest.h new file mode 100644 index 00000000000..5c56a40b0ff --- /dev/null +++ b/3rdparty/jsoncpp/src/test_lib_json/jsontest.h @@ -0,0 +1,280 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#ifndef JSONTEST_H_INCLUDED +#define JSONTEST_H_INCLUDED + +#include <json/config.h> +#include <json/value.h> +#include <json/writer.h> +#include <stdio.h> +#include <deque> +#include <sstream> +#include <string> + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// Mini Unit Testing framework +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +/** \brief Unit testing framework. + * \warning: all assertions are non-aborting, test case execution will continue + * even if an assertion namespace. + * This constraint is for portability: the framework needs to compile + * on Visual Studio 6 and must not require exception usage. + */ +namespace JsonTest { + +class Failure { +public: + const char* file_; + unsigned int line_; + std::string expr_; + std::string message_; + unsigned int nestingLevel_; +}; + +/// Context used to create the assertion callstack on failure. +/// Must be a POD to allow inline initialisation without stepping +/// into the debugger. +struct PredicateContext { + typedef unsigned int Id; + Id id_; + const char* file_; + unsigned int line_; + const char* expr_; + PredicateContext* next_; + /// Related Failure, set when the PredicateContext is converted + /// into a Failure. + Failure* failure_; +}; + +class TestResult { +public: + TestResult(); + + /// \internal Implementation detail for assertion macros + /// Not encapsulated to prevent step into when debugging failed assertions + /// Incremented by one on assertion predicate entry, decreased by one + /// by addPredicateContext(). + PredicateContext::Id predicateId_; + + /// \internal Implementation detail for predicate macros + PredicateContext* predicateStackTail_; + + void setTestName(const std::string& name); + + /// Adds an assertion failure. + TestResult& + addFailure(const char* file, unsigned int line, const char* expr = 0); + + /// Removes the last PredicateContext added to the predicate stack + /// chained list. + /// Next messages will be targed at the PredicateContext that was removed. + TestResult& popPredicateContext(); + + bool failed() const; + + void printFailure(bool printTestName) const; + + // Generic operator that will work with anything ostream can deal with. + template <typename T> TestResult& operator<<(const T& value) { + std::ostringstream oss; + oss.precision(16); + oss.setf(std::ios_base::floatfield); + oss << value; + return addToLastFailure(oss.str()); + } + + // Specialized versions. + TestResult& operator<<(bool value); + // std:ostream does not support 64bits integers on all STL implementation + TestResult& operator<<(Json::Int64 value); + TestResult& operator<<(Json::UInt64 value); + +private: + TestResult& addToLastFailure(const std::string& message); + unsigned int getAssertionNestingLevel() const; + /// Adds a failure or a predicate context + void addFailureInfo(const char* file, + unsigned int line, + const char* expr, + unsigned int nestingLevel); + static std::string indentText(const std::string& text, + const std::string& indent); + + typedef std::deque<Failure> Failures; + Failures failures_; + std::string name_; + PredicateContext rootPredicateNode_; + PredicateContext::Id lastUsedPredicateId_; + /// Failure which is the target of the messages added using operator << + Failure* messageTarget_; +}; + +class TestCase { +public: + TestCase(); + + virtual ~TestCase(); + + void run(TestResult& result); + + virtual const char* testName() const = 0; + +protected: + TestResult* result_; + +private: + virtual void runTestCase() = 0; +}; + +/// Function pointer type for TestCase factory +typedef TestCase* (*TestCaseFactory)(); + +class Runner { +public: + Runner(); + + /// Adds a test to the suite + Runner& add(TestCaseFactory factory); + + /// Runs test as specified on the command-line + /// If no command-line arguments are provided, run all tests. + /// If --list-tests is provided, then print the list of all test cases + /// If --test <testname> is provided, then run test testname. + int runCommandLine(int argc, const char* argv[]) const; + + /// Runs all the test cases + bool runAllTest(bool printSummary) const; + + /// Returns the number of test case in the suite + unsigned int testCount() const; + + /// Returns the name of the test case at the specified index + std::string testNameAt(unsigned int index) const; + + /// Runs the test case at the specified index using the specified TestResult + void runTestAt(unsigned int index, TestResult& result) const; + + static void printUsage(const char* appName); + +private: // prevents copy construction and assignment + Runner(const Runner& other); + Runner& operator=(const Runner& other); + +private: + void listTests() const; + bool testIndex(const std::string& testName, unsigned int& index) const; + static void preventDialogOnCrash(); + +private: + typedef std::deque<TestCaseFactory> Factories; + Factories tests_; +}; + +template <typename T, typename U> +TestResult& checkEqual(TestResult& result, + const T& expected, + const U& actual, + const char* file, + unsigned int line, + const char* expr) { + if (static_cast<U>(expected) != actual) { + result.addFailure(file, line, expr); + result << "Expected: " << static_cast<U>(expected) << "\n"; + result << "Actual : " << actual; + } + return result; +} + +TestResult& checkStringEqual(TestResult& result, + const std::string& expected, + const std::string& actual, + const char* file, + unsigned int line, + const char* expr); + +} // namespace JsonTest + +/// \brief Asserts that the given expression is true. +/// JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y; +/// JSONTEST_ASSERT( x == y ); +#define JSONTEST_ASSERT(expr) \ + if (expr) { \ + } else \ + result_->addFailure(__FILE__, __LINE__, #expr) + +/// \brief Asserts that the given predicate is true. +/// The predicate may do other assertions and be a member function of the +/// fixture. +#define JSONTEST_ASSERT_PRED(expr) \ + { \ + JsonTest::PredicateContext _minitest_Context = { \ + result_->predicateId_, __FILE__, __LINE__, #expr \ + }; \ + result_->predicateStackTail_->next_ = &_minitest_Context; \ + result_->predicateId_ += 1; \ + result_->predicateStackTail_ = &_minitest_Context; \ + (expr); \ + result_->popPredicateContext(); \ + } + +/// \brief Asserts that two values are equals. +#define JSONTEST_ASSERT_EQUAL(expected, actual) \ + JsonTest::checkEqual(*result_, \ + expected, \ + actual, \ + __FILE__, \ + __LINE__, \ + #expected " == " #actual) + +/// \brief Asserts that two values are equals. +#define JSONTEST_ASSERT_STRING_EQUAL(expected, actual) \ + JsonTest::checkStringEqual(*result_, \ + std::string(expected), \ + std::string(actual), \ + __FILE__, \ + __LINE__, \ + #expected " == " #actual) + +/// \brief Asserts that a given expression throws an exception +#define JSONTEST_ASSERT_THROWS(expr) \ + { \ + bool _threw = false; \ + try { \ + expr; \ + } \ + catch (...) { \ + _threw = true; \ + } \ + if (!_threw) \ + result_->addFailure( \ + __FILE__, __LINE__, "expected exception thrown: " #expr); \ + } + +/// \brief Begin a fixture test case. +#define JSONTEST_FIXTURE(FixtureType, name) \ + class Test##FixtureType##name : public FixtureType { \ + public: \ + static JsonTest::TestCase* factory() { \ + return new Test##FixtureType##name(); \ + } \ + \ + public: /* overidden from TestCase */ \ + virtual const char* testName() const { return #FixtureType "/" #name; } \ + virtual void runTestCase(); \ + }; \ + \ + void Test##FixtureType##name::runTestCase() + +#define JSONTEST_FIXTURE_FACTORY(FixtureType, name) \ + &Test##FixtureType##name::factory + +#define JSONTEST_REGISTER_FIXTURE(runner, FixtureType, name) \ + (runner).add(JSONTEST_FIXTURE_FACTORY(FixtureType, name)) + +#endif // ifndef JSONTEST_H_INCLUDED diff --git a/3rdparty/jsoncpp/src/test_lib_json/main.cpp b/3rdparty/jsoncpp/src/test_lib_json/main.cpp new file mode 100644 index 00000000000..51c5e7442b1 --- /dev/null +++ b/3rdparty/jsoncpp/src/test_lib_json/main.cpp @@ -0,0 +1,1637 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +#include "jsontest.h" +#include <json/config.h> +#include <json/json.h> +#include <stdexcept> + +// Make numeric limits more convenient to talk about. +// Assumes int type in 32 bits. +#define kint32max Json::Value::maxInt +#define kint32min Json::Value::minInt +#define kuint32max Json::Value::maxUInt +#define kint64max Json::Value::maxInt64 +#define kint64min Json::Value::minInt64 +#define kuint64max Json::Value::maxUInt64 + +static const double kdint64max = double(kint64max); +static const float kfint64max = float(kint64max); +static const float kfint32max = float(kint32max); +static const float kfuint32max = float(kuint32max); + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// Json Library test cases +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + +#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +static inline double uint64ToDouble(Json::UInt64 value) { + return static_cast<double>(value); +} +#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) +static inline double uint64ToDouble(Json::UInt64 value) { + return static_cast<double>(Json::Int64(value / 2)) * 2.0 + + Json::Int64(value & 1); +} +#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) + +struct ValueTest : JsonTest::TestCase { + Json::Value null_; + Json::Value emptyArray_; + Json::Value emptyObject_; + Json::Value integer_; + Json::Value unsignedInteger_; + Json::Value smallUnsignedInteger_; + Json::Value real_; + Json::Value float_; + Json::Value array1_; + Json::Value object1_; + Json::Value emptyString_; + Json::Value string1_; + Json::Value string_; + Json::Value true_; + Json::Value false_; + + ValueTest() + : emptyArray_(Json::arrayValue), emptyObject_(Json::objectValue), + integer_(123456789), unsignedInteger_(34567890u), + smallUnsignedInteger_(Json::Value::UInt(Json::Value::maxInt)), + real_(1234.56789), float_(0.00390625f), emptyString_(""), string1_("a"), + string_("sometext with space"), true_(true), false_(false) { + array1_.append(1234); + object1_["id"] = 1234; + } + + struct IsCheck { + /// Initialize all checks to \c false by default. + IsCheck(); + + bool isObject_; + bool isArray_; + bool isBool_; + bool isString_; + bool isNull_; + + bool isInt_; + bool isInt64_; + bool isUInt_; + bool isUInt64_; + bool isIntegral_; + bool isDouble_; + bool isNumeric_; + }; + + void checkConstMemberCount(const Json::Value& value, + unsigned int expectedCount); + + void checkMemberCount(Json::Value& value, unsigned int expectedCount); + + void checkIs(const Json::Value& value, const IsCheck& check); + + void checkIsLess(const Json::Value& x, const Json::Value& y); + + void checkIsEqual(const Json::Value& x, const Json::Value& y); + + /// Normalize the representation of floating-point number by stripped leading + /// 0 in exponent. + static std::string normalizeFloatingPointStr(const std::string& s); +}; + +std::string ValueTest::normalizeFloatingPointStr(const std::string& s) { + std::string::size_type index = s.find_last_of("eE"); + if (index != std::string::npos) { + std::string::size_type hasSign = + (s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0; + std::string::size_type exponentStartIndex = index + 1 + hasSign; + std::string normalized = s.substr(0, exponentStartIndex); + std::string::size_type indexDigit = + s.find_first_not_of('0', exponentStartIndex); + std::string exponent = "0"; + if (indexDigit != + std::string::npos) // There is an exponent different from 0 + { + exponent = s.substr(indexDigit); + } + return normalized + exponent; + } + return s; +} + +JSONTEST_FIXTURE(ValueTest, checkNormalizeFloatingPointStr) { + JSONTEST_ASSERT_STRING_EQUAL("0.0", normalizeFloatingPointStr("0.0")); + JSONTEST_ASSERT_STRING_EQUAL("0e0", normalizeFloatingPointStr("0e0")); + JSONTEST_ASSERT_STRING_EQUAL("1234.0", normalizeFloatingPointStr("1234.0")); + JSONTEST_ASSERT_STRING_EQUAL("1234.0e0", + normalizeFloatingPointStr("1234.0e0")); + JSONTEST_ASSERT_STRING_EQUAL("1234.0e+0", + normalizeFloatingPointStr("1234.0e+0")); + JSONTEST_ASSERT_STRING_EQUAL("1234e-1", normalizeFloatingPointStr("1234e-1")); + JSONTEST_ASSERT_STRING_EQUAL("1234e10", normalizeFloatingPointStr("1234e10")); + JSONTEST_ASSERT_STRING_EQUAL("1234e10", + normalizeFloatingPointStr("1234e010")); + JSONTEST_ASSERT_STRING_EQUAL("1234e+10", + normalizeFloatingPointStr("1234e+010")); + JSONTEST_ASSERT_STRING_EQUAL("1234e-10", + normalizeFloatingPointStr("1234e-010")); + JSONTEST_ASSERT_STRING_EQUAL("1234e+100", + normalizeFloatingPointStr("1234e+100")); + JSONTEST_ASSERT_STRING_EQUAL("1234e-100", + normalizeFloatingPointStr("1234e-100")); + JSONTEST_ASSERT_STRING_EQUAL("1234e+1", + normalizeFloatingPointStr("1234e+001")); +} + +JSONTEST_FIXTURE(ValueTest, memberCount) { + JSONTEST_ASSERT_PRED(checkMemberCount(emptyArray_, 0)); + JSONTEST_ASSERT_PRED(checkMemberCount(emptyObject_, 0)); + JSONTEST_ASSERT_PRED(checkMemberCount(array1_, 1)); + JSONTEST_ASSERT_PRED(checkMemberCount(object1_, 1)); + JSONTEST_ASSERT_PRED(checkMemberCount(null_, 0)); + JSONTEST_ASSERT_PRED(checkMemberCount(integer_, 0)); + JSONTEST_ASSERT_PRED(checkMemberCount(unsignedInteger_, 0)); + JSONTEST_ASSERT_PRED(checkMemberCount(smallUnsignedInteger_, 0)); + JSONTEST_ASSERT_PRED(checkMemberCount(real_, 0)); + JSONTEST_ASSERT_PRED(checkMemberCount(emptyString_, 0)); + JSONTEST_ASSERT_PRED(checkMemberCount(string_, 0)); + JSONTEST_ASSERT_PRED(checkMemberCount(true_, 0)); +} + +JSONTEST_FIXTURE(ValueTest, objects) { + // Types + IsCheck checks; + checks.isObject_ = true; + JSONTEST_ASSERT_PRED(checkIs(emptyObject_, checks)); + JSONTEST_ASSERT_PRED(checkIs(object1_, checks)); + + JSONTEST_ASSERT_EQUAL(Json::objectValue, emptyObject_.type()); + + // Empty object okay + JSONTEST_ASSERT(emptyObject_.isConvertibleTo(Json::nullValue)); + + // Non-empty object not okay + JSONTEST_ASSERT(!object1_.isConvertibleTo(Json::nullValue)); + + // Always okay + JSONTEST_ASSERT(emptyObject_.isConvertibleTo(Json::objectValue)); + + // Never okay + JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::arrayValue)); + JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::uintValue)); + JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::realValue)); + JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::booleanValue)); + JSONTEST_ASSERT(!emptyObject_.isConvertibleTo(Json::stringValue)); + + // Access through const reference + const Json::Value& constObject = object1_; + + JSONTEST_ASSERT_EQUAL(Json::Value(1234), constObject["id"]); + JSONTEST_ASSERT_EQUAL(Json::Value(), constObject["unknown id"]); + + // Access through non-const reference + JSONTEST_ASSERT_EQUAL(Json::Value(1234), object1_["id"]); + JSONTEST_ASSERT_EQUAL(Json::Value(), object1_["unknown id"]); + + object1_["some other id"] = "foo"; + JSONTEST_ASSERT_EQUAL(Json::Value("foo"), object1_["some other id"]); +} + +JSONTEST_FIXTURE(ValueTest, arrays) { + const unsigned int index0 = 0; + + // Types + IsCheck checks; + checks.isArray_ = true; + JSONTEST_ASSERT_PRED(checkIs(emptyArray_, checks)); + JSONTEST_ASSERT_PRED(checkIs(array1_, checks)); + + JSONTEST_ASSERT_EQUAL(Json::arrayValue, array1_.type()); + + // Empty array okay + JSONTEST_ASSERT(emptyArray_.isConvertibleTo(Json::nullValue)); + + // Non-empty array not okay + JSONTEST_ASSERT(!array1_.isConvertibleTo(Json::nullValue)); + + // Always okay + JSONTEST_ASSERT(emptyArray_.isConvertibleTo(Json::arrayValue)); + + // Never okay + JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::objectValue)); + JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::uintValue)); + JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::realValue)); + JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::booleanValue)); + JSONTEST_ASSERT(!emptyArray_.isConvertibleTo(Json::stringValue)); + + // Access through const reference + const Json::Value& constArray = array1_; + JSONTEST_ASSERT_EQUAL(Json::Value(1234), constArray[index0]); + JSONTEST_ASSERT_EQUAL(Json::Value(1234), constArray[0]); + + // Access through non-const reference + JSONTEST_ASSERT_EQUAL(Json::Value(1234), array1_[index0]); + JSONTEST_ASSERT_EQUAL(Json::Value(1234), array1_[0]); + + array1_[2] = Json::Value(17); + JSONTEST_ASSERT_EQUAL(Json::Value(), array1_[1]); + JSONTEST_ASSERT_EQUAL(Json::Value(17), array1_[2]); +} + +JSONTEST_FIXTURE(ValueTest, null) { + JSONTEST_ASSERT_EQUAL(Json::nullValue, null_.type()); + + IsCheck checks; + checks.isNull_ = true; + JSONTEST_ASSERT_PRED(checkIs(null_, checks)); + + JSONTEST_ASSERT(null_.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(null_.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(null_.isConvertibleTo(Json::uintValue)); + JSONTEST_ASSERT(null_.isConvertibleTo(Json::realValue)); + JSONTEST_ASSERT(null_.isConvertibleTo(Json::booleanValue)); + JSONTEST_ASSERT(null_.isConvertibleTo(Json::stringValue)); + JSONTEST_ASSERT(null_.isConvertibleTo(Json::arrayValue)); + JSONTEST_ASSERT(null_.isConvertibleTo(Json::objectValue)); + + JSONTEST_ASSERT_EQUAL(Json::Int(0), null_.asInt()); + JSONTEST_ASSERT_EQUAL(Json::LargestInt(0), null_.asLargestInt()); + JSONTEST_ASSERT_EQUAL(Json::UInt(0), null_.asUInt()); + JSONTEST_ASSERT_EQUAL(Json::LargestUInt(0), null_.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(0.0, null_.asDouble()); + JSONTEST_ASSERT_EQUAL(0.0, null_.asFloat()); + JSONTEST_ASSERT_STRING_EQUAL("", null_.asString()); +} + +JSONTEST_FIXTURE(ValueTest, strings) { + JSONTEST_ASSERT_EQUAL(Json::stringValue, string1_.type()); + + IsCheck checks; + checks.isString_ = true; + JSONTEST_ASSERT_PRED(checkIs(emptyString_, checks)); + JSONTEST_ASSERT_PRED(checkIs(string_, checks)); + JSONTEST_ASSERT_PRED(checkIs(string1_, checks)); + + // Empty string okay + JSONTEST_ASSERT(emptyString_.isConvertibleTo(Json::nullValue)); + + // Non-empty string not okay + JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::nullValue)); + + // Always okay + JSONTEST_ASSERT(string1_.isConvertibleTo(Json::stringValue)); + + // Never okay + JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::objectValue)); + JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::arrayValue)); + JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::uintValue)); + JSONTEST_ASSERT(!string1_.isConvertibleTo(Json::realValue)); + + JSONTEST_ASSERT_STRING_EQUAL("a", string1_.asString()); + JSONTEST_ASSERT_STRING_EQUAL("a", string1_.asCString()); +} + +JSONTEST_FIXTURE(ValueTest, bools) { + JSONTEST_ASSERT_EQUAL(Json::booleanValue, false_.type()); + + IsCheck checks; + checks.isBool_ = true; + JSONTEST_ASSERT_PRED(checkIs(false_, checks)); + JSONTEST_ASSERT_PRED(checkIs(true_, checks)); + + // False okay + JSONTEST_ASSERT(false_.isConvertibleTo(Json::nullValue)); + + // True not okay + JSONTEST_ASSERT(!true_.isConvertibleTo(Json::nullValue)); + + // Always okay + JSONTEST_ASSERT(true_.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(true_.isConvertibleTo(Json::uintValue)); + JSONTEST_ASSERT(true_.isConvertibleTo(Json::realValue)); + JSONTEST_ASSERT(true_.isConvertibleTo(Json::booleanValue)); + JSONTEST_ASSERT(true_.isConvertibleTo(Json::stringValue)); + + // Never okay + JSONTEST_ASSERT(!true_.isConvertibleTo(Json::arrayValue)); + JSONTEST_ASSERT(!true_.isConvertibleTo(Json::objectValue)); + + JSONTEST_ASSERT_EQUAL(true, true_.asBool()); + JSONTEST_ASSERT_EQUAL(1, true_.asInt()); + JSONTEST_ASSERT_EQUAL(1, true_.asLargestInt()); + JSONTEST_ASSERT_EQUAL(1, true_.asUInt()); + JSONTEST_ASSERT_EQUAL(1, true_.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(1.0, true_.asDouble()); + JSONTEST_ASSERT_EQUAL(1.0, true_.asFloat()); + + JSONTEST_ASSERT_EQUAL(false, false_.asBool()); + JSONTEST_ASSERT_EQUAL(0, false_.asInt()); + JSONTEST_ASSERT_EQUAL(0, false_.asLargestInt()); + JSONTEST_ASSERT_EQUAL(0, false_.asUInt()); + JSONTEST_ASSERT_EQUAL(0, false_.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(0.0, false_.asDouble()); + JSONTEST_ASSERT_EQUAL(0.0, false_.asFloat()); +} + +JSONTEST_FIXTURE(ValueTest, integers) { + IsCheck checks; + Json::Value val; + + // Conversions that don't depend on the value. + JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::realValue)); + JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::stringValue)); + JSONTEST_ASSERT(Json::Value(17).isConvertibleTo(Json::booleanValue)); + JSONTEST_ASSERT(!Json::Value(17).isConvertibleTo(Json::arrayValue)); + JSONTEST_ASSERT(!Json::Value(17).isConvertibleTo(Json::objectValue)); + + JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::realValue)); + JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::stringValue)); + JSONTEST_ASSERT(Json::Value(17U).isConvertibleTo(Json::booleanValue)); + JSONTEST_ASSERT(!Json::Value(17U).isConvertibleTo(Json::arrayValue)); + JSONTEST_ASSERT(!Json::Value(17U).isConvertibleTo(Json::objectValue)); + + JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::realValue)); + JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::stringValue)); + JSONTEST_ASSERT(Json::Value(17.0).isConvertibleTo(Json::booleanValue)); + JSONTEST_ASSERT(!Json::Value(17.0).isConvertibleTo(Json::arrayValue)); + JSONTEST_ASSERT(!Json::Value(17.0).isConvertibleTo(Json::objectValue)); + + // Default int + val = Json::Value(Json::intValue); + + JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); + + checks = IsCheck(); + checks.isInt_ = true; + checks.isInt64_ = true; + checks.isUInt_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(0, val.asInt()); + JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(0, val.asUInt()); + JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); + JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); + JSONTEST_ASSERT_EQUAL(false, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); + + // Default uint + val = Json::Value(Json::uintValue); + + JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); + + checks = IsCheck(); + checks.isInt_ = true; + checks.isInt64_ = true; + checks.isUInt_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(0, val.asInt()); + JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(0, val.asUInt()); + JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); + JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); + JSONTEST_ASSERT_EQUAL(false, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); + + // Default real + val = Json::Value(Json::realValue); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + + checks = IsCheck(); + checks.isInt_ = true; + checks.isInt64_ = true; + checks.isUInt_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT_EQUAL(0, val.asInt()); + JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(0, val.asUInt()); + JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); + JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); + JSONTEST_ASSERT_EQUAL(false, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); + + // Zero (signed constructor arg) + val = Json::Value(0); + + JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); + + checks = IsCheck(); + checks.isInt_ = true; + checks.isInt64_ = true; + checks.isUInt_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(0, val.asInt()); + JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(0, val.asUInt()); + JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); + JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); + JSONTEST_ASSERT_EQUAL(false, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); + + // Zero (unsigned constructor arg) + val = Json::Value(0u); + + JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); + + checks = IsCheck(); + checks.isInt_ = true; + checks.isInt64_ = true; + checks.isUInt_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(0, val.asInt()); + JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(0, val.asUInt()); + JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); + JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); + JSONTEST_ASSERT_EQUAL(false, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); + + // Zero (floating-point constructor arg) + val = Json::Value(0.0); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isInt_ = true; + checks.isInt64_ = true; + checks.isUInt_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(0, val.asInt()); + JSONTEST_ASSERT_EQUAL(0, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(0, val.asUInt()); + JSONTEST_ASSERT_EQUAL(0, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(0.0, val.asDouble()); + JSONTEST_ASSERT_EQUAL(0.0, val.asFloat()); + JSONTEST_ASSERT_EQUAL(false, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("0", val.asString()); + + // 2^20 (signed constructor arg) + val = Json::Value(1 << 20); + + JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); + checks = IsCheck(); + checks.isInt_ = true; + checks.isInt64_ = true; + checks.isUInt_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("1048576", val.asString()); + + // 2^20 (unsigned constructor arg) + val = Json::Value(Json::UInt(1 << 20)); + + JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); + + checks = IsCheck(); + checks.isInt_ = true; + checks.isInt64_ = true; + checks.isUInt_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("1048576", val.asString()); + + // 2^20 (floating-point constructor arg) + val = Json::Value((1 << 20) / 1.0); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isInt_ = true; + checks.isInt64_ = true; + checks.isUInt_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL((1 << 20), val.asInt()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestInt()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asUInt()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble()); + JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("1048576", + normalizeFloatingPointStr(val.asString())); + + // -2^20 + val = Json::Value(-(1 << 20)); + + JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); + + checks = IsCheck(); + checks.isInt_ = true; + checks.isInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asInt()); + JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asDouble()); + JSONTEST_ASSERT_EQUAL(-(1 << 20), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("-1048576", val.asString()); + + // int32 max + val = Json::Value(kint32max); + + JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); + + checks = IsCheck(); + checks.isInt_ = true; + checks.isInt64_ = true; + checks.isUInt_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(kint32max, val.asInt()); + JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(kint32max, val.asUInt()); + JSONTEST_ASSERT_EQUAL(kint32max, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(kint32max, val.asDouble()); + JSONTEST_ASSERT_EQUAL(kfint32max, val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("2147483647", val.asString()); + + // int32 min + val = Json::Value(kint32min); + + JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); + + checks = IsCheck(); + checks.isInt_ = true; + checks.isInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(kint32min, val.asInt()); + JSONTEST_ASSERT_EQUAL(kint32min, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(kint32min, val.asDouble()); + JSONTEST_ASSERT_EQUAL(kint32min, val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("-2147483648", val.asString()); + + // uint32 max + val = Json::Value(kuint32max); + + JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); + + checks = IsCheck(); + checks.isInt64_ = true; + checks.isUInt_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + +#ifndef JSON_NO_INT64 + JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestInt()); +#endif + JSONTEST_ASSERT_EQUAL(kuint32max, val.asUInt()); + JSONTEST_ASSERT_EQUAL(kuint32max, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(kuint32max, val.asDouble()); + JSONTEST_ASSERT_EQUAL(kfuint32max, val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("4294967295", val.asString()); + +#ifdef JSON_NO_INT64 + // int64 max + val = Json::Value(double(kint64max)); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(double(kint64max), val.asDouble()); + JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("9.22337e+18", val.asString()); + + // int64 min + val = Json::Value(double(kint64min)); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(double(kint64min), val.asDouble()); + JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("-9.22337e+18", val.asString()); + + // uint64 max + val = Json::Value(double(kuint64max)); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(double(kuint64max), val.asDouble()); + JSONTEST_ASSERT_EQUAL(float(kuint64max), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("1.84467e+19", val.asString()); +#else // ifdef JSON_NO_INT64 + // 2^40 (signed constructor arg) + val = Json::Value(Json::Int64(1) << 40); + + JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); + + checks = IsCheck(); + checks.isInt64_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asInt64()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestInt()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asUInt64()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("1099511627776", val.asString()); + + // 2^40 (unsigned constructor arg) + val = Json::Value(Json::UInt64(1) << 40); + + JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); + + checks = IsCheck(); + checks.isInt64_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asInt64()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestInt()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asUInt64()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("1099511627776", val.asString()); + + // 2^40 (floating-point constructor arg) + val = Json::Value((Json::Int64(1) << 40) / 1.0); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isInt64_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asInt64()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestInt()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asUInt64()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble()); + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("1099511627776", + normalizeFloatingPointStr(val.asString())); + + // -2^40 + val = Json::Value(-(Json::Int64(1) << 40)); + + JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); + + checks = IsCheck(); + checks.isInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asInt64()); + JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asDouble()); + JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 40), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("-1099511627776", val.asString()); + + // int64 max + val = Json::Value(Json::Int64(kint64max)); + + JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); + + checks = IsCheck(); + checks.isInt64_ = true; + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(kint64max, val.asInt64()); + JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(kint64max, val.asUInt64()); + JSONTEST_ASSERT_EQUAL(kint64max, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(double(kint64max), val.asDouble()); + JSONTEST_ASSERT_EQUAL(float(kint64max), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("9223372036854775807", val.asString()); + + // int64 max (floating point constructor). Note that kint64max is not exactly + // representable as a double, and will be rounded up to be higher. + val = Json::Value(double(kint64max)); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(Json::UInt64(1) << 63, val.asUInt64()); + JSONTEST_ASSERT_EQUAL(Json::UInt64(1) << 63, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(uint64ToDouble(Json::UInt64(1) << 63), val.asDouble()); + JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(Json::UInt64(1) << 63)), + val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("9.2233720368547758e+18", + normalizeFloatingPointStr(val.asString())); + + // int64 min + val = Json::Value(Json::Int64(kint64min)); + + JSONTEST_ASSERT_EQUAL(Json::intValue, val.type()); + + checks = IsCheck(); + checks.isInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(kint64min, val.asInt64()); + JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(double(kint64min), val.asDouble()); + JSONTEST_ASSERT_EQUAL(float(kint64min), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("-9223372036854775808", val.asString()); + + // int64 min (floating point constructor). Note that kint64min *is* exactly + // representable as a double. + val = Json::Value(double(kint64min)); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(kint64min, val.asInt64()); + JSONTEST_ASSERT_EQUAL(kint64min, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asDouble()); + JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("-9.2233720368547758e+18", + normalizeFloatingPointStr(val.asString())); + + // 10^19 + const Json::UInt64 ten_to_19 = static_cast<Json::UInt64>(1e19); + val = Json::Value(Json::UInt64(ten_to_19)); + + JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); + + checks = IsCheck(); + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(ten_to_19, val.asUInt64()); + JSONTEST_ASSERT_EQUAL(ten_to_19, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(uint64ToDouble(ten_to_19), val.asDouble()); + JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(ten_to_19)), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("10000000000000000000", val.asString()); + + // 10^19 (double constructor). Note that 10^19 is not exactly representable + // as a double. + val = Json::Value(uint64ToDouble(ten_to_19)); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(1e19, val.asDouble()); + JSONTEST_ASSERT_EQUAL(1e19, val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("1e+19", + normalizeFloatingPointStr(val.asString())); + + // uint64 max + val = Json::Value(Json::UInt64(kuint64max)); + + JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); + + checks = IsCheck(); + checks.isUInt64_ = true; + checks.isIntegral_ = true; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(kuint64max, val.asUInt64()); + JSONTEST_ASSERT_EQUAL(kuint64max, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(uint64ToDouble(kuint64max), val.asDouble()); + JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(kuint64max)), val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("18446744073709551615", val.asString()); + + // uint64 max (floating point constructor). Note that kuint64max is not + // exactly representable as a double, and will be rounded up to be higher. + val = Json::Value(uint64ToDouble(kuint64max)); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + + JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asDouble()); + JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asFloat()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_STRING_EQUAL("1.8446744073709552e+19", + normalizeFloatingPointStr(val.asString())); +#endif +} + +JSONTEST_FIXTURE(ValueTest, nonIntegers) { + IsCheck checks; + Json::Value val; + + // Small positive number + val = Json::Value(1.5); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); + + JSONTEST_ASSERT_EQUAL(1.5, val.asDouble()); + JSONTEST_ASSERT_EQUAL(1.5, val.asFloat()); + JSONTEST_ASSERT_EQUAL(1, val.asInt()); + JSONTEST_ASSERT_EQUAL(1, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(1, val.asUInt()); + JSONTEST_ASSERT_EQUAL(1, val.asLargestUInt()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_EQUAL("1.5", val.asString()); + + // Small negative number + val = Json::Value(-1.5); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); + + JSONTEST_ASSERT_EQUAL(-1.5, val.asDouble()); + JSONTEST_ASSERT_EQUAL(-1.5, val.asFloat()); + JSONTEST_ASSERT_EQUAL(-1, val.asInt()); + JSONTEST_ASSERT_EQUAL(-1, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_EQUAL("-1.5", val.asString()); + + // A bit over int32 max + val = Json::Value(kint32max + 0.5); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(val.isConvertibleTo(Json::uintValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); + + JSONTEST_ASSERT_EQUAL(2147483647.5, val.asDouble()); + JSONTEST_ASSERT_EQUAL(float(2147483647.5), val.asFloat()); + JSONTEST_ASSERT_EQUAL(2147483647U, val.asUInt()); +#ifdef JSON_HAS_INT64 + JSONTEST_ASSERT_EQUAL(2147483647L, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL(2147483647U, val.asLargestUInt()); +#endif + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_EQUAL("2147483647.5", + normalizeFloatingPointStr(val.asString())); + + // A bit under int32 min + val = Json::Value(kint32min - 0.5); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); + + JSONTEST_ASSERT_EQUAL(-2147483648.5, val.asDouble()); + JSONTEST_ASSERT_EQUAL(float(-2147483648.5), val.asFloat()); +#ifdef JSON_HAS_INT64 + JSONTEST_ASSERT_EQUAL(-Json::Int64(1) << 31, val.asLargestInt()); +#endif + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_EQUAL("-2147483648.5", + normalizeFloatingPointStr(val.asString())); + + // A bit over uint32 max + val = Json::Value(kuint32max + 0.5); + + JSONTEST_ASSERT_EQUAL(Json::realValue, val.type()); + + checks = IsCheck(); + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED(checkIs(val, checks)); + + JSONTEST_ASSERT(val.isConvertibleTo(Json::realValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::booleanValue)); + JSONTEST_ASSERT(val.isConvertibleTo(Json::stringValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::nullValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::intValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::uintValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::arrayValue)); + JSONTEST_ASSERT(!val.isConvertibleTo(Json::objectValue)); + + JSONTEST_ASSERT_EQUAL(4294967295.5, val.asDouble()); + JSONTEST_ASSERT_EQUAL(float(4294967295.5), val.asFloat()); +#ifdef JSON_HAS_INT64 + JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 32) - 1, val.asLargestInt()); + JSONTEST_ASSERT_EQUAL((Json::UInt64(1) << 32) - Json::UInt64(1), + val.asLargestUInt()); +#endif + JSONTEST_ASSERT_EQUAL(true, val.asBool()); + JSONTEST_ASSERT_EQUAL("4294967295.5", + normalizeFloatingPointStr(val.asString())); + + val = Json::Value(1.2345678901234); + JSONTEST_ASSERT_STRING_EQUAL("1.2345678901234001", + normalizeFloatingPointStr(val.asString())); + + // A 16-digit floating point number. + val = Json::Value(2199023255552000.0f); + JSONTEST_ASSERT_EQUAL(float(2199023255552000), val.asFloat()); + JSONTEST_ASSERT_STRING_EQUAL("2199023255552000", + normalizeFloatingPointStr(val.asString())); + + // A very large floating point number. + val = Json::Value(3.402823466385289e38); + JSONTEST_ASSERT_EQUAL(float(3.402823466385289e38), val.asFloat()); + JSONTEST_ASSERT_STRING_EQUAL("3.402823466385289e+38", + normalizeFloatingPointStr(val.asString())); + + // An even larger floating point number. + val = Json::Value(1.2345678e300); + JSONTEST_ASSERT_EQUAL(double(1.2345678e300), val.asDouble()); + JSONTEST_ASSERT_STRING_EQUAL("1.2345678e+300", + normalizeFloatingPointStr(val.asString())); +} + +void ValueTest::checkConstMemberCount(const Json::Value& value, + unsigned int expectedCount) { + unsigned int count = 0; + Json::Value::const_iterator itEnd = value.end(); + for (Json::Value::const_iterator it = value.begin(); it != itEnd; ++it) { + ++count; + } + JSONTEST_ASSERT_EQUAL(expectedCount, count) << "Json::Value::const_iterator"; +} + +void ValueTest::checkMemberCount(Json::Value& value, + unsigned int expectedCount) { + JSONTEST_ASSERT_EQUAL(expectedCount, value.size()); + + unsigned int count = 0; + Json::Value::iterator itEnd = value.end(); + for (Json::Value::iterator it = value.begin(); it != itEnd; ++it) { + ++count; + } + JSONTEST_ASSERT_EQUAL(expectedCount, count) << "Json::Value::iterator"; + + JSONTEST_ASSERT_PRED(checkConstMemberCount(value, expectedCount)); +} + +ValueTest::IsCheck::IsCheck() + : isObject_(false), isArray_(false), isBool_(false), isString_(false), + isNull_(false), isInt_(false), isInt64_(false), isUInt_(false), + isUInt64_(false), isIntegral_(false), isDouble_(false), + isNumeric_(false) {} + +void ValueTest::checkIs(const Json::Value& value, const IsCheck& check) { + JSONTEST_ASSERT_EQUAL(check.isObject_, value.isObject()); + JSONTEST_ASSERT_EQUAL(check.isArray_, value.isArray()); + JSONTEST_ASSERT_EQUAL(check.isBool_, value.isBool()); + JSONTEST_ASSERT_EQUAL(check.isDouble_, value.isDouble()); + JSONTEST_ASSERT_EQUAL(check.isInt_, value.isInt()); + JSONTEST_ASSERT_EQUAL(check.isUInt_, value.isUInt()); + JSONTEST_ASSERT_EQUAL(check.isIntegral_, value.isIntegral()); + JSONTEST_ASSERT_EQUAL(check.isNumeric_, value.isNumeric()); + JSONTEST_ASSERT_EQUAL(check.isString_, value.isString()); + JSONTEST_ASSERT_EQUAL(check.isNull_, value.isNull()); + +#ifdef JSON_HAS_INT64 + JSONTEST_ASSERT_EQUAL(check.isInt64_, value.isInt64()); + JSONTEST_ASSERT_EQUAL(check.isUInt64_, value.isUInt64()); +#else + JSONTEST_ASSERT_EQUAL(false, value.isInt64()); + JSONTEST_ASSERT_EQUAL(false, value.isUInt64()); +#endif +} + +JSONTEST_FIXTURE(ValueTest, compareNull) { + JSONTEST_ASSERT_PRED(checkIsEqual(Json::Value(), Json::Value())); +} + +JSONTEST_FIXTURE(ValueTest, compareInt) { + JSONTEST_ASSERT_PRED(checkIsLess(0, 10)); + JSONTEST_ASSERT_PRED(checkIsEqual(10, 10)); + JSONTEST_ASSERT_PRED(checkIsEqual(-10, -10)); + JSONTEST_ASSERT_PRED(checkIsLess(-10, 0)); +} + +JSONTEST_FIXTURE(ValueTest, compareUInt) { + JSONTEST_ASSERT_PRED(checkIsLess(0u, 10u)); + JSONTEST_ASSERT_PRED(checkIsLess(0u, Json::Value::maxUInt)); + JSONTEST_ASSERT_PRED(checkIsEqual(10u, 10u)); +} + +JSONTEST_FIXTURE(ValueTest, compareDouble) { + JSONTEST_ASSERT_PRED(checkIsLess(0.0, 10.0)); + JSONTEST_ASSERT_PRED(checkIsEqual(10.0, 10.0)); + JSONTEST_ASSERT_PRED(checkIsEqual(-10.0, -10.0)); + JSONTEST_ASSERT_PRED(checkIsLess(-10.0, 0.0)); +} + +JSONTEST_FIXTURE(ValueTest, compareString) { + JSONTEST_ASSERT_PRED(checkIsLess("", " ")); + JSONTEST_ASSERT_PRED(checkIsLess("", "a")); + JSONTEST_ASSERT_PRED(checkIsLess("abcd", "zyui")); + JSONTEST_ASSERT_PRED(checkIsLess("abc", "abcd")); + JSONTEST_ASSERT_PRED(checkIsEqual("abcd", "abcd")); + JSONTEST_ASSERT_PRED(checkIsEqual(" ", " ")); + JSONTEST_ASSERT_PRED(checkIsLess("ABCD", "abcd")); + JSONTEST_ASSERT_PRED(checkIsEqual("ABCD", "ABCD")); +} + +JSONTEST_FIXTURE(ValueTest, compareBoolean) { + JSONTEST_ASSERT_PRED(checkIsLess(false, true)); + JSONTEST_ASSERT_PRED(checkIsEqual(false, false)); + JSONTEST_ASSERT_PRED(checkIsEqual(true, true)); +} + +JSONTEST_FIXTURE(ValueTest, compareArray) { + // array compare size then content + Json::Value emptyArray(Json::arrayValue); + Json::Value l1aArray; + l1aArray.append(0); + Json::Value l1bArray; + l1bArray.append(10); + Json::Value l2aArray; + l2aArray.append(0); + l2aArray.append(0); + Json::Value l2bArray; + l2bArray.append(0); + l2bArray.append(10); + JSONTEST_ASSERT_PRED(checkIsLess(emptyArray, l1aArray)); + JSONTEST_ASSERT_PRED(checkIsLess(emptyArray, l2aArray)); + JSONTEST_ASSERT_PRED(checkIsLess(l1aArray, l2aArray)); + JSONTEST_ASSERT_PRED(checkIsLess(l2aArray, l2bArray)); + JSONTEST_ASSERT_PRED(checkIsEqual(emptyArray, Json::Value(emptyArray))); + JSONTEST_ASSERT_PRED(checkIsEqual(l1aArray, Json::Value(l1aArray))); + JSONTEST_ASSERT_PRED(checkIsEqual(l2bArray, Json::Value(l2bArray))); +} + +JSONTEST_FIXTURE(ValueTest, compareObject) { + // object compare size then content + Json::Value emptyObject(Json::objectValue); + Json::Value l1aObject; + l1aObject["key1"] = 0; + Json::Value l1bObject; + l1aObject["key1"] = 10; + Json::Value l2aObject; + l2aObject["key1"] = 0; + l2aObject["key2"] = 0; + JSONTEST_ASSERT_PRED(checkIsLess(emptyObject, l1aObject)); + JSONTEST_ASSERT_PRED(checkIsLess(emptyObject, l2aObject)); + JSONTEST_ASSERT_PRED(checkIsLess(l1aObject, l2aObject)); + JSONTEST_ASSERT_PRED(checkIsEqual(emptyObject, Json::Value(emptyObject))); + JSONTEST_ASSERT_PRED(checkIsEqual(l1aObject, Json::Value(l1aObject))); + JSONTEST_ASSERT_PRED(checkIsEqual(l2aObject, Json::Value(l2aObject))); +} + +JSONTEST_FIXTURE(ValueTest, compareType) { + // object of different type are ordered according to their type + JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(), Json::Value(1))); + JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(1), Json::Value(1u))); + JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(1u), Json::Value(1.0))); + JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(1.0), Json::Value("a"))); + JSONTEST_ASSERT_PRED(checkIsLess(Json::Value("a"), Json::Value(true))); + JSONTEST_ASSERT_PRED( + checkIsLess(Json::Value(true), Json::Value(Json::arrayValue))); + JSONTEST_ASSERT_PRED(checkIsLess(Json::Value(Json::arrayValue), + Json::Value(Json::objectValue))); +} + +void ValueTest::checkIsLess(const Json::Value& x, const Json::Value& y) { + JSONTEST_ASSERT(x < y); + JSONTEST_ASSERT(y > x); + JSONTEST_ASSERT(x <= y); + JSONTEST_ASSERT(y >= x); + JSONTEST_ASSERT(!(x == y)); + JSONTEST_ASSERT(!(y == x)); + JSONTEST_ASSERT(!(x >= y)); + JSONTEST_ASSERT(!(y <= x)); + JSONTEST_ASSERT(!(x > y)); + JSONTEST_ASSERT(!(y < x)); + JSONTEST_ASSERT(x.compare(y) < 0); + JSONTEST_ASSERT(y.compare(x) >= 0); +} + +void ValueTest::checkIsEqual(const Json::Value& x, const Json::Value& y) { + JSONTEST_ASSERT(x == y); + JSONTEST_ASSERT(y == x); + JSONTEST_ASSERT(x <= y); + JSONTEST_ASSERT(y <= x); + JSONTEST_ASSERT(x >= y); + JSONTEST_ASSERT(y >= x); + JSONTEST_ASSERT(!(x < y)); + JSONTEST_ASSERT(!(y < x)); + JSONTEST_ASSERT(!(x > y)); + JSONTEST_ASSERT(!(y > x)); + JSONTEST_ASSERT(x.compare(y) == 0); + JSONTEST_ASSERT(y.compare(x) == 0); +} + +JSONTEST_FIXTURE(ValueTest, typeChecksThrowExceptions) { +#if JSON_USE_EXCEPTION + + Json::Value intVal(1); + Json::Value strVal("Test"); + Json::Value objVal(Json::objectValue); + Json::Value arrVal(Json::arrayValue); + + JSONTEST_ASSERT_THROWS(intVal["test"]); + JSONTEST_ASSERT_THROWS(strVal["test"]); + JSONTEST_ASSERT_THROWS(arrVal["test"]); + + JSONTEST_ASSERT_THROWS(intVal.removeMember("test")); + JSONTEST_ASSERT_THROWS(strVal.removeMember("test")); + JSONTEST_ASSERT_THROWS(arrVal.removeMember("test")); + + JSONTEST_ASSERT_THROWS(intVal.getMemberNames()); + JSONTEST_ASSERT_THROWS(strVal.getMemberNames()); + JSONTEST_ASSERT_THROWS(arrVal.getMemberNames()); + + JSONTEST_ASSERT_THROWS(intVal[0]); + JSONTEST_ASSERT_THROWS(objVal[0]); + JSONTEST_ASSERT_THROWS(strVal[0]); + + JSONTEST_ASSERT_THROWS(intVal.clear()); + + JSONTEST_ASSERT_THROWS(intVal.resize(1)); + JSONTEST_ASSERT_THROWS(strVal.resize(1)); + JSONTEST_ASSERT_THROWS(objVal.resize(1)); + + JSONTEST_ASSERT_THROWS(intVal.asCString()); + + JSONTEST_ASSERT_THROWS(objVal.asString()); + JSONTEST_ASSERT_THROWS(arrVal.asString()); + + JSONTEST_ASSERT_THROWS(strVal.asInt()); + JSONTEST_ASSERT_THROWS(objVal.asInt()); + JSONTEST_ASSERT_THROWS(arrVal.asInt()); + + JSONTEST_ASSERT_THROWS(strVal.asUInt()); + JSONTEST_ASSERT_THROWS(objVal.asUInt()); + JSONTEST_ASSERT_THROWS(arrVal.asUInt()); + + JSONTEST_ASSERT_THROWS(strVal.asInt64()); + JSONTEST_ASSERT_THROWS(objVal.asInt64()); + JSONTEST_ASSERT_THROWS(arrVal.asInt64()); + + JSONTEST_ASSERT_THROWS(strVal.asUInt64()); + JSONTEST_ASSERT_THROWS(objVal.asUInt64()); + JSONTEST_ASSERT_THROWS(arrVal.asUInt64()); + + JSONTEST_ASSERT_THROWS(strVal.asDouble()); + JSONTEST_ASSERT_THROWS(objVal.asDouble()); + JSONTEST_ASSERT_THROWS(arrVal.asDouble()); + + JSONTEST_ASSERT_THROWS(strVal.asFloat()); + JSONTEST_ASSERT_THROWS(objVal.asFloat()); + JSONTEST_ASSERT_THROWS(arrVal.asFloat()); + + JSONTEST_ASSERT_THROWS(strVal.asBool()); + JSONTEST_ASSERT_THROWS(objVal.asBool()); + JSONTEST_ASSERT_THROWS(arrVal.asBool()); + +#endif +} + +JSONTEST_FIXTURE(ValueTest, offsetAccessors) { + Json::Value x; + JSONTEST_ASSERT(x.getOffsetStart() == 0); + JSONTEST_ASSERT(x.getOffsetLimit() == 0); + x.setOffsetStart(10); + x.setOffsetLimit(20); + JSONTEST_ASSERT(x.getOffsetStart() == 10); + JSONTEST_ASSERT(x.getOffsetLimit() == 20); + Json::Value y(x); + JSONTEST_ASSERT(y.getOffsetStart() == 10); + JSONTEST_ASSERT(y.getOffsetLimit() == 20); + Json::Value z; + z.swap(y); + JSONTEST_ASSERT(z.getOffsetStart() == 10); + JSONTEST_ASSERT(z.getOffsetLimit() == 20); + JSONTEST_ASSERT(y.getOffsetStart() == 0); + JSONTEST_ASSERT(y.getOffsetLimit() == 0); +} + +struct WriterTest : JsonTest::TestCase {}; + +JSONTEST_FIXTURE(WriterTest, dropNullPlaceholders) { + Json::FastWriter writer; + Json::Value nullValue; + JSONTEST_ASSERT(writer.write(nullValue) == "null\n"); + + writer.dropNullPlaceholders(); + JSONTEST_ASSERT(writer.write(nullValue) == "\n"); +} + +struct ReaderTest : JsonTest::TestCase {}; + +JSONTEST_FIXTURE(ReaderTest, parseWithNoErrors) { + Json::Reader reader; + Json::Value root; + bool ok = reader.parse("{ \"property\" : \"value\" }", root); + JSONTEST_ASSERT(ok); + JSONTEST_ASSERT(reader.getFormattedErrorMessages().size() == 0); + JSONTEST_ASSERT(reader.getStructuredErrors().size() == 0); +} + +JSONTEST_FIXTURE(ReaderTest, parseWithNoErrorsTestingOffsets) { + Json::Reader reader; + Json::Value root; + bool ok = reader.parse("{ \"property\" : [\"value\", \"value2\"], \"obj\" : " + "{ \"nested\" : 123, \"bool\" : true}, \"null\" : " + "null, \"false\" : false }", + root); + JSONTEST_ASSERT(ok); + JSONTEST_ASSERT(reader.getFormattedErrorMessages().size() == 0); + JSONTEST_ASSERT(reader.getStructuredErrors().size() == 0); + JSONTEST_ASSERT(root["property"].getOffsetStart() == 15); + JSONTEST_ASSERT(root["property"].getOffsetLimit() == 34); + JSONTEST_ASSERT(root["property"][0].getOffsetStart() == 16); + JSONTEST_ASSERT(root["property"][0].getOffsetLimit() == 23); + JSONTEST_ASSERT(root["property"][1].getOffsetStart() == 25); + JSONTEST_ASSERT(root["property"][1].getOffsetLimit() == 33); + JSONTEST_ASSERT(root["obj"].getOffsetStart() == 44); + JSONTEST_ASSERT(root["obj"].getOffsetLimit() == 76); + JSONTEST_ASSERT(root["obj"]["nested"].getOffsetStart() == 57); + JSONTEST_ASSERT(root["obj"]["nested"].getOffsetLimit() == 60); + JSONTEST_ASSERT(root["obj"]["bool"].getOffsetStart() == 71); + JSONTEST_ASSERT(root["obj"]["bool"].getOffsetLimit() == 75); + JSONTEST_ASSERT(root["null"].getOffsetStart() == 87); + JSONTEST_ASSERT(root["null"].getOffsetLimit() == 91); + JSONTEST_ASSERT(root["false"].getOffsetStart() == 103); + JSONTEST_ASSERT(root["false"].getOffsetLimit() == 108); + JSONTEST_ASSERT(root.getOffsetStart() == 0); + JSONTEST_ASSERT(root.getOffsetLimit() == 110); +} + +JSONTEST_FIXTURE(ReaderTest, parseWithOneError) { + Json::Reader reader; + Json::Value root; + bool ok = reader.parse("{ \"property\" :: \"value\" }", root); + JSONTEST_ASSERT(!ok); + JSONTEST_ASSERT(reader.getFormattedErrorMessages() == + "* Line 1, Column 15\n Syntax error: value, object or array " + "expected.\n"); + std::vector<Json::Reader::StructuredError> errors = + reader.getStructuredErrors(); + JSONTEST_ASSERT(errors.size() == 1); + JSONTEST_ASSERT(errors.at(0).offset_start == 14); + JSONTEST_ASSERT(errors.at(0).offset_limit == 15); + JSONTEST_ASSERT(errors.at(0).message == + "Syntax error: value, object or array expected."); +} + +JSONTEST_FIXTURE(ReaderTest, parseChineseWithOneError) { + Json::Reader reader; + Json::Value root; + bool ok = reader.parse("{ \"pr佐藤erty\" :: \"value\" }", root); + JSONTEST_ASSERT(!ok); + JSONTEST_ASSERT(reader.getFormattedErrorMessages() == + "* Line 1, Column 19\n Syntax error: value, object or array " + "expected.\n"); + std::vector<Json::Reader::StructuredError> errors = + reader.getStructuredErrors(); + JSONTEST_ASSERT(errors.size() == 1); + JSONTEST_ASSERT(errors.at(0).offset_start == 18); + JSONTEST_ASSERT(errors.at(0).offset_limit == 19); + JSONTEST_ASSERT(errors.at(0).message == + "Syntax error: value, object or array expected."); +} + +JSONTEST_FIXTURE(ReaderTest, parseWithDetailError) { + Json::Reader reader; + Json::Value root; + bool ok = reader.parse("{ \"property\" : \"v\\alue\" }", root); + JSONTEST_ASSERT(!ok); + JSONTEST_ASSERT(reader.getFormattedErrorMessages() == + "* Line 1, Column 16\n Bad escape sequence in string\nSee " + "Line 1, Column 20 for detail.\n"); + std::vector<Json::Reader::StructuredError> errors = + reader.getStructuredErrors(); + JSONTEST_ASSERT(errors.size() == 1); + JSONTEST_ASSERT(errors.at(0).offset_start == 15); + JSONTEST_ASSERT(errors.at(0).offset_limit == 23); + JSONTEST_ASSERT(errors.at(0).message == "Bad escape sequence in string"); +} + +int main(int argc, const char* argv[]) { + JsonTest::Runner runner; + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, memberCount); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, objects); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrays); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, null); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, strings); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, bools); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, integers); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, nonIntegers); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareNull); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareInt); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareUInt); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareDouble); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareString); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareBoolean); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareArray); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareObject); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, compareType); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, offsetAccessors); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, typeChecksThrowExceptions); + + JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithNoErrors); + JSONTEST_REGISTER_FIXTURE( + runner, ReaderTest, parseWithNoErrorsTestingOffsets); + JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithOneError); + JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseChineseWithOneError); + JSONTEST_REGISTER_FIXTURE(runner, ReaderTest, parseWithDetailError); + + JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders); + + return runner.runCommandLine(argc, argv); +} diff --git a/3rdparty/jsoncpp/src/test_lib_json/sconscript b/3rdparty/jsoncpp/src/test_lib_json/sconscript new file mode 100644 index 00000000000..915fd01c0a3 --- /dev/null +++ b/3rdparty/jsoncpp/src/test_lib_json/sconscript @@ -0,0 +1,10 @@ +Import( 'env_testing buildUnitTests' ) + +buildUnitTests( env_testing, Split( """ + main.cpp + jsontest.cpp + """ ), + 'test_lib_json' ) + +# For 'check' to work, 'libs' must be built first. +env_testing.Depends('test_lib_json', '#libs') |