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__