#ifndef __TPUNITPP_HPP__
#define __TPUNITPP_HPP__
<stdio.h>
extern "C" int printf(const char*, ...);
#define TPUNITPP_VERSION 1000002
#define TPUNITPP_VERSION_MAJOR 1
#define TPUNITPP_VERSION_MINOR 0
#define TPUNITPP_VERSION_PATCH 2
#define ABORT() __assert(__FILE__, __LINE__); return;
#define FAIL()  __assert(__FILE__, __LINE__);
#define PASS()  
#define TRACE(message) __trace(__FILE__, __LINE__, message);
#define ASSERT_TRUE(condition) do { if(condition) { PASS(); } else { ABORT(); } } while(0)
#define EXPECT_TRUE(condition) do { if(condition) { PASS(); } else { FAIL(); } } while(0)
#define ASSERT_FALSE(condition) do { if(condition) { ABORT(); } else { PASS(); } } while(0)
#define EXPECT_FALSE(condition) do { if(condition) { FAIL(); } else { PASS(); } } while(0)
#define ASSERT_EQUAL(lhs, rhs) do { if((lhs) == (rhs)) { PASS(); } else { ABORT(); } } while(0)
#define EXPECT_EQUAL(lhs, rhs) do { if((lhs) == (rhs)) { PASS(); } else { FAIL(); } } while(0)
#define ASSERT_NOT_EQUAL(lhs, rhs) do { if((lhs) != (rhs)) { PASS(); } else { ABORT(); } } while(0)
#define EXPECT_NOT_EQUAL(lhs, rhs) do { if((lhs) != (rhs)) { PASS(); } else { FAIL(); } } while(0)
#define ASSERT_GREATER_THAN(lhs, rhs) do { if((lhs) > (rhs)) { PASS(); } else { ABORT(); } } while(0)
#define EXPECT_GREATER_THAN(lhs, rhs) do { if((lhs) > (rhs)) { PASS(); } else { FAIL(); } } while(0)
#define ASSERT_GREATER_THAN_EQUAL(lhs, rhs) do { if((lhs) >= (rhs)) { PASS(); } else { ABORT(); } } while(0)
#define EXPECT_GREATER_THAN_EQUAL(lhs, rhs) do { if((lhs) >= (rhs)) { PASS(); } else { FAIL(); } } while(0)
#define ASSERT_LESS_THAN(lhs, rhs) do { if((lhs) < (rhs)) { PASS(); } else { ABORT(); } } while(0)
#define EXPECT_LESS_THAN(lhs, rhs) do { if((lhs) < (rhs)) { PASS(); } else { FAIL(); } } while(0)
#define ASSERT_LESS_THAN_EQUAL(lhs, rhs) do { if((lhs) <= (rhs)) { PASS(); } else { ABORT(); } } while(0)
#define EXPECT_LESS_THAN_EQUAL(lhs, rhs) do { if((lhs) <= (rhs)) { PASS(); } else { FAIL(); } } while(0)
#define ASSERT(condition) do { if(condition) { PASS(); } else { ABORT(); } } while(0)
#define ASSERT_FLOAT_EQUAL(lhs, rhs) do { if(__fp_equal(lhs, rhs, 4)) { PASS(); } else { ABORT(); } } while(0)
#define EXPECT_FLOAT_EQUAL(lhs, rhs) do { if(__fp_equal(lhs, rhs, 4)) { PASS(); } else { FAIL(); } } while(0)
#define ASSERT_FLOAT_NEAR(lhs, rhs, abs_error) do { if((((lhs) > (rhs)) ? (lhs) - (rhs) : (rhs) - (lhs)) <= (abs_error)) { PASS(); } else { ABORT(); } } while(0)
#define EXPECT_FLOAT_NEAR(lhs, rhs, abs_error) do { if((((lhs) > (rhs)) ? (lhs) - (rhs) : (rhs) - (lhs)) <= (abs_error)) { PASS(); } else { FAIL(); } } while(0)
#define ASSERT_THROW(statement, exception) do { try { statement; ABORT(); } catch(const exception& e) { PASS(); } catch(...) { ABORT(); } } while(0)
#define EXPECT_THROW(statement, exception) do { try { statement; FAIL(); } catch(const exception& e) { PASS(); } catch(...) { FAIL(); } } while(0)
#define ASSERT_NO_THROW(statement) do { try { statement; PASS(); } catch(...) { ABORT(); } } while(0)
#define EXPECT_NO_THROW(statement) do { try { statement; PASS(); } catch(...) { FAIL(); } } while(0)
#define ASSERT_ANY_THROW(statement) do { try { statement; ABORT(); } catch(...) { PASS(); } } while(0)
#define EXPECT_ANY_THROW(statement) do { try { statement; FAIL(); } catch(...) { PASS(); } } while(0)
#define AFTER(M)        After(&M, "After: " #M)
#define AFTER_CLASS(M)  AfterClass(&M, "AfterClass: " #M)
#define BEFORE(M)       Before(&M, "Before: " #M)
#define BEFORE_CLASS(M) BeforeClass(&M, "BeforeClass: " #M)
#define TEST(M)         Test(&M, #M)
namespace tpunit
{
   
