File indexing completed on 2024-12-15 04:02:45

0001 /*
0002  * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
0003  *
0004  * This file is part of the KGantt library.
0005  *
0006  * SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #ifndef __KDAB__UNITTEST__TEST_H__
0010 #define __KDAB__UNITTEST__TEST_H__
0011 
0012 #ifndef KDAB_NO_UNIT_TESTS
0013 
0014 #include "kganttglobal.h"
0015 
0016 #include <QtGlobal>
0017 
0018 #include <string>
0019 #include <iostream>
0020 
0021 namespace KDAB {
0022 namespace UnitTest {
0023 
0024 #define assertNotNull( x ) _assertNotNull( ( x ), #x, __FILE__, __LINE__ )
0025 #define assertNull( x ) _assertNull( ( x ), #x, __FILE__, __LINE__ )
0026 #define assertTrue( x )  _assertTrue( (x), #x, __FILE__, __LINE__ )
0027 #define assertFalse( x ) _assertFalse( (x), #x, __FILE__, __LINE__ )
0028 #define assertEqual( x, y ) _assertEqual( (x), (y), #x, #y, __FILE__, __LINE__ )
0029 #define assertNotEqual( x, y ) _assertNotEqual( (x), (y), #x, #y, __FILE__, __LINE__ )
0030 // to be phased out:
0031 #define assertNearEqual( x, y, z )
0032 #define assertEqualWithEpsilons( x, y, z ) _assertEqualWithEpsilons( (x), (y), (z), #x, #y, #z, __FILE__, __LINE__ )
0033 #if 0
0034 #define assertIsNaN( x ) _assertIsNaN( (x), #x, __FILE__, __LINE__ )
0035 #define assertIsNotNaN( x ) _assertIsNotNaN( (x), #x, __FILE__, __LINE__ )
0036 #endif
0037 
0038 #define assertThrowsExceptionWithCode( x, E, code ) \
0039 do {                           \
0040   try {                        \
0041     x;                         \
0042     fail( __FILE__, __LINE__ ) \
0043       << "\"" #x "\" didn't throw \"" #E "\"" << std::endl; \
0044   } catch ( E & ppq_ut_thrown ) {                           \
0045     success();                 \
0046     ( void )ppq_ut_thrown;     \
0047     code;                      \
0048   } catch ( ... ) {            \
0049     fail( __FILE__, __LINE__ ) \
0050       << "\"" #x "\" threw something, but it wasn't \"" #E "\"" << std::endl; \
0051   }                            \
0052 } while ( false )
0053 
0054 #define assertThrowsException( x, E ) assertThrowsExceptionWithCode( x, E, do{}while (0) )
0055 
0056 #define assertDoesNotThrowException( x, E ) \
0057 do {                           \
0058   try {                        \
0059     x;                         \
0060     success();                 \
0061   } catch ( E & ) {         \
0062     fail( __FILE__, __LINE__ ) \
0063       << "\"" #x "\" threw \"" #E "\", but shouldn't" << std::endl; \
0064   } catch ( ... ) {            \
0065     fail( __FILE__, __LINE__ ) \
0066       << "\"" #x "\" threw something, but it wasn't \"" #E "\"" << std::endl; \
0067   }                            \
0068 } while ( false )
0069 
0070 
0071   class Test {
0072     const std::string mName;
0073     unsigned int mFailed, mSucceeded;
0074   public:
0075     Test( const std::string & name );
0076     virtual ~Test() {}
0077 
0078     const std::string & name() const { return mName; }
0079     unsigned int failed() const { return mFailed; }
0080     unsigned int succeeded() const { return mSucceeded; }
0081 
0082     virtual void run() = 0;
0083 
0084   protected:
0085     void _assertNotNull( const void * x, const char * expression, const char * file, unsigned int line );
0086     void _assertNull( const void * x, const char * expression, const char * file, unsigned int line );
0087 #if 0
0088     void _assertIsNaN( qreal v, const char * expression, const char * file, unsigned int line );
0089     void _assertIsNotNaN( qreal v, const char * expression, const char * file, unsigned int line );
0090 #endif
0091     void _assertTrue( bool x, const char * expression, const char * file, unsigned int line );
0092     void _assertFalse( bool x, const char * expression, const char * file, unsigned int line );
0093 
0094     void _assertEqualWithEpsilons( float x1, float x2, int prec, const char * expr1, const char * expr2, const char * exprPrec, const char * file, unsigned int line );
0095     void _assertEqualWithEpsilons( qreal x1, qreal x2, int prec, const char * expr1, const char * expr2, const char * exprPrec, const char * file, unsigned int line );
0096     void _assertEqualWithEpsilons( long double x1, long double x2, int prec, const char * expr1, const char * expr2, const char * exprPrec, const char * file, unsigned int line );
0097 
0098     template <typename T, typename S>
0099     void _assertEqual( const T & x1, const S & x2, const char * expr1, const char * expr2, const char * file, unsigned int line ) {
0100       if ( x1 == x2 ) this->success();
0101       else {
0102           this->fail( file, line ) << '"' << expr1 << "\" yielded " << x1 << "; expected: " << x2 << "(\"" << expr2 << "\")" << std::endl;
0103       }
0104     }
0105     template <typename T, typename S>
0106     void _assertNotEqual( const T & x1, const S & x2, const char * expr1, const char * expr2, const char * file, unsigned int line ) {
0107       if ( x1 != x2 ) this->success();
0108       else {
0109           this->fail( file, line ) << '"' << expr1 << "\" yielded " << x1 << "; expected something not equal to: " << x2 << "(\"" << expr2 << "\")" << std::endl;
0110       }
0111     }
0112 
0113   protected:
0114     std::ostream & fail( const char * file, unsigned int line );
0115     void success() {
0116       ++mSucceeded;
0117     }
0118   };
0119 
0120   class TestFactory {
0121   public:
0122     virtual ~TestFactory() {}
0123     virtual Test * create() const = 0;
0124   };
0125 
0126 }
0127 }
0128 
0129 #include "testregistry.h"
0130 
0131 namespace KDAB {
0132 namespace UnitTest {
0133 
0134   template <typename T_Test>
0135   class GenericFactory : public TestFactory {
0136   public:
0137     GenericFactory( const char * group = nullptr ) {
0138       TestRegistry::instance()->registerTestFactory( this, group );
0139     }
0140     Test * create() const override { return new T_Test(); }
0141   };
0142 
0143 }
0144 }
0145 
0146 #include "libutil.h"
0147 
0148 // Use these macros to export your UnitTest class so that it gets executed by the test runner.
0149 // Use the second macro if your class is within a namespace.
0150 // Arguments :
0151 // - Namespace (unquoted) : the namespace in which the test class in contained
0152 // - Class (unquoted) : the test class, without namespace
0153 // - Group (quoted) : the name of the group this unit test belongs to
0154 #define KDAB_EXPORT_UNITTEST( Class, Group ) \
0155     static const KDAB::UnitTest::GenericFactory< Class > __##Class##_unittest( Group ); \
0156     KDAB_EXPORT_STATIC_SYMBOLS( Class )
0157 
0158 #define KDAB_EXPORT_SCOPED_UNITTEST( Namespace, Class, Group ) \
0159     static const KDAB::UnitTest::GenericFactory< Namespace::Class > __##Class##_unittest( Group ); \
0160     KDAB_EXPORT_STATIC_SYMBOLS( Class )
0161 
0162 // Use this macro to import the test explicitly (for windows static libs only)
0163 #define KDAB_IMPORT_UNITTEST( Class ) KDAB_IMPORT_STATIC_SYMBOLS( Class )
0164 
0165 // Convenience macros that create a simple test class for a single test and export it.
0166 // Usage : KDAB_UNITTEST_SIMPLE( MyClass, "mygroup" ) { doSomething(); assertEqual(...); }
0167 #define KDAB_UNITTEST_SIMPLE( Class, Group )                 \
0168     class Class##Test : public KDAB::UnitTest::Test {  \
0169     public:                                                 \
0170         Class##Test() : Test( #Class ) {}                   \
0171         void run();                                         \
0172     };                                                      \
0173     KDAB_EXPORT_UNITTEST( Class##Test, Group )               \
0174     void Class##Test::run()
0175 
0176 #define KDAB_SCOPED_UNITTEST_SIMPLE( Namespace, Class, Group )   \
0177     namespace Namespace {                                       \
0178         class Class##Test : public KDAB::UnitTest::Test {  \
0179         public:                                                 \
0180             Class##Test() : Test( #Namespace "::" #Class ) {}    \
0181             void run() override;                          \
0182         };                                                      \
0183     }                                                           \
0184     KDAB_EXPORT_SCOPED_UNITTEST( Namespace, Class##Test, Group ) \
0185     void Namespace::Class##Test::run()
0186 
0187 #endif // KDAB_NO_UNIT_TESTS
0188 
0189 #endif // __KDAB__UNITTEST__TEST_H__