Home | History | Annotate | Download | only in test_lib_json
      1 // Copyright 2007-2010 Baptiste Lepilleur
      2 // Distributed under MIT license, or public domain if desired and
      3 // recognized in your jurisdiction.
      4 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
      5 
      6 #ifndef JSONTEST_H_INCLUDED
      7 # define JSONTEST_H_INCLUDED
      8 
      9 # include <json/config.h>
     10 # include <json/value.h>
     11 # include <json/writer.h>
     12 # include <stdio.h>
     13 # include <deque>
     14 # include <sstream>
     15 # include <string>
     16 
     17 // //////////////////////////////////////////////////////////////////
     18 // //////////////////////////////////////////////////////////////////
     19 // Mini Unit Testing framework
     20 // //////////////////////////////////////////////////////////////////
     21 // //////////////////////////////////////////////////////////////////
     22 
     23 
     24 
     25 /** \brief Unit testing framework.
     26  * \warning: all assertions are non-aborting, test case execution will continue
     27  *           even if an assertion namespace.
     28  *           This constraint is for portability: the framework needs to compile
     29  *           on Visual Studio 6 and must not require exception usage.
     30  */
     31 namespace JsonTest {
     32 
     33 
     34    class Failure
     35    {
     36    public:
     37       const char *file_;
     38       unsigned int line_;
     39       std::string expr_;
     40       std::string message_;
     41       unsigned int nestingLevel_;
     42    };
     43 
     44 
     45    /// Context used to create the assertion callstack on failure.
     46    /// Must be a POD to allow inline initialisation without stepping
     47    /// into the debugger.
     48    struct PredicateContext
     49    {
     50       typedef unsigned int Id;
     51       Id id_;
     52       const char *file_;
     53       unsigned int line_;
     54       const char *expr_;
     55       PredicateContext *next_;
     56       /// Related Failure, set when the PredicateContext is converted
     57       /// into a Failure.
     58       Failure *failure_;
     59    };
     60 
     61    class TestResult
     62    {
     63    public:
     64       TestResult();
     65 
     66       /// \internal Implementation detail for assertion macros
     67       /// Not encapsulated to prevent step into when debugging failed assertions
     68       /// Incremented by one on assertion predicate entry, decreased by one
     69       /// by addPredicateContext().
     70       PredicateContext::Id predicateId_;
     71 
     72       /// \internal Implementation detail for predicate macros
     73       PredicateContext *predicateStackTail_;
     74 
     75       void setTestName( const std::string &name );
     76 
     77       /// Adds an assertion failure.
     78       TestResult &addFailure( const char *file, unsigned int line,
     79                               const char *expr = 0 );
     80 
     81       /// Removes the last PredicateContext added to the predicate stack
     82       /// chained list.
     83       /// Next messages will be targed at the PredicateContext that was removed.
     84       TestResult &popPredicateContext();
     85 
     86       bool failed() const;
     87 
     88       void printFailure( bool printTestName ) const;
     89 
     90       // Generic operator that will work with anything ostream can deal with.
     91       template <typename T>
     92       TestResult &operator << ( const T& value ) {
     93          std::ostringstream oss;
     94          oss.precision( 16 );
     95          oss.setf( std::ios_base::floatfield );
     96          oss << value;
     97          return addToLastFailure(oss.str());
     98       }
     99 
    100       // Specialized versions.
    101       TestResult &operator << ( bool value );
    102       // std:ostream does not support 64bits integers on all STL implementation
    103       TestResult &operator << ( Json::Int64 value );
    104       TestResult &operator << ( Json::UInt64 value );
    105 
    106    private:
    107       TestResult &addToLastFailure( const std::string &message );
    108       unsigned int getAssertionNestingLevel() const;
    109       /// Adds a failure or a predicate context
    110       void addFailureInfo( const char *file, unsigned int line,
    111                            const char *expr, unsigned int nestingLevel  );
    112       static std::string indentText( const std::string &text,
    113                                      const std::string &indent );
    114 
    115       typedef std::deque<Failure> Failures;
    116       Failures failures_;
    117       std::string name_;
    118       PredicateContext rootPredicateNode_;
    119       PredicateContext::Id lastUsedPredicateId_;
    120       /// Failure which is the target of the messages added using operator <<
    121       Failure *messageTarget_;
    122    };
    123 
    124 
    125    class TestCase
    126    {
    127    public:
    128       TestCase();
    129 
    130       virtual ~TestCase();
    131 
    132       void run( TestResult &result );
    133 
    134       virtual const char *testName() const = 0;
    135 
    136    protected:
    137       TestResult *result_;
    138 
    139    private:
    140       virtual void runTestCase() = 0;
    141    };
    142 
    143    /// Function pointer type for TestCase factory
    144    typedef TestCase *(*TestCaseFactory)();
    145 
    146    class Runner
    147    {
    148    public:
    149       Runner();
    150 
    151       /// Adds a test to the suite
    152       Runner &add( TestCaseFactory factory );
    153 
    154       /// Runs test as specified on the command-line
    155       /// If no command-line arguments are provided, run all tests.
    156       /// If --list-tests is provided, then print the list of all test cases
    157       /// If --test <testname> is provided, then run test testname.
    158       int runCommandLine( int argc, const char *argv[] ) const;
    159 
    160       /// Runs all the test cases
    161       bool runAllTest( bool printSummary ) const;
    162 
    163       /// Returns the number of test case in the suite
    164       unsigned int testCount() const;
    165 
    166       /// Returns the name of the test case at the specified index
    167       std::string testNameAt( unsigned int index ) const;
    168 
    169       /// Runs the test case at the specified index using the specified TestResult
    170       void runTestAt( unsigned int index, TestResult &result ) const;
    171 
    172       static void printUsage( const char *appName );
    173 
    174    private: // prevents copy construction and assignment
    175       Runner( const Runner &other );
    176       Runner &operator =( const Runner &other );
    177 
    178    private:
    179       void listTests() const;
    180       bool testIndex( const std::string &testName, unsigned int &index ) const;
    181       static void preventDialogOnCrash();
    182 
    183    private:
    184       typedef std::deque<TestCaseFactory> Factories;
    185       Factories tests_;
    186    };
    187 
    188    template<typename T, typename U>
    189    TestResult &
    190    checkEqual( TestResult &result, const T &expected, const U &actual,
    191                const char *file, unsigned int line, const char *expr )
    192    {
    193       if ( expected != actual )
    194       {
    195          result.addFailure( file, line, expr );
    196          result << "Expected: " << expected << "\n";
    197          result << "Actual  : " << actual;
    198       }
    199       return result;
    200    }
    201 
    202 
    203    TestResult &
    204    checkStringEqual( TestResult &result,
    205                      const std::string &expected, const std::string &actual,
    206                      const char *file, unsigned int line, const char *expr );
    207 
    208 } // namespace JsonTest
    209 
    210 
    211 /// \brief Asserts that the given expression is true.
    212 /// JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y;
    213 /// JSONTEST_ASSERT( x == y );
    214 #define JSONTEST_ASSERT( expr )                                               \
    215    if ( expr )                                                                \
    216    {                                                                          \
    217    }                                                                          \
    218    else                                                                       \
    219       result_->addFailure( __FILE__, __LINE__, #expr )
    220 
    221 /// \brief Asserts that the given predicate is true.
    222 /// The predicate may do other assertions and be a member function of the fixture.
    223 #define JSONTEST_ASSERT_PRED( expr )                                    \
    224    {                                                                    \
    225       JsonTest::PredicateContext _minitest_Context = {                  \
    226          result_->predicateId_, __FILE__, __LINE__, #expr };            \
    227       result_->predicateStackTail_->next_ = &_minitest_Context;         \
    228       result_->predicateId_ += 1;                                       \
    229       result_->predicateStackTail_ = &_minitest_Context;                \
    230       (expr);                                                           \
    231       result_->popPredicateContext();                                   \
    232    }                                                                    \
    233    *result_
    234 
    235 /// \brief Asserts that two values are equals.
    236 #define JSONTEST_ASSERT_EQUAL( expected, actual )          \
    237    JsonTest::checkEqual( *result_, expected, actual,       \
    238                          __FILE__, __LINE__,               \
    239                          #expected " == " #actual )
    240 
    241 /// \brief Asserts that two values are equals.
    242 #define JSONTEST_ASSERT_STRING_EQUAL( expected, actual ) \
    243    JsonTest::checkStringEqual( *result_,                 \
    244       std::string(expected), std::string(actual),        \
    245       __FILE__, __LINE__,                                \
    246       #expected " == " #actual )
    247 
    248 /// \brief Begin a fixture test case.
    249 #define JSONTEST_FIXTURE( FixtureType, name )                  \
    250    class Test##FixtureType##name : public FixtureType          \
    251    {                                                           \
    252    public:                                                     \
    253       static JsonTest::TestCase *factory()                     \
    254       {                                                        \
    255          return new Test##FixtureType##name();                 \
    256       }                                                        \
    257    public: /* overidden from TestCase */                       \
    258       virtual const char *testName() const                     \
    259       {                                                        \
    260          return #FixtureType "/" #name;                        \
    261       }                                                        \
    262       virtual void runTestCase();                              \
    263    };                                                          \
    264                                                                \
    265    void Test##FixtureType##name::runTestCase()
    266 
    267 #define JSONTEST_FIXTURE_FACTORY( FixtureType, name ) \
    268    &Test##FixtureType##name::factory
    269 
    270 #define JSONTEST_REGISTER_FIXTURE( runner, FixtureType, name ) \
    271    (runner).add( JSONTEST_FIXTURE_FACTORY( FixtureType, name ) )
    272 
    273 #endif // ifndef JSONTEST_H_INCLUDED
    274