   class TestFixture
   {
      private:
         
         struct method
         {
            method(TestFixture* obj, void (TestFixture::*addr)(), const char* name, unsigned char type)
               : _this(obj)
               , _addr(addr)
               , _name()
               , _type(type)
               , _next(0)
            {
               char* dest = _name;
               while(name && *name != 0)
                  { *dest++ = *name++; }
               dest = 0;
            }
            ~method()
               { delete _next; }
            TestFixture* _this;
            void (TestFixture::*_addr)();
            char _name[256];
            enum
            {
               AFTER_METHOD,  AFTER_CLASS_METHOD,
               BEFORE_METHOD, BEFORE_CLASS_METHOD,
               TEST_METHOD
            };
            unsigned char _type;
            method* _next;
         };
         
         struct fixture
         {
            fixture()
               : _afters(0),  _after_classes(0) 
               , _befores(0), _before_classes(0) 
               , _tests(0),   _next(0)
               {}
            ~fixture()
            {
               delete _afters;
               delete _after_classes;
               delete _befores;
               delete _before_classes;
               delete _tests;
               delete _next;
            }
            method* _afters;
            method* _after_classes;
            method* _befores;
            method* _before_classes;
            method* _tests;
            fixture* _next;
         };
         
         struct stats
         {
            stats()
               : _assertions(0)
               , _failures(0)
               , _passes(0)
               , _traces(0)
               {}
            int _assertions;
            int _failures;
            int _passes;
            int _traces;
         };
      public:
         
@param
         TestFixture(method* m0,      method* m1  = 0, method* m2  = 0, method* m3  = 0, method* m4  = 0,
                     method* m5  = 0, method* m6  = 0, method* m7  = 0, method* m8  = 0, method* m9  = 0,
                     method* m10 = 0, method* m11 = 0, method* m12 = 0, method* m13 = 0, method* m14 = 0,
                     method* m15 = 0, method* m16 = 0, method* m17 = 0, method* m18 = 0, method* m19 = 0,
                     method* m20 = 0, method* m21 = 0, method* m22 = 0, method* m23 = 0, method* m24 = 0,
                     method* m25 = 0, method* m26 = 0, method* m27 = 0, method* m28 = 0, method* m29 = 0)
         {
            fixture* f = &__fixtures();
            while(f->_next) { f = f->_next; }
            f = f->_next = new fixture;
            #define SET_FIXTURE_METHOD(M) \
               if(M) \
               { \
                  method** m = 0; \
                  switch(M->_type) \
                  { \
                     case method::AFTER_METHOD:        m = &f->_afters;         break; \
                     case method::AFTER_CLASS_METHOD:  m = &f->_after_classes;  break; \
                     case method::BEFORE_METHOD:       m = &f->_befores;        break; \
                     case method::BEFORE_CLASS_METHOD: m = &f->_before_classes; break; \
                     case method::TEST_METHOD:         m = &f->_tests;          break; \
                  } \
                  while(*m && (*m)->_next) { m = &(*m)->_next; } \
                  (*m) ? (*m)->_next = M : *m = M; \
               }
            SET_FIXTURE_METHOD(m0)  SET_FIXTURE_METHOD(m1)  SET_FIXTURE_METHOD(m2)  SET_FIXTURE_METHOD(m3)
            SET_FIXTURE_METHOD(m4)  SET_FIXTURE_METHOD(m5)  SET_FIXTURE_METHOD(m6)  SET_FIXTURE_METHOD(m7)
            SET_FIXTURE_METHOD(m8)  SET_FIXTURE_METHOD(m9)  SET_FIXTURE_METHOD(m10) SET_FIXTURE_METHOD(m11)
            SET_FIXTURE_METHOD(m12) SET_FIXTURE_METHOD(m13) SET_FIXTURE_METHOD(m14) SET_FIXTURE_METHOD(m15)
            SET_FIXTURE_METHOD(m16) SET_FIXTURE_METHOD(m17) SET_FIXTURE_METHOD(m18) SET_FIXTURE_METHOD(m19)
            SET_FIXTURE_METHOD(m20) SET_FIXTURE_METHOD(m21) SET_FIXTURE_METHOD(m22) SET_FIXTURE_METHOD(m23)
            SET_FIXTURE_METHOD(m24) SET_FIXTURE_METHOD(m25) SET_FIXTURE_METHOD(m26) SET_FIXTURE_METHOD(m27)
            SET_FIXTURE_METHOD(m28) SET_FIXTURE_METHOD(m29)
            #undef SET_FIXTURE_METHOD
         }
         
@param
@param
         template <typename C>
         method* After(void (C::*_method)(), const char* _name)
            { return new method(this, reinterpret_cast<void (TestFixture::*)()>(_method), _name, method::AFTER_METHOD); }
         
@param
@param
         template <typename C>
         method* AfterClass(void (C::*_method)(), const char* _name)
            { return new method(this, reinterpret_cast<void (TestFixture::*)()>(_method), _name, method::AFTER_CLASS_METHOD); }
         
@param
@param
         template <typename C>
         method* Before(void (C::*_method)(), const char* _name)
            { return new method(this, reinterpret_cast<void (TestFixture::*)()>(_method), _name, method::BEFORE_METHOD); }
         
@param
@param
         template <typename C>
         method* BeforeClass(void (C::*_method)(), const char* _name)
            { return new method(this, reinterpret_cast<void (TestFixture::*)()>(_method), _name, method::BEFORE_CLASS_METHOD); }
         
@param
@param
         template <typename C>
         method* Test(void (C::*_method)(), const char* _name)
            { return new method(this, reinterpret_cast<void (TestFixture::*)()>(_method), _name, method::TEST_METHOD); }
      protected:
         static int __do_run()
         {
            fixture* f = __fixtures()._next;
            while(f)
            {
               printf("[--------------]\n");
               __do_methods(f->_before_classes);
               __do_tests(f);
               __do_methods(f->_after_classes);
               printf("[--------------]\n\n");
               f = f->_next;
            }
            printf("[==============]\n");
            printf("[ TEST RESULTS ]\n");
            printf("[==============]\n");
            printf("[    PASSED    ] %4i tests\n", __stats()._passes);
            printf("[    FAILED    ] %4i tests\n", __stats()._failures);
            printf("[==============]\n");
            return __stats()._failures;
         }
         
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
         static bool __fp_equal(float lhs, float rhs, unsigned char ulps)
         {
            union
            {
               float f;
               char  c[4];
            } lhs_u, rhs_u;
            lhs_u.f = lhs;
            rhs_u.f = rhs;
            bool lil_endian = (static_cast<unsigned char>(0x00FF)) == 0xFF;
            int msb = lil_endian ? 3 : 0;
            int lsb = lil_endian ? 0 : 3;
            if(lhs_u.c[msb] < 0)
            {
               lhs_u.c[0 ^ lsb] = 0x00 - lhs_u.c[0 ^ lsb];
               lhs_u.c[1 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[0 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[1 ^ lsb];
               lhs_u.c[2 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[1 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[2 ^ lsb];
               lhs_u.c[3 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[2 ^ lsb]) > 0x00) ? 0x7F : 0x80) - lhs_u.c[3 ^ lsb];
            }
            if(rhs_u.c[msb] < 0)
            {
               rhs_u.c[0 ^ lsb] = 0x00 - rhs_u.c[0 ^ lsb];
               rhs_u.c[1 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[0 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[1 ^ lsb];
               rhs_u.c[2 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[1 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[2 ^ lsb];
               rhs_u.c[3 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[2 ^ lsb]) > 0x00) ? 0x7F : 0x80) - rhs_u.c[3 ^ lsb];
            }
            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]) &&
                   ((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;
         }
         
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
         static bool __fp_equal(double lhs, double rhs, unsigned char ulps)
         {
            union
            {
               double d;
               char   c[8];
            } lhs_u, rhs_u;
            lhs_u.d = lhs;
            rhs_u.d = rhs;
            bool lil_endian = static_cast<unsigned char>(0x00FF) == 0xFF;
            int msb = lil_endian ? 7 : 0;
            int lsb = lil_endian ? 0 : 7;
            if(lhs_u.c[msb] < 0)
            {
               lhs_u.c[0 ^ lsb] = 0x00 - lhs_u.c[0 ^ lsb];
               lhs_u.c[1 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[0 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[1 ^ lsb];
               lhs_u.c[2 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[1 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[2 ^ lsb];
               lhs_u.c[3 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[2 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[3 ^ lsb];
               lhs_u.c[4 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[3 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[4 ^ lsb];
               lhs_u.c[5 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[4 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[5 ^ lsb];
               lhs_u.c[6 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[5 ^ lsb]) > 0x00) ? 0xFF : 0x00) - lhs_u.c[6 ^ lsb];
               lhs_u.c[7 ^ lsb] = ((static_cast<unsigned char>(lhs_u.c[6 ^ lsb]) > 0x00) ? 0x7F : 0x80) - lhs_u.c[7 ^ lsb];
            }
            if(rhs_u.c[msb] < 0)
            {
               rhs_u.c[0 ^ lsb] = 0x00 - rhs_u.c[0 ^ lsb];
               rhs_u.c[1 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[0 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[1 ^ lsb];
               rhs_u.c[2 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[1 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[2 ^ lsb];
               rhs_u.c[3 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[2 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[3 ^ lsb];
               rhs_u.c[4 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[3 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[4 ^ lsb];
               rhs_u.c[5 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[4 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[5 ^ lsb];
               rhs_u.c[6 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[5 ^ lsb]) > 0x00) ? 0xFF : 0x00) - rhs_u.c[6 ^ lsb];
               rhs_u.c[7 ^ lsb] = ((static_cast<unsigned char>(rhs_u.c[6 ^ lsb]) > 0x00) ? 0x7F : 0x80) - rhs_u.c[7 ^ lsb];
            }
            return (lhs_u.c[1] == rhs_u.c[1] && lhs_u.c[2] == rhs_u.c[2] &&
                    lhs_u.c[3] == rhs_u.c[3] && lhs_u.c[4] == rhs_u.c[4] &&
                    lhs_u.c[5] == rhs_u.c[5] && lhs_u.c[6] == rhs_u.c[6] &&
                    lhs_u.c[msb] == rhs_u.c[msb]) &&
                   ((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;
         }
         static void __assert(const char* _file, int _line)
            { printf("[              ]    assert #%i at %s:%i\n", ++__stats()._assertions, _file, _line); }
         static void __trace(const char* _file, int _line, const char* _message)
            { printf("[              ]    trace #%i at %s:%i: %s\n", ++__stats()._traces, _file, _line, _message); }
      private:
         static void __do_methods(method* m)
         {
            while(m)
            {
               (*m->_this.*m->_addr)();
               m = m->_next;
            }
         }
         static void __do_tests(fixture* f)
         {
            method* t = f->_tests;
            while(t)
            {
               __do_methods(f->_befores);
               int _prev_assertions = __stats()._assertions;
               printf("[ RUN          ] %s\n", t->_name);
               (*t->_this.*t->_addr)();
               if(_prev_assertions == __stats()._assertions)
               {
                  printf("[       PASSED ] %s\n", t->_name);
                  __stats()._passes++;
               }
               else
               {
                  printf("[       FAILED ] %s\n", t->_name);
                  __stats()._failures++;
               }
               t = t->_next;
               __do_methods(f->_afters);
            }
         }
         static stats& __stats()
         {
            static stats _stats;
            return _stats;
         }
         static fixture& __fixtures()
         {
            static fixture _fixtures;
            return _fixtures;
         }
   };
   
   class Tests : private TestFixture
   {
      public:
         
@return
         static int Run() { return TestFixture::__do_run(); }
      private:
         Tests() : TestFixture(0) {  }
   };
} 
#endif