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);
153 void TestUtilities::testRemoveStringEnd()
155 const char *ends[] = {"abc", "c", "bc", "", NULL};
156 UASSERT(removeStringEnd("abc", ends) == "");
157 UASSERT(removeStringEnd("bc", ends) == "b");
158 UASSERT(removeStringEnd("12c", ends) == "12");
159 UASSERT(removeStringEnd("foo", ends) == "");
163 void TestUtilities::testUrlEncode()
165 UASSERT(urlencode("\"Aardvarks lurk, OK?\"")
166 == "%22Aardvarks%20lurk%2C%20OK%3F%22");
170 void TestUtilities::testUrlDecode()
172 UASSERT(urldecode("%22Aardvarks%20lurk%2C%20OK%3F%22")
173 == "\"Aardvarks lurk, OK?\"");
177 void TestUtilities::testPadString()
179 UASSERT(padStringRight("hello", 8) == "hello ");
182 void TestUtilities::testStartsWith()
184 UASSERT(str_starts_with(std::string(), std::string()) == true);
185 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
186 std::string()) == true);
187 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
188 std::string("the")) == true);
189 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
190 std::string("The")) == false);
191 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
192 std::string("The"), true) == true);
193 UASSERT(str_starts_with(std::string("T"), std::string("The")) == false);
196 void TestUtilities::testStrEqual()
198 UASSERT(str_equal(narrow_to_wide("abc"), narrow_to_wide("abc")));
199 UASSERT(str_equal(narrow_to_wide("ABC"), narrow_to_wide("abc"), true));
203 void TestUtilities::testStringTrim()
205 UASSERT(trim(" a") == "a");
206 UASSERT(trim(" a ") == "a");
207 UASSERT(trim("a ") == "a");
208 UASSERT(trim("") == "");
212 void TestUtilities::testStrToIntConversion()
214 UASSERT(mystoi("123", 0, 1000) == 123);
215 UASSERT(mystoi("123", 0, 10) == 10);
219 void TestUtilities::testStringReplace()
221 std::string test_str;
222 test_str = "Hello there";
223 str_replace(test_str, "there", "world");
224 UASSERT(test_str == "Hello world");
225 test_str = "ThisAisAaAtest";
226 str_replace(test_str, 'A', ' ');
227 UASSERT(test_str == "This is a test");
231 void TestUtilities::testStringAllowed()
233 UASSERT(string_allowed("hello", "abcdefghijklmno") == true);
234 UASSERT(string_allowed("123", "abcdefghijklmno") == false);
235 UASSERT(string_allowed_blacklist("hello", "123") == true);
236 UASSERT(string_allowed_blacklist("hello123", "123") == false);
239 void TestUtilities::testAsciiPrintableHelper()
241 UASSERT(IS_ASCII_PRINTABLE_CHAR('e') == true);
242 UASSERT(IS_ASCII_PRINTABLE_CHAR('\0') == false);
244 // Ensures that there is no cutting off going on...
245 // If there were, 331 would be cut to 75 in this example
246 // and 73 is a valid ASCII char.
248 UASSERT(IS_ASCII_PRINTABLE_CHAR(ch) == false);
251 void TestUtilities::testUTF8()
253 UASSERT(wide_to_utf8(utf8_to_wide("")) == "");
254 UASSERT(wide_to_utf8(utf8_to_wide("the shovel dug a crumbly node!"))
255 == "the shovel dug a crumbly node!");
258 void TestUtilities::testRemoveEscapes()
260 UASSERT(unescape_enriched<wchar_t>(
261 L"abc\x1bXdef") == L"abcdef");
262 UASSERT(unescape_enriched<wchar_t>(
263 L"abc\x1b(escaped)def") == L"abcdef");
264 UASSERT(unescape_enriched<wchar_t>(
265 L"abc\x1b((escaped with parenthesis\\))def") == L"abcdef");
266 UASSERT(unescape_enriched<wchar_t>(
267 L"abc\x1b(incomplete") == L"abc");
268 UASSERT(unescape_enriched<wchar_t>(
269 L"escape at the end\x1b") == L"escape at the end");
270 // Nested escapes not supported
271 UASSERT(unescape_enriched<wchar_t>(
272 L"abc\x1b(outer \x1b(inner escape)escape)def") == L"abcescape)def");
275 void TestUtilities::testWrapRows()
277 UASSERT(wrap_rows("12345678",4) == "1234\n5678");
278 // test that wrap_rows doesn't wrap inside multibyte sequences
280 const unsigned char s[] = {
281 0x2f, 0x68, 0x6f, 0x6d, 0x65, 0x2f, 0x72, 0x61, 0x70, 0x74, 0x6f,
282 0x72, 0x2f, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0x2f,
283 0x6d, 0x69, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x62, 0x69,
284 0x6e, 0x2f, 0x2e, 0x2e, 0};
285 std::string str((char *)s);
286 UASSERT(utf8_to_wide(wrap_rows(str, 20)) != L"<invalid UTF-8 string>");
289 const unsigned char s[] = {
290 0x74, 0x65, 0x73, 0x74, 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81,
291 0xd1, 0x82, 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82,
292 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0};
293 std::string str((char *)s);
294 UASSERT(utf8_to_wide(wrap_rows(str, 8)) != L"<invalid UTF-8 string>");
299 void TestUtilities::testIsNumber()
301 UASSERT(is_number("123") == true);
302 UASSERT(is_number("") == false);
303 UASSERT(is_number("123a") == false);
307 void TestUtilities::testIsPowerOfTwo()
309 UASSERT(is_power_of_two(0) == false);
310 UASSERT(is_power_of_two(1) == true);
311 UASSERT(is_power_of_two(2) == true);
312 UASSERT(is_power_of_two(3) == false);
313 for (int exponent = 2; exponent <= 31; ++exponent) {
314 UASSERT(is_power_of_two((1 << exponent) - 1) == false);
315 UASSERT(is_power_of_two((1 << exponent)) == true);
316 UASSERT(is_power_of_two((1 << exponent) + 1) == false);
318 UASSERT(is_power_of_two(U32_MAX) == false);
321 void TestUtilities::testMyround()
323 UASSERT(myround(4.6f) == 5);
324 UASSERT(myround(1.2f) == 1);
325 UASSERT(myround(-3.1f) == -3);
326 UASSERT(myround(-6.5f) == -7);