Translated using Weblate (Russian)
[oweals/minetest.git] / src / unittest / test_serialization.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
20 #include "test.h"
21
22 #include "util/string.h"
23 #include "util/serialize.h"
24 #include <cmath>
25
26 class TestSerialization : public TestBase {
27 public:
28         TestSerialization() { TestManager::registerTestModule(this); }
29         const char *getName() { return "TestSerialization"; }
30
31         void runTests(IGameDef *gamedef);
32         void buildTestStrings();
33
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();
44         void testVecPut();
45         void testStringLengthLimits();
46         void testBufReader();
47         void testFloatFormat();
48
49         std::string teststring2;
50         std::wstring teststring2_w;
51         std::string teststring2_w_encoded;
52
53         static const u8 test_serialized_data[12 * 13 - 8];
54 };
55
56 static TestSerialization g_test_instance;
57
58 void TestSerialization::runTests(IGameDef *gamedef)
59 {
60         buildTestStrings();
61
62         TEST(testSerializeString);
63         TEST(testDeSerializeString);
64         TEST(testSerializeWideString);
65         TEST(testDeSerializeWideString);
66         TEST(testSerializeLongString);
67         TEST(testDeSerializeLongString);
68         TEST(testSerializeJsonString);
69         TEST(testSerializeHex);
70         TEST(testStreamRead);
71         TEST(testStreamWrite);
72         TEST(testVecPut);
73         TEST(testStringLengthLimits);
74         TEST(testBufReader);
75         TEST(testFloatFormat);
76 }
77
78 ////////////////////////////////////////////////////////////////////////////////
79
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])
84 {
85         return std::string(s, N - 1);
86 }
87
88 void TestSerialization::buildTestStrings()
89 {
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++) {
94                 tmp_os << (char)i;
95                 tmp_os_w << (wchar_t)i;
96                 tmp_os_w_encoded << (char)0 << (char)i;
97         }
98         teststring2 = tmp_os.str();
99         teststring2_w = tmp_os_w.str();
100         teststring2_w_encoded = tmp_os_w_encoded.str();
101 }
102
103 void TestSerialization::testSerializeString()
104 {
105         // Test blank string
106         UASSERT(serializeString("") == mkstr("\0\0"));
107
108         // Test basic string
109         UASSERT(serializeString("Hello world!") == mkstr("\0\14Hello world!"));
110
111         // Test character range
112         UASSERT(serializeString(teststring2) == mkstr("\1\0") + teststring2);
113 }
114
115 void TestSerialization::testDeSerializeString()
116 {
117         // Test deserialize
118         {
119                 std::istringstream is(serializeString(teststring2), std::ios::binary);
120                 UASSERT(deSerializeString(is) == teststring2);
121                 UASSERT(!is.eof());
122                 is.get();
123                 UASSERT(is.eof());
124         }
125
126         // Test deserialize an incomplete length specifier
127         {
128                 std::istringstream is(mkstr("\x53"), std::ios::binary);
129                 EXCEPTION_CHECK(SerializationError, deSerializeString(is));
130         }
131
132         // Test deserialize a string with incomplete data
133         {
134                 std::istringstream is(mkstr("\x00\x55 abcdefg"), std::ios::binary);
135                 EXCEPTION_CHECK(SerializationError, deSerializeString(is));
136         }
137 }
138
139 void TestSerialization::testSerializeWideString()
140 {
141         // Test blank string
142         UASSERT(serializeWideString(L"") == mkstr("\0\0"));
143
144         // Test basic string
145         UASSERT(serializeWideString(utf8_to_wide("Hello world!")) ==
146                 mkstr("\0\14\0H\0e\0l\0l\0o\0 \0w\0o\0r\0l\0d\0!"));
147
148         // Test character range
149         UASSERT(serializeWideString(teststring2_w) ==
150                 mkstr("\1\0") + teststring2_w_encoded);
151 }
152
153 void TestSerialization::testDeSerializeWideString()
154 {
155         // Test deserialize
156         {
157                 std::istringstream is(serializeWideString(teststring2_w), std::ios::binary);
158                 UASSERT(deSerializeWideString(is) == teststring2_w);
159                 UASSERT(!is.eof());
160                 is.get();
161                 UASSERT(is.eof());
162         }
163
164         // Test deserialize an incomplete length specifier
165         {
166                 std::istringstream is(mkstr("\x53"), std::ios::binary);
167                 EXCEPTION_CHECK(SerializationError, deSerializeWideString(is));
168         }
169
170         // Test deserialize a string with an incomplete character
171         {
172                 std::istringstream is(mkstr("\x00\x07\0a\0b\0c\0d\0e\0f\0"), std::ios::binary);
173                 EXCEPTION_CHECK(SerializationError, deSerializeWideString(is));
174         }
175
176         // Test deserialize a string with incomplete data
177         {
178                 std::istringstream is(mkstr("\x00\x08\0a\0b\0c\0d\0e\0f"), std::ios::binary);
179                 EXCEPTION_CHECK(SerializationError, deSerializeWideString(is));
180         }
181 }
182
183 void TestSerialization::testSerializeLongString()
184 {
185         // Test blank string
186         UASSERT(serializeLongString("") == mkstr("\0\0\0\0"));
187
188         // Test basic string
189         UASSERT(serializeLongString("Hello world!") == mkstr("\0\0\0\14Hello world!"));
190
191         // Test character range
192         UASSERT(serializeLongString(teststring2) == mkstr("\0\0\1\0") + teststring2);
193 }
194
195 void TestSerialization::testDeSerializeLongString()
196 {
197         // Test deserialize
198         {
199                 std::istringstream is(serializeLongString(teststring2), std::ios::binary);
200                 UASSERT(deSerializeLongString(is) == teststring2);
201                 UASSERT(!is.eof());
202                 is.get();
203                 UASSERT(is.eof());
204         }
205
206         // Test deserialize an incomplete length specifier
207         {
208                 std::istringstream is(mkstr("\x53"), std::ios::binary);
209                 EXCEPTION_CHECK(SerializationError, deSerializeLongString(is));
210         }
211
212         // Test deserialize a string with incomplete data
213         {
214                 std::istringstream is(mkstr("\x00\x00\x00\x05 abc"), std::ios::binary);
215                 EXCEPTION_CHECK(SerializationError, deSerializeLongString(is));
216         }
217
218         // Test deserialize a string with a length too large
219         {
220                 std::istringstream is(mkstr("\xFF\xFF\xFF\xFF blah"), std::ios::binary);
221                 EXCEPTION_CHECK(SerializationError, deSerializeLongString(is));
222         }
223 }
224
225
226 void TestSerialization::testSerializeJsonString()
227 {
228         // Test blank string
229         UASSERT(serializeJsonString("") == "\"\"");
230
231         // Test basic string
232         UASSERT(serializeJsonString("Hello world!") == "\"Hello world!\"");
233
234         // MSVC fails when directly using "\\\\"
235         std::string backslash = "\\";
236         UASSERT(serializeJsonString(teststring2) ==
237                 mkstr("\"") +
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" +
261                 "\"");
262
263         // Test deserialize
264         std::istringstream is(serializeJsonString(teststring2), std::ios::binary);
265         UASSERT(deSerializeJsonString(is) == teststring2);
266         UASSERT(!is.eof());
267         is.get();
268         UASSERT(is.eof());
269 }
270
271 void TestSerialization::testSerializeHex()
272 {
273         // Test blank string
274         UASSERT(serializeHexString("") == "");
275         UASSERT(serializeHexString("", true) == "");
276
277         // Test basic string
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");
282
283         // Test binary string
284         UASSERT(serializeHexString(mkstr("\x00\x0a\xb0\x63\x1f\x00\xff")) ==
285                 "000ab0631f00ff");
286         UASSERT(serializeHexString(mkstr("\x00\x0a\xb0\x63\x1f\x00\xff"), true) ==
287                 "00 0a b0 63 1f 00 ff");
288 }
289
290
291 void TestSerialization::testStreamRead()
292 {
293         std::string datastr(
294                 (const char *)test_serialized_data,
295                 sizeof(test_serialized_data));
296         std::istringstream is(datastr, std::ios_base::binary);
297
298         UASSERT(readU8(is) == 0x11);
299         UASSERT(readU16(is) == 0x2233);
300         UASSERT(readU32(is) == 0x44556677);
301         UASSERT(readU64(is) == 0x8899AABBCCDDEEFFLL);
302
303         UASSERT(readS8(is) == -128);
304         UASSERT(readS16(is) == 30000);
305         UASSERT(readS32(is) == -6);
306         UASSERT(readS64(is) == -43);
307
308         UASSERT(readF1000(is) == 53.534f);
309         UASSERT(readF1000(is) == -300000.32f);
310         UASSERT(readF1000(is) == F1000_MIN);
311         UASSERT(readF1000(is) == F1000_MAX);
312
313         UASSERT(deSerializeString(is) == "foobar!");
314
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));
319
320         UASSERT(deSerializeWideString(is) == L"\x02~woof~\x5455");
321
322         UASSERT(readV3F1000(is) == v3f(500, 10024.2f, -192.54f));
323         UASSERT(readARGB8(is) == video::SColor(255, 128, 50, 128));
324
325         UASSERT(deSerializeLongString(is) == "some longer string here");
326
327         UASSERT(is.rdbuf()->in_avail() == 2);
328         UASSERT(readU16(is) == 0xF00D);
329         UASSERT(is.rdbuf()->in_avail() == 0);
330 }
331
332
333 void TestSerialization::testStreamWrite()
334 {
335         std::ostringstream os(std::ios_base::binary);
336         std::string data;
337
338         writeU8(os, 0x11);
339         writeU16(os, 0x2233);
340         writeU32(os, 0x44556677);
341         writeU64(os, 0x8899AABBCCDDEEFFLL);
342
343         writeS8(os, -128);
344         writeS16(os, 30000);
345         writeS32(os, -6);
346         writeS64(os, -43);
347
348         writeF1000(os, 53.53467f);
349         writeF1000(os, -300000.32f);
350         writeF1000(os, F1000_MIN);
351         writeF1000(os, F1000_MAX);
352
353         os << serializeString("foobar!");
354
355         data = os.str();
356         UASSERT(data.size() < sizeof(test_serialized_data));
357         UASSERT(!memcmp(&data[0], test_serialized_data, data.size()));
358
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));
363
364         os << serializeWideString(L"\x02~woof~\x5455");
365
366         writeV3F1000(os, v3f(500, 10024.2f, -192.54f));
367         writeARGB8(os, video::SColor(255, 128, 50, 128));
368
369         os << serializeLongString("some longer string here");
370
371         writeU16(os, 0xF00D);
372
373         data = os.str();
374         UASSERT(data.size() == sizeof(test_serialized_data));
375         UASSERT(!memcmp(&data[0], test_serialized_data, sizeof(test_serialized_data)));
376 }
377
378
379 void TestSerialization::testVecPut()
380 {
381         std::vector<u8> buf;
382
383         putU8(&buf, 0x11);
384         putU16(&buf, 0x2233);
385         putU32(&buf, 0x44556677);
386         putU64(&buf, 0x8899AABBCCDDEEFFLL);
387
388         putS8(&buf, -128);
389         putS16(&buf, 30000);
390         putS32(&buf, -6);
391         putS64(&buf, -43);
392
393         putF1000(&buf, 53.53467f);
394         putF1000(&buf, -300000.32f);
395         putF1000(&buf, F1000_MIN);
396         putF1000(&buf, F1000_MAX);
397
398         putString(&buf, "foobar!");
399
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));
404
405         putWideString(&buf, L"\x02~woof~\x5455");
406
407         putV3F1000(&buf, v3f(500, 10024.2f, -192.54f));
408         putARGB8(&buf, video::SColor(255, 128, 50, 128));
409
410         putLongString(&buf, "some longer string here");
411
412         putU16(&buf, 0xF00D);
413
414         UASSERT(buf.size() == sizeof(test_serialized_data));
415         UASSERT(!memcmp(&buf[0], test_serialized_data, sizeof(test_serialized_data)));
416 }
417
418
419 void TestSerialization::testStringLengthLimits()
420 {
421         std::vector<u8> buf;
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');
425
426         EXCEPTION_CHECK(SerializationError, putString(&buf, too_long));
427
428         putLongString(&buf, too_long);
429         too_long.resize(too_long.size() - 1);
430         putString(&buf, too_long);
431
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);
435 }
436
437
438 void TestSerialization::testBufReader()
439 {
440         u8 u8_data;
441         u16 u16_data;
442         u32 u32_data;
443         u64 u64_data;
444         s8 s8_data;
445         s16 s16_data;
446         s32 s32_data;
447         s64 s64_data;
448         f32 f32_data, f32_data2, f32_data3, f32_data4;
449         video::SColor scolor_data;
450         v2s16 v2s16_data;
451         v3s16 v3s16_data;
452         v2s32 v2s32_data;
453         v3s32 v3s32_data;
454         v3f v3f_data;
455         std::string string_data;
456         std::wstring widestring_data;
457         std::string longstring_data;
458         u8 raw_data[10] = {0};
459
460         BufReader buf(test_serialized_data, sizeof(test_serialized_data));
461
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");
484
485         // Verify the offset and data is unchanged after a failed read
486         size_t orig_pos = buf.pos;
487         u32_data = 0;
488         UASSERT(buf.getU32NoEx(&u32_data) == false);
489         UASSERT(buf.pos == orig_pos);
490         UASSERT(u32_data == 0);
491
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 == "");
496
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"");
501
502         UASSERT(buf.getU16() == 0xF00D);
503
504         UASSERT(buf.remaining() == 0);
505
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());
511
512         EXCEPTION_CHECK(SerializationError, buf.getS8());
513         EXCEPTION_CHECK(SerializationError, buf.getS16());
514         EXCEPTION_CHECK(SerializationError, buf.getS32());
515         EXCEPTION_CHECK(SerializationError, buf.getS64());
516
517         EXCEPTION_CHECK(SerializationError, buf.getF1000());
518         EXCEPTION_CHECK(SerializationError, buf.getARGB8());
519
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());
525
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)));
531
532         // See if we can skip backwards
533         buf.pos = 5;
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);
538
539         UASSERT(buf.getU32() == 0x99AABBCC);
540         UASSERT(buf.pos == 12);
541
542         // Now let's try it all over again using the NoEx variants
543         buf.pos = 0;
544
545         UASSERT(buf.getU8NoEx(&u8_data));
546         UASSERT(buf.getU16NoEx(&u16_data));
547         UASSERT(buf.getU32NoEx(&u32_data));
548         UASSERT(buf.getU64NoEx(&u64_data));
549
550         UASSERT(buf.getS8NoEx(&s8_data));
551         UASSERT(buf.getS16NoEx(&s16_data));
552         UASSERT(buf.getS32NoEx(&s32_data));
553         UASSERT(buf.getS64NoEx(&s64_data));
554
555         UASSERT(buf.getF1000NoEx(&f32_data));
556         UASSERT(buf.getF1000NoEx(&f32_data2));
557         UASSERT(buf.getF1000NoEx(&f32_data3));
558         UASSERT(buf.getF1000NoEx(&f32_data4));
559
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));
568
569         UASSERT(buf.getLongStringNoEx(&longstring_data));
570
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");
593
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);
601
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));
607
608         UASSERT(!buf.getS8NoEx(&s8_data));
609         UASSERT(!buf.getS16NoEx(&s16_data));
610         UASSERT(!buf.getS32NoEx(&s32_data));
611         UASSERT(!buf.getS64NoEx(&s64_data));
612
613         UASSERT(!buf.getF1000NoEx(&f32_data));
614         UASSERT(!buf.getARGB8NoEx(&scolor_data));
615
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));
621
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)));
626 }
627
628 void TestSerialization::testFloatFormat()
629 {
630         FloatType type = getFloatSerializationType();
631         u32 i;
632         f32 fs, fm;
633
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 }
645         };
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);
651                         UASSERT(false);
652                 }
653
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);
658                         UASSERT(false);
659                 }
660         }
661
662         if (type == FLOATTYPE_SLOW) {
663                 // conversion using memcpy is not possible
664                 // Skip exact float comparison checks below
665                 return;
666         }
667
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;
675 #else
676         bool is_iec559 = std::numeric_limits<f32>::is_iec559;
677 #endif
678         if (!is_iec559)
679                 return;
680
681         auto test_single = [&fs, &fm](const u32 &i) -> bool {
682                 memcpy(&fm, &i, 4);
683                 fs = u32Tof32Slow(i);
684                 if (fm != fs) {
685                         printf("u32Tof32Slow failed on 0x%X, expected %.9g, actual %.9g\n",
686                                 i, fm, fs);
687                         return false;
688                 }
689                 if (f32Tou32Slow(fs) != i) {
690                         printf("f32Tou32Slow failed on %.9g, expected 0x%X, actual 0x%X\n",
691                                 fs, i, f32Tou32Slow(fs));
692                         return false;
693                 }
694                 return true;
695         };
696
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));
701
702         // Ensure +inf and -inf are tested
703         UASSERT(test_single(0x7F800000UL));
704         UASSERT(test_single(0xFF800000UL));
705
706         // Test from 0x80000000UL to 0xFF800000UL (negative)
707         for (i = 0x80000000UL; i <= 0xFF800000UL; i += 277)
708                 UASSERT(test_single(i));
709 }
710
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,
725 };