source: trunk/src/lol/unit.h @ 912

Last change on this file since 912 was 912, checked in by sam, 8 years ago

test: replace CppUnit with our LolUnit test suite.

CppUnit is really too large for our needs, would require to be precompiled
for many platforms, in all combinations of debug and release modes, with
additional variants for libstdc++ versions. We replace it with our own
lightweight implementation, LolUnit. Good riddance.

File size: 4.3 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11//
12// The Unit test framework
13// -----------------------
14//
15
16#if !defined __LOL_UNIT_H__
17#define __LOL_UNIT_H__
18
19#include <iostream>
20#include <cstdio>
21#include <cmath>
22
23namespace lol
24{
25
26using namespace std;
27
28class FixtureBase
29{
30    friend class TestRunner;
31
32public:
33    virtual void setUp(void) {};
34    virtual void tearDown(void) {};
35
36protected:
37    FixtureBase() : m_next(NULL), m_tests(0), m_fails(0) {}
38    virtual ~FixtureBase() {}
39
40    /* The FixtureBase class keeps track of all instanciated children
41     * fixtures through this method. */
42    static FixtureBase *GetOrSetTest(FixtureBase *set = NULL)
43    {
44        static FixtureBase *head = NULL, *tail = NULL;
45        if (set)
46        {
47            if (!head)
48                head = set;
49            if (tail)
50                tail->m_next = set;
51            tail = set;
52        }
53        return head;
54    }
55
56    virtual int RunFixture() = 0;
57
58    /* Prevent compiler complaints about unreachable code */
59    static inline bool True() { return true; }
60
61    FixtureBase *m_next;
62    int m_tests, m_fails;
63};
64
65template<class T> class Fixture : protected FixtureBase
66{
67public:
68    typedef T FixtureClass;
69
70    class TestCase
71    {
72    public:
73        void (FixtureClass::* m_fun)();
74        char const *m_name;
75        TestCase *m_next;
76
77        static void AddTestCase(TestCase *that, char const *name,
78                                void (FixtureClass::*fun)())
79        {
80            that->m_name = name;
81            that->m_fun = fun;
82            GetOrSetTestCase(that);
83        }
84    };
85
86    Fixture<T>()
87    {
88        GetOrSetTest(this);
89    }
90
91    /* Run all test cases in this fixture. */
92    virtual int RunFixture()
93    {
94        for (TestCase *head = GetOrSetTestCase(); head; head = head->m_next)
95        {
96            (static_cast<FixtureClass *>(this)->*head->m_fun)();
97            std::cout << ".";
98        }
99        return 0;
100    }
101
102    /* Each Fixture class specialisation keeps track of its instanciated
103     * test cases through this method. */
104    static TestCase *GetOrSetTestCase(TestCase *set = NULL)
105    {
106        static TestCase *head = NULL, *tail = NULL;
107        if (set)
108        {
109            if (!head) head = set;
110            if (tail) tail->m_next = set;
111            tail = set;
112        }
113        return head;
114    }
115};
116
117class TestRunner
118{
119public:
120    int Run()
121    {
122        int ret = 0;
123        for (FixtureBase *head = FixtureBase::GetOrSetTest(); head; head = head->m_next)
124        {
125            head->setUp();
126            if (head->RunFixture())
127                ret = 1;
128            head->tearDown();
129        }
130        std::cout << std::endl;
131        return ret;
132    }
133};
134
135#define LOLUNIT_FIXTURE(FixtureName) \
136    class FixtureName : public lol::Fixture<FixtureName>
137
138#define LOLUNIT_TEST(TestCaseName) \
139    class TestCase##TestCaseName : public TestCase \
140    { \
141    public: \
142        TestCase##TestCaseName() \
143        { \
144            AddTestCase(this, #TestCaseName, \
145                    (void (FixtureClass::*)()) &FixtureClass::TestCaseName); \
146        } \
147    }; \
148    TestCase##TestCaseName test_case_##TestCaseName; \
149    void TestCaseName()
150
151#define LOLUNIT_SETUP_FIXTURE(ClassName) \
152    ClassName ClassName##Test_Instance;
153
154#define LOLUNIT_ASSERT(cond) \
155    do { if (True() && !(cond)) \
156    { \
157        std::cout << "FAIL! " #cond << std::endl; \
158        return; \
159    } } while(!True())
160
161#define LOLUNIT_ASSERT_EQUAL(a, b) \
162    do { if (True() && (a) != (b)) \
163    { \
164        std::cout << "FAIL! " #a " != " #b << std::endl; \
165        std::cout << "expected: " << (a) << std::endl; \
166        std::cout << "returned: " << (b) << std::endl; \
167        return; \
168    } } while(!True())
169
170#define LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, t) \
171    do { if (True() && fabs((a) - (b)) > fabs((t))) \
172    { \
173        std::cout << "FAIL! " #a " != " #b << std::endl; \
174        std::cout << "expected: " << (a) << std::endl; \
175        std::cout << "returned: " << (b) << std::endl; \
176        return; \
177    } } while(!True())
178
179} /* namespace lol */
180
181#endif // __LOL_UNIT_H__
182
Note: See TracBrowser for help on using the repository browser.