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();
50 void testIsPowerOfTwo();
54 static TestUtilities g_test_instance;
56 void TestUtilities::runTests(IGameDef *gamedef)
58 TEST(testAngleWrapAround);
62 TEST(testRemoveStringEnd);
69 TEST(testStrToIntConversion);
70 TEST(testStringReplace);
71 TEST(testStringAllowed);
72 TEST(testAsciiPrintableHelper);
76 TEST(testIsPowerOfTwo);
80 ////////////////////////////////////////////////////////////////////////////////
82 inline float ref_WrapDegrees180(float f)
84 // This is a slower alternative to the wrapDegrees_180() function;
85 // used as a reference for testing
86 float value = fmodf(f + 180, 360);
93 inline float ref_WrapDegrees_0_360(float f)
95 // This is a slower alternative to the wrapDegrees_0_360() function;
96 // used as a reference for testing
97 float value = fmodf(f, 360);
100 return value < 0 ? value + 360 : value;
104 void TestUtilities::testAngleWrapAround()
106 UASSERT(fabs(modulo360f(100.0) - 100.0) < 0.001);
107 UASSERT(fabs(modulo360f(720.5) - 0.5) < 0.001);
108 UASSERT(fabs(modulo360f(-0.5) - (-0.5)) < 0.001);
109 UASSERT(fabs(modulo360f(-365.5) - (-5.5)) < 0.001);
111 for (float f = -720; f <= -360; f += 0.25) {
112 UASSERT(fabs(modulo360f(f) - modulo360f(f + 360)) < 0.001);
115 for (float f = -1440; f <= 1440; f += 0.25) {
116 UASSERT(fabs(modulo360f(f) - fmodf(f, 360)) < 0.001);
117 UASSERT(fabs(wrapDegrees_180(f) - ref_WrapDegrees180(f)) < 0.001);
118 UASSERT(fabs(wrapDegrees_0_360(f) - ref_WrapDegrees_0_360(f)) < 0.001);
119 UASSERT(wrapDegrees_0_360(fabs(wrapDegrees_180(f) - wrapDegrees_0_360(f))) < 0.001);
124 void TestUtilities::testLowercase()
126 UASSERT(lowercase("Foo bAR") == "foo bar");
130 void TestUtilities::testTrim()
132 UASSERT(trim("") == "");
133 UASSERT(trim("dirt_with_grass") == "dirt_with_grass");
134 UASSERT(trim("\n \t\r Foo bAR \r\n\t\t ") == "Foo bAR");
135 UASSERT(trim("\n \t\r \r\n\t\t ") == "");
139 void TestUtilities::testIsYes()
141 UASSERT(is_yes("YeS") == true);
142 UASSERT(is_yes("") == false);
143 UASSERT(is_yes("FAlse") == false);
144 UASSERT(is_yes("-1") == true);
145 UASSERT(is_yes("0") == false);
146 UASSERT(is_yes("1") == true);
147 UASSERT(is_yes("2") == true);
151 void TestUtilities::testRemoveStringEnd()
153 const char *ends[] = {"abc", "c", "bc", "", NULL};
154 UASSERT(removeStringEnd("abc", ends) == "");
155 UASSERT(removeStringEnd("bc", ends) == "b");
156 UASSERT(removeStringEnd("12c", ends) == "12");
157 UASSERT(removeStringEnd("foo", ends) == "");
161 void TestUtilities::testUrlEncode()
163 UASSERT(urlencode("\"Aardvarks lurk, OK?\"")
164 == "%22Aardvarks%20lurk%2C%20OK%3F%22");
168 void TestUtilities::testUrlDecode()
170 UASSERT(urldecode("%22Aardvarks%20lurk%2C%20OK%3F%22")
171 == "\"Aardvarks lurk, OK?\"");
175 void TestUtilities::testPadString()
177 UASSERT(padStringRight("hello", 8) == "hello ");
180 void TestUtilities::testStartsWith()
182 UASSERT(str_starts_with(std::string(), std::string()) == true);
183 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
184 std::string()) == true);
185 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
186 std::string("the")) == true);
187 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
188 std::string("The")) == false);
189 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
190 std::string("The"), true) == true);
191 UASSERT(str_starts_with(std::string("T"), std::string("The")) == false);
194 void TestUtilities::testStrEqual()
196 UASSERT(str_equal(narrow_to_wide("abc"), narrow_to_wide("abc")));
197 UASSERT(str_equal(narrow_to_wide("ABC"), narrow_to_wide("abc"), true));
201 void TestUtilities::testStringTrim()
203 UASSERT(trim(" a") == "a");
204 UASSERT(trim(" a ") == "a");
205 UASSERT(trim("a ") == "a");
206 UASSERT(trim("") == "");
210 void TestUtilities::testStrToIntConversion()
212 UASSERT(mystoi("123", 0, 1000) == 123);
213 UASSERT(mystoi("123", 0, 10) == 10);
217 void TestUtilities::testStringReplace()
219 std::string test_str;
220 test_str = "Hello there";
221 str_replace(test_str, "there", "world");
222 UASSERT(test_str == "Hello world");
223 test_str = "ThisAisAaAtest";
224 str_replace(test_str, 'A', ' ');
225 UASSERT(test_str == "This is a test");
229 void TestUtilities::testStringAllowed()
231 UASSERT(string_allowed("hello", "abcdefghijklmno") == true);
232 UASSERT(string_allowed("123", "abcdefghijklmno") == false);
233 UASSERT(string_allowed_blacklist("hello", "123") == true);
234 UASSERT(string_allowed_blacklist("hello123", "123") == false);
237 void TestUtilities::testAsciiPrintableHelper()
239 UASSERT(IS_ASCII_PRINTABLE_CHAR('e') == true);
240 UASSERT(IS_ASCII_PRINTABLE_CHAR('\0') == false);
242 // Ensures that there is no cutting off going on...
243 // If there were, 331 would be cut to 75 in this example
244 // and 73 is a valid ASCII char.
246 UASSERT(IS_ASCII_PRINTABLE_CHAR(ch) == false);
249 void TestUtilities::testUTF8()
251 UASSERT(wide_to_utf8(utf8_to_wide("")) == "");
252 UASSERT(wide_to_utf8(utf8_to_wide("the shovel dug a crumbly node!"))
253 == "the shovel dug a crumbly node!");
256 void TestUtilities::testWrapRows()
258 UASSERT(wrap_rows("12345678",4) == "1234\n5678");
259 // test that wrap_rows doesn't wrap inside multibyte sequences
261 const unsigned char s[] = {
262 0x2f, 0x68, 0x6f, 0x6d, 0x65, 0x2f, 0x72, 0x61, 0x70, 0x74, 0x6f,
263 0x72, 0x2f, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0x2f,
264 0x6d, 0x69, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x62, 0x69,
265 0x6e, 0x2f, 0x2e, 0x2e, 0};
266 std::string str((char *)s);
267 UASSERT(utf8_to_wide(wrap_rows(str, 20)) != L"<invalid UTF-8 string>");
270 const unsigned char s[] = {
271 0x74, 0x65, 0x73, 0x74, 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81,
272 0xd1, 0x82, 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82,
273 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0};
274 std::string str((char *)s);
275 UASSERT(utf8_to_wide(wrap_rows(str, 8)) != L"<invalid UTF-8 string>");
280 void TestUtilities::testIsNumber()
282 UASSERT(is_number("123") == true);
283 UASSERT(is_number("") == false);
284 UASSERT(is_number("123a") == false);
288 void TestUtilities::testIsPowerOfTwo()
290 UASSERT(is_power_of_two(0) == false);
291 UASSERT(is_power_of_two(1) == true);
292 UASSERT(is_power_of_two(2) == true);
293 UASSERT(is_power_of_two(3) == false);
294 for (int exponent = 2; exponent <= 31; ++exponent) {
295 UASSERT(is_power_of_two((1 << exponent) - 1) == false);
296 UASSERT(is_power_of_two((1 << exponent)) == true);
297 UASSERT(is_power_of_two((1 << exponent) + 1) == false);
299 UASSERT(is_power_of_two(U32_MAX) == false);
302 void TestUtilities::testMyround()
304 UASSERT(myround(4.6f) == 5);
305 UASSERT(myround(1.2f) == 1);
306 UASSERT(myround(-3.1f) == -3);
307 UASSERT(myround(-6.5f) == -7);