3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "util/string.h"
23 #include "util/serialize.h"
26 class TestSerialization : public TestBase {
28 TestSerialization() { TestManager::registerTestModule(this); }
29 const char *getName() { return "TestSerialization"; }
31 void runTests(IGameDef *gamedef);
32 void buildTestStrings();
34 void testSerializeString();
35 void testSerializeWideString();
36 void testSerializeLongString();
37 void testSerializeJsonString();
38 void testSerializeHex();
39 void testDeSerializeString();
40 void testDeSerializeWideString();
41 void testDeSerializeLongString();
42 void testStreamRead();
43 void testStreamWrite();
45 void testStringLengthLimits();
47 void testFloatFormat();
49 std::string teststring2;
50 std::wstring teststring2_w;
51 std::string teststring2_w_encoded;
53 static const u8 test_serialized_data[12 * 13 - 8];
56 static TestSerialization g_test_instance;
58 void TestSerialization::runTests(IGameDef *gamedef)
62 TEST(testSerializeString);
63 TEST(testDeSerializeString);
64 TEST(testSerializeWideString);
65 TEST(testDeSerializeWideString);
66 TEST(testSerializeLongString);
67 TEST(testDeSerializeLongString);
68 TEST(testSerializeJsonString);
69 TEST(testSerializeHex);
71 TEST(testStreamWrite);
73 TEST(testStringLengthLimits);
75 TEST(testFloatFormat);
78 ////////////////////////////////////////////////////////////////////////////////
80 // To be used like this:
81 // mkstr("Some\0string\0with\0embedded\0nuls")
82 // since std::string("...") doesn't work as expected in that case.
83 template<size_t N> std::string mkstr(const char (&s)[N])
85 return std::string(s, N - 1);
88 void TestSerialization::buildTestStrings()
90 std::ostringstream tmp_os;
91 std::wostringstream tmp_os_w;
92 std::ostringstream tmp_os_w_encoded;
93 for (int i = 0; i < 256; i++) {
95 tmp_os_w << (wchar_t)i;
96 tmp_os_w_encoded << (char)0 << (char)i;
98 teststring2 = tmp_os.str();
99 teststring2_w = tmp_os_w.str();
100 teststring2_w_encoded = tmp_os_w_encoded.str();
103 void TestSerialization::testSerializeString()
106 UASSERT(serializeString("") == mkstr("\0\0"));
109 UASSERT(serializeString("Hello world!") == mkstr("\0\14Hello world!"));
111 // Test character range
112 UASSERT(serializeString(teststring2) == mkstr("\1\0") + teststring2);
115 void TestSerialization::testDeSerializeString()
119 std::istringstream is(serializeString(teststring2), std::ios::binary);
120 UASSERT(deSerializeString(is) == teststring2);
126 // Test deserialize an incomplete length specifier
128 std::istringstream is(mkstr("\x53"), std::ios::binary);
129 EXCEPTION_CHECK(SerializationError, deSerializeString(is));
132 // Test deserialize a string with incomplete data
134 std::istringstream is(mkstr("\x00\x55 abcdefg"), std::ios::binary);
135 EXCEPTION_CHECK(SerializationError, deSerializeString(is));
139 void TestSerialization::testSerializeWideString()
142 UASSERT(serializeWideString(L"") == mkstr("\0\0"));
145 UASSERT(serializeWideString(utf8_to_wide("Hello world!")) ==
146 mkstr("\0\14\0H\0e\0l\0l\0o\0 \0w\0o\0r\0l\0d\0!"));
148 // Test character range
149 UASSERT(serializeWideString(teststring2_w) ==
150 mkstr("\1\0") + teststring2_w_encoded);
153 void TestSerialization::testDeSerializeWideString()
157 std::istringstream is(serializeWideString(teststring2_w), std::ios::binary);
158 UASSERT(deSerializeWideString(is) == teststring2_w);
164 // Test deserialize an incomplete length specifier
166 std::istringstream is(mkstr("\x53"), std::ios::binary);
167 EXCEPTION_CHECK(SerializationError, deSerializeWideString(is));
170 // Test deserialize a string with an incomplete character
172 std::istringstream is(mkstr("\x00\x07\0a\0b\0c\0d\0e\0f\0"), std::ios::binary);
173 EXCEPTION_CHECK(SerializationError, deSerializeWideString(is));
176 // Test deserialize a string with incomplete data
178 std::istringstream is(mkstr("\x00\x08\0a\0b\0c\0d\0e\0f"), std::ios::binary);
179 EXCEPTION_CHECK(SerializationError, deSerializeWideString(is));
183 void TestSerialization::testSerializeLongString()
186 UASSERT(serializeLongString("") == mkstr("\0\0\0\0"));
189 UASSERT(serializeLongString("Hello world!") == mkstr("\0\0\0\14Hello world!"));
191 // Test character range
192 UASSERT(serializeLongString(teststring2) == mkstr("\0\0\1\0") + teststring2);
195 void TestSerialization::testDeSerializeLongString()
199 std::istringstream is(serializeLongString(teststring2), std::ios::binary);
200 UASSERT(deSerializeLongString(is) == teststring2);
206 // Test deserialize an incomplete length specifier
208 std::istringstream is(mkstr("\x53"), std::ios::binary);
209 EXCEPTION_CHECK(SerializationError, deSerializeLongString(is));
212 // Test deserialize a string with incomplete data
214 std::istringstream is(mkstr("\x00\x00\x00\x05 abc"), std::ios::binary);
215 EXCEPTION_CHECK(SerializationError, deSerializeLongString(is));
218 // Test deserialize a string with a length too large
220 std::istringstream is(mkstr("\xFF\xFF\xFF\xFF blah"), std::ios::binary);
221 EXCEPTION_CHECK(SerializationError, deSerializeLongString(is));
226 void TestSerialization::testSerializeJsonString()
229 UASSERT(serializeJsonString("") == "\"\"");
232 UASSERT(serializeJsonString("Hello world!") == "\"Hello world!\"");
234 // MSVC fails when directly using "\\\\"
235 std::string backslash = "\\";
236 UASSERT(serializeJsonString(teststring2) ==
238 "\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007" +
239 "\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f" +
240 "\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017" +
241 "\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f" +
242 " !\\\"" + teststring2.substr(0x23, 0x2f-0x23) +
243 "\\/" + teststring2.substr(0x30, 0x5c-0x30) +
244 backslash + backslash + teststring2.substr(0x5d, 0x7f-0x5d) + "\\u007f" +
245 "\\u0080\\u0081\\u0082\\u0083\\u0084\\u0085\\u0086\\u0087" +
246 "\\u0088\\u0089\\u008a\\u008b\\u008c\\u008d\\u008e\\u008f" +
247 "\\u0090\\u0091\\u0092\\u0093\\u0094\\u0095\\u0096\\u0097" +
248 "\\u0098\\u0099\\u009a\\u009b\\u009c\\u009d\\u009e\\u009f" +
249 "\\u00a0\\u00a1\\u00a2\\u00a3\\u00a4\\u00a5\\u00a6\\u00a7" +
250 "\\u00a8\\u00a9\\u00aa\\u00ab\\u00ac\\u00ad\\u00ae\\u00af" +
251 "\\u00b0\\u00b1\\u00b2\\u00b3\\u00b4\\u00b5\\u00b6\\u00b7" +
252 "\\u00b8\\u00b9\\u00ba\\u00bb\\u00bc\\u00bd\\u00be\\u00bf" +
253 "\\u00c0\\u00c1\\u00c2\\u00c3\\u00c4\\u00c5\\u00c6\\u00c7" +
254 "\\u00c8\\u00c9\\u00ca\\u00cb\\u00cc\\u00cd\\u00ce\\u00cf" +
255 "\\u00d0\\u00d1\\u00d2\\u00d3\\u00d4\\u00d5\\u00d6\\u00d7" +
256 "\\u00d8\\u00d9\\u00da\\u00db\\u00dc\\u00dd\\u00de\\u00df" +
257 "\\u00e0\\u00e1\\u00e2\\u00e3\\u00e4\\u00e5\\u00e6\\u00e7" +
258 "\\u00e8\\u00e9\\u00ea\\u00eb\\u00ec\\u00ed\\u00ee\\u00ef" +
259 "\\u00f0\\u00f1\\u00f2\\u00f3\\u00f4\\u00f5\\u00f6\\u00f7" +
260 "\\u00f8\\u00f9\\u00fa\\u00fb\\u00fc\\u00fd\\u00fe\\u00ff" +
264 std::istringstream is(serializeJsonString(teststring2), std::ios::binary);
265 UASSERT(deSerializeJsonString(is) == teststring2);
271 void TestSerialization::testSerializeHex()
274 UASSERT(serializeHexString("") == "");
275 UASSERT(serializeHexString("", true) == "");
278 UASSERT(serializeHexString("Hello world!") ==
279 "48656c6c6f20776f726c6421");
280 UASSERT(serializeHexString("Hello world!", true) ==
281 "48 65 6c 6c 6f 20 77 6f 72 6c 64 21");
283 // Test binary string
284 UASSERT(serializeHexString(mkstr("\x00\x0a\xb0\x63\x1f\x00\xff")) ==
286 UASSERT(serializeHexString(mkstr("\x00\x0a\xb0\x63\x1f\x00\xff"), true) ==
287 "00 0a b0 63 1f 00 ff");
291 void TestSerialization::testStreamRead()
294 (const char *)test_serialized_data,
295 sizeof(test_serialized_data));
296 std::istringstream is(datastr, std::ios_base::binary);
298 UASSERT(readU8(is) == 0x11);
299 UASSERT(readU16(is) == 0x2233);
300 UASSERT(readU32(is) == 0x44556677);
301 UASSERT(readU64(is) == 0x8899AABBCCDDEEFFLL);
303 UASSERT(readS8(is) == -128);
304 UASSERT(readS16(is) == 30000);
305 UASSERT(readS32(is) == -6);
306 UASSERT(readS64(is) == -43);
308 UASSERT(readF1000(is) == 53.534f);
309 UASSERT(readF1000(is) == -300000.32f);
310 UASSERT(readF1000(is) == F1000_MIN);
311 UASSERT(readF1000(is) == F1000_MAX);
313 UASSERT(deSerializeString(is) == "foobar!");
315 UASSERT(readV2S16(is) == v2s16(500, 500));
316 UASSERT(readV3S16(is) == v3s16(4207, 604, -30));
317 UASSERT(readV2S32(is) == v2s32(1920, 1080));
318 UASSERT(readV3S32(is) == v3s32(-400, 6400054, 290549855));
320 UASSERT(deSerializeWideString(is) == L"\x02~woof~\x5455");
322 UASSERT(readV3F1000(is) == v3f(500, 10024.2f, -192.54f));
323 UASSERT(readARGB8(is) == video::SColor(255, 128, 50, 128));
325 UASSERT(deSerializeLongString(is) == "some longer string here");
327 UASSERT(is.rdbuf()->in_avail() == 2);
328 UASSERT(readU16(is) == 0xF00D);
329 UASSERT(is.rdbuf()->in_avail() == 0);
333 void TestSerialization::testStreamWrite()
335 std::ostringstream os(std::ios_base::binary);
339 writeU16(os, 0x2233);
340 writeU32(os, 0x44556677);
341 writeU64(os, 0x8899AABBCCDDEEFFLL);
348 writeF1000(os, 53.53467f);
349 writeF1000(os, -300000.32f);
350 writeF1000(os, F1000_MIN);
351 writeF1000(os, F1000_MAX);
353 os << serializeString("foobar!");
356 UASSERT(data.size() < sizeof(test_serialized_data));
357 UASSERT(!memcmp(&data[0], test_serialized_data, data.size()));
359 writeV2S16(os, v2s16(500, 500));
360 writeV3S16(os, v3s16(4207, 604, -30));
361 writeV2S32(os, v2s32(1920, 1080));
362 writeV3S32(os, v3s32(-400, 6400054, 290549855));
364 os << serializeWideString(L"\x02~woof~\x5455");
366 writeV3F1000(os, v3f(500, 10024.2f, -192.54f));
367 writeARGB8(os, video::SColor(255, 128, 50, 128));
369 os << serializeLongString("some longer string here");
371 writeU16(os, 0xF00D);
374 UASSERT(data.size() == sizeof(test_serialized_data));
375 UASSERT(!memcmp(&data[0], test_serialized_data, sizeof(test_serialized_data)));
379 void TestSerialization::testVecPut()
384 putU16(&buf, 0x2233);
385 putU32(&buf, 0x44556677);
386 putU64(&buf, 0x8899AABBCCDDEEFFLL);
393 putF1000(&buf, 53.53467f);
394 putF1000(&buf, -300000.32f);
395 putF1000(&buf, F1000_MIN);
396 putF1000(&buf, F1000_MAX);
398 putString(&buf, "foobar!");
400 putV2S16(&buf, v2s16(500, 500));
401 putV3S16(&buf, v3s16(4207, 604, -30));
402 putV2S32(&buf, v2s32(1920, 1080));
403 putV3S32(&buf, v3s32(-400, 6400054, 290549855));
405 putWideString(&buf, L"\x02~woof~\x5455");
407 putV3F1000(&buf, v3f(500, 10024.2f, -192.54f));
408 putARGB8(&buf, video::SColor(255, 128, 50, 128));
410 putLongString(&buf, "some longer string here");
412 putU16(&buf, 0xF00D);
414 UASSERT(buf.size() == sizeof(test_serialized_data));
415 UASSERT(!memcmp(&buf[0], test_serialized_data, sizeof(test_serialized_data)));
419 void TestSerialization::testStringLengthLimits()
422 std::string too_long(STRING_MAX_LEN + 1, 'A');
423 std::string way_too_large(LONG_STRING_MAX_LEN + 1, 'B');
424 std::wstring too_long_wide(WIDE_STRING_MAX_LEN + 1, L'C');
426 EXCEPTION_CHECK(SerializationError, putString(&buf, too_long));
428 putLongString(&buf, too_long);
429 too_long.resize(too_long.size() - 1);
430 putString(&buf, too_long);
432 EXCEPTION_CHECK(SerializationError, putWideString(&buf, too_long_wide));
433 too_long_wide.resize(too_long_wide.size() - 1);
434 putWideString(&buf, too_long_wide);
438 void TestSerialization::testBufReader()
448 f32 f32_data, f32_data2, f32_data3, f32_data4;
449 video::SColor scolor_data;
455 std::string string_data;
456 std::wstring widestring_data;
457 std::string longstring_data;
458 u8 raw_data[10] = {0};
460 BufReader buf(test_serialized_data, sizeof(test_serialized_data));
462 // Try reading data like normal
463 UASSERT(buf.getU8() == 0x11);
464 UASSERT(buf.getU16() == 0x2233);
465 UASSERT(buf.getU32() == 0x44556677);
466 UASSERT(buf.getU64() == 0x8899AABBCCDDEEFFLL);
467 UASSERT(buf.getS8() == -128);
468 UASSERT(buf.getS16() == 30000);
469 UASSERT(buf.getS32() == -6);
470 UASSERT(buf.getS64() == -43);
471 UASSERT(buf.getF1000() == 53.534f);
472 UASSERT(buf.getF1000() == -300000.32f);
473 UASSERT(buf.getF1000() == F1000_MIN);
474 UASSERT(buf.getF1000() == F1000_MAX);
475 UASSERT(buf.getString() == "foobar!");
476 UASSERT(buf.getV2S16() == v2s16(500, 500));
477 UASSERT(buf.getV3S16() == v3s16(4207, 604, -30));
478 UASSERT(buf.getV2S32() == v2s32(1920, 1080));
479 UASSERT(buf.getV3S32() == v3s32(-400, 6400054, 290549855));
480 UASSERT(buf.getWideString() == L"\x02~woof~\x5455");
481 UASSERT(buf.getV3F1000() == v3f(500, 10024.2f, -192.54f));
482 UASSERT(buf.getARGB8() == video::SColor(255, 128, 50, 128));
483 UASSERT(buf.getLongString() == "some longer string here");
485 // Verify the offset and data is unchanged after a failed read
486 size_t orig_pos = buf.pos;
488 UASSERT(buf.getU32NoEx(&u32_data) == false);
489 UASSERT(buf.pos == orig_pos);
490 UASSERT(u32_data == 0);
492 // Now try the same for a failed string read
493 UASSERT(buf.getStringNoEx(&string_data) == false);
494 UASSERT(buf.pos == orig_pos);
495 UASSERT(string_data == "");
497 // Now try the same for a failed string read
498 UASSERT(buf.getWideStringNoEx(&widestring_data) == false);
499 UASSERT(buf.pos == orig_pos);
500 UASSERT(widestring_data == L"");
502 UASSERT(buf.getU16() == 0xF00D);
504 UASSERT(buf.remaining() == 0);
506 // Check to make sure these each blow exceptions as they're supposed to
507 EXCEPTION_CHECK(SerializationError, buf.getU8());
508 EXCEPTION_CHECK(SerializationError, buf.getU16());
509 EXCEPTION_CHECK(SerializationError, buf.getU32());
510 EXCEPTION_CHECK(SerializationError, buf.getU64());
512 EXCEPTION_CHECK(SerializationError, buf.getS8());
513 EXCEPTION_CHECK(SerializationError, buf.getS16());
514 EXCEPTION_CHECK(SerializationError, buf.getS32());
515 EXCEPTION_CHECK(SerializationError, buf.getS64());
517 EXCEPTION_CHECK(SerializationError, buf.getF1000());
518 EXCEPTION_CHECK(SerializationError, buf.getARGB8());
520 EXCEPTION_CHECK(SerializationError, buf.getV2S16());
521 EXCEPTION_CHECK(SerializationError, buf.getV3S16());
522 EXCEPTION_CHECK(SerializationError, buf.getV2S32());
523 EXCEPTION_CHECK(SerializationError, buf.getV3S32());
524 EXCEPTION_CHECK(SerializationError, buf.getV3F1000());
526 EXCEPTION_CHECK(SerializationError, buf.getString());
527 EXCEPTION_CHECK(SerializationError, buf.getWideString());
528 EXCEPTION_CHECK(SerializationError, buf.getLongString());
529 EXCEPTION_CHECK(SerializationError,
530 buf.getRawData(raw_data, sizeof(raw_data)));
532 // See if we can skip backwards
534 UASSERT(buf.getRawDataNoEx(raw_data, 3) == true);
535 UASSERT(raw_data[0] == 0x66);
536 UASSERT(raw_data[1] == 0x77);
537 UASSERT(raw_data[2] == 0x88);
539 UASSERT(buf.getU32() == 0x99AABBCC);
540 UASSERT(buf.pos == 12);
542 // Now let's try it all over again using the NoEx variants
545 UASSERT(buf.getU8NoEx(&u8_data));
546 UASSERT(buf.getU16NoEx(&u16_data));
547 UASSERT(buf.getU32NoEx(&u32_data));
548 UASSERT(buf.getU64NoEx(&u64_data));
550 UASSERT(buf.getS8NoEx(&s8_data));
551 UASSERT(buf.getS16NoEx(&s16_data));
552 UASSERT(buf.getS32NoEx(&s32_data));
553 UASSERT(buf.getS64NoEx(&s64_data));
555 UASSERT(buf.getF1000NoEx(&f32_data));
556 UASSERT(buf.getF1000NoEx(&f32_data2));
557 UASSERT(buf.getF1000NoEx(&f32_data3));
558 UASSERT(buf.getF1000NoEx(&f32_data4));
560 UASSERT(buf.getStringNoEx(&string_data));
561 UASSERT(buf.getV2S16NoEx(&v2s16_data));
562 UASSERT(buf.getV3S16NoEx(&v3s16_data));
563 UASSERT(buf.getV2S32NoEx(&v2s32_data));
564 UASSERT(buf.getV3S32NoEx(&v3s32_data));
565 UASSERT(buf.getWideStringNoEx(&widestring_data));
566 UASSERT(buf.getV3F1000NoEx(&v3f_data));
567 UASSERT(buf.getARGB8NoEx(&scolor_data));
569 UASSERT(buf.getLongStringNoEx(&longstring_data));
571 // and make sure we got the correct data
572 UASSERT(u8_data == 0x11);
573 UASSERT(u16_data == 0x2233);
574 UASSERT(u32_data == 0x44556677);
575 UASSERT(u64_data == 0x8899AABBCCDDEEFFLL);
576 UASSERT(s8_data == -128);
577 UASSERT(s16_data == 30000);
578 UASSERT(s32_data == -6);
579 UASSERT(s64_data == -43);
580 UASSERT(f32_data == 53.534f);
581 UASSERT(f32_data2 == -300000.32f);
582 UASSERT(f32_data3 == F1000_MIN);
583 UASSERT(f32_data4 == F1000_MAX);
584 UASSERT(string_data == "foobar!");
585 UASSERT(v2s16_data == v2s16(500, 500));
586 UASSERT(v3s16_data == v3s16(4207, 604, -30));
587 UASSERT(v2s32_data == v2s32(1920, 1080));
588 UASSERT(v3s32_data == v3s32(-400, 6400054, 290549855));
589 UASSERT(widestring_data == L"\x02~woof~\x5455");
590 UASSERT(v3f_data == v3f(500, 10024.2f, -192.54f));
591 UASSERT(scolor_data == video::SColor(255, 128, 50, 128));
592 UASSERT(longstring_data == "some longer string here");
594 UASSERT(buf.remaining() == 2);
595 UASSERT(buf.getRawDataNoEx(raw_data, 3) == false);
596 UASSERT(buf.remaining() == 2);
597 UASSERT(buf.getRawDataNoEx(raw_data, 2) == true);
598 UASSERT(raw_data[0] == 0xF0);
599 UASSERT(raw_data[1] == 0x0D);
600 UASSERT(buf.remaining() == 0);
602 // Make sure no more available data causes a failure
603 UASSERT(!buf.getU8NoEx(&u8_data));
604 UASSERT(!buf.getU16NoEx(&u16_data));
605 UASSERT(!buf.getU32NoEx(&u32_data));
606 UASSERT(!buf.getU64NoEx(&u64_data));
608 UASSERT(!buf.getS8NoEx(&s8_data));
609 UASSERT(!buf.getS16NoEx(&s16_data));
610 UASSERT(!buf.getS32NoEx(&s32_data));
611 UASSERT(!buf.getS64NoEx(&s64_data));
613 UASSERT(!buf.getF1000NoEx(&f32_data));
614 UASSERT(!buf.getARGB8NoEx(&scolor_data));
616 UASSERT(!buf.getV2S16NoEx(&v2s16_data));
617 UASSERT(!buf.getV3S16NoEx(&v3s16_data));
618 UASSERT(!buf.getV2S32NoEx(&v2s32_data));
619 UASSERT(!buf.getV3S32NoEx(&v3s32_data));
620 UASSERT(!buf.getV3F1000NoEx(&v3f_data));
622 UASSERT(!buf.getStringNoEx(&string_data));
623 UASSERT(!buf.getWideStringNoEx(&widestring_data));
624 UASSERT(!buf.getLongStringNoEx(&longstring_data));
625 UASSERT(!buf.getRawDataNoEx(raw_data, sizeof(raw_data)));
628 void TestSerialization::testFloatFormat()
630 FloatType type = getFloatSerializationType();
634 // Check precision of float calculations on this platform
635 const std::unordered_map<f32, u32> float_results = {
636 { 0.0f, 0x00000000UL },
637 { 1.0f, 0x3F800000UL },
638 { -1.0f, 0xBF800000UL },
639 { 0.1f, 0x3DCCCCCDUL },
640 { -0.1f, 0xBDCCCCCDUL },
641 { 1945329.25f, 0x49ED778AUL },
642 { -23298764.f, 0xCBB1C166UL },
643 { 0.5f, 0x3F000000UL },
644 { -0.5f, 0xBF000000UL }
646 for (const auto &v : float_results) {
647 i = f32Tou32Slow(v.first);
648 if (std::abs((s64)v.second - i) > 32) {
649 printf("Inaccurate float values on %.9g, expected 0x%X, actual 0x%X\n",
650 v.first, v.second, i);
654 fs = u32Tof32Slow(v.second);
655 if (std::fabs(v.first - fs) > std::fabs(v.first * 0.000005f)) {
656 printf("Inaccurate float values on 0x%X, expected %.9g, actual 0x%.9g\n",
657 v.second, v.first, fs);
662 if (type == FLOATTYPE_SLOW) {
663 // conversion using memcpy is not possible
664 // Skip exact float comparison checks below
668 // The code below compares the IEEE conversion functions with a
669 // known good IEC559/IEEE754 implementation. This test neeeds
670 // IEC559 compliance in the compiler.
671 #if defined(__GNUC__) && (!defined(__STDC_IEC_559__) || defined(__FAST_MATH__))
672 // GNU C++ lies about its IEC559 support when -ffast-math is active.
673 // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=84949
674 bool is_iec559 = false;
676 bool is_iec559 = std::numeric_limits<f32>::is_iec559;
681 auto test_single = [&fs, &fm](const u32 &i) -> bool {
683 fs = u32Tof32Slow(i);
685 printf("u32Tof32Slow failed on 0x%X, expected %.9g, actual %.9g\n",
689 if (f32Tou32Slow(fs) != i) {
690 printf("f32Tou32Slow failed on %.9g, expected 0x%X, actual 0x%X\n",
691 fs, i, f32Tou32Slow(fs));
697 // Use step of prime 277 to speed things up from 3 minutes to a few seconds
698 // Test from 0 to 0xFF800000UL (positive)
699 for (i = 0x00000000UL; i <= 0x7F800000UL; i += 277)
700 UASSERT(test_single(i));
702 // Ensure +inf and -inf are tested
703 UASSERT(test_single(0x7F800000UL));
704 UASSERT(test_single(0xFF800000UL));
706 // Test from 0x80000000UL to 0xFF800000UL (negative)
707 for (i = 0x80000000UL; i <= 0xFF800000UL; i += 277)
708 UASSERT(test_single(i));
711 const u8 TestSerialization::test_serialized_data[12 * 13 - 8] = {
712 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
713 0xdd, 0xee, 0xff, 0x80, 0x75, 0x30, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xff,
714 0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x00, 0x00, 0xd1, 0x1e, 0xee, 0x1e,
715 0x5b, 0xc0, 0x80, 0x00, 0x02, 0x80, 0x7F, 0xFF, 0xFD, 0x80, 0x00, 0x07,
716 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x21, 0x01, 0xf4, 0x01, 0xf4, 0x10,
717 0x6f, 0x02, 0x5c, 0xff, 0xe2, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x04,
718 0x38, 0xff, 0xff, 0xfe, 0x70, 0x00, 0x61, 0xa8, 0x36, 0x11, 0x51, 0x70,
719 0x5f, 0x00, 0x08, 0x00,
720 0x02, 0x00, 0x7e, 0x00, 'w', 0x00, 'o', 0x00, 'o', 0x00, 'f', 0x00, // \x02~woof~\x5455
721 0x7e, 0x54, 0x55, 0x00, 0x07, 0xa1, 0x20, 0x00, 0x98, 0xf5, 0x08, 0xff,
722 0xfd, 0x0f, 0xe4, 0xff, 0x80, 0x32, 0x80, 0x00, 0x00, 0x00, 0x17, 0x73,
723 0x6f, 0x6d, 0x65, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x73,
724 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x65, 0x72, 0x65, 0xF0, 0x0D,