LCOV - code coverage report
Current view: top level - UTests - UTester.hpp (source / functions) Hit Total Coverage
Test: Coverage example Lines: 53 71 74.6 %
Date: 2021-12-02 17:21:05 Functions: 222 247 89.9 %

          Line data    Source code
       1             : ///////////////////////////////////////////////////////////////////////////
       2             : // Inastemp - Berenger Bramas MPCDF - 2016
       3             : // Under LGPL Licence, please you must read the LICENCE file.
       4             : ///////////////////////////////////////////////////////////////////////////
       5             : #ifndef UTESTER_HPP
       6             : #define UTESTER_HPP
       7             : 
       8             : #include <iostream>
       9             : #include <list>
      10             : #include <string>
      11             : #include <cstdio>
      12             : #include <atomic>
      13             : 
      14             : template < class TestClass >
      15             : class UTester {
      16             :     // Test function pointer
      17             :     typedef void (TestClass::*TestFunc)(void);
      18             : 
      19             :     /** Test descriptor */
      20             :     struct TestFuncDescriptor {
      21             :         TestFunc func;    //< Test adress
      22             :         std::string name; //< Test name
      23             :     };
      24             : 
      25             : 
      26             :     std::list< TestFuncDescriptor > tests; //< all tests
      27             : 
      28             :     std::atomic<int> totalTests; //< number of tests
      29             : 
      30             :     std::atomic<int> currentTest; //< current processing test in the run
      31             :     std::atomic<int> currentStep; //< current processing step in the run
      32             : 
      33             :     std::atomic<int> failedSteps; //< number of failed step in the current test
      34             :     std::atomic<int> failedTests; //< number of failed tests
      35             : 
      36             : protected:
      37             :     /** Constructor */
      38          25 :     UTester() {
      39          25 :         totalTests = 0;
      40          25 :     }
      41             : 
      42          25 :     virtual ~UTester(){}
      43             : 
      44             :     /** Callback before processing test */
      45          25 :     virtual void Before() {
      46          25 :     }
      47             : 
      48             :     /** Callback after processing test */
      49          25 :     virtual void After() {
      50          25 :     }
      51             : 
      52             :     /** Callback before each unit test */
      53          45 :     virtual void PreTest() {
      54          45 :     }
      55             : 
      56             :     /** Callback after each unit test */
      57          45 :     virtual void PostTest() {
      58          45 :     }
      59             : 
      60             :     /**
      61             :     * This function has to add tests
      62             :         * <code> AddTest(&MyTest::TestOne); </code>
      63             :     */
      64             :     virtual void SetTests() = 0;
      65             : 
      66             :     /**
      67             :     * Add a test without giving a name
      68             :     * @param inFunc test function address
      69             :     */
      70             :     void AddTest(TestFunc inFunc) {
      71             :         char buff[256];
      72             :         sprintf(buff, "Unnamed Test number %d", totalTests + 1);
      73             :         AddTest(inFunc, buff);
      74             :     }
      75             : 
      76             :     /**
      77             :     * Add a test with a name
      78             :     * @param inFunc test function address
      79             :     * @param inFuncName function name
      80             :     */
      81          45 :     void AddTest(TestFunc inFunc, const std::string& inFuncName) {
      82          45 :         ++totalTests;
      83          90 :         TestFuncDescriptor desc;
      84          45 :         desc.func = inFunc;
      85          45 :         desc.name = inFuncName;
      86          45 :         tests.push_back(desc);
      87          45 :     }
      88             : 
      89         285 :     void uassertIsTrue(const bool shouldBeTrue,
      90             :                        const std::string str, const int line, const std::string file) {
      91         285 :         ++currentStep;
      92         285 :         if (!shouldBeTrue) {
      93           0 :             std::cout << ">> Step " << currentStep << " Equality Failed: " << str << "\n";
      94           0 :             std::cout << ">>     In file :" << file << "\n";
      95           0 :             std::cout << ">>     At line :" << line << "\n";
      96           0 :             ++failedSteps;
      97             :         }
      98         285 :     }
      99             : 
     100             :     template < class ValueType >
     101      495054 :     void uassertAreEqual(const ValueType v1, const ValueType v2,
     102             :                          const std::string str, const int line, const std::string file) {
     103      495054 :         ++currentStep;
     104      495054 :         if (!(v1 == v2)) {
     105           0 :             std::cout << ">> Step " << currentStep << " Equality Failed: " << str << "\n";
     106           0 :             std::cout << ">>     In file :" << file << "\n";
     107           0 :             std::cout << ">>     At line :" << line << "\n";
     108           0 :             std::cout << ">>     v1 :" << v1 << "\n";
     109           0 :             std::cout << ">>     v2 :" << v2 << "\n";
     110           0 :             ++failedSteps;
     111             :         }
     112      495054 :     }
     113             : 
     114             :     template < class ValueType >
     115           3 :     void uassertAreDiff(const ValueType v1, const ValueType v2,
     116             :                         const std::string str, const int line, const std::string file) {
     117           3 :         ++currentStep;
     118           3 :         if (!(v1 != v2)) {
     119           0 :             std::cout << ">> Step " << currentStep << " Difference Failed: " << str << "\n";
     120           0 :             std::cout << ">>     In file :" << file << "\n";
     121           0 :             std::cout << ">>     At line :" << line << "\n";
     122           0 :             std::cout << ">>     v1 :" << v1 << "\n";
     123           0 :             std::cout << ">>     v2 :" << v2 << "\n";
     124           0 :             ++failedSteps;
     125             :         }
     126           3 :     }
     127             : 
     128             : public:
     129             :     /**
     130             :     * Processing the test
     131             :         * return application exit code (= nb of errors)
     132             :     */
     133          25 :     int Run() {
     134          25 :         tests.clear();
     135             :         // register tests
     136          25 :         SetTests();
     137             : 
     138          25 :         TestClass* const toTest = static_cast< TestClass* >(this);
     139          25 :         currentTest             = 0;
     140          25 :         failedTests             = 0;
     141             : 
     142          25 :         Before();
     143             : 
     144             :         // for each tests
     145          25 :         const typename std::list< TestFuncDescriptor >::const_iterator end = tests.end();
     146          70 :         for (typename std::list< TestFuncDescriptor >::iterator iter = tests.begin(); iter != end; ++iter) {
     147          45 :             currentStep = 0;
     148          45 :             failedSteps = 0;
     149             : 
     150          45 :             std::cout << "[Start] " << (*iter).name << "\n";
     151             : 
     152          45 :             PreTest();
     153          45 :             TestFunc ff = (*iter).func;
     154          45 :             (toTest->*ff)();
     155          45 :             PostTest();
     156             : 
     157          45 :             if (failedSteps) {
     158           0 :                 std::cout << "[Finished] FAILED (" << failedSteps << "/" << currentStep << " steps failed)\n";
     159           0 :                 ++failedTests;
     160             :             } else {
     161          45 :                 std::cout << "[Finished] PASSED (" << currentStep << " steps)\n";
     162             :             }
     163             : 
     164          45 :             ++currentTest;
     165             :         }
     166             : 
     167             : 
     168          25 :         After();
     169             : 
     170          25 :         std::cout << "Test is over, " << (totalTests - failedTests) << " Passed, " << failedTests << " Failed\n";
     171             : 
     172          50 :         return failedTests;
     173             :     }
     174             : };
     175             : 
     176             : #define UASSERTETRUE(condition) \
     177             :     this->uassertIsTrue(condition, #condition, __LINE__, __FILE__);
     178             : 
     179             : #define UASSERTEEQUAL(v1, v2) \
     180             :     this->uassertAreEqual(v1, v2, #v1 " == " #v2, __LINE__, __FILE__);
     181             : 
     182             : #define UASSERTEDIFF(v1, v2) \
     183             :     this->uassertAreDiff(v1, v2, #v1 " != " #v2, __LINE__, __FILE__);
     184             : 
     185             : #define UASSERTETRUE_OFFSET(condition, offset) \
     186             :     this->uassertIsTrue(condition, #condition, __LINE__ + offset, __FILE__);
     187             : 
     188             : #define UASSERTEEQUAL_OFFSET(v1, v2, offset) \
     189             :     this->uassertAreEqual(v1, v2, #v1 " == " #v2, __LINE__ + offset, __FILE__);
     190             : 
     191             : #define UASSERTEDIFF_OFFSET(v1, v2, offset) \
     192             :     this->uassertAreDiff(v1, v2, #v1 " != " #v2, __LINE__ + offset, __FILE__);
     193             : 
     194             : #endif
     195             : 
     196             : #define TestClass(X)\
     197             :     int main(void){\
     198             :     X Controller;\
     199             :     return Controller.Run();\
     200             :     }

Generated by: LCOV version 1.14