diff options
Diffstat (limited to 'src/unittest/test_serialization.cpp')
-rw-r--r-- | src/unittest/test_serialization.cpp | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/src/unittest/test_serialization.cpp b/src/unittest/test_serialization.cpp index cfcfec0cd..b526792c4 100644 --- a/src/unittest/test_serialization.cpp +++ b/src/unittest/test_serialization.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" #include "util/serialize.h" +#include <cmath> class TestSerialization : public TestBase { public: @@ -43,6 +44,7 @@ public: void testVecPut(); void testStringLengthLimits(); void testBufReader(); + void testFloatFormat(); std::string teststring2; std::wstring teststring2_w; @@ -70,6 +72,7 @@ void TestSerialization::runTests(IGameDef *gamedef) TEST(testVecPut); TEST(testStringLengthLimits); TEST(testBufReader); + TEST(testFloatFormat); } //////////////////////////////////////////////////////////////////////////////// @@ -631,6 +634,75 @@ void TestSerialization::testBufReader() UASSERT(!buf.getRawDataNoEx(raw_data, sizeof(raw_data))); } +void TestSerialization::testFloatFormat() +{ + FloatType type = getFloatSerializationType(); + u32 i; + f32 fs, fm; + + // Check precision of float calculations on this platform + const std::unordered_map<f32, u32> float_results = { + { 0.0f, 0x00000000UL }, + { 1.0f, 0x3F800000UL }, + { -1.0f, 0xBF800000UL }, + { 0.1f, 0x3DCCCCCDUL }, + { -0.1f, 0xBDCCCCCDUL }, + { 1945329.25f, 0x49ED778AUL }, + { -23298764.f, 0xCBB1C166UL }, + { 0.5f, 0x3F000000UL }, + { -0.5f, 0xBF000000UL } + }; + for (const auto &v : float_results) { + i = f32Tou32Slow(v.first); + if (std::abs((s64)v.second - i) > 32) { + printf("Inaccurate float values on %.9g, expected 0x%X, actual 0x%X\n", + v.first, v.second, i); + UASSERT(false); + } + + fs = u32Tof32Slow(v.second); + if (std::fabs(v.first - fs) > std::fabs(v.first * 0.000005f)) { + printf("Inaccurate float values on 0x%X, expected %.9g, actual 0x%.9g\n", + v.second, v.first, fs); + UASSERT(false); + } + } + + if (type == FLOATTYPE_SLOW) { + // conversion using memcpy is not possible + // Skip exact float comparison checks below + return; + } + + auto test_single = [&fs, &fm](const u32 &i) -> bool { + memcpy(&fm, &i, 4); + fs = u32Tof32Slow(i); + if (fm != fs) { + printf("u32Tof32Slow failed on 0x%X, expected %.9g, actual %.9g\n", + i, fm, fs); + return false; + } + if (f32Tou32Slow(fs) != i) { + printf("f32Tou32Slow failed on %.9g, expected 0x%X, actual 0x%X\n", + fs, i, f32Tou32Slow(fs)); + return false; + } + return true; + }; + + // Use step of prime 277 to speed things up from 3 minutes to a few seconds + // Test from 0 to 0xFF800000UL (positive) + for (i = 0x00000000UL; i <= 0x7F800000UL; i += 277) + UASSERT(test_single(i)); + + // Ensure +inf and -inf are tested + UASSERT(test_single(0x7F800000UL)); + UASSERT(test_single(0xFF800000UL)); + + // Test from 0x80000000UL to 0xFF800000UL (negative) + for (i = 0x80000000UL; i <= 0xFF800000UL; i += 277) + UASSERT(test_single(i)); +} const u8 TestSerialization::test_serialized_data[12 * 13] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, |