mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-05-05 08:35:28 +02:00

Json::Value array; array.append( 1234 ); int value = array[0].asInt(); // did not compile previously
260 lines
9.3 KiB
C++
260 lines
9.3 KiB
C++
// 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 <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();
|
|
|
|
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>
|
|
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 ( 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(); \
|
|
} \
|
|
*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
|