Add more auto_test cases.

This commit is contained in:
Beman
2015-03-14 08:20:41 -04:00
parent affdcac443
commit ff4b22bdec

View File

@ -15,11 +15,14 @@
#include <boost/endian/conversion.hpp>
#include <boost/detail/lightweight_main.hpp>
#include <boost/endian/detail/lightweight_test.hpp>
#include <boost/array.hpp>
#include <boost/math/constants/constants.hpp>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <limits>
#include <cstring>
using namespace boost::endian;
using std::cout;
@ -31,6 +34,7 @@ using std::numeric_limits;
namespace
{
// to_big() and to_little() provide convenient independent functions for
// creating test values of known endianness.
@ -52,6 +56,49 @@ namespace
return x;
}
template <class T>
struct test_case
{
std::string desc;
T value; // native value and representation
std::string big; // as hex characters; invariant size() == 2*sizeof(T)
std::string little; // as hex characters; invariant size() == 2*sizeof(T)
// big and little endian expected values are held as strings so representation is
// independent of platform endianness and readers do not have to perform mental
// gymnastics to reason about what the expected representation is for a platform.
const test_case& assign(const std::string& desc_, const T& value_,
const std::string& big_, const std::string& little_)
{
desc = desc_;
std::memcpy(&value, &value_, sizeof(T)); // use memcpy in case copy assignment or
// copy construction alters representation
big = big_;
little = little_;
return *this;
}
};
// to_big_inplace() and to_little_inplace() provide convenient independent functions to
// aid creating test values of known endianness. They do so in place to avoid the
// possibility that floating point assignment or copy construction modifies the
// representation, such as for normalization.
template <class T>
void to_big_inplace(T& x)
{
# ifdef BOOST_LITTLE_ENDIAN
std::reverse(reinterpret_cast<char*>(&x), reinterpret_cast<char*>(&x) + sizeof(T));
# endif
}
template <class T>
void to_little_inplace(T& x)
{
# ifdef BOOST_BIG_ENDIAN
std::reverse(reinterpret_cast<char*>(&x), reinterpret_cast<char*>(&x) + sizeof(T));
# endif
}
template <class T>
std::string to_hex(const T& x)
@ -69,6 +116,71 @@ namespace
return tmp;
}
const std::size_t n_test_cases = 10;
boost::array<test_case<float>, n_test_cases> float_test_cases;
boost::array<test_case<double>, n_test_cases> double_test_cases;
void build_auto_test_cases()
{
using namespace boost::math::constants;
int i = 0;
float_test_cases[i].assign("numeric_limits<float>::min()",
numeric_limits<float>::min(), "00800000", "00008000");
double_test_cases[i++].assign("numeric_limits<double>::min()",
numeric_limits<double>::min(), "0010000000000000", "0000000000001000");
float_test_cases[i].assign("numeric_limits<float>::max()",
numeric_limits<float>::max(), "7f7fffff", "ffff7f7f");
double_test_cases[i++].assign("numeric_limits<double>::max()",
numeric_limits<double>::max(), "7fefffffffffffff", "ffffffffffffef7f");
float_test_cases[i].assign("numeric_limits<float>::round_error()",
numeric_limits<float>::round_error(), "3f000000", "0000003f");
double_test_cases[i++].assign("numeric_limits<double>::round_error()",
numeric_limits<double>::round_error(), "3fe0000000000000", "000000000000e03f");
float_test_cases[i].assign("numeric_limits<float>::infinity()",
numeric_limits<float>::infinity(), "7f800000", "0000807f");
double_test_cases[i++].assign("numeric_limits<double>::infinity()",
numeric_limits<double>::infinity(), "7ff0000000000000", "000000000000f07f");
float_test_cases[i].assign("-numeric_limits<float>::infinity()",
-numeric_limits<float>::infinity(), "ff800000", "000080ff");
double_test_cases[i++].assign("-numeric_limits<double>::infinity()",
-numeric_limits<double>::infinity(), "fff0000000000000", "000000000000f0ff");
float_test_cases[i].assign("numeric_limits<float>::quiet_NaN()",
numeric_limits<float>::quiet_NaN(), "7fc00000", "0000c07f");
double_test_cases[i++].assign("numeric_limits<double>::quiet_NaN()",
numeric_limits<double>::quiet_NaN(), "7ff8000000000000", "000000000000f87f");
float_test_cases[i].assign("numeric_limits<float>::signaling_NaN()",
numeric_limits<float>::signaling_NaN(), "7fc00001", "0100c07f");
double_test_cases[i++].assign("numeric_limits<double>::signaling_NaN()",
numeric_limits<double>::signaling_NaN(), "7ff8000000000001", "010000000000f87f");
float_test_cases[i].assign("numeric_limits<float>::denorm_min()",
numeric_limits<float>::denorm_min(), "00000001", "01000000");
double_test_cases[i++].assign("numeric_limits<double>::denorm_min()",
numeric_limits<double>::denorm_min(), "0000000000000001", "0100000000000000");
float_test_cases[i].assign("pi<float>()",
pi<float>(), "40490fdb", "db0f4940");
double_test_cases[i++].assign("pi<double>()",
pi<double>(), "400921fb54442d18", "182d4454fb210940");
uint32_t vf1 (0x12345678U);
float_test_cases[i].assign("native uint32_t 0x12345678U as float",
*reinterpret_cast<const float*>(&vf1), "12345678", "78563412");
uint64_t vd1 (0x0123456789abcdefULL);
double_test_cases[i++].assign("native uint64_t 0x0123456789abcdefULL as double",
*reinterpret_cast<const double*>(&vd1), "0123456789abcdef", "efcdab8967452301");
BOOST_ASSERT(i == n_test_cases);
}
template <class T>
void show_value(const char* desc, const T& value)
{
@ -81,6 +193,7 @@ namespace
template <class T>
void report_limits(const char* type)
{
using namespace boost::math::constants;
cout << "\nHeader <limits> values for std::numeric_limits<" << type << ">\n\n";
cout << " is_specialized " << numeric_limits<T>::is_specialized << "\n";
cout << " is_signed " << numeric_limits<T>::is_signed << "\n";
@ -116,6 +229,7 @@ namespace
show_value("denorm_min()", numeric_limits<T>::denorm_min());
show_value("0.0", static_cast<T>(0.0));
show_value("1.0", static_cast<T>(1.0));
show_value("pi()", pi<T>());
}
template <class T>
@ -202,6 +316,19 @@ namespace
BOOST_TEST_MEM_EQ(native_to_little(1.0), to_little(0x3ff0000000000000ULL));
}
template <class T>
void auto_test(const char* msg, const boost::array<test_case<T>, n_test_cases>& cases)
{
cout << "auto test " << msg << " ..." << endl;
for (int i = 0; i < n_test_cases; ++i)
{
cout << " " << cases[i].desc << endl;
BOOST_TEST_EQ(to_hex(native_to_big(cases[i].value)), cases[i].big);
BOOST_TEST_EQ(to_hex(native_to_little(cases[i].value)), cases[i].little);
}
}
} // unnamed namespace
//--------------------------------------------------------------------------------------//
@ -225,6 +352,10 @@ int cpp_main(int, char *[])
double_value_test();
round_trip_test<double>("double");
build_auto_test_cases();
auto_test<float>("float", float_test_cases);
auto_test<double>("double", double_test_cases);
cout << "\n done" << endl;
return ::boost::endian::report_errors();