]> git.lizzy.rs Git - minetest.git/blob - src/unittest/test_serialization.cpp
7e58dadca2d932643a238ec43a9c088db10d20d3
[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
25 class TestSerialization : public TestBase {
26 public:
27         TestSerialization() { TestManager::registerTestModule(this); }
28         const char *getName() { return "TestSerialization"; }
29
30         void runTests(IGameDef *gamedef);
31         void buildTestStrings();
32
33         void testSerializeString();
34         void testSerializeWideString();
35         void testSerializeLongString();
36         void testSerializeJsonString();
37         void testSerializeHex();
38         void testDeSerializeString();
39         void testDeSerializeWideString();
40         void testDeSerializeLongString();
41         void testStreamRead();
42         void testStreamWrite();
43
44         std::string teststring2;
45         std::wstring teststring2_w;
46         std::string teststring2_w_encoded;
47
48         static const u8 test_serialized_data[12 * 13];
49 };
50
51 static TestSerialization g_test_instance;
52
53 void TestSerialization::runTests(IGameDef *gamedef)
54 {
55         buildTestStrings();
56
57         TEST(testSerializeString);
58         TEST(testDeSerializeString);
59         TEST(testSerializeWideString);
60         TEST(testDeSerializeWideString);
61         TEST(testSerializeLongString);
62         TEST(testDeSerializeLongString);
63         TEST(testSerializeJsonString);
64         TEST(testSerializeHex);
65         TEST(testStreamRead);
66         TEST(testStreamWrite);
67 }
68
69 ////////////////////////////////////////////////////////////////////////////////
70
71 // To be used like this:
72 //   mkstr("Some\0string\0with\0embedded\0nuls")
73 // since std::string("...") doesn't work as expected in that case.
74 template<size_t N> std::string mkstr(const char (&s)[N])
75 {
76         return std::string(s, N - 1);
77 }
78
79 void TestSerialization::buildTestStrings()
80 {
81         std::ostringstream tmp_os;
82         std::wostringstream tmp_os_w;
83         std::ostringstream tmp_os_w_encoded;
84         for (int i = 0; i < 256; i++) {
85                 tmp_os << (char)i;
86                 tmp_os_w << (wchar_t)i;
87                 tmp_os_w_encoded << (char)0 << (char)i;
88         }
89         teststring2 = tmp_os.str();
90         teststring2_w = tmp_os_w.str();
91         teststring2_w_encoded = tmp_os_w_encoded.str();
92 }
93
94 void TestSerialization::testSerializeString()
95 {
96         // Test blank string
97         UASSERT(serializeString("") == mkstr("\0\0"));
98
99         // Test basic string
100         UASSERT(serializeString("Hello world!") == mkstr("\0\14Hello world!"));
101
102         // Test character range
103         UASSERT(serializeString(teststring2) == mkstr("\1\0") + teststring2);
104 }
105
106 void TestSerialization::testDeSerializeString()
107 {
108         // Test deserialize
109         {
110                 std::istringstream is(serializeString(teststring2), std::ios::binary);
111                 UASSERT(deSerializeString(is) == teststring2);
112                 UASSERT(!is.eof());
113                 is.get();
114                 UASSERT(is.eof());
115         }
116
117         // Test deserialize an incomplete length specifier
118         {
119                 std::istringstream is(mkstr("\x53"), std::ios::binary);
120                 EXCEPTION_CHECK(SerializationError, deSerializeString(is));
121         }
122
123         // Test deserialize a string with incomplete data
124         {
125                 std::istringstream is(mkstr("\x00\x55 abcdefg"), std::ios::binary);
126                 EXCEPTION_CHECK(SerializationError, deSerializeString(is));
127         }
128 }
129
130 void TestSerialization::testSerializeWideString()
131 {
132         // Test blank string
133         UASSERT(serializeWideString(L"") == mkstr("\0\0"));
134
135         // Test basic string
136         UASSERT(serializeWideString(utf8_to_wide("Hello world!")) ==
137                 mkstr("\0\14\0H\0e\0l\0l\0o\0 \0w\0o\0r\0l\0d\0!"));
138
139         // Test character range
140         UASSERT(serializeWideString(teststring2_w) ==
141                 mkstr("\1\0") + teststring2_w_encoded);
142 }
143
144 void TestSerialization::testDeSerializeWideString()
145 {
146         // Test deserialize
147         {
148                 std::istringstream is(serializeWideString(teststring2_w), std::ios::binary);
149                 UASSERT(deSerializeWideString(is) == teststring2_w);
150                 UASSERT(!is.eof());
151                 is.get();
152                 UASSERT(is.eof());
153         }
154
155         // Test deserialize an incomplete length specifier
156         {
157                 std::istringstream is(mkstr("\x53"), std::ios::binary);
158                 EXCEPTION_CHECK(SerializationError, deSerializeWideString(is));
159         }
160
161         // Test deserialize a string with an incomplete character
162         {
163                 std::istringstream is(mkstr("\x00\x07\0a\0b\0c\0d\0e\0f\0"), std::ios::binary);
164                 EXCEPTION_CHECK(SerializationError, deSerializeWideString(is));
165         }
166
167         // Test deserialize a string with incomplete data
168         {
169                 std::istringstream is(mkstr("\x00\x08\0a\0b\0c\0d\0e\0f"), std::ios::binary);
170                 EXCEPTION_CHECK(SerializationError, deSerializeWideString(is));
171         }
172 }
173
174 void TestSerialization::testSerializeLongString()
175 {
176         // Test blank string
177         UASSERT(serializeLongString("") == mkstr("\0\0\0\0"));
178
179         // Test basic string
180         UASSERT(serializeLongString("Hello world!") == mkstr("\0\0\0\14Hello world!"));
181
182         // Test character range
183         UASSERT(serializeLongString(teststring2) == mkstr("\0\0\1\0") + teststring2);
184 }
185
186 void TestSerialization::testDeSerializeLongString()
187 {
188         // Test deserialize
189         {
190                 std::istringstream is(serializeLongString(teststring2), std::ios::binary);
191                 UASSERT(deSerializeLongString(is) == teststring2);
192                 UASSERT(!is.eof());
193                 is.get();
194                 UASSERT(is.eof());
195         }
196
197         // Test deserialize an incomplete length specifier
198         {
199                 std::istringstream is(mkstr("\x53"), std::ios::binary);
200                 EXCEPTION_CHECK(SerializationError, deSerializeLongString(is));
201         }
202
203         // Test deserialize a string with incomplete data
204         {
205                 std::istringstream is(mkstr("\x00\x00\x00\x05 abc"), std::ios::binary);
206                 EXCEPTION_CHECK(SerializationError, deSerializeLongString(is));
207         }
208
209         // Test deserialize a string with a length too large
210         {
211                 std::istringstream is(mkstr("\xFF\xFF\xFF\xFF blah"), std::ios::binary);
212                 EXCEPTION_CHECK(SerializationError, deSerializeLongString(is));
213         }
214 }
215
216
217 void TestSerialization::testSerializeJsonString()
218 {
219         // Test blank string
220         UASSERT(serializeJsonString("") == "\"\"");
221
222         // Test basic string
223         UASSERT(serializeJsonString("Hello world!") == "\"Hello world!\"");
224
225         // MSVC fails when directly using "\\\\"
226         std::string backslash = "\\";
227         UASSERT(serializeJsonString(teststring2) ==
228                 mkstr("\"") +
229                 "\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007" +
230                 "\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f" +
231                 "\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017" +
232                 "\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f" +
233                 " !\\\"" + teststring2.substr(0x23, 0x2f-0x23) +
234                 "\\/" + teststring2.substr(0x30, 0x5c-0x30) +
235                 backslash + backslash + teststring2.substr(0x5d, 0x7f-0x5d) + "\\u007f" +
236                 "\\u0080\\u0081\\u0082\\u0083\\u0084\\u0085\\u0086\\u0087" +
237                 "\\u0088\\u0089\\u008a\\u008b\\u008c\\u008d\\u008e\\u008f" +
238                 "\\u0090\\u0091\\u0092\\u0093\\u0094\\u0095\\u0096\\u0097" +
239                 "\\u0098\\u0099\\u009a\\u009b\\u009c\\u009d\\u009e\\u009f" +
240                 "\\u00a0\\u00a1\\u00a2\\u00a3\\u00a4\\u00a5\\u00a6\\u00a7" +
241                 "\\u00a8\\u00a9\\u00aa\\u00ab\\u00ac\\u00ad\\u00ae\\u00af" +
242                 "\\u00b0\\u00b1\\u00b2\\u00b3\\u00b4\\u00b5\\u00b6\\u00b7" +
243                 "\\u00b8\\u00b9\\u00ba\\u00bb\\u00bc\\u00bd\\u00be\\u00bf" +
244                 "\\u00c0\\u00c1\\u00c2\\u00c3\\u00c4\\u00c5\\u00c6\\u00c7" +
245                 "\\u00c8\\u00c9\\u00ca\\u00cb\\u00cc\\u00cd\\u00ce\\u00cf" +
246                 "\\u00d0\\u00d1\\u00d2\\u00d3\\u00d4\\u00d5\\u00d6\\u00d7" +
247                 "\\u00d8\\u00d9\\u00da\\u00db\\u00dc\\u00dd\\u00de\\u00df" +
248                 "\\u00e0\\u00e1\\u00e2\\u00e3\\u00e4\\u00e5\\u00e6\\u00e7" +
249                 "\\u00e8\\u00e9\\u00ea\\u00eb\\u00ec\\u00ed\\u00ee\\u00ef" +
250                 "\\u00f0\\u00f1\\u00f2\\u00f3\\u00f4\\u00f5\\u00f6\\u00f7" +
251                 "\\u00f8\\u00f9\\u00fa\\u00fb\\u00fc\\u00fd\\u00fe\\u00ff" +
252                 "\"");
253
254         // Test deserialize
255         std::istringstream is(serializeJsonString(teststring2), std::ios::binary);
256         UASSERT(deSerializeJsonString(is) == teststring2);
257         UASSERT(!is.eof());
258         is.get();
259         UASSERT(is.eof());
260 }
261
262 void TestSerialization::testSerializeHex()
263 {
264         // Test blank string
265         UASSERT(serializeHexString("") == "");
266         UASSERT(serializeHexString("", true) == "");
267
268         // Test basic string
269         UASSERT(serializeHexString("Hello world!") ==
270                 "48656c6c6f20776f726c6421");
271         UASSERT(serializeHexString("Hello world!", true) ==
272                 "48 65 6c 6c 6f 20 77 6f 72 6c 64 21");
273
274         // Test binary string
275         UASSERT(serializeHexString(mkstr("\x00\x0a\xb0\x63\x1f\x00\xff")) ==
276                 "000ab0631f00ff");
277         UASSERT(serializeHexString(mkstr("\x00\x0a\xb0\x63\x1f\x00\xff"), true) ==
278                 "00 0a b0 63 1f 00 ff");
279 }
280
281
282 void TestSerialization::testStreamRead()
283 {
284         std::string datastr(
285                 (const char *)test_serialized_data,
286                 sizeof(test_serialized_data));
287         std::istringstream is(datastr, std::ios_base::binary);
288
289         UASSERT(readU8(is) == 0x11);
290         UASSERT(readU16(is) == 0x2233);
291         UASSERT(readU32(is) == 0x44556677);
292         UASSERT(readU64(is) == 0x8899AABBCCDDEEFF);
293
294         UASSERT(readS8(is) == -128);
295         UASSERT(readS16(is) == 30000);
296         UASSERT(readS32(is) == -6);
297         UASSERT(readS64(is) == -43);
298
299         UASSERT(fabs(readF1000(is) - 53.534f) < 0.005);
300         UASSERT(fabs(readF1000(is) - -300000.32f) < 0.05);
301         UASSERT(fabs(readF1000(is) - -2147483.f) < 0.05);
302         UASSERT(fabs(readF1000(is) - 2147483.f) < 0.05);
303
304         UASSERT(deSerializeString(is) == "foobar!");
305
306         UASSERT(readV2S16(is) == v2s16(500, 500));
307         UASSERT(readV3S16(is) == v3s16(4207, 604, -30));
308         UASSERT(readV2S32(is) == v2s32(1920, 1080));
309         UASSERT(readV3S32(is) == v3s32(-400, 6400054, 290549855));
310
311         v2f vec2 = readV2F1000(is);
312         UASSERT(fabs(vec2.X - 500.656f) < 0.005);
313         UASSERT(fabs(vec2.Y - 350.345f) < 0.005);
314
315         UASSERT(deSerializeWideString(is) == L"\x02~woof~\x5455");
316
317         v3f vec3 = readV3F1000(is);
318         UASSERT(fabs(vec3.X - 500.f) < 0.005);
319         UASSERT(fabs(vec3.Y - 10024.2f) < 0.005);
320         UASSERT(fabs(vec3.Z - -192.54f) < 0.005);
321
322         UASSERT(readARGB8(is) == video::SColor(255, 128, 50, 128));
323
324         UASSERT(deSerializeLongString(is) == "some longer string here");
325
326         UASSERT(is.rdbuf()->in_avail() == 2);
327         UASSERT(readU16(is) == 0xF00D);
328         UASSERT(is.rdbuf()->in_avail() == 0);
329 }
330
331
332 void TestSerialization::testStreamWrite()
333 {
334         std::ostringstream os(std::ios_base::binary);
335         std::string data;
336
337         writeU8(os, 0x11);
338         writeU16(os, 0x2233);
339         writeU32(os, 0x44556677);
340         writeU64(os, 0x8899AABBCCDDEEFF);
341
342         writeS8(os, -128);
343         writeS16(os, 30000);
344         writeS32(os, -6);
345         writeS64(os, -43);
346
347         writeF1000(os, 53.53467f);
348         writeF1000(os, -300000.32f);
349         writeF1000(os, -2147483.f);
350         writeF1000(os, 2147483.f);
351
352         os << serializeString("foobar!");
353
354         data = os.str();
355         UASSERT(data.size() < sizeof(test_serialized_data));
356         UASSERT(!memcmp(&data[0], test_serialized_data, data.size()));
357
358         writeV2S16(os, v2s16(500, 500));
359         writeV3S16(os, v3s16(4207, 604, -30));
360         writeV2S32(os, v2s32(1920, 1080));
361         writeV3S32(os, v3s32(-400, 6400054, 290549855));
362         writeV2F1000(os, v2f(500.65661f, 350.34567f));
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 const u8 TestSerialization::test_serialized_data[12 * 13] = {
380         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc,
381         0xdd, 0xee, 0xff, 0x80, 0x75, 0x30, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xff,
382         0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x00, 0x00, 0xd1, 0x1e, 0xee, 0x1e,
383         0x5b, 0xc0, 0x80, 0x00, 0x02, 0x80, 0x7F, 0xFF, 0xFD, 0x80, 0x00, 0x07,
384         0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x21, 0x01, 0xf4, 0x01, 0xf4, 0x10,
385         0x6f, 0x02, 0x5c, 0xff, 0xe2, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x04,
386         0x38, 0xff, 0xff, 0xfe, 0x70, 0x00, 0x61, 0xa8, 0x36, 0x11, 0x51, 0x70,
387         0x5f, 0x00, 0x07, 0xa3, 0xb0, 0x00, 0x05, 0x58, 0x89, 0x00, 0x08, 0x00,
388         0x02, 0x00, 0x7e, 0x00, 0x77, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x66, 0x00,
389         0x7e, 0x54, 0x55, 0x00, 0x07, 0xa1, 0x20, 0x00, 0x98, 0xf5, 0x08, 0xff,
390         0xfd, 0x0f, 0xe4, 0xff, 0x80, 0x32, 0x80, 0x00, 0x00, 0x00, 0x17, 0x73,
391         0x6f, 0x6d, 0x65, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x73,
392         0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x65, 0x72, 0x65, 0xF0, 0x0D,
393 };