Add UTF and other utility unit tests
[oweals/minetest.git] / src / unittest / test_utilities.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
20 #include "test.h"
21
22 #include "util/numeric.h"
23 #include "util/string.h"
24
25 class TestUtilities : public TestBase {
26 public:
27         TestUtilities() { TestManager::registerTestModule(this); }
28         const char *getName() { return "TestUtilities"; }
29
30         void runTests(IGameDef *gamedef);
31
32         void testAngleWrapAround();
33         void testLowercase();
34         void testTrim();
35         void testIsYes();
36         void testRemoveStringEnd();
37         void testUrlEncode();
38         void testUrlDecode();
39         void testPadString();
40         void testStartsWith();
41         void testStrEqual();
42         void testStringTrim();
43         void testStrToIntConversion();
44         void testStringReplace();
45         void testStringAllowed();
46         void testUTF8();
47         void testWrapRows();
48         void testIsNumber();
49         void testIsPowerOfTwo();
50         void testMyround();
51 };
52
53 static TestUtilities g_test_instance;
54
55 void TestUtilities::runTests(IGameDef *gamedef)
56 {
57         TEST(testAngleWrapAround);
58         TEST(testLowercase);
59         TEST(testTrim);
60         TEST(testIsYes);
61         TEST(testRemoveStringEnd);
62         TEST(testUrlEncode);
63         TEST(testUrlDecode);
64         TEST(testPadString);
65         TEST(testStartsWith);
66         TEST(testStrEqual);
67         TEST(testStringTrim);
68         TEST(testStrToIntConversion);
69         TEST(testStringReplace);
70         TEST(testStringAllowed);
71         TEST(testUTF8);
72         TEST(testWrapRows);
73         TEST(testIsNumber);
74         TEST(testIsPowerOfTwo);
75         TEST(testMyround);
76 }
77
78 ////////////////////////////////////////////////////////////////////////////////
79
80 inline float ref_WrapDegrees180(float f)
81 {
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);
85         if (value < 0)
86                 value += 360;
87         return value - 180;
88 }
89
90
91 inline float ref_WrapDegrees_0_360(float f)
92 {
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);
96         if (value < 0)
97                 value += 360;
98         return value < 0 ? value + 360 : value;
99 }
100
101
102 void TestUtilities::testAngleWrapAround()
103 {
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);
108
109         for (float f = -720; f <= -360; f += 0.25) {
110                 UASSERT(fabs(modulo360f(f) - modulo360f(f + 360)) < 0.001);
111         }
112
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);
118         }
119 }
120
121
122 void TestUtilities::testLowercase()
123 {
124         UASSERT(lowercase("Foo bAR") == "foo bar");
125 }
126
127
128 void TestUtilities::testTrim()
129 {
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  ") == "");
134 }
135
136
137 void TestUtilities::testIsYes()
138 {
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);
146 }
147
148
149 void TestUtilities::testRemoveStringEnd()
150 {
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) == "");
156 }
157
158
159 void TestUtilities::testUrlEncode()
160 {
161         UASSERT(urlencode("\"Aardvarks lurk, OK?\"")
162                         == "%22Aardvarks%20lurk%2C%20OK%3F%22");
163 }
164
165
166 void TestUtilities::testUrlDecode()
167 {
168         UASSERT(urldecode("%22Aardvarks%20lurk%2C%20OK%3F%22")
169                         == "\"Aardvarks lurk, OK?\"");
170 }
171
172
173 void TestUtilities::testPadString()
174 {
175         UASSERT(padStringRight("hello", 8) == "hello   ");
176 }
177
178 void TestUtilities::testStartsWith()
179 {
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);
190 }
191
192 void TestUtilities::testStrEqual()
193 {
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));
196 }
197
198
199 void TestUtilities::testStringTrim()
200 {
201         UASSERT(trim("  a") == "a");
202         UASSERT(trim("   a  ") == "a");
203         UASSERT(trim("a   ") == "a");
204         UASSERT(trim("") == "");
205 }
206
207
208 void TestUtilities::testStrToIntConversion()
209 {
210         UASSERT(mystoi("123", 0, 1000) == 123);
211         UASSERT(mystoi("123", 0, 10) == 10);
212 }
213
214
215 void TestUtilities::testStringReplace()
216 {
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");
224 }
225
226
227 void TestUtilities::testStringAllowed()
228 {
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);
233 }
234
235 void TestUtilities::testUTF8()
236 {
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!");
240 }
241
242 void TestUtilities::testWrapRows()
243 {
244         UASSERT(wrap_rows("12345678",4) == "1234\n5678");
245 }
246
247
248 void TestUtilities::testIsNumber()
249 {
250         UASSERT(is_number("123") == true);
251         UASSERT(is_number("") == false);
252         UASSERT(is_number("123a") == false);
253 }
254
255
256 void TestUtilities::testIsPowerOfTwo()
257 {
258         UASSERT(is_power_of_two(0) == false);
259         UASSERT(is_power_of_two(1) == true);
260         UASSERT(is_power_of_two(2) == true);
261         UASSERT(is_power_of_two(3) == false);
262         for (int exponent = 2; exponent <= 31; ++exponent) {
263                 UASSERT(is_power_of_two((1 << exponent) - 1) == false);
264                 UASSERT(is_power_of_two((1 << exponent)) == true);
265                 UASSERT(is_power_of_two((1 << exponent) + 1) == false);
266         }
267         UASSERT(is_power_of_two((u32)-1) == false);
268 }
269
270 void TestUtilities::testMyround()
271 {
272         UASSERT(myround(4.6f) == 5);
273         UASSERT(myround(1.2f) == 1);
274         UASSERT(myround(-3.1f) == -3);
275         UASSERT(myround(-6.5f) == -7);
276 }
277