Changeset 932


Ignore:
Timestamp:
Sep 8, 2011, 11:39:08 PM (8 years ago)
Author:
sam
Message:

lolunit: add some comments to document the framework internals.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/lol/unit.h

    r930 r932  
    2828using namespace std;
    2929
     30/*
     31 * This is the base class for all fixtures. It keeps track of all
     32 * fixtures registered through the LOLUNIT_FIXTURE macro and puts them
     33 * in a linked list.
     34 */
    3035class FixtureBase
    3136{
     
    6671    char const *m_fixturename, *m_currentname;
    6772    std::stringstream m_errorlog, m_context;
    68 };
    69 
    70 template<class T> class Fixture : protected FixtureBase
    71 {
    72 public:
    73     typedef T FixtureClass;
    74 
    75     class TestCase
    76     {
    77     public:
    78         void (FixtureClass::* m_fun)();
    79         char const *m_testname;
    80         TestCase *m_next;
    81 
    82         static void AddTestCase(TestCase *that, char const *name,
    83                                 void (FixtureClass::*fun)())
    84         {
    85             that->m_fun = fun;
    86             that->m_testname = name;
    87             that->m_next = NULL;
    88             GetOrSetTestCase(that);
    89         }
    90     };
    91 
    92     Fixture<T>()
    93     {
    94         GetOrSetTest(this);
    95     }
    96 
    97     /* Run all test cases in this fixture. */
    98     virtual void runFixture()
    99     {
    100         m_errorlog.str("");
    101         m_testcases = 0;
    102         m_failcases = 0;
    103         for (TestCase *c = GetOrSetTestCase(); c; c = c->m_next)
    104         {
    105             m_testcases++;
    106             m_asserts = 0;
    107             m_failure = false;
    108             m_currentname = c->m_testname;
    109             m_context.str("");
    110 
    111             std::cout << '.';
    112             (static_cast<FixtureClass *>(this)->*c->m_fun)();
    113             if (m_failure) std::cout << 'F';
    114         }
    115     }
    116 
    117     /* Each Fixture class specialisation keeps track of its instanciated
    118      * test cases through this method. */
    119     static TestCase *GetOrSetTestCase(TestCase *set = NULL)
    120     {
    121         static TestCase *head = NULL, *tail = NULL;
    122         if (set)
    123         {
    124             if (!head) head = set;
    125             if (tail) tail->m_next = set;
    126             tail = set;
    127         }
    128         return head;
    129     }
    130 };
    131 
    132 class TextTestRunner
    133 {
    134 public:
    135     bool run()
    136     {
    137         bool ret = true;
    138         std::stringstream errors("");
    139         int failcases = 0, testcases = 0;
    140 
    141         for (FixtureBase *f = FixtureBase::GetOrSetTest(); f; f = f->m_next)
    142         {
    143             f->setUp();
    144             f->runFixture();
    145             f->tearDown();
    146 
    147             errors << f->m_errorlog.str();
    148             testcases += f->m_testcases;
    149             failcases += f->m_failcases;
    150         }
    151         std::cout << std::endl;
    152 
    153         std::cout << std::endl << std::endl;
    154         if (failcases)
    155         {
    156             std::cout << "!!!FAILURES!!!" << std::endl;
    157             std::cout << "Test Results:" << std::endl;
    158             std::cout << "Run:  " << testcases
    159                       << "  Failures: " << failcases
    160                       << "  Errors: 0" << std::endl; /* TODO: handle errors */
    161 
    162             std::cout << errors.str();
    163             ret = false;
    164         }
    165         else
    166         {
    167             std::cout << "OK (" << testcases << " tests)" << std::endl;
    168         }
    169         std::cout << std::endl << std::endl;
    170 
    171         return ret;
    172     }
    17373};
    17474
     
    18989    class FixtureName : public lol::Fixture<FixtureName>
    19090
     91/*
     92 * This template specialises FixtureBase and provides registration of
     93 * test cases in a linked list through the LOLUNIT_TEST macro.
     94 */
     95template<class T> class Fixture : protected FixtureBase
     96{
     97public:
     98    typedef T FixtureClass;
     99
     100    class TestCase
     101    {
     102    public:
     103        void (FixtureClass::* m_fun)();
     104        char const *m_testname;
     105        TestCase *m_next;
     106
     107        static void AddTestCase(TestCase *that, char const *name,
     108                                void (FixtureClass::*fun)())
     109        {
     110            that->m_fun = fun;
     111            that->m_testname = name;
     112            that->m_next = NULL;
     113            GetOrSetTestCase(that);
     114        }
     115    };
     116
     117    Fixture<T>()
     118    {
     119        GetOrSetTest(this);
     120    }
     121
     122    /* Run all test cases in this fixture. */
     123    virtual void runFixture()
     124    {
     125        m_errorlog.str("");
     126        m_testcases = 0;
     127        m_failcases = 0;
     128        for (TestCase *c = GetOrSetTestCase(); c; c = c->m_next)
     129        {
     130            m_testcases++;
     131            m_asserts = 0;
     132            m_failure = false;
     133            m_currentname = c->m_testname;
     134            m_context.str("");
     135
     136            std::cout << '.';
     137            (static_cast<FixtureClass *>(this)->*c->m_fun)();
     138            if (m_failure) std::cout << 'F';
     139        }
     140    }
     141
     142    /* Each Fixture class specialisation keeps track of its instanciated
     143     * test cases through this method. */
     144    static TestCase *GetOrSetTestCase(TestCase *set = NULL)
     145    {
     146        static TestCase *head = NULL, *tail = NULL;
     147        if (set)
     148        {
     149            if (!head) head = set;
     150            if (tail) tail->m_next = set;
     151            tail = set;
     152        }
     153        return head;
     154    }
     155};
     156
    191157#define LOLUNIT_TEST(TestCaseName) \
    192158    class TestCase##TestCaseName : public TestCase \
     
    201167    TestCase##TestCaseName lol_unit_test_case_##TestCaseName; \
    202168    void TestCaseName()
     169
     170/*
     171 * This simple class runs all automatically registered tests and reports
     172 * on error and success in the standard output.
     173 */
     174class TextTestRunner
     175{
     176public:
     177    bool run()
     178    {
     179        bool ret = true;
     180        std::stringstream errors("");
     181        int failcases = 0, testcases = 0;
     182
     183        for (FixtureBase *f = FixtureBase::GetOrSetTest(); f; f = f->m_next)
     184        {
     185            f->setUp();
     186            f->runFixture();
     187            f->tearDown();
     188
     189            errors << f->m_errorlog.str();
     190            testcases += f->m_testcases;
     191            failcases += f->m_failcases;
     192        }
     193        std::cout << std::endl;
     194
     195        std::cout << std::endl << std::endl;
     196        if (failcases)
     197        {
     198            std::cout << "!!!FAILURES!!!" << std::endl;
     199            std::cout << "Test Results:" << std::endl;
     200            std::cout << "Run:  " << testcases
     201                      << "  Failures: " << failcases
     202                      << "  Errors: 0" << std::endl; /* TODO: handle errors */
     203
     204            std::cout << errors.str();
     205            ret = false;
     206        }
     207        else
     208        {
     209            std::cout << "OK (" << testcases << " tests)" << std::endl;
     210        }
     211        std::cout << std::endl << std::endl;
     212
     213        return ret;
     214    }
     215};
    203216
    204217#define LOLUNIT_ASSERT_GENERIC(msg, cond) \
     
    267280    } while(!True())
    268281
     282/*
     283 * Public assert macros
     284 */
     285
    269286#define LOLUNIT_FAIL(msg) \
    270287    do { \
     
    276293                   << __FILE__ << std::endl; \
    277294        m_errorlog << "forced failure" << std::endl; \
    278         m_errorlog << "- " << msg << std::endl; \
     295        m_errorlog << LOLUNIT_MSG(msg); \
    279296        m_errorlog << m_context.str(); \
    280297        m_failure = true; \
     
    287304        m_context << "- Context : " << #n << " = " << (n) << std::endl; \
    288305    } while(!True())
     306
    289307#define LOLUNIT_UNSET_CONTEXT(n) \
    290308    m_context.str("")
     
    350368    LOLUNIT_ASSERT_DOUBLES_EQUAL_GENERIC("", a, b, t)
    351369#define LOLUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(msg, a, b, t) \
    352     LOLUNIT_ASSERT_DOUBLES_EQUAL_GENERIC("- " << msg << std::endl, a, b, t)
     370    LOLUNIT_ASSERT_DOUBLES_EQUAL_GENERIC(LOLUNIT_MSG(msg), a, b, t)
    353371
    354372} /* namespace lol */
Note: See TracChangeset for help on using the changeset viewer.