From 62e0453ce0ee0f03fca4626882263ec41dc1d64d Mon Sep 17 00:00:00 2001 From: "Ricardo M. Correia" Date: Mon, 14 May 2012 21:15:27 +0200 Subject: Add test case for CBigNum::setint64(). One of the test cases currently aborts when using gcc's flag -ftrapv, due to negating an INT64_MIN int64 variable, which is an undefined operation. This will be fixed in a subsequent commit. --- src/test/bignum_tests.cpp | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/test/bignum_tests.cpp (limited to 'src/test') diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp new file mode 100644 index 0000000000..ca17766d13 --- /dev/null +++ b/src/test/bignum_tests.cpp @@ -0,0 +1,110 @@ +#include +#include + +#include "bignum.h" + +BOOST_AUTO_TEST_SUITE(bignum_tests) + + +// For the following test case, it is useful to use additional tools. +// +// The simplest one to use is the compiler flag -ftrapv, which detects integer +// overflows and similar errors. However, due to optimizations and compilers +// taking advantage of undefined behavior sometimes it may not actually detect +// anything. +// +// You can also use compiler-based stack protection to possibly detect possible +// stack buffer overruns. +// +// For more accurate diagnostics, you can use an undefined arithmetic operation +// detector such as the clang-based tool: +// +// "IOC: An Integer Overflow Checker for C/C++" +// +// Available at: http://embed.cs.utah.edu/ioc/ +// +// It might also be useful to use Google's AddressSanitizer to detect +// stack buffer overruns, which valgrind can't currently detect. + +// Let's force this code not to be inlined, in order to actually +// test a generic version of the function. This increases the chance +// that -ftrapv will detect overflows. +void mysetint64(CBigNum& num, int64 n) __attribute__((noinline)); + +void mysetint64(CBigNum& num, int64 n) +{ + num.setint64(n); +} + +// For each number, we do 2 tests: one with inline code, then we reset the +// value to 0, then the second one with a non-inlined function. +BOOST_AUTO_TEST_CASE(bignum_setint64) +{ + int64 n; + + { + n = 0; + CBigNum num(n); + BOOST_CHECK(num.ToString() == "0"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "0"); + } + { + n = 1; + CBigNum num(n); + BOOST_CHECK(num.ToString() == "1"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "1"); + } + { + n = -1; + CBigNum num(n); + BOOST_CHECK(num.ToString() == "-1"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "-1"); + } + { + n = 5; + CBigNum num(n); + BOOST_CHECK(num.ToString() == "5"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "5"); + } + { + n = -5; + CBigNum num(n); + BOOST_CHECK(num.ToString() == "-5"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "-5"); + } + { + n = LLONG_MIN; + CBigNum num(n); + BOOST_CHECK(num.ToString() == "-9223372036854775808"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "-9223372036854775808"); + } + { + n = LLONG_MAX; + CBigNum num(n); + BOOST_CHECK(num.ToString() == "9223372036854775807"); + num.setulong(0); + BOOST_CHECK(num.ToString() == "0"); + mysetint64(num, n); + BOOST_CHECK(num.ToString() == "9223372036854775807"); + } +} + +BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.3 From 78e851f94f67b56e9baa8a62d6266c6bf979ee9e Mon Sep 17 00:00:00 2001 From: "Ricardo M. Correia" Date: Thu, 31 May 2012 19:12:01 +0200 Subject: Fix noinline definition so that it works for more compilers. --- src/test/bignum_tests.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/test') diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp index ca17766d13..16e4449e94 100644 --- a/src/test/bignum_tests.cpp +++ b/src/test/bignum_tests.cpp @@ -2,6 +2,7 @@ #include #include "bignum.h" +#include "util.h" BOOST_AUTO_TEST_SUITE(bignum_tests) @@ -29,9 +30,7 @@ BOOST_AUTO_TEST_SUITE(bignum_tests) // Let's force this code not to be inlined, in order to actually // test a generic version of the function. This increases the chance // that -ftrapv will detect overflows. -void mysetint64(CBigNum& num, int64 n) __attribute__((noinline)); - -void mysetint64(CBigNum& num, int64 n) +NOINLINE void mysetint64(CBigNum& num, int64 n) { num.setint64(n); } -- cgit v1.2.3 From 10b45b4c2e11994aa2aed966f83d84f83852d1e1 Mon Sep 17 00:00:00 2001 From: "Ricardo M. Correia" Date: Thu, 31 May 2012 20:31:15 +0200 Subject: Use C++-style numeric limits instead of C-style. --- src/test/bignum_tests.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/test') diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp index 16e4449e94..38c625bba1 100644 --- a/src/test/bignum_tests.cpp +++ b/src/test/bignum_tests.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include "bignum.h" #include "util.h" @@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE(bignum_setint64) BOOST_CHECK(num.ToString() == "-5"); } { - n = LLONG_MIN; + n = std::numeric_limits::min(); CBigNum num(n); BOOST_CHECK(num.ToString() == "-9223372036854775808"); num.setulong(0); @@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(bignum_setint64) BOOST_CHECK(num.ToString() == "-9223372036854775808"); } { - n = LLONG_MAX; + n = std::numeric_limits::max(); CBigNum num(n); BOOST_CHECK(num.ToString() == "9223372036854775807"); num.setulong(0); -- cgit v1.2.3 From 31ac53fbdc2346876da201b9e1495565b38b46ba Mon Sep 17 00:00:00 2001 From: "Ricardo M. Correia" Date: Thu, 7 Jun 2012 19:14:18 +0200 Subject: Move NOINLINE definition to test where it's used. --- src/test/bignum_tests.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/test') diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp index 38c625bba1..8620f81f17 100644 --- a/src/test/bignum_tests.cpp +++ b/src/test/bignum_tests.cpp @@ -6,6 +6,22 @@ BOOST_AUTO_TEST_SUITE(bignum_tests) +// Unfortunately there's no standard way of preventing a function from being +// inlined, so we define a macro for it. +// +// You should use it like this: +// NOINLINE void function() {...} +#if defined(__GNUC__) +// This also works and will be defined for any compiler implementing gcc +// extensions, such as clang and icc. +#define NOINLINE __attribute__((noinline)) +#elif defined(_MSC_VER) +#define NOINLINE __declspec(noinline) +#else +// We give out a warning because it impacts the correctness of one bignum test. +#warning You should define NOINLINE for your compiler. +#define NOINLINE +#endif // For the following test case, it is useful to use additional tools. // -- cgit v1.2.3