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.
22 #include "util/numeric.h"
23 #include "util/string.h"
25 class TestUtilities : public TestBase {
27 TestUtilities() { TestManager::registerTestModule(this); }
28 const char *getName() { return "TestUtilities"; }
30 void runTests(IGameDef *gamedef);
32 void testAngleWrapAround();
36 void testRemoveStringEnd();
40 void testStartsWith();
42 void testStringTrim();
43 void testStrToIntConversion();
44 void testStringReplace();
45 void testStringAllowed();
46 void testAsciiPrintableHelper();
48 void testRemoveEscapes();
51 void testIsPowerOfTwo();
55 static TestUtilities g_test_instance;
57 void TestUtilities::runTests(IGameDef *gamedef)
59 TEST(testAngleWrapAround);
63 TEST(testRemoveStringEnd);
70 TEST(testStrToIntConversion);
71 TEST(testStringReplace);
72 TEST(testStringAllowed);
73 TEST(testAsciiPrintableHelper);
75 TEST(testRemoveEscapes);
78 TEST(testIsPowerOfTwo);
82 ////////////////////////////////////////////////////////////////////////////////
84 inline float ref_WrapDegrees180(float f)
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);
95 inline float ref_WrapDegrees_0_360(float f)
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);
102 return value < 0 ? value + 360 : value;
106 void TestUtilities::testAngleWrapAround()
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);
113 for (float f = -720; f <= -360; f += 0.25) {
114 UASSERT(fabs(modulo360f(f) - modulo360f(f + 360)) < 0.001);
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);
126 void TestUtilities::testLowercase()
128 UASSERT(lowercase("Foo bAR") == "foo bar");
132 void TestUtilities::testTrim()
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 ") == "");
141 void TestUtilities::testIsYes()
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);
155 void TestUtilities::testRemoveStringEnd()
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) == "");
165 void TestUtilities::testUrlEncode()
167 UASSERT(urlencode("\"Aardvarks lurk, OK?\"")
168 == "%22Aardvarks%20lurk%2C%20OK%3F%22");
172 void TestUtilities::testUrlDecode()
174 UASSERT(urldecode("%22Aardvarks%20lurk%2C%20OK%3F%22")
175 == "\"Aardvarks lurk, OK?\"");
179 void TestUtilities::testPadString()
181 UASSERT(padStringRight("hello", 8) == "hello ");
184 void TestUtilities::testStartsWith()
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);
198 void TestUtilities::testStrEqual()
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));
205 void TestUtilities::testStringTrim()
207 UASSERT(trim(" a") == "a");
208 UASSERT(trim(" a ") == "a");
209 UASSERT(trim("a ") == "a");
210 UASSERT(trim("") == "");
214 void TestUtilities::testStrToIntConversion()
216 UASSERT(mystoi("123", 0, 1000) == 123);
217 UASSERT(mystoi("123", 0, 10) == 10);
221 void TestUtilities::testStringReplace()
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");
233 void TestUtilities::testStringAllowed()
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);
241 void TestUtilities::testAsciiPrintableHelper()
243 UASSERT(IS_ASCII_PRINTABLE_CHAR('e') == true);
244 UASSERT(IS_ASCII_PRINTABLE_CHAR('\0') == false);
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.
250 UASSERT(IS_ASCII_PRINTABLE_CHAR(ch) == false);
253 void TestUtilities::testUTF8()
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!");
260 void TestUtilities::testRemoveEscapes()
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");
277 void TestUtilities::testWrapRows()
279 UASSERT(wrap_rows("12345678",4) == "1234\n5678");
280 // test that wrap_rows doesn't wrap inside multibyte sequences
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>");
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>");
301 void TestUtilities::testIsNumber()
303 UASSERT(is_number("123") == true);
304 UASSERT(is_number("") == false);
305 UASSERT(is_number("123a") == false);
309 void TestUtilities::testIsPowerOfTwo()
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);
320 UASSERT(is_power_of_two(U32_MAX) == false);
323 void TestUtilities::testMyround()
325 UASSERT(myround(4.6f) == 5);
326 UASSERT(myround(1.2f) == 1);
327 UASSERT(myround(-3.1f) == -3);
328 UASSERT(myround(-6.5f) == -7);