Line data Source code
1 : /**
2 : * Copyright (c) 2011 Trevor Pounds
3 : *
4 : * Permission is hereby granted, free of charge, to any person obtaining a copy
5 : * of this software and associated documentation files (the "Software"), to deal
6 : * in the Software without restriction, including without limitation the rights
7 : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : * copies of the Software, and to permit persons to whom the Software is
9 : * furnished to do so, subject to the following conditions:
10 : *
11 : * The above copyright notice and this permission notice shall be included in
12 : * all copies or substantial portions of the Software.
13 : *
14 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : * THE SOFTWARE.
21 : */
22 : #ifndef __TPUNITPP_HPP__
23 : #define __TPUNITPP_HPP__
24 :
25 : /**
26 : * Declare printf dependency inline to workaround
27 : * potential #include <stdio.h> compiler/linker bugs.
28 : */
29 : extern "C" int printf(const char*, ...);
30 :
31 : /**
32 : * TPUNITPP_VERSION macro contains an integer represented by
33 : * the value (M*1000000 + N*1000 + P) where M is the major
34 : * version, N is the minor version, and P is the patch version.
35 : *
36 : * TPUNITPP_VERSION_MAJOR is an integer of the major version.
37 : * TPUNITPP_VERSION_MINOR is an integer of the minor version.
38 : * TPUNITPP_VERSION_PATCH is an integer of the patch version.
39 : */
40 : #define TPUNITPP_VERSION 1000002
41 : #define TPUNITPP_VERSION_MAJOR 1
42 : #define TPUNITPP_VERSION_MINOR 0
43 : #define TPUNITPP_VERSION_PATCH 2
44 :
45 : /**
46 : * ABORT(); generates a failure, immediately returning from the
47 : * currently executing test function.
48 : * FAIL(); generates a failure, allowing the currently executing
49 : * test function to continue.
50 : * PASS(); does nothing, effectively considered a NOP but may be
51 : * useful for annotating test cases with their desired intent.
52 : * TRACE(message); adds a trace to the test output with a user
53 : * specified string message.
54 : */
55 : #define ABORT() __assert(__FILE__, __LINE__); return;
56 : #define FAIL() __assert(__FILE__, __LINE__);
57 : #define PASS() /* do nothing */
58 : #define TRACE(message) __trace(__FILE__, __LINE__, message);
59 :
60 : /**
61 : * The set of core macros for basic predicate testing of boolean
62 : * expressions and value comparisons.
63 : *
64 : * ASSERT_*(...); generates a failure, immediately returning from
65 : * the currently executing test function if the supplied predicate
66 : * is not satisfied.
67 : * EXPECT_*(...); generates a failure, allowing the currently
68 : * executing test function to continue if the supplied predicate
69 : * is not satisified.
70 : */
71 : #define ASSERT_TRUE(condition) do { if(condition) { PASS(); } else { ABORT(); } } while(0)
72 : #define EXPECT_TRUE(condition) do { if(condition) { PASS(); } else { FAIL(); } } while(0)
73 : #define ASSERT_FALSE(condition) do { if(condition) { ABORT(); } else { PASS(); } } while(0)
74 : #define EXPECT_FALSE(condition) do { if(condition) { FAIL(); } else { PASS(); } } while(0)
75 : #define ASSERT_EQUAL(lhs, rhs) do { if((lhs) == (rhs)) { PASS(); } else { ABORT(); } } while(0)
76 : #define EXPECT_EQUAL(lhs, rhs) do { if((lhs) == (rhs)) { PASS(); } else { FAIL(); } } while(0)
77 : #define ASSERT_NOT_EQUAL(lhs, rhs) do { if((lhs) != (rhs)) { PASS(); } else { ABORT(); } } while(0)
78 : #define EXPECT_NOT_EQUAL(lhs, rhs) do { if((lhs) != (rhs)) { PASS(); } else { FAIL(); } } while(0)
79 : #define ASSERT_GREATER_THAN(lhs, rhs) do { if((lhs) > (rhs)) { PASS(); } else { ABORT(); } } while(0)
80 : #define EXPECT_GREATER_THAN(lhs, rhs) do { if((lhs) > (rhs)) { PASS(); } else { FAIL(); } } while(0)
81 : #define ASSERT_GREATER_THAN_EQUAL(lhs, rhs) do { if((lhs) >= (rhs)) { PASS(); } else { ABORT(); } } while(0)
82 : #define EXPECT_GREATER_THAN_EQUAL(lhs, rhs) do { if((lhs) >= (rhs)) { PASS(); } else { FAIL(); } } while(0)
83 : #define ASSERT_LESS_THAN(lhs, rhs) do { if((lhs) < (rhs)) { PASS(); } else { ABORT(); } } while(0)
84 : #define EXPECT_LESS_THAN(lhs, rhs) do { if((lhs) < (rhs)) { PASS(); } else { FAIL(); } } while(0)
85 : #define ASSERT_LESS_THAN_EQUAL(lhs, rhs) do { if((lhs) <= (rhs)) { PASS(); } else { ABORT(); } } while(0)
86 : #define EXPECT_LESS_THAN_EQUAL(lhs, rhs) do { if((lhs) <= (rhs)) { PASS(); } else { FAIL(); } } while(0)
87 :
88 : #define ASSERT(condition) do { if(condition) { PASS(); } else { ABORT(); } } while(0)
89 :
90 : /**
91 : * The set of floating-point macros used to compare double/float values.
92 : *
93 : * ASSERT|EXPECT_FLOAT_EQUAL(lhs, rhs); generates a failure if the given
94 : * floating-point values are not within 4 ULPs of each other.
95 : * ASSERT|EXPECT_FLOAT_NEAR(lhs, rhs, abs_error); generates a failure if
96 : * the given floating-point values exceed the absolute error.
97 : */
98 : #define ASSERT_FLOAT_EQUAL(lhs, rhs) do { if(__fp_equal(lhs, rhs, 4)) { PASS(); } else { ABORT(); } } while(0)
99 : #define EXPECT_FLOAT_EQUAL(lhs, rhs) do { if(__fp_equal(lhs, rhs, 4)) { PASS(); } else { FAIL(); } } while(0)
100 : #define ASSERT_FLOAT_NEAR(lhs, rhs, abs_error) do { if((((lhs) > (rhs)) ? (lhs) - (rhs) : (rhs) - (lhs)) <= (abs_error)) { PASS(); } else { ABORT(); } } while(0)
101 : #define EXPECT_FLOAT_NEAR(lhs, rhs, abs_error) do { if((((lhs) > (rhs)) ? (lhs) - (rhs) : (rhs) - (lhs)) <= (abs_error)) { PASS(); } else { FAIL(); } } while(0)
102 :
103 : /**
104 : * The set of macros for checking whether a statement will throw or not
105 : * throw an exception. Note, the checked exception macros will generally
106 : * not work with compilers that do not support exceptions or have them
107 : * explicitly turned off using a compiler flag (e.g. -fno-exceptions).
108 : *
109 : * ASSERT|EXPECT_THROW(statement, exception); generates a failure if
110 : * the given statement does not throw the supplied excetion.
111 : * ASSERT|EXPECT_NO_THROW(statement, exception); generates a failure
112 : * if the given statement throws any exception. Useful for ensuring
113 : * a statement never throws an exception.
114 : * ASSERT|EXPECT_ANY_THROW(statement); generates a failure if the
115 : * given statement does not throw any exceptions.
116 : */
117 : #define ASSERT_THROW(statement, exception) do { try { statement; ABORT(); } catch(const exception& e) { PASS(); } catch(...) { ABORT(); } } while(0)
118 : #define EXPECT_THROW(statement, exception) do { try { statement; FAIL(); } catch(const exception& e) { PASS(); } catch(...) { FAIL(); } } while(0)
119 : #define ASSERT_NO_THROW(statement) do { try { statement; PASS(); } catch(...) { ABORT(); } } while(0)
120 : #define EXPECT_NO_THROW(statement) do { try { statement; PASS(); } catch(...) { FAIL(); } } while(0)
121 : #define ASSERT_ANY_THROW(statement) do { try { statement; ABORT(); } catch(...) { PASS(); } } while(0)
122 : #define EXPECT_ANY_THROW(statement) do { try { statement; FAIL(); } catch(...) { PASS(); } } while(0)
123 :
124 : /**
125 : * The set of convenience macros for registering functions with the test
126 : * fixture.
127 : *
128 : * AFTER(function); registers a function to run once after each subsequent
129 : * test function within a test fixture.
130 : * AFTER_CLASS(function); registers a function to run once after all test
131 : * functions within a test fixture. Useful for cleaning up shared state
132 : * used by all test functions.
133 : * BEFORE(function); registers a function to run once before each subsequent
134 : * test function within a test fixture.
135 : * BEFORE_CLASS(function); registers a function to run once before all test
136 : * functions within a test fixture. Useful for initializing shared state
137 : * used by all test functions.
138 : * TEST(function); registers a function to run as a test within a test fixture.
139 : */
140 : #define AFTER(M) After(&M, "After: " #M)
141 : #define AFTER_CLASS(M) AfterClass(&M, "AfterClass: " #M)
142 : #define BEFORE(M) Before(&M, "Before: " #M)
143 : #define BEFORE_CLASS(M) BeforeClass(&M, "BeforeClass: " #M)
144 : #define TEST(M) Test(&M, #M)
145 :
146 : namespace tpunit
147 : {
148 : /**
149 : * The primary class that provides the integration point for creating user
150 : * defined test cases. To get started one only needs to derive from TestFixture,
151 : * define a few test methods and register them with the base constructor.
152 : */
153 : class TestFixture
154 : {
155 : private:
156 :
157 : /**
158 : * An internal class representing a TestFixture class.
159 : */
160 : struct method
161 : {
162 197 : method(TestFixture* obj, void (TestFixture::*addr)(), const char* name, unsigned char type)
163 : : _this(obj)
164 : , _addr(addr)
165 : , _name()
166 : , _type(type)
167 197 : , _next(0)
168 : {
169 197 : char* dest = _name;
170 7826 : while(name && *name != 0)
171 7432 : { *dest++ = *name++; }
172 197 : dest = 0;
173 197 : }
174 :
175 197 : ~method()
176 197 : { delete _next; }
177 :
178 : TestFixture* _this;
179 : void (TestFixture::*_addr)();
180 : char _name[256];
181 :
182 : enum
183 : {
184 : AFTER_METHOD, AFTER_CLASS_METHOD,
185 : BEFORE_METHOD, BEFORE_CLASS_METHOD,
186 : TEST_METHOD
187 : };
188 : unsigned char _type;
189 :
190 : method* _next;
191 : };
192 :
193 : /**
194 : * An internal class representing a TestFixture class.
195 : */
196 : struct fixture
197 : {
198 30 : fixture()
199 : : _afters(0), _after_classes(0)
200 : , _befores(0), _before_classes(0)
201 30 : , _tests(0), _next(0)
202 30 : {}
203 :
204 30 : ~fixture()
205 : {
206 30 : delete _afters;
207 30 : delete _after_classes;
208 30 : delete _befores;
209 30 : delete _before_classes;
210 30 : delete _tests;
211 30 : delete _next;
212 30 : }
213 :
214 : method* _afters;
215 : method* _after_classes;
216 : method* _befores;
217 : method* _before_classes;
218 : method* _tests;
219 :
220 : fixture* _next;
221 : };
222 :
223 : /**
224 : * A struct holding test statistics.
225 : */
226 : struct stats
227 : {
228 1 : stats()
229 : : _assertions(0)
230 : , _failures(0)
231 : , _passes(0)
232 1 : , _traces(0)
233 1 : {}
234 :
235 : int _assertions;
236 : int _failures;
237 : int _passes;
238 : int _traces;
239 : };
240 :
241 : public:
242 :
243 : /**
244 : * The base constructor of all test fixtures used to register methods executed by the default runner.
245 : *
246 : * @param[in] m0...m29 A list of methods to register with the test fixture.
247 : */
248 29 : TestFixture(method* m0, method* m1 = 0, method* m2 = 0, method* m3 = 0, method* m4 = 0,
249 : method* m5 = 0, method* m6 = 0, method* m7 = 0, method* m8 = 0, method* m9 = 0,
250 : method* m10 = 0, method* m11 = 0, method* m12 = 0, method* m13 = 0, method* m14 = 0,
251 : method* m15 = 0, method* m16 = 0, method* m17 = 0, method* m18 = 0, method* m19 = 0,
252 : method* m20 = 0, method* m21 = 0, method* m22 = 0, method* m23 = 0, method* m24 = 0,
253 : method* m25 = 0, method* m26 = 0, method* m27 = 0, method* m28 = 0, method* m29 = 0)
254 : {
255 29 : fixture* f = &__fixtures();
256 29 : while(f->_next) { f = f->_next; }
257 29 : f = f->_next = new fixture;
258 :
259 : #define SET_FIXTURE_METHOD(M) \
260 : if(M) \
261 : { \
262 : method** m = 0; \
263 : switch(M->_type) \
264 : { \
265 : case method::AFTER_METHOD: m = &f->_afters; break; \
266 : case method::AFTER_CLASS_METHOD: m = &f->_after_classes; break; \
267 : case method::BEFORE_METHOD: m = &f->_befores; break; \
268 : case method::BEFORE_CLASS_METHOD: m = &f->_before_classes; break; \
269 : case method::TEST_METHOD: m = &f->_tests; break; \
270 : } \
271 : while(*m && (*m)->_next) { m = &(*m)->_next; } \
272 : (*m) ? (*m)->_next = M : *m = M; \
273 : }
274 29 : SET_FIXTURE_METHOD(m0) SET_FIXTURE_METHOD(m1) SET_FIXTURE_METHOD(m2) SET_FIXTURE_METHOD(m3)
275 29 : SET_FIXTURE_METHOD(m4) SET_FIXTURE_METHOD(m5) SET_FIXTURE_METHOD(m6) SET_FIXTURE_METHOD(m7)
276 29 : SET_FIXTURE_METHOD(m8) SET_FIXTURE_METHOD(m9) SET_FIXTURE_METHOD(m10) SET_FIXTURE_METHOD(m11)
277 29 : SET_FIXTURE_METHOD(m12) SET_FIXTURE_METHOD(m13) SET_FIXTURE_METHOD(m14) SET_FIXTURE_METHOD(m15)
278 29 : SET_FIXTURE_METHOD(m16) SET_FIXTURE_METHOD(m17) SET_FIXTURE_METHOD(m18) SET_FIXTURE_METHOD(m19)
279 29 : SET_FIXTURE_METHOD(m20) SET_FIXTURE_METHOD(m21) SET_FIXTURE_METHOD(m22) SET_FIXTURE_METHOD(m23)
280 29 : SET_FIXTURE_METHOD(m24) SET_FIXTURE_METHOD(m25) SET_FIXTURE_METHOD(m26) SET_FIXTURE_METHOD(m27)
281 29 : SET_FIXTURE_METHOD(m28) SET_FIXTURE_METHOD(m29)
282 : #undef SET_FIXTURE_METHOD
283 29 : }
284 :
285 : /**
286 : * Registers a method to run once immediately after each test method registered with the test fixture.
287 : *
288 : * @param[in] _method A method to register with the test fixture.
289 : * @param[in] _name The internal name of the method used when status messages are displayed.
290 : */
291 : template <typename C>
292 : method* After(void (C::*_method)(), const char* _name)
293 : { return new method(this, reinterpret_cast<void (TestFixture::*)()>(_method), _name, method::AFTER_METHOD); }
294 :
295 : /**
296 : * Registers a method to run once immediately after all after/before/test methods registered with
297 : * the test fixture. Useful for cleaning up shared state used by methods in a test fixture.
298 : *
299 : * @param[in] _method A method to register with the test fixture.
300 : * @param[in] _name The internal name of the method used when status messages are displayed.
301 : */
302 : template <typename C>
303 : method* AfterClass(void (C::*_method)(), const char* _name)
304 : { return new method(this, reinterpret_cast<void (TestFixture::*)()>(_method), _name, method::AFTER_CLASS_METHOD); }
305 :
306 : /**
307 : * Registers a method to run once immediately before each test method registered with the test fixture.
308 : *
309 : * @param[in] _method A method to register with the test fixture.
310 : * @param[in] _name The internal name of the method used when status messages are displayed.
311 : */
312 : template <typename C>
313 : method* Before(void (C::*_method)(), const char* _name)
314 : { return new method(this, reinterpret_cast<void (TestFixture::*)()>(_method), _name, method::BEFORE_METHOD); }
315 :
316 : /**
317 : * Registers a method to run once immediately before all after/before/test methods registered with
318 : * the test fixture. Useful for intializing shared state used by methods in a test fixture.
319 : *
320 : * @param[in] _method A method to register with the test fixture.
321 : * @param[in] _name The internal name of the method used when status messages are displayed.
322 : */
323 : template <typename C>
324 : method* BeforeClass(void (C::*_method)(), const char* _name)
325 : { return new method(this, reinterpret_cast<void (TestFixture::*)()>(_method), _name, method::BEFORE_CLASS_METHOD); }
326 :
327 : /**
328 : * Registers a method to run as a test with the test fixture.
329 : *
330 : * @param[in] _method A method to register with the test fixture.
331 : * @param[in] _name The internal name of the method used when status messages are displayed.
332 : */
333 : template <typename C>
334 197 : method* Test(void (C::*_method)(), const char* _name)
335 197 : { return new method(this, reinterpret_cast<void (TestFixture::*)()>(_method), _name, method::TEST_METHOD); }
336 :
337 : protected:
338 :
339 1 : static int __do_run()
340 : {
341 1 : fixture* f = __fixtures()._next;
342 31 : while(f)
343 : {
344 29 : printf("[--------------]\n");
345 29 : __do_methods(f->_before_classes);
346 29 : __do_tests(f);
347 29 : __do_methods(f->_after_classes);
348 29 : printf("[--------------]\n\n");
349 29 : f = f->_next;
350 : }
351 1 : printf("[==============]\n");
352 1 : printf("[ TEST RESULTS ]\n");
353 1 : printf("[==============]\n");
354 1 : printf("[ PASSED ] %4i tests\n", __stats()._passes);
355 1 : printf("[ FAILED ] %4i tests\n", __stats()._failures);
356 1 : printf("[==============]\n");
357 1 : return __stats()._failures;
358 : }
359 :
360 : /**
361 : * Determine if two binary32 single precision IEEE 754 floating-point
362 : * numbers are equal using unit in the last place (ULP) analysis.
363 : *
364 : * http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
365 : */
366 : static bool __fp_equal(float lhs, float rhs, unsigned char ulps)
367 : {
368 : union
369 : {
370 : float f;
371 : char c[4];
372 : } lhs_u, rhs_u;
373 : lhs_u.f = lhs;
374 : rhs_u.f = rhs;
375 :
376 : bool lil_endian = (static_cast<unsigned char>(0x00FF)) == 0xFF;
377 : int msb = lil_endian ? 3 : 0;
378 : int lsb = lil_endian ? 0 : 3;
379 : if(lhs_u.c[msb] < 0)
380 : {
381 : lhs_u.c[0 ^ lsb] = 0x00 - lhs_u.c[0 ^ lsb];
382 : lhs_u.c[1 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[0 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[1 ^ lsb];
383 : lhs_u.c[2 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[1 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[2 ^ lsb];
384 : lhs_u.c[3 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[2 ^ lsb]) > 0x00) ? 0x7F : 0x80) - lhs_u.c[3 ^ lsb];
385 : }
386 : if(rhs_u.c[msb] < 0)
387 : {
388 : rhs_u.c[0 ^ lsb] = 0x00 - rhs_u.c[0 ^ lsb];
389 : rhs_u.c[1 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[0 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[1 ^ lsb];
390 : rhs_u.c[2 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[1 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[2 ^ lsb];
391 : rhs_u.c[3 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[2 ^ lsb]) > 0x00) ? 0x7F : 0x80) - rhs_u.c[3 ^ lsb];
392 : }
393 : return (lhs_u.c[1] == rhs_u.c[1] && lhs_u.c[2] == rhs_u.c[2] && lhs_u.c[msb] == rhs_u.c[msb]) &&
394 : ((lhs_u.c[lsb] > rhs_u.c[lsb]) ? lhs_u.c[lsb] - rhs_u.c[lsb] : rhs_u.c[lsb] - lhs_u.c[lsb]) <= ulps;
395 : }
396 :
397 : /**
398 : * Determine if two binary64 double precision IEEE 754 floating-point
399 : * numbers are equal using unit in the last place (ULP) analysis.
400 : *
401 : * http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
402 : */
403 : static bool __fp_equal(double lhs, double rhs, unsigned char ulps)
404 : {
405 : union
406 : {
407 : double d;
408 : char c[8];
409 : } lhs_u, rhs_u;
410 : lhs_u.d = lhs;
411 : rhs_u.d = rhs;
412 :
413 : bool lil_endian = static_cast<unsigned char>(0x00FF) == 0xFF;
414 : int msb = lil_endian ? 7 : 0;
415 : int lsb = lil_endian ? 0 : 7;
416 : if(lhs_u.c[msb] < 0)
417 : {
418 : lhs_u.c[0 ^ lsb] = 0x00 - lhs_u.c[0 ^ lsb];
419 : lhs_u.c[1 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[0 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[1 ^ lsb];
420 : lhs_u.c[2 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[1 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[2 ^ lsb];
421 : lhs_u.c[3 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[2 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[3 ^ lsb];
422 : lhs_u.c[4 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[3 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[4 ^ lsb];
423 : lhs_u.c[5 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[4 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[5 ^ lsb];
424 : lhs_u.c[6 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[5 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[6 ^ lsb];
425 : lhs_u.c[7 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[6 ^ lsb]) > 0x00) ? 0x7F : 0x80) - lhs_u.c[7 ^ lsb];
426 : }
427 : if(rhs_u.c[msb] < 0)
428 : {
429 : rhs_u.c[0 ^ lsb] = 0x00 - rhs_u.c[0 ^ lsb];
430 : rhs_u.c[1 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[0 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[1 ^ lsb];
431 : rhs_u.c[2 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[1 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[2 ^ lsb];
432 : rhs_u.c[3 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[2 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[3 ^ lsb];
433 : rhs_u.c[4 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[3 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[4 ^ lsb];
434 : rhs_u.c[5 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[4 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[5 ^ lsb];
435 : rhs_u.c[6 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[5 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[6 ^ lsb];
436 : rhs_u.c[7 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[6 ^ lsb]) > 0x00) ? 0x7F : 0x80) - rhs_u.c[7 ^ lsb];
437 : }
438 : return (lhs_u.c[1] == rhs_u.c[1] && lhs_u.c[2] == rhs_u.c[2] &&
439 : lhs_u.c[3] == rhs_u.c[3] && lhs_u.c[4] == rhs_u.c[4] &&
440 : lhs_u.c[5] == rhs_u.c[5] && lhs_u.c[6] == rhs_u.c[6] &&
441 : lhs_u.c[msb] == rhs_u.c[msb]) &&
442 : ((lhs_u.c[lsb] > rhs_u.c[lsb]) ? lhs_u.c[lsb] - rhs_u.c[lsb] : rhs_u.c[lsb] - lhs_u.c[lsb]) <= ulps;
443 : }
444 :
445 0 : static void __assert(const char* _file, int _line)
446 0 : { printf("[ ] assert #%i at %s:%i\n", ++__stats()._assertions, _file, _line); }
447 :
448 : static void __trace(const char* _file, int _line, const char* _message)
449 : { printf("[ ] trace #%i at %s:%i: %s\n", ++__stats()._traces, _file, _line, _message); }
450 :
451 : private:
452 :
453 452 : static void __do_methods(method* m)
454 : {
455 904 : while(m)
456 : {
457 0 : (*m->_this.*m->_addr)();
458 0 : m = m->_next;
459 : }
460 452 : }
461 :
462 29 : static void __do_tests(fixture* f)
463 : {
464 29 : method* t = f->_tests;
465 255 : while(t)
466 : {
467 197 : __do_methods(f->_befores);
468 :
469 197 : int _prev_assertions = __stats()._assertions;
470 197 : printf("[ RUN ] %s\n", t->_name);
471 197 : (*t->_this.*t->_addr)();
472 197 : if(_prev_assertions == __stats()._assertions)
473 : {
474 197 : printf("[ PASSED ] %s\n", t->_name);
475 197 : __stats()._passes++;
476 : }
477 : else
478 : {
479 0 : printf("[ FAILED ] %s\n", t->_name);
480 0 : __stats()._failures++;
481 : }
482 197 : t = t->_next;
483 :
484 197 : __do_methods(f->_afters);
485 : }
486 29 : }
487 :
488 594 : static stats& __stats()
489 : {
490 594 : static stats _stats;
491 594 : return _stats;
492 : }
493 :
494 30 : static fixture& __fixtures()
495 : {
496 30 : static fixture _fixtures;
497 30 : return _fixtures;
498 : }
499 : };
500 :
501 : /**
502 : * A class containing the primary entry point for running all registered
503 : * tpunit++ test cases. Generally this class is wrapped by the user's
504 : * \em main function.
505 : */
506 : class Tests : private TestFixture
507 : {
508 : public:
509 :
510 : /**
511 : * Run all of the registered test cases and return the number of failed assertions.
512 : *
513 : * @return The number of failing assertions. (e.g. zero if all tests pass, otherwise non-zero)
514 : */
515 1 : static int Run() { return TestFixture::__do_run(); }
516 :
517 : private:
518 :
519 : Tests() : TestFixture(0) { /* disable instance creation */ }
520 : };
521 : } // namespace tpunit
522 : #endif //__TPUNITPP_HPP__
|