diff options
Diffstat (limited to 'lib/jsoncpp/src/test_lib_json/jsontest.h')
-rw-r--r-- | lib/jsoncpp/src/test_lib_json/jsontest.h | 252 |
1 files changed, 252 insertions, 0 deletions
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 |