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