]> git.lizzy.rs Git - minetest.git/blob - src/unittest/test_utilities.cpp
Extend minetest.is_yes()
[minetest.git] / src / unittest / test_utilities.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/numeric.h"
23 #include "util/string.h"
24
25 class TestUtilities : public TestBase {
26 public:
27         TestUtilities() { TestManager::registerTestModule(this); }
28         const char *getName() { return "TestUtilities"; }
29
30         void runTests(IGameDef *gamedef);
31
32         void testAngleWrapAround();
33         void testLowercase();
34         void testTrim();
35         void testIsYes();
36         void testRemoveStringEnd();
37         void testUrlEncode();
38         void testUrlDecode();
39         void testPadString();
40         void testStartsWith();
41         void testStrEqual();
42         void testStringTrim();
43         void testStrToIntConversion();
44         void testStringReplace();
45         void testStringAllowed();
46         void testAsciiPrintableHelper();
47         void testUTF8();
48         void testRemoveEscapes();
49         void testWrapRows();
50         void testIsNumber();
51         void testIsPowerOfTwo();
52         void testMyround();
53 };
54
55 static TestUtilities g_test_instance;
56
57 void TestUtilities::runTests(IGameDef *gamedef)
58 {
59         TEST(testAngleWrapAround);
60         TEST(testLowercase);
61         TEST(testTrim);
62         TEST(testIsYes);
63         TEST(testRemoveStringEnd);
64         TEST(testUrlEncode);
65         TEST(testUrlDecode);
66         TEST(testPadString);
67         TEST(testStartsWith);
68         TEST(testStrEqual);
69         TEST(testStringTrim);
70         TEST(testStrToIntConversion);
71         TEST(testStringReplace);
72         TEST(testStringAllowed);
73         TEST(testAsciiPrintableHelper);
74         TEST(testUTF8);
75         TEST(testRemoveEscapes);
76         TEST(testWrapRows);
77         TEST(testIsNumber);
78         TEST(testIsPowerOfTwo);
79         TEST(testMyround);
80 }
81
82 ////////////////////////////////////////////////////////////////////////////////
83
84 inline float ref_WrapDegrees180(float f)
85 {
86         // This is a slower alternative to the wrapDegrees_180() function;
87         // used as a reference for testing
88         float value = fmodf(f + 180, 360);
89         if (value < 0)
90                 value += 360;
91         return value - 180;
92 }
93
94
95 inline float ref_WrapDegrees_0_360(float f)
96 {
97         // This is a slower alternative to the wrapDegrees_0_360() function;
98         // used as a reference for testing
99         float value = fmodf(f, 360);
100         if (value < 0)
101                 value += 360;
102         return value < 0 ? value + 360 : value;
103 }
104
105
106 void TestUtilities::testAngleWrapAround()
107 {
108         UASSERT(fabs(modulo360f(100.0) - 100.0) < 0.001);
109         UASSERT(fabs(modulo360f(720.5) - 0.5) < 0.001);
110         UASSERT(fabs(modulo360f(-0.5) - (-0.5)) < 0.001);
111         UASSERT(fabs(modulo360f(-365.5) - (-5.5)) < 0.001);
112
113         for (float f = -720; f <= -360; f += 0.25) {
114                 UASSERT(fabs(modulo360f(f) - modulo360f(f + 360)) < 0.001);
115         }
116
117         for (float f = -1440; f <= 1440; f += 0.25) {
118                 UASSERT(fabs(modulo360f(f) - fmodf(f, 360)) < 0.001);
119                 UASSERT(fabs(wrapDegrees_180(f) - ref_WrapDegrees180(f)) < 0.001);
120                 UASSERT(fabs(wrapDegrees_0_360(f) - ref_WrapDegrees_0_360(f)) < 0.001);
121                 UASSERT(wrapDegrees_0_360(fabs(wrapDegrees_180(f) - wrapDegrees_0_360(f))) < 0.001);
122         }
123 }
124
125
126 void TestUtilities::testLowercase()
127 {
128         UASSERT(lowercase("Foo bAR") == "foo bar");
129 }
130
131
132 void TestUtilities::testTrim()
133 {
134         UASSERT(trim("") == "");
135         UASSERT(trim("dirt_with_grass") == "dirt_with_grass");
136         UASSERT(trim("\n \t\r  Foo bAR  \r\n\t\t  ") == "Foo bAR");
137         UASSERT(trim("\n \t\r    \r\n\t\t  ") == "");
138 }
139
140
141 void TestUtilities::testIsYes()
142 {
143         UASSERT(is_yes("YeS") == true);
144         UASSERT(is_yes("") == false);
145         UASSERT(is_yes("FAlse") == false);
146         UASSERT(is_yes("-1") == true);
147         UASSERT(is_yes("0") == false);
148         UASSERT(is_yes("1") == true);
149         UASSERT(is_yes("2") == true);
150         UASSERT(is_yes("on") == true);
151         UASSERT(is_yes("off") == false);
152 }
153
154
155 void TestUtilities::testRemoveStringEnd()
156 {
157         const char *ends[] = {"abc", "c", "bc", "", NULL};
158         UASSERT(removeStringEnd("abc", ends) == "");
159         UASSERT(removeStringEnd("bc", ends) == "b");
160         UASSERT(removeStringEnd("12c", ends) == "12");
161         UASSERT(removeStringEnd("foo", ends) == "");
162 }
163
164
165 void TestUtilities::testUrlEncode()
166 {
167         UASSERT(urlencode("\"Aardvarks lurk, OK?\"")
168                         == "%22Aardvarks%20lurk%2C%20OK%3F%22");
169 }
170
171
172 void TestUtilities::testUrlDecode()
173 {
174         UASSERT(urldecode("%22Aardvarks%20lurk%2C%20OK%3F%22")
175                         == "\"Aardvarks lurk, OK?\"");
176 }
177
178
179 void TestUtilities::testPadString()
180 {
181         UASSERT(padStringRight("hello", 8) == "hello   ");
182 }
183
184 void TestUtilities::testStartsWith()
185 {
186         UASSERT(str_starts_with(std::string(), std::string()) == true);
187         UASSERT(str_starts_with(std::string("the sharp pickaxe"),
188                 std::string()) == true);
189         UASSERT(str_starts_with(std::string("the sharp pickaxe"),
190                 std::string("the")) == true);
191         UASSERT(str_starts_with(std::string("the sharp pickaxe"),
192                 std::string("The")) == false);
193         UASSERT(str_starts_with(std::string("the sharp pickaxe"),
194                 std::string("The"), true) == true);
195         UASSERT(str_starts_with(std::string("T"), std::string("The")) == false);
196 }
197
198 void TestUtilities::testStrEqual()
199 {
200         UASSERT(str_equal(narrow_to_wide("abc"), narrow_to_wide("abc")));
201         UASSERT(str_equal(narrow_to_wide("ABC"), narrow_to_wide("abc"), true));
202 }
203
204
205 void TestUtilities::testStringTrim()
206 {
207         UASSERT(trim("  a") == "a");
208         UASSERT(trim("   a  ") == "a");
209         UASSERT(trim("a   ") == "a");
210         UASSERT(trim("") == "");
211 }
212
213
214 void TestUtilities::testStrToIntConversion()
215 {
216         UASSERT(mystoi("123", 0, 1000) == 123);
217         UASSERT(mystoi("123", 0, 10) == 10);
218 }
219
220
221 void TestUtilities::testStringReplace()
222 {
223         std::string test_str;
224         test_str = "Hello there";
225         str_replace(test_str, "there", "world");
226         UASSERT(test_str == "Hello world");
227         test_str = "ThisAisAaAtest";
228         str_replace(test_str, 'A', ' ');
229         UASSERT(test_str == "This is a test");
230 }
231
232
233 void TestUtilities::testStringAllowed()
234 {
235         UASSERT(string_allowed("hello", "abcdefghijklmno") == true);
236         UASSERT(string_allowed("123", "abcdefghijklmno") == false);
237         UASSERT(string_allowed_blacklist("hello", "123") == true);
238         UASSERT(string_allowed_blacklist("hello123", "123") == false);
239 }
240
241 void TestUtilities::testAsciiPrintableHelper()
242 {
243         UASSERT(IS_ASCII_PRINTABLE_CHAR('e') == true);
244         UASSERT(IS_ASCII_PRINTABLE_CHAR('\0') == false);
245
246         // Ensures that there is no cutting off going on...
247         // If there were, 331 would be cut to 75 in this example
248         // and 73 is a valid ASCII char.
249         int ch = 331;
250         UASSERT(IS_ASCII_PRINTABLE_CHAR(ch) == false);
251 }
252
253 void TestUtilities::testUTF8()
254 {
255         UASSERT(wide_to_utf8(utf8_to_wide("")) == "");
256         UASSERT(wide_to_utf8(utf8_to_wide("the shovel dug a crumbly node!"))
257                 == "the shovel dug a crumbly node!");
258 }
259
260 void TestUtilities::testRemoveEscapes()
261 {
262         UASSERT(unescape_enriched<wchar_t>(
263                 L"abc\x1bXdef") == L"abcdef");
264         UASSERT(unescape_enriched<wchar_t>(
265                 L"abc\x1b(escaped)def") == L"abcdef");
266         UASSERT(unescape_enriched<wchar_t>(
267                 L"abc\x1b((escaped with parenthesis\\))def") == L"abcdef");
268         UASSERT(unescape_enriched<wchar_t>(
269                 L"abc\x1b(incomplete") == L"abc");
270         UASSERT(unescape_enriched<wchar_t>(
271                 L"escape at the end\x1b") == L"escape at the end");
272         // Nested escapes not supported
273         UASSERT(unescape_enriched<wchar_t>(
274                 L"abc\x1b(outer \x1b(inner escape)escape)def") == L"abcescape)def");
275 }
276
277 void TestUtilities::testWrapRows()
278 {
279         UASSERT(wrap_rows("12345678",4) == "1234\n5678");
280         // test that wrap_rows doesn't wrap inside multibyte sequences
281         {
282                 const unsigned char s[] = {
283                         0x2f, 0x68, 0x6f, 0x6d, 0x65, 0x2f, 0x72, 0x61, 0x70, 0x74, 0x6f,
284                         0x72, 0x2f, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0x2f,
285                         0x6d, 0x69, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x62, 0x69,
286                         0x6e, 0x2f, 0x2e, 0x2e, 0};
287                 std::string str((char *)s);
288                 UASSERT(utf8_to_wide(wrap_rows(str, 20)) != L"<invalid UTF-8 string>");
289         };
290         {
291                 const unsigned char s[] = {
292                         0x74, 0x65, 0x73, 0x74, 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81,
293                         0xd1, 0x82, 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82,
294                         0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0};
295                 std::string str((char *)s);
296                 UASSERT(utf8_to_wide(wrap_rows(str, 8)) != L"<invalid UTF-8 string>");
297         }
298 }
299
300
301 void TestUtilities::testIsNumber()
302 {
303         UASSERT(is_number("123") == true);
304         UASSERT(is_number("") == false);
305         UASSERT(is_number("123a") == false);
306 }
307
308
309 void TestUtilities::testIsPowerOfTwo()
310 {
311         UASSERT(is_power_of_two(0) == false);
312         UASSERT(is_power_of_two(1) == true);
313         UASSERT(is_power_of_two(2) == true);
314         UASSERT(is_power_of_two(3) == false);
315         for (int exponent = 2; exponent <= 31; ++exponent) {
316                 UASSERT(is_power_of_two((1 << exponent) - 1) == false);
317                 UASSERT(is_power_of_two((1 << exponent)) == true);
318                 UASSERT(is_power_of_two((1 << exponent) + 1) == false);
319         }
320         UASSERT(is_power_of_two(U32_MAX) == false);
321 }
322
323 void TestUtilities::testMyround()
324 {
325         UASSERT(myround(4.6f) == 5);
326         UASSERT(myround(1.2f) == 1);
327         UASSERT(myround(-3.1f) == -3);
328         UASSERT(myround(-6.5f) == -7);
329 }
330