aboutsummaryrefslogtreecommitdiff
path: root/lib/jsoncpp/src/test_lib_json
diff options
context:
space:
mode:
Diffstat (limited to 'lib/jsoncpp/src/test_lib_json')
-rw-r--r--lib/jsoncpp/src/test_lib_json/jsontest.cpp598
-rw-r--r--lib/jsoncpp/src/test_lib_json/jsontest.h252
-rw-r--r--lib/jsoncpp/src/test_lib_json/main.cpp244
-rw-r--r--lib/jsoncpp/src/test_lib_json/sconscript10
4 files changed, 1104 insertions, 0 deletions
diff --git a/lib/jsoncpp/src/test_lib_json/jsontest.cpp b/lib/jsoncpp/src/test_lib_json/jsontest.cpp
new file mode 100644
index 0000000000..dfd2b5c77d
--- /dev/null
+++ b/lib/jsoncpp/src/test_lib_json/jsontest.cpp
@@ -0,0 +1,598 @@
+#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 << ( bool value )
+{
+ return addToLastFailure( value ? "true" : "false" );
+}
+
+
+TestResult &
+TestResult::operator << ( int value )
+{
+ char buffer[32];
+ sprintf( buffer, "%d", value );
+ return addToLastFailure( buffer );
+}
+
+
+TestResult &
+TestResult::operator << ( unsigned int value )
+{
+ char buffer[32];
+ sprintf( buffer, "%u", value );
+ return addToLastFailure( buffer );
+}
+
+
+TestResult &
+TestResult::operator << ( double value )
+{
+ char buffer[32];
+ sprintf( buffer, "%16g", value );
+ return addToLastFailure( buffer );
+}
+
+
+TestResult &
+TestResult::operator << ( const char *value )
+{
+ return addToLastFailure( value ? value
+ : "<NULL>" );
+}
+
+
+TestResult &
+TestResult::operator << ( const std::string &value )
+{
+ return addToLastFailure( value );
+}
+
+
+
+// class TestCase
+// //////////////////////////////////////////////////////////////////
+
+TestCase::TestCase()
+ : result_( 0 )
+{
+}
+
+
+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 caugth:" ) << 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)
+// 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)
+ // Install a hook to prevent MSVCRT error and assertion from
+ // popping a dialog.
+ _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/lib/jsoncpp/src/test_lib_json/jsontest.h b/lib/jsoncpp/src/test_lib_json/jsontest.h
new file mode 100644
index 0000000000..b2553baea1
--- /dev/null
+++ b/lib/jsoncpp/src/test_lib_json/jsontest.h
@@ -0,0 +1,252 @@
+#ifndef JSONTEST_H_INCLUDED
+# define JSONTEST_H_INCLUDED
+
+# include <json/config.h>
+# include <stdio.h>
+# include <deque>
+# 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;
+
+ TestResult &operator << ( bool value );
+ TestResult &operator << ( int value );
+ TestResult &operator << ( unsigned int value );
+ TestResult &operator << ( double value );
+ TestResult &operator << ( const char *value );
+ TestResult &operator << ( const std::string &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();
+
+ 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>
+ TestResult &
+ checkEqual( TestResult &result, const T &expected, const T &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;
+ }
+
+ 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 ( condition ) \
+ { \
+ } \
+ 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(); \
+ } \
+ *result_
+
+/// \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), \
+ #expected " == " #actual )
+
+/// \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/lib/jsoncpp/src/test_lib_json/main.cpp b/lib/jsoncpp/src/test_lib_json/main.cpp
new file mode 100644
index 0000000000..b80776d630
--- /dev/null
+++ b/lib/jsoncpp/src/test_lib_json/main.cpp
@@ -0,0 +1,244 @@
+#include <json/json.h>
+#include "jsontest.h"
+
+
+// TODO:
+// - boolean value returns that they are integral. Should not be.
+// - unsigned integer in integer range are not considered to be valid integer. Should check range.
+
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// Json Library test cases
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+
+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 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 )
+ , smallUnsignedInteger_( Json::Value::UInt( Json::Value::maxInt ) )
+ , unsignedInteger_( 34567890u )
+ , real_( 1234.56789 )
+ , 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 isDouble_;
+ bool isInt_;
+ bool isUInt_;
+ bool isIntegral_;
+ bool isNumeric_;
+ bool isString_;
+ bool isNull_;
+ };
+
+ 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 );
+};
+
+
+JSONTEST_FIXTURE( ValueTest, size )
+{
+ 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(real_, 0) );
+ JSONTEST_ASSERT_PRED( checkMemberCount(emptyString_, 0) );
+ JSONTEST_ASSERT_PRED( checkMemberCount(string_, 0) );
+ JSONTEST_ASSERT_PRED( checkMemberCount(true_, 0) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isObject )
+{
+ IsCheck checks;
+ checks.isObject_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( emptyObject_, checks ) );
+ JSONTEST_ASSERT_PRED( checkIs( object1_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isArray )
+{
+ IsCheck checks;
+ checks.isArray_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( emptyArray_, checks ) );
+ JSONTEST_ASSERT_PRED( checkIs( array1_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isNull )
+{
+ IsCheck checks;
+ checks.isNull_ = true;
+ checks.isObject_ = true;
+ checks.isArray_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( null_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isString )
+{
+ IsCheck checks;
+ checks.isString_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( emptyString_, checks ) );
+ JSONTEST_ASSERT_PRED( checkIs( string_, checks ) );
+ JSONTEST_ASSERT_PRED( checkIs( string1_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isBool )
+{
+ IsCheck checks;
+ checks.isBool_ = true;
+ checks.isIntegral_ = true;
+ checks.isNumeric_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( false_, checks ) );
+ JSONTEST_ASSERT_PRED( checkIs( true_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isDouble )
+{
+ IsCheck checks;
+ checks.isDouble_ = true;
+ checks.isNumeric_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( real_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isInt )
+{
+ IsCheck checks;
+ checks.isInt_ = true;
+ checks.isNumeric_ = true;
+ checks.isIntegral_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( integer_, checks ) );
+}
+
+
+JSONTEST_FIXTURE( ValueTest, isUInt )
+{
+ IsCheck checks;
+ checks.isUInt_ = true;
+ checks.isNumeric_ = true;
+ checks.isIntegral_ = true;
+ JSONTEST_ASSERT_PRED( checkIs( unsignedInteger_, checks ) );
+ JSONTEST_ASSERT_PRED( checkIs( smallUnsignedInteger_, checks ) );
+}
+
+
+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 )
+ , isDouble_( false )
+ , isInt_( false )
+ , isUInt_( false )
+ , isIntegral_( false )
+ , isNumeric_( false )
+ , isString_( false )
+ , isNull_( 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() );
+}
+
+
+
+int main( int argc, const char *argv[] )
+{
+ JsonTest::Runner runner;
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, size );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isObject );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isArray );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isBool );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isInt );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isUInt );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isDouble );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isString );
+ JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isNull );
+ return runner.runCommandLine( argc, argv );
+}
diff --git a/lib/jsoncpp/src/test_lib_json/sconscript b/lib/jsoncpp/src/test_lib_json/sconscript
new file mode 100644
index 0000000000..915fd01c0a
--- /dev/null
+++ b/lib/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')