#include "config.h" #include #include #include #ifdef HAVE_LIMITS #include #endif #include #include #include "asserts.h" #include "types.h" #include "error.h" #include "rmath.h" #define TEST(expected,code) \ thrown = false; \ try { \ code; \ } \ catch(error e) { \ thrown = true; \ if (thrown != expected) { \ std::cerr << e; \ } \ } \ catch(...) { \ assert(0); \ } void test1(void) { { safe_num i8; bool thrown = false; i8 = 0; TEST(false,i8 += 10); assert(!thrown); assert(i8 == 10); TEST(false,i8 += 200); assert(!thrown); assert(i8 == 210); TEST(false,i8 += 45); assert(!thrown); assert(i8 == 255); TEST(true,i8 += 1); assert(thrown); assert(i8 == 255); } { safe_num i8; bool thrown = false; i8 = 0; TEST(false,i8 += 10); assert(!thrown); assert(i8 == 10); TEST(false,i8 += 110); assert(!thrown); assert(i8 == 120); TEST(false,i8 += 7); assert(!thrown); assert(i8 == 127); TEST(true,i8 += 1); assert(thrown); assert(i8 == 127); } } void test2(void) { safe_num i8; bool thrown = false; i8 = 1; TEST(false,i8 *= 10); assert(!thrown); assert(i8 == 10); TEST(false,i8 *= 25); assert(!thrown); assert(i8 == 250); TEST(true,i8 *= 10); assert(thrown); assert(i8 == 250); } void test3(void) { safe_num n1, n2; safe_num num; bool thrown = false; for (n1 = 0; n1 < 1250; ++n1) { for (n2 = 0; n2 < 1250; ++n2) { num = n1; TEST(false,num = n1 * n2); assert(!thrown); if (num != n1 * n2) std::cerr << "*** ERROR: safe_num operator*(" << n1 << ", " << n2 << ") failed" << std::endl; assert(num == n1 * n2); } TEST(true,num = n1 * (max_limit(n2) - safe_num(1))); } } void test4(void) { assert(max_limit() == true); assert(min_limit() == false); assert(max_limit() == CHAR_MAX); assert(min_limit() == CHAR_MIN); assert(max_limit() == SCHAR_MAX); assert(min_limit() == SCHAR_MIN); assert(max_limit() == UCHAR_MAX); assert(min_limit() == 0); assert(max_limit() == SHRT_MAX); assert(min_limit() == SHRT_MIN); assert(max_limit() == USHRT_MAX); assert(min_limit() == 0); assert(max_limit() == INT_MAX); assert(min_limit() == INT_MIN); assert(max_limit() == UINT_MAX); assert(min_limit() == 0); assert(max_limit() == LONG_MAX); assert(min_limit() == LONG_MIN); assert(max_limit() == ULONG_MAX); assert(min_limit() == 0); assert(max_limit() == FLT_MAX); assert(min_limit() == FLT_MIN); assert(max_limit() == DBL_MAX); assert(min_limit() == DBL_MIN); #ifdef HAVE_LIMITS assert(max_limit() == std::numeric_limits::max()); assert(min_limit() == std::numeric_limits::min()); assert(max_limit() == std::numeric_limits::max()); assert(min_limit() == std::numeric_limits::min()); assert(max_limit() == std::numeric_limits::max()); assert(min_limit() == std::numeric_limits::min()); assert(max_limit() == std::numeric_limits::max()); assert(min_limit() == std::numeric_limits::min()); assert(max_limit() == std::numeric_limits::max()); assert(min_limit() == std::numeric_limits::min()); assert(max_limit() == std::numeric_limits::max()); assert(min_limit() == std::numeric_limits::min()); assert(max_limit() == std::numeric_limits::max()); assert(min_limit() == std::numeric_limits::min()); assert(max_limit() == std::numeric_limits::max()); assert(min_limit() == std::numeric_limits::min()); assert(max_limit() == std::numeric_limits::max()); assert(min_limit() == std::numeric_limits::min()); assert(max_limit() == std::numeric_limits::max()); assert(min_limit() == std::numeric_limits::min()); assert(max_limit() == std::numeric_limits::max()); assert(min_limit() == std::numeric_limits::min()); assert(max_limit() == std::numeric_limits::max()); assert(min_limit() == std::numeric_limits::min()); #endif } void test5(void) { bool thrown; safe_num si; TEST(false,si = 0); assert(si.value() == 0); TEST(false,si++ == 0); assert(si.value() == 1); TEST(false,si++ == 1); assert(si.value() == 2); TEST(false,++si == 3); assert(si.value() == 3); TEST(false,si-- == 3); assert(si.value() == 2); TEST(false,--si == 1) assert(si.value() == 1); TEST(false,--si == 0); TEST(true,--si == 0); TEST(false,si = max_limit()); TEST(true,++si == max_limit()); safe_num si1, si2; si1 = 5; si2 = 6; assert(si1 != si2); assert(si1 < si2); assert(si2 > si1); assert(si1 <= si2); assert(si2 >= si1); assert(si2 % si1 == 1); si = 10; TEST(false,si += 5); TEST(false,si == 15); TEST(false,si -= 5); TEST(false,si == 10); TEST(false,si *= 5); TEST(false,si == 50); TEST(false,si /= 5); TEST(false,si == 10); TEST(false,si %= 6); TEST(false,si == 4); } void test6(void) { bool thrown; safe_num si; TEST(false,si = 0); assert(si.value() == 0); TEST(false,si++ == 0); assert(si.value() == 1); TEST(false,si++ == 1); assert(si.value() == 2); TEST(false,++si == 3); assert(si.value() == 3); TEST(false,si-- == 3); assert(si.value() == 2); TEST(false,--si == 1) assert(si.value() == 1); TEST(false,--si == 0); TEST(false,--si == -1); TEST(false,si = max_limit()); TEST(true,++si == max_limit()); TEST(false,si = min_limit()); TEST(true,--si == max_limit()); } void test7(void) { bool thrown; TEST(false,absolute(-max_limit())); TEST(true,absolute(min_limit())); } void test8(void) { short si; safe_num ci1, ci2, ci; bool thrown; bool should_throw; for (ci1 = min_limit(); ci1 < max_limit(); ++ci1) { for (ci2 = min_limit(); ci2 < max_limit(); ++ci2) { // addition thrown = false; try { ci = ci1 + ci2; } catch(...) { thrown = true; } should_throw = false; si = ci1.value() + ci2.value(); if ((si > max_limit()) || (si < min_limit())) should_throw = true; if (ci2 == min_limit()) should_throw = true; assert(thrown == should_throw); // subtraction thrown = false; try { ci = ci1 - ci2; } catch(...) { thrown = true; } should_throw = false; si = ci1.value() - ci2.value(); if ((si > max_limit()) || (si < min_limit())) should_throw = true; if (ci2 == min_limit()) should_throw = true; assert(thrown == should_throw); // multiplication thrown = false; try { ci = ci1 * ci2; } catch(...) { thrown = true; } should_throw = false; si = ci1.value() * ci2.value(); if ((si > max_limit()) || (si < min_limit())) should_throw = true; if ((ci1 != 0) && (ci1 != 1) && (ci2 == min_limit())) should_throw = true; assert(thrown == should_throw); // division thrown = false; try { ci = ci1 / ci2; } catch(...) { thrown = true; } should_throw = false; if (ci2.value() == 0) should_throw = true; else { si = ci1.value() / ci2.value(); if ((si > max_limit()) || (si < min_limit())) should_throw = true; } assert(thrown == should_throw); } } } void test9(void) { uint64 free = 0; uint64 total = 0; safe_num num = 0; free = 256258287ul; total = 258030784ul; num = free; num *= 100; num /= total; free = 131067261ul; total = 131072000ul; num = free; num *= 100; num /= total; free = 256258286ul; total = 258030784ul; num = free; num *= 100; num /= total; free = 131067260ul; total = 131072000ul; num = free; num *= 100; num /= total; free = 256258286ul; total = 258030784ul; num = free; num *= 100; num /= total; } int main(int argc, char *argv[]) { try { test1(); test2(); test3(); test4(); test5(); test6(); test7(); test8(); test9(); } catch(error e) { std::cerr << e; assert(0); } catch(...) { std::cerr << err_unknown; assert(0); } return(0); }