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();
49 void testIsPowerOfTwo();
53 static TestUtilities g_test_instance;
55 void TestUtilities::runTests(IGameDef *gamedef)
57 TEST(testAngleWrapAround);
61 TEST(testRemoveStringEnd);
68 TEST(testStrToIntConversion);
69 TEST(testStringReplace);
70 TEST(testStringAllowed);
74 TEST(testIsPowerOfTwo);
78 ////////////////////////////////////////////////////////////////////////////////
80 inline float ref_WrapDegrees180(float f)
82 // This is a slower alternative to the wrapDegrees_180() function;
83 // used as a reference for testing
84 float value = fmodf(f + 180, 360);
91 inline float ref_WrapDegrees_0_360(float f)
93 // This is a slower alternative to the wrapDegrees_0_360() function;
94 // used as a reference for testing
95 float value = fmodf(f, 360);
98 return value < 0 ? value + 360 : value;
102 void TestUtilities::testAngleWrapAround()
104 UASSERT(fabs(modulo360f(100.0) - 100.0) < 0.001);
105 UASSERT(fabs(modulo360f(720.5) - 0.5) < 0.001);
106 UASSERT(fabs(modulo360f(-0.5) - (-0.5)) < 0.001);
107 UASSERT(fabs(modulo360f(-365.5) - (-5.5)) < 0.001);
109 for (float f = -720; f <= -360; f += 0.25) {
110 UASSERT(fabs(modulo360f(f) - modulo360f(f + 360)) < 0.001);
113 for (float f = -1440; f <= 1440; f += 0.25) {
114 UASSERT(fabs(modulo360f(f) - fmodf(f, 360)) < 0.001);
115 UASSERT(fabs(wrapDegrees_180(f) - ref_WrapDegrees180(f)) < 0.001);
116 UASSERT(fabs(wrapDegrees_0_360(f) - ref_WrapDegrees_0_360(f)) < 0.001);
117 UASSERT(wrapDegrees_0_360(fabs(wrapDegrees_180(f) - wrapDegrees_0_360(f))) < 0.001);
122 void TestUtilities::testLowercase()
124 UASSERT(lowercase("Foo bAR") == "foo bar");
128 void TestUtilities::testTrim()
130 UASSERT(trim("") == "");
131 UASSERT(trim("dirt_with_grass") == "dirt_with_grass");
132 UASSERT(trim("\n \t\r Foo bAR \r\n\t\t ") == "Foo bAR");
133 UASSERT(trim("\n \t\r \r\n\t\t ") == "");
137 void TestUtilities::testIsYes()
139 UASSERT(is_yes("YeS") == true);
140 UASSERT(is_yes("") == false);
141 UASSERT(is_yes("FAlse") == false);
142 UASSERT(is_yes("-1") == true);
143 UASSERT(is_yes("0") == false);
144 UASSERT(is_yes("1") == true);
145 UASSERT(is_yes("2") == true);
149 void TestUtilities::testRemoveStringEnd()
151 const char *ends[] = {"abc", "c", "bc", "", NULL};
152 UASSERT(removeStringEnd("abc", ends) == "");
153 UASSERT(removeStringEnd("bc", ends) == "b");
154 UASSERT(removeStringEnd("12c", ends) == "12");
155 UASSERT(removeStringEnd("foo", ends) == "");
159 void TestUtilities::testUrlEncode()
161 UASSERT(urlencode("\"Aardvarks lurk, OK?\"")
162 == "%22Aardvarks%20lurk%2C%20OK%3F%22");
166 void TestUtilities::testUrlDecode()
168 UASSERT(urldecode("%22Aardvarks%20lurk%2C%20OK%3F%22")
169 == "\"Aardvarks lurk, OK?\"");
173 void TestUtilities::testPadString()
175 UASSERT(padStringRight("hello", 8) == "hello ");
178 void TestUtilities::testStartsWith()
180 UASSERT(str_starts_with(std::string(), std::string()) == true);
181 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
182 std::string()) == true);
183 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
184 std::string("the")) == true);
185 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
186 std::string("The")) == false);
187 UASSERT(str_starts_with(std::string("the sharp pickaxe"),
188 std::string("The"), true) == true);
189 UASSERT(str_starts_with(std::string("T"), std::string("The")) == false);
192 void TestUtilities::testStrEqual()
194 UASSERT(str_equal(narrow_to_wide("abc"), narrow_to_wide("abc")));
195 UASSERT(str_equal(narrow_to_wide("ABC"), narrow_to_wide("abc"), true));
199 void TestUtilities::testStringTrim()
201 UASSERT(trim(" a") == "a");
202 UASSERT(trim(" a ") == "a");
203 UASSERT(trim("a ") == "a");
204 UASSERT(trim("") == "");
208 void TestUtilities::testStrToIntConversion()
210 UASSERT(mystoi("123", 0, 1000) == 123);
211 UASSERT(mystoi("123", 0, 10) == 10);
215 void TestUtilities::testStringReplace()
217 std::string test_str;
218 test_str = "Hello there";
219 str_replace(test_str, "there", "world");
220 UASSERT(test_str == "Hello world");
221 test_str = "ThisAisAaAtest";
222 str_replace(test_str, 'A', ' ');
223 UASSERT(test_str == "This is a test");
227 void TestUtilities::testStringAllowed()
229 UASSERT(string_allowed("hello", "abcdefghijklmno") == true);
230 UASSERT(string_allowed("123", "abcdefghijklmno") == false);
231 UASSERT(string_allowed_blacklist("hello", "123") == true);
232 UASSERT(string_allowed_blacklist("hello123", "123") == false);
235 void TestUtilities::testUTF8()
237 UASSERT(wide_to_utf8(utf8_to_wide("")) == "");
238 UASSERT(wide_to_utf8(utf8_to_wide("the shovel dug a crumbly node!"))
239 == "the shovel dug a crumbly node!");
242 void TestUtilities::testWrapRows()
244 UASSERT(wrap_rows("12345678",4) == "1234\n5678");
245 // test that wrap_rows doesn't wrap inside multibyte sequences
247 const unsigned char s[] = {
248 0x2f, 0x68, 0x6f, 0x6d, 0x65, 0x2f, 0x72, 0x61, 0x70, 0x74, 0x6f,
249 0x72, 0x2f, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0x2f,
250 0x6d, 0x69, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x62, 0x69,
251 0x6e, 0x2f, 0x2e, 0x2e, 0};
252 std::string str((char *)s);
253 UASSERT(utf8_to_wide(wrap_rows(str, 20)) != L"<invalid UTF-8 string>");
256 const unsigned char s[] = {
257 0x74, 0x65, 0x73, 0x74, 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81,
258 0xd1, 0x82, 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82,
259 0x20, 0xd1, 0x82, 0xd0, 0xb5, 0xd1, 0x81, 0xd1, 0x82, 0};
260 std::string str((char *)s);
261 UASSERT(utf8_to_wide(wrap_rows(str, 8)) != L"<invalid UTF-8 string>");
266 void TestUtilities::testIsNumber()
268 UASSERT(is_number("123") == true);
269 UASSERT(is_number("") == false);
270 UASSERT(is_number("123a") == false);
274 void TestUtilities::testIsPowerOfTwo()
276 UASSERT(is_power_of_two(0) == false);
277 UASSERT(is_power_of_two(1) == true);
278 UASSERT(is_power_of_two(2) == true);
279 UASSERT(is_power_of_two(3) == false);
280 for (int exponent = 2; exponent <= 31; ++exponent) {
281 UASSERT(is_power_of_two((1 << exponent) - 1) == false);
282 UASSERT(is_power_of_two((1 << exponent)) == true);
283 UASSERT(is_power_of_two((1 << exponent) + 1) == false);
285 UASSERT(is_power_of_two(U32_MAX) == false);
288 void TestUtilities::testMyround()
290 UASSERT(myround(4.6f) == 5);
291 UASSERT(myround(1.2f) == 1);
292 UASSERT(myround(-3.1f) == -3);
293 UASSERT(myround(-6.5f) == -7);