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();
37 void testRemoveStringEnd();
41 void testStartsWith();
43 void testStringTrim();
44 void testStrToIntConversion();
45 void testStringReplace();
46 void testStringAllowed();
47 void testAsciiPrintableHelper();
49 void testRemoveEscapes();
52 void testIsPowerOfTwo();
56 static TestUtilities g_test_instance;
58 void TestUtilities::runTests(IGameDef *gamedef)
60 TEST(testAngleWrapAround);
64 TEST(testRemoveStringEnd);
71 TEST(testStrToIntConversion);
72 TEST(testStringReplace);
73 TEST(testStringAllowed);
74 TEST(testAsciiPrintableHelper);
76 TEST(testRemoveEscapes);
79 TEST(testIsPowerOfTwo);
83 ////////////////////////////////////////////////////////////////////////////////
85 inline float ref_WrapDegrees180(float f)
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);
96 inline float ref_WrapDegrees_0_360(float f)
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);
103 return value < 0 ? value + 360 : value;
107 void TestUtilities::testAngleWrapAround()
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);
114 for (float f = -720; f <= -360; f += 0.25) {
115 UASSERT(std::fabs(modulo360f(f) - modulo360f(f + 360)) < 0.001);
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);
127 void TestUtilities::testLowercase()
129 UASSERT(lowercase("Foo bAR") == "foo bar");
133 void TestUtilities::testTrim()
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 ") == "");
142 void TestUtilities::testIsYes()
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);
154 void TestUtilities::testRemoveStringEnd()
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) == "");
164 void TestUtilities::testUrlEncode()
166 UASSERT(urlencode("\"Aardvarks lurk, OK?\"")
167 == "%22Aardvarks%20lurk%2C%20OK%3F%22");
171 void TestUtilities::testUrlDecode()
173 UASSERT(urldecode("%22Aardvarks%20lurk%2C%20OK%3F%22")
174 == "\"Aardvarks lurk, OK?\"");
178 void TestUtilities::testPadString()
180 UASSERT(padStringRight("hello", 8) == "hello ");
183 void TestUtilities::testStartsWith()
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);
197 void TestUtilities::testStrEqual()
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));
204 void TestUtilities::testStringTrim()
206 UASSERT(trim(" a") == "a");
207 UASSERT(trim(" a ") == "a");
208 UASSERT(trim("a ") == "a");
209 UASSERT(trim("") == "");
213 void TestUtilities::testStrToIntConversion()
215 UASSERT(mystoi("123", 0, 1000) == 123);
216 UASSERT(mystoi("123", 0, 10) == 10);
220 void TestUtilities::testStringReplace()
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");
232 void TestUtilities::testStringAllowed()
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);
240 void TestUtilities::testAsciiPrintableHelper()
242 UASSERT(IS_ASCII_PRINTABLE_CHAR('e') == true);
243 UASSERT(IS_ASCII_PRINTABLE_CHAR('\0') == false);
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.
249 UASSERT(IS_ASCII_PRINTABLE_CHAR(ch) == false);
252 void TestUtilities::testUTF8()
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!");
259 void TestUtilities::testRemoveEscapes()
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");
276 void TestUtilities::testWrapRows()
278 UASSERT(wrap_rows("12345678",4) == "1234\n5678");
279 // test that wrap_rows doesn't wrap inside multibyte sequences
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>");
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>");
300 void TestUtilities::testIsNumber()
302 UASSERT(is_number("123") == true);
303 UASSERT(is_number("") == false);
304 UASSERT(is_number("123a") == false);
308 void TestUtilities::testIsPowerOfTwo()
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);
319 UASSERT(is_power_of_two(U32_MAX) == false);
322 void TestUtilities::testMyround()
324 UASSERT(myround(4.6f) == 5);
325 UASSERT(myround(1.2f) == 1);
326 UASSERT(myround(-3.1f) == -3);
327 UASSERT(myround(-6.5f) == -7);