This is useful when doing several asserts in one loop, for instance: there isn't always a way to deduce the loop index from the assert failure, so these macros allow the user to give more context information.legacy
| @@ -17,6 +17,7 @@ | |||||
| #define __LOL_UNIT_H__ | #define __LOL_UNIT_H__ | ||||
| #include <iostream> | #include <iostream> | ||||
| #include <iomanip> | |||||
| #include <sstream> | #include <sstream> | ||||
| #include <cstdio> | #include <cstdio> | ||||
| #include <cmath> | #include <cmath> | ||||
| @@ -63,7 +64,7 @@ protected: | |||||
| int m_testcases, m_failcases; | int m_testcases, m_failcases; | ||||
| int m_asserts, m_failure; | int m_asserts, m_failure; | ||||
| char const *m_fixturename, *m_currentname; | char const *m_fixturename, *m_currentname; | ||||
| std::stringstream m_errorlog; | |||||
| std::stringstream m_errorlog, m_context; | |||||
| }; | }; | ||||
| template<class T> class Fixture : protected FixtureBase | template<class T> class Fixture : protected FixtureBase | ||||
| @@ -105,6 +106,7 @@ public: | |||||
| m_asserts = 0; | m_asserts = 0; | ||||
| m_failure = false; | m_failure = false; | ||||
| m_currentname = c->m_testname; | m_currentname = c->m_testname; | ||||
| m_context.str(""); | |||||
| (static_cast<FixtureClass *>(this)->*c->m_fun)(); | (static_cast<FixtureClass *>(this)->*c->m_fun)(); | ||||
| std::cout << (m_failure ? 'F' : '.'); | std::cout << (m_failure ? 'F' : '.'); | ||||
| } | } | ||||
| @@ -226,9 +228,10 @@ public: | |||||
| << " (F) line: " << __LINE__ << " " \ | << " (F) line: " << __LINE__ << " " \ | ||||
| << __FILE__ << std::endl; \ | << __FILE__ << std::endl; \ | ||||
| m_errorlog << "equality assertion failed" << std::endl; \ | m_errorlog << "equality assertion failed" << std::endl; \ | ||||
| m_errorlog << "- Expected: " << (a) << std::endl; \ | |||||
| m_errorlog << "- Actual : " << (b) << std::endl; \ | |||||
| m_errorlog << "- Expected: " << #a << " = " << (a) << std::endl; \ | |||||
| m_errorlog << "- Actual : " << #b << " = " << (b) << std::endl; \ | |||||
| m_errorlog << message; \ | m_errorlog << message; \ | ||||
| m_errorlog << m_context.str(); \ | |||||
| m_failure = true; \ | m_failure = true; \ | ||||
| return; \ | return; \ | ||||
| } \ | } \ | ||||
| @@ -245,10 +248,14 @@ public: | |||||
| << " (F) line: " << __LINE__ << " " \ | << " (F) line: " << __LINE__ << " " \ | ||||
| << __FILE__ << std::endl; \ | << __FILE__ << std::endl; \ | ||||
| m_errorlog << "double equality assertion failed" << std::endl; \ | m_errorlog << "double equality assertion failed" << std::endl; \ | ||||
| m_errorlog << "- Expected: " << (a) << std::endl; \ | |||||
| m_errorlog << "- Actual : " << (b) << std::endl; \ | |||||
| m_errorlog << "- Delta : " << (t) << std::endl; \ | |||||
| std::streamsize old_prec = m_errorlog.precision(); \ | |||||
| m_errorlog << std::setprecision(16); \ | |||||
| m_errorlog << "- Expected: " << #a << " = " << (a) << std::endl; \ | |||||
| m_errorlog << "- Actual : " << #b << " = " << (b) << std::endl; \ | |||||
| m_errorlog << "- Delta : " << #t << " = " << (t) << std::endl; \ | |||||
| m_errorlog << std::setprecision(old_prec); \ | |||||
| m_errorlog << message; \ | m_errorlog << message; \ | ||||
| m_errorlog << m_context.str(); \ | |||||
| m_failure = true; \ | m_failure = true; \ | ||||
| return; \ | return; \ | ||||
| } \ | } \ | ||||
| @@ -264,10 +271,20 @@ public: | |||||
| << __FILE__ << std::endl; \ | << __FILE__ << std::endl; \ | ||||
| m_errorlog << "forced failure" << std::endl; \ | m_errorlog << "forced failure" << std::endl; \ | ||||
| m_errorlog << "- " << message << std::endl; \ | m_errorlog << "- " << message << std::endl; \ | ||||
| m_errorlog << m_context.str(); \ | |||||
| m_failure = true; \ | m_failure = true; \ | ||||
| return; \ | return; \ | ||||
| } while(!True()) | } while(!True()) | ||||
| #define LOLUNIT_SET_CONTEXT(n) \ | |||||
| do { \ | |||||
| m_context.str(""); \ | |||||
| m_context << "- Context : " << #n << " = " << (n) << std::endl; \ | |||||
| } while(!True()) | |||||
| #define LOLUNIT_UNSET_CONTEXT(n) \ | |||||
| m_context.str("") | |||||
| #define LOLUNIT_ASSERT(cond) \ | #define LOLUNIT_ASSERT(cond) \ | ||||
| LOLUNIT_ASSERT_GENERIC("", cond) | LOLUNIT_ASSERT_GENERIC("", cond) | ||||
| @@ -45,6 +45,7 @@ public: | |||||
| { | { | ||||
| half a = (half)pairs[i].f; | half a = (half)pairs[i].f; | ||||
| uint16_t b = pairs[i].x; | uint16_t b = pairs[i].x; | ||||
| LOLUNIT_SET_CONTEXT(i); | |||||
| LOLUNIT_ASSERT_EQUAL(a.bits, b); | LOLUNIT_ASSERT_EQUAL(a.bits, b); | ||||
| } | } | ||||
| } | } | ||||
| @@ -55,6 +56,7 @@ public: | |||||
| { | { | ||||
| half a = half::makeaccurate(pairs[i].f); | half a = half::makeaccurate(pairs[i].f); | ||||
| uint16_t b = pairs[i].x; | uint16_t b = pairs[i].x; | ||||
| LOLUNIT_SET_CONTEXT(i); | |||||
| LOLUNIT_ASSERT_EQUAL(a.bits, b); | LOLUNIT_ASSERT_EQUAL(a.bits, b); | ||||
| } | } | ||||
| } | } | ||||
| @@ -65,6 +67,7 @@ public: | |||||
| { | { | ||||
| half a = half::makebits(i); | half a = half::makebits(i); | ||||
| uint16_t b = i; | uint16_t b = i; | ||||
| LOLUNIT_SET_CONTEXT(i); | |||||
| LOLUNIT_ASSERT_EQUAL(a.bits, b); | LOLUNIT_ASSERT_EQUAL(a.bits, b); | ||||
| } | } | ||||
| } | } | ||||
| @@ -140,6 +143,7 @@ public: | |||||
| { | { | ||||
| for (uint32_t i = 0; i < 0x10000; i++) | for (uint32_t i = 0; i < 0x10000; i++) | ||||
| { | { | ||||
| LOLUNIT_SET_CONTEXT(i); | |||||
| half h = half::makebits(i); | half h = half::makebits(i); | ||||
| if (h.is_nan()) | if (h.is_nan()) | ||||
| { | { | ||||
| @@ -165,6 +169,7 @@ public: | |||||
| { | { | ||||
| float a = (float)half::makebits(pairs[i].x); | float a = (float)half::makebits(pairs[i].x); | ||||
| float b = pairs[i].f; | float b = pairs[i].f; | ||||
| LOLUNIT_SET_CONTEXT(i); | |||||
| LOLUNIT_ASSERT_EQUAL(a, b); | LOLUNIT_ASSERT_EQUAL(a, b); | ||||
| } | } | ||||
| @@ -173,6 +178,7 @@ public: | |||||
| half h = half::makebits(i); | half h = half::makebits(i); | ||||
| float f = (float)h; | float f = (float)h; | ||||
| half g = (half)f; | half g = (half)f; | ||||
| LOLUNIT_SET_CONTEXT(i); | |||||
| if (h.is_nan()) | if (h.is_nan()) | ||||
| { | { | ||||
| LOLUNIT_ASSERT(isnan(f)); | LOLUNIT_ASSERT(isnan(f)); | ||||
| @@ -301,8 +307,8 @@ HalfTest::TestPair const HalfTest::pairs[] = | |||||
| { 0.125f, 0x3000 }, | { 0.125f, 0x3000 }, | ||||
| { 15.9375f, 0x4bf8 }, | { 15.9375f, 0x4bf8 }, | ||||
| { 31.0f / (1 << 14), 0x17c0 }, /* 0x1.fp-10 */ | { 31.0f / (1 << 14), 0x17c0 }, /* 0x1.fp-10 */ | ||||
| { 31.0f / (1 << 18), 0x07c0 }, /* 0x1.fp-14, denormal */ | |||||
| { 31.0f / (1 << 19), 0x03e0 }, /* 0x1.fp-15, denormal */ | |||||
| { 31.0f / (1 << 18), 0x07c0 }, /* 0x1.fp-14, normal float, denormal half */ | |||||
| { 31.0f / (1 << 19), 0x03e0 }, /* 0x1.fp-15, normal float, denormal half */ | |||||
| }; | }; | ||||
| } /* namespace lol */ | } /* namespace lol */ | ||||
| @@ -37,6 +37,7 @@ public: | |||||
| double a = sin(f); | double a = sin(f); | ||||
| #endif | #endif | ||||
| double b = lol_sin(f); | double b = lol_sin(f); | ||||
| LOLUNIT_SET_CONTEXT(f); | |||||
| LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11); | LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11); | ||||
| } | } | ||||
| @@ -49,6 +50,7 @@ public: | |||||
| double a = sin(f); | double a = sin(f); | ||||
| #endif | #endif | ||||
| double b = lol_sin(f); | double b = lol_sin(f); | ||||
| LOLUNIT_SET_CONTEXT(f); | |||||
| LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11); | LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11); | ||||
| } | } | ||||
| } | } | ||||
| @@ -64,6 +66,7 @@ public: | |||||
| double a = cos(f); | double a = cos(f); | ||||
| #endif | #endif | ||||
| double b = lol_cos(f); | double b = lol_cos(f); | ||||
| LOLUNIT_SET_CONTEXT(f); | |||||
| LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11); | LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11); | ||||
| } | } | ||||
| @@ -76,6 +79,7 @@ public: | |||||
| double a = cos(f); | double a = cos(f); | ||||
| #endif | #endif | ||||
| double b = lol_cos(f); | double b = lol_cos(f); | ||||
| LOLUNIT_SET_CONTEXT(f); | |||||
| LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11); | LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(f) * 1e-11); | ||||
| } | } | ||||
| } | } | ||||
| @@ -94,6 +98,7 @@ public: | |||||
| #endif | #endif | ||||
| double b1, b2; | double b1, b2; | ||||
| lol_sincos(f, &b1, &b2); | lol_sincos(f, &b1, &b2); | ||||
| LOLUNIT_SET_CONTEXT(f); | |||||
| LOLUNIT_ASSERT_DOUBLES_EQUAL(a1, b1, fabs(f) * 1e-11); | LOLUNIT_ASSERT_DOUBLES_EQUAL(a1, b1, fabs(f) * 1e-11); | ||||
| LOLUNIT_ASSERT_DOUBLES_EQUAL(a2, b2, fabs(f) * 1e-11); | LOLUNIT_ASSERT_DOUBLES_EQUAL(a2, b2, fabs(f) * 1e-11); | ||||
| } | } | ||||
| @@ -110,6 +115,7 @@ public: | |||||
| #endif | #endif | ||||
| double b1, b2; | double b1, b2; | ||||
| lol_sincos(f, &b1, &b2); | lol_sincos(f, &b1, &b2); | ||||
| LOLUNIT_SET_CONTEXT(f); | |||||
| LOLUNIT_ASSERT_DOUBLES_EQUAL(a1, b1, fabs(f) * 1e-11); | LOLUNIT_ASSERT_DOUBLES_EQUAL(a1, b1, fabs(f) * 1e-11); | ||||
| LOLUNIT_ASSERT_DOUBLES_EQUAL(a2, b2, fabs(f) * 1e-11); | LOLUNIT_ASSERT_DOUBLES_EQUAL(a2, b2, fabs(f) * 1e-11); | ||||
| } | } | ||||
| @@ -126,6 +132,7 @@ public: | |||||
| double a = tan(f); | double a = tan(f); | ||||
| #endif | #endif | ||||
| double b = lol_tan(f); | double b = lol_tan(f); | ||||
| LOLUNIT_SET_CONTEXT(f); | |||||
| if (fabs(a) > 1e4) | if (fabs(a) > 1e4) | ||||
| LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(a) * fabs(a) * 1e-11); | LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(a) * fabs(a) * 1e-11); | ||||
| else if (fabs(a) > 1.0) | else if (fabs(a) > 1.0) | ||||
| @@ -143,6 +150,7 @@ public: | |||||
| double a = tan(f); | double a = tan(f); | ||||
| #endif | #endif | ||||
| double b = lol_tan(f); | double b = lol_tan(f); | ||||
| LOLUNIT_SET_CONTEXT(f); | |||||
| if (fabs(a) > 1e4) | if (fabs(a) > 1e4) | ||||
| LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(a) * fabs(a) * 1e-11); | LOLUNIT_ASSERT_DOUBLES_EQUAL(a, b, fabs(a) * fabs(a) * 1e-11); | ||||
| else if (fabs(a) > 1.0) | else if (fabs(a) > 1.0) | ||||