mirror of
https://github.com/SOCI/soci.git
synced 2026-02-14 01:28:54 -06:00
Move other ASSERT_EQUAL_XXX macros to a header too
Prepare for reusing them from other source files. Note that this requires using test_context from test-assert.h, which now has to include test-context.h.
This commit is contained in:
@@ -36,8 +36,6 @@
|
||||
#include <clocale>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
@@ -47,7 +45,6 @@
|
||||
#include "soci-mktime.h"
|
||||
|
||||
#include "test-assert.h"
|
||||
#include "test-context.h"
|
||||
#include "test-myint.h"
|
||||
|
||||
// Although SQL standard mandates right padding CHAR(N) values to their length
|
||||
@@ -187,71 +184,6 @@ template<> struct type_conversion<PhonebookEntry3>
|
||||
namespace tests
|
||||
{
|
||||
|
||||
// Compare doubles for approximate equality. This has to be used everywhere
|
||||
// where we write "3.14" (or "6.28") to the database as a string and then
|
||||
// compare the value read back with the literal 3.14 floating point constant
|
||||
// because they are not the same.
|
||||
//
|
||||
// It is also used for the backends which currently don't handle doubles
|
||||
// correctly.
|
||||
//
|
||||
// Notice that this function is normally not used directly but rather from the
|
||||
// macro below.
|
||||
inline bool are_doubles_approx_equal(double const a, double const b)
|
||||
{
|
||||
// The formula taken from CATCH test framework
|
||||
// https://github.com/philsquared/Catch/
|
||||
// Thanks to Richard Harris for his help refining this formula
|
||||
double const epsilon(std::numeric_limits<float>::epsilon() * 100);
|
||||
double const scale(1.0);
|
||||
return std::fabs(a - b) < epsilon * (scale + (std::max)(std::fabs(a), std::fabs(b)));
|
||||
}
|
||||
|
||||
// This is a macro to ensure we use the correct line numbers. The weird
|
||||
// do/while construction is used to make this a statement and the even weirder
|
||||
// condition in while ensures that the loop is executed exactly once without
|
||||
// triggering warnings from MSVC about the condition being always false.
|
||||
#define ASSERT_EQUAL_APPROX(a, b) \
|
||||
do { \
|
||||
if (!are_doubles_approx_equal((a), (b))) { \
|
||||
FAIL( "Approximate equality check failed: " \
|
||||
<< std::fixed \
|
||||
<< std::setprecision(std::numeric_limits<double>::digits10 + 1) \
|
||||
<< (a) << " != " << (b) ); \
|
||||
} \
|
||||
} while ( (void)0, 0 )
|
||||
|
||||
|
||||
// Compare two floating point numbers either exactly or approximately depending
|
||||
// on test_context::has_fp_bug() return value.
|
||||
inline bool
|
||||
are_doubles_equal(test_context_base const& tc, double a, double b)
|
||||
{
|
||||
return tc.has_fp_bug()
|
||||
? are_doubles_approx_equal(a, b)
|
||||
: are_doubles_exactly_equal(a, b);
|
||||
}
|
||||
|
||||
// This macro should be used when where we don't have any problems with string
|
||||
// literals vs floating point literals mismatches described above and would
|
||||
// ideally compare the numbers exactly but, unfortunately, currently can't do
|
||||
// this unconditionally because at least some backends are currently buggy and
|
||||
// don't handle the floating point values correctly.
|
||||
//
|
||||
// This can be only used from inside the common_tests class as it relies on
|
||||
// having an accessible "tc_" variable to determine whether exact or
|
||||
// approximate comparison should be used.
|
||||
#define ASSERT_EQUAL(a, b) \
|
||||
do { \
|
||||
if (!are_doubles_equal(tc_, (a), (b))) { \
|
||||
FAIL( "Equality check failed: " \
|
||||
<< std::fixed \
|
||||
<< std::setprecision(std::numeric_limits<double>::digits10 + 1) \
|
||||
<< (a) << " != " << (b) ); \
|
||||
} \
|
||||
} while ( (void)0, 0 )
|
||||
|
||||
|
||||
// Define the test cases in their own namespace to avoid clashes with the test
|
||||
// cases defined in individual backend tests: as only line number is used for
|
||||
// building the name of the "anonymous" function by the TEST_CASE macro, we
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
|
||||
#include "soci-compiler.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
|
||||
#include "test-context.h"
|
||||
|
||||
namespace soci
|
||||
{
|
||||
|
||||
@@ -29,11 +34,59 @@ are_doubles_exactly_equal(double a, double b)
|
||||
SOCI_GCC_WARNING_RESTORE(float-equal)
|
||||
}
|
||||
|
||||
// Compare doubles for approximate equality. This has to be used everywhere
|
||||
// where we write "3.14" (or "6.28") to the database as a string and then
|
||||
// compare the value read back with the literal 3.14 floating point constant
|
||||
// because they are not the same.
|
||||
//
|
||||
// It is also used for the backends which currently don't handle doubles
|
||||
// correctly.
|
||||
//
|
||||
// Notice that this function is normally not used directly but rather from the
|
||||
// macro below.
|
||||
inline bool are_doubles_approx_equal(double const a, double const b)
|
||||
{
|
||||
// The formula taken from CATCH test framework
|
||||
// https://github.com/philsquared/Catch/
|
||||
// Thanks to Richard Harris for his help refining this formula
|
||||
double const epsilon(std::numeric_limits<float>::epsilon() * 100);
|
||||
double const scale(1.0);
|
||||
return std::fabs(a - b) < epsilon * (scale + (std::max)(std::fabs(a), std::fabs(b)));
|
||||
}
|
||||
|
||||
// Compare two floating point numbers either exactly or approximately depending
|
||||
// on test_context::has_fp_bug() return value.
|
||||
inline bool
|
||||
are_doubles_equal(test_context_base const& tc, double a, double b)
|
||||
{
|
||||
return tc.has_fp_bug()
|
||||
? are_doubles_approx_equal(a, b)
|
||||
: are_doubles_exactly_equal(a, b);
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
|
||||
} // namespace soci
|
||||
|
||||
// This macro can be only used inside CATCH tests.
|
||||
// Define macros for comparing floating point numbers.
|
||||
//
|
||||
// All of them can only be used inside CATCH test cases.
|
||||
|
||||
// This is a macro to ensure we use the correct line numbers. The weird
|
||||
// do/while construction is used to make this a statement and the even weirder
|
||||
// condition in while ensures that the loop is executed exactly once without
|
||||
// triggering warnings from MSVC about the condition being always false.
|
||||
#define ASSERT_EQUAL_APPROX(a, b) \
|
||||
do { \
|
||||
if (!are_doubles_approx_equal((a), (b))) { \
|
||||
FAIL( "Approximate equality check failed: " \
|
||||
<< std::fixed \
|
||||
<< std::setprecision(std::numeric_limits<double>::digits10 + 1) \
|
||||
<< (a) << " != " << (b) ); \
|
||||
} \
|
||||
} while ( (void)0, 0 )
|
||||
|
||||
|
||||
#define ASSERT_EQUAL_EXACT(a, b) \
|
||||
do { \
|
||||
if (!are_doubles_exactly_equal((a), (b))) { \
|
||||
@@ -44,4 +97,24 @@ are_doubles_exactly_equal(double a, double b)
|
||||
} \
|
||||
} while ( (void)0, 0 )
|
||||
|
||||
// This macro should be used when where we don't have any problems with string
|
||||
// literals vs floating point literals mismatches described above and would
|
||||
// ideally compare the numbers exactly but, unfortunately, currently can't do
|
||||
// this unconditionally because at least some backends are currently buggy and
|
||||
// don't handle the floating point values correctly.
|
||||
//
|
||||
// This can be only used from inside the common_tests class as it relies on
|
||||
// having an accessible "tc_" variable to determine whether exact or
|
||||
// approximate comparison should be used.
|
||||
#define ASSERT_EQUAL(a, b) \
|
||||
do { \
|
||||
if (!are_doubles_equal(tc_, (a), (b))) { \
|
||||
FAIL( "Equality check failed: " \
|
||||
<< std::fixed \
|
||||
<< std::setprecision(std::numeric_limits<double>::digits10 + 1) \
|
||||
<< (a) << " != " << (b) ); \
|
||||
} \
|
||||
} while ( (void)0, 0 )
|
||||
|
||||
|
||||
#endif // SOCI_TEST_ASSERT_H_INCLUDED
|
||||
|
||||
Reference in New Issue
Block a user