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.
23 #include "util/numeric.h"
24 #include "util/string.h"
26 class TestUtilities : public TestBase {
28 TestUtilities() { TestManager::registerTestModule(this); }
29 const char *getName() { return "TestUtilities"; }
31 void runTests(IGameDef *gamedef);
33 void testAngleWrapAround();
34 void testWrapDegrees_0_360_v3f();
38 void testRemoveStringEnd();
42 void testStartsWith();
44 void testStringTrim();
45 void testStrToIntConversion();
46 void testStringReplace();
47 void testStringAllowed();
48 void testAsciiPrintableHelper();
50 void testRemoveEscapes();
53 void testIsPowerOfTwo();
55 void testStringJoin();
58 static TestUtilities g_test_instance;
60 void TestUtilities::runTests(IGameDef *gamedef)
62 TEST(testAngleWrapAround);
63 TEST(testWrapDegrees_0_360_v3f);
67 TEST(testRemoveStringEnd);
74 TEST(testStrToIntConversion);
75 TEST(testStringReplace);
76 TEST(testStringAllowed);
77 TEST(testAsciiPrintableHelper);
79 TEST(testRemoveEscapes);
82 TEST(testIsPowerOfTwo);
87 ////////////////////////////////////////////////////////////////////////////////
89 inline float ref_WrapDegrees180(float f)
91 // This is a slower alternative to the wrapDegrees_180() function;
92 // used as a reference for testing
93 float value = fmodf(f + 180, 360);
100 inline float ref_WrapDegrees_0_360(float f)
102 // This is a slower alternative to the wrapDegrees_0_360() function;
103 // used as a reference for testing
104 float value = fmodf(f, 360);
107 return value < 0 ? value + 360 : value;
111 void TestUtilities::testAngleWrapAround() {
112 UASSERT(fabs(modulo360f(100.0) - 100.0) < 0.001);
113 UASSERT(fabs(modulo360f(720.5) - 0.5) < 0.001);
114 UASSERT(fabs(modulo360f(-0.5) - (-0.5)) < 0.001);
115 UASSERT(fabs(modulo360f(-365.5) - (-5.5)) < 0.001);
117 for (float f = -720; f <= -360; f += 0.25) {
118 UASSERT(std::fabs(modulo360f(f) - modulo360f(f + 360)) < 0.001);
121 for (float f = -1440; f <= 1440; f += 0.25) {
122 UASSERT(std::fabs(modulo360f(f) - fmodf(f, 360)) < 0.001);
123 UASSERT(std::fabs(wrapDegrees_180(f) - ref_WrapDegrees180(f)) < 0.001);
124 UASSERT(std::fabs(wrapDegrees_0_360(f) - ref_WrapDegrees_0_360(f)) < 0.001);
125 UASSERT(wrapDegrees_0_360(
126 std::fabs(wrapDegrees_180(f) - wrapDegrees_0_360(f))) < 0.001);
131 void TestUtilities::testWrapDegrees_0_360_v3f()
133 // only x test with little step
134 for (float x = -720.f; x <= 720; x += 0.05) {
135 v3f r = wrapDegrees_0_360_v3f(v3f(x, 0, 0));
136 UASSERT(r.X >= 0.0f && r.X < 360.0f)
141 // only y test with little step
142 for (float y = -720.f; y <= 720; y += 0.05) {
143 v3f r = wrapDegrees_0_360_v3f(v3f(0, y, 0));
145 UASSERT(r.Y >= 0.0f && r.Y < 360.0f)
149 // only z test with little step
150 for (float z = -720.f; z <= 720; z += 0.05) {
151 v3f r = wrapDegrees_0_360_v3f(v3f(0, 0, z));
154 UASSERT(r.Z >= 0.0f && r.Z < 360.0f)
157 // test the whole coordinate translation
158 for (float x = -720.f; x <= 720; x += 2.5) {
159 for (float y = -720.f; y <= 720; y += 2.5) {
160 for (float z = -720.f; z <= 720; z += 2.5) {
161 v3f r = wrapDegrees_0_360_v3f(v3f(x, y, z));
162 UASSERT(r.X >= 0.0f && r.X < 360.0f)
163 UASSERT(r.Y >= 0.0f && r.Y < 360.0f)
164 UASSERT(r.Z >= 0.0f && r.Z < 360.0f)
171 void TestUtilities::testLowercase()
173 UASSERT(lowercase("Foo bAR") == "foo bar");
174 UASSERT(lowercase("eeeeeeaaaaaaaaaaaààààà") == "eeeeeeaaaaaaaaaaaààààà");
175 UASSERT(lowercase("MINETEST-powa") == "minetest-powa");
179 void TestUtilities::testTrim()
181 UASSERT(trim("") == "");
182 UASSERT(trim("dirt_with_grass") == "dirt_with_grass");
183 UASSERT(trim("\n \t\r Foo bAR \r\n\t\t ") == "Foo bAR");
184 UASSERT(trim("\n \t\r \r\n\t\t ") == "");
188 void TestUtilities::testIsYes()
190 UASSERT(is_yes("YeS") == true);
191 UASSERT(is_yes("") == false);
192 UASSERT(is_yes("FAlse") == false);
193 UASSERT(is_yes("-1") == true);
194 UASSERT(is_yes("0") == false);
195 UASSERT(is_yes("1") == true);
196 UASSERT(is_yes("2") == true);
200 void TestUtilities::testRemoveStringEnd()
202 const char *ends[] = {"abc", "c", "bc", "", NULL};
203 UASSERT(removeStringEnd("abc", ends) == "");
204 UASSERT(removeStringEnd("bc", ends) == "b");
205 UASSERT(removeStringEnd("12c", ends) == "12");
206 UASSERT(removeStringEnd("foo", ends) == "");
210 void TestUtilities::testUrlEncode()
212 UASSERT(urlencode("\"Aardvarks lurk, OK?\"")
213 == "%22Aardvarks%20lurk%2C%20OK%3F%22");
217 void TestUtilities::testUrlDecode()
219 UASSERT(urldecode("%22Aardvarks%20lurk%2C%20OK%3F%22")
220 == "\"Aardvarks lurk, OK?\"");
224 void TestUtilities::testPadString()
226 UASSERT(padStringRight("hello", 8) == "hello ");
229 void TestUtilities::testStartsWith()
231 UASSERT(str_starts_with(std::string(), std::string()) == true);
232 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
233 std::string()) == true);
234 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
235 std::string("the")) == true);
236 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
237 std::string("The")) == false);
238 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
239 std::string("The"), true) == true);
240 UASSERT(str_starts_with(std::string("T"), std::string("The")) == false);
243 void TestUtilities::testStrEqual()
245 UASSERT(str_equal(narrow_to_wide("abc"), narrow_to_wide("abc")));
246 UASSERT(str_equal(narrow_to_wide("ABC"), narrow_to_wide("abc"), true));
250 void TestUtilities::testStringTrim()
252 UASSERT(trim(" a") == "a");
253 UASSERT(trim(" a ") == "a");
254 UASSERT(trim("a ") == "a");
255 UASSERT(trim("") == "");
259 void TestUtilities::testStrToIntConversion()
261 UASSERT(mystoi("123", 0, 1000) == 123);
262 UASSERT(mystoi("123", 0, 10) == 10);
266 void TestUtilities::testStringReplace()
268 std::string test_str;
269 test_str = "Hello there";
270 str_replace(test_str, "there", "world");
271 UASSERT(test_str == "Hello world");
272 test_str = "ThisAisAaAtest";
273 str_replace(test_str, 'A', ' ');
274 UASSERT(test_str == "This is a test");
278 void TestUtilities::testStringAllowed()
280 UASSERT(string_allowed("hello", "abcdefghijklmno") == true);
281 UASSERT(string_allowed("123", "abcdefghijklmno") == false);
282 UASSERT(string_allowed_blacklist("hello", "123") == true);
283 UASSERT(string_allowed_blacklist("hello123", "123") == false);
286 void TestUtilities::testAsciiPrintableHelper()
288 UASSERT(IS_ASCII_PRINTABLE_CHAR('e') == true);
289 UASSERT(IS_ASCII_PRINTABLE_CHAR('\0') == false);
291 // Ensures that there is no cutting off going on...
292 // If there were, 331 would be cut to 75 in this example
293 // and 73 is a valid ASCII char.
295 UASSERT(IS_ASCII_PRINTABLE_CHAR(ch) == false);
298 void TestUtilities::testUTF8()
300 UASSERT(wide_to_utf8(utf8_to_wide("")) == "");
301 UASSERT(wide_to_utf8(utf8_to_wide("the shovel dug a crumbly node!"))
302 == "the shovel dug a crumbly node!");
305 void TestUtilities::testRemoveEscapes()
307 UASSERT(unescape_enriched<wchar_t>(
308 L"abc\x1bXdef") == L"abcdef");
309 UASSERT(unescape_enriched<wchar_t>(
310 L"abc\x1b(escaped)def") == L"abcdef");
311 UASSERT(unescape_enriched<wchar_t>(
312 L"abc\x1b((escaped with parenthesis\\))def") == L"abcdef");
313 UASSERT(unescape_enriched<wchar_t>(
314 L"abc\x1b(incomplete") == L"abc");
315 UASSERT(unescape_enriched<wchar_t>(
316 L"escape at the end\x1b") == L"escape at the end");
317 // Nested escapes not supported
318 UASSERT(unescape_enriched<wchar_t>(
319 L"abc\x1b(outer \x1b(inner escape)escape)def") == L"abcescape)def");
322 void TestUtilities::testWrapRows()
324 UASSERT(wrap_rows("12345678",4) == "1234\n5678");
325 // test that wrap_rows doesn't wrap inside multibyte sequences
327 const unsigned char s[] = {
328 0x2f, 0x68, 0x6f, 0x6d, 0x65, 0x2f, 0x72, 0x61, 0x70, 0x74, 0x6f,
329 0x72, 0x2f, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0x2f,
330 0x6d, 0x69, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x62, 0x69,
331 0x6e, 0x2f, 0x2e, 0x2e, 0};
332 std::string str((char *)s);
333 UASSERT(utf8_to_wide(wrap_rows(str, 20)) != L"<invalid UTF-8 string>");
336 const unsigned char s[] = {
337 0x74, 0x65, 0x73, 0x74, 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81,
338 0xd1, 0x82, 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82,
339 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0};
340 std::string str((char *)s);
341 UASSERT(utf8_to_wide(wrap_rows(str, 8)) != L"<invalid UTF-8 string>");
346 void TestUtilities::testIsNumber()
348 UASSERT(is_number("123") == true);
349 UASSERT(is_number("") == false);
350 UASSERT(is_number("123a") == false);
354 void TestUtilities::testIsPowerOfTwo()
356 UASSERT(is_power_of_two(0) == false);
357 UASSERT(is_power_of_two(1) == true);
358 UASSERT(is_power_of_two(2) == true);
359 UASSERT(is_power_of_two(3) == false);
360 for (int exponent = 2; exponent <= 31; ++exponent) {
361 UASSERT(is_power_of_two((1 << exponent) - 1) == false);
362 UASSERT(is_power_of_two((1 << exponent)) == true);
363 UASSERT(is_power_of_two((1 << exponent) + 1) == false);
365 UASSERT(is_power_of_two(U32_MAX) == false);
368 void TestUtilities::testMyround()
370 UASSERT(myround(4.6f) == 5);
371 UASSERT(myround(1.2f) == 1);
372 UASSERT(myround(-3.1f) == -3);
373 UASSERT(myround(-6.5f) == -7);
376 void TestUtilities::testStringJoin()
378 std::vector<std::string> input;
379 UASSERT(str_join(input, ",") == "");
381 input.emplace_back("one");
382 UASSERT(str_join(input, ",") == "one");
384 input.emplace_back("two");
385 UASSERT(str_join(input, ",") == "one,two");
387 input.emplace_back("three");
388 UASSERT(str_join(input, ",") == "one,two,three");
391 UASSERT(str_join(input, ",") == "one,,three");
394 UASSERT(str_join(input, " and ") == "one and two and three");