Added test cases for natural_string_sort() and regexp_parse_uint32() functions.
[MUtilities.git] / test / src / GlobalTest.cpp
blob40390dd36f82d1cbdd7a5e2cc33fdbde7dd7a1dc
1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2016 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library 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 GNU
13 // Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
22 #include "MUtilsTest.h"
24 //MUtils
25 #include <MUtils/OSSupport.h>
27 //Qt
28 #include <QSet>
30 //===========================================================================
31 // TESTBED CLASS
32 //===========================================================================
34 class GlobalTest : public Testbed
36 protected:
37 virtual void SetUp()
41 virtual void TearDown()
46 //===========================================================================
47 // TEST METHODS
48 //===========================================================================
50 //-----------------------------------------------------------------
51 // Random
52 //-----------------------------------------------------------------
54 #define TEST_RANDOM_MAX 99991
55 #define TEST_RANDOM(X,Y) do \
56 { \
57 MUtils::seed_rand(); \
58 QSet<X> test; \
59 int attempts = 0; \
60 while(test.count() != TEST_RANDOM_MAX) \
61 { \
62 if(++attempts <= 64) \
63 { \
64 if(attempts > 1) \
65 { \
66 MUtils::OS::sleep_ms(1); \
67 } \
68 test.clear(); \
69 for (size_t i = 0; i < TEST_RANDOM_MAX; ++i) \
70 { \
71 test.insert(MUtils::next_rand_##Y()); \
72 } \
73 } \
74 else \
75 { \
76 FAIL(); /*too many attempts!*/ \
77 } \
78 } \
79 } \
80 while(0)
82 TEST_F(GlobalTest, RandomU32)
84 TEST_RANDOM(quint32, u32);
87 TEST_F(GlobalTest, RandomU64)
89 TEST_RANDOM(quint64, u64);
92 TEST_F(GlobalTest, RandomStr)
94 TEST_RANDOM(QString, str);
97 #undef TEST_RANDOM
98 #undef RND_LIMIT
100 //-----------------------------------------------------------------
101 // Trim String
102 //-----------------------------------------------------------------
104 #define TEST_TRIM_STR(X,Y,Z) do \
107 QString test((Y)); \
108 MUtils::trim_##X(test); \
109 ASSERT_QSTR(test, (Z)); \
112 const QString test((Y)); \
113 ASSERT_QSTR(MUtils::trim_##X(test), (Z)); \
116 while(0)
118 TEST_F(GlobalTest, TrimStringLeft)
120 TEST_TRIM_STR(left, "", "");
121 TEST_TRIM_STR(left, " ", "");
122 TEST_TRIM_STR(left, "! test !", "! test !");
123 TEST_TRIM_STR(left, " test ", "test ");
124 TEST_TRIM_STR(left, " ! test ! ", "! test ! ");
127 TEST_F(GlobalTest, TrimStringRight)
129 TEST_TRIM_STR(right, "", "");
130 TEST_TRIM_STR(right, " ", "");
131 TEST_TRIM_STR(right, "! test !", "! test !");
132 TEST_TRIM_STR(right, " test ", " test");
133 TEST_TRIM_STR(right, " ! test ! ", " ! test !");
136 #undef TEST_TRIM_STR
138 //-----------------------------------------------------------------
139 // Clean File Path
140 //-----------------------------------------------------------------
142 #define TEST_CLEAN_FILE(X,Y,Z) do \
144 ASSERT_QSTR(MUtils::clean_file_##X((Y)), (Z)); \
146 while(0)
148 static const char *const VALID_FILENAME_CHARS = "!#$%&'()+,-.0123456789;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{}~";
150 TEST_F(GlobalTest, CleanFileName)
152 TEST_CLEAN_FILE(name, "", "");
153 TEST_CLEAN_FILE(name, VALID_FILENAME_CHARS, VALID_FILENAME_CHARS);
154 TEST_CLEAN_FILE(name, "example.txt", "example.txt");
155 TEST_CLEAN_FILE(name, " example.txt", " example.txt");
156 TEST_CLEAN_FILE(name, "example.txt ", "example.txt");
157 TEST_CLEAN_FILE(name, ".example.txt", ".example.txt");
158 TEST_CLEAN_FILE(name, "example.txt.", "example.txt");
159 TEST_CLEAN_FILE(name, "foo<>:\"/\\|?*\t\r\nbar", "foo____________bar");
160 TEST_CLEAN_FILE(name, "NUL", "___");
161 TEST_CLEAN_FILE(name, "xNUL", "xNUL");
162 TEST_CLEAN_FILE(name, "NULx", "NULx");
163 TEST_CLEAN_FILE(name, "NUL.txt", "___.txt");
164 TEST_CLEAN_FILE(name, "NULx.txt", "NULx.txt");
165 TEST_CLEAN_FILE(name, "xNUL.txt", "xNUL.txt");
168 TEST_F(GlobalTest, CleanFilePath)
170 TEST_CLEAN_FILE(path, "", "");
171 TEST_CLEAN_FILE(path, VALID_FILENAME_CHARS, VALID_FILENAME_CHARS);
172 TEST_CLEAN_FILE(path, "c:\\foo\\bar\\example.txt", "c:/foo/bar/example.txt");
173 TEST_CLEAN_FILE(path, "c:/foo/bar/example.txt", "c:/foo/bar/example.txt");
174 TEST_CLEAN_FILE(path, "foo\\bar\\example.txt", "foo/bar/example.txt");
175 TEST_CLEAN_FILE(path, "\\foo\\bar\\example.txt", "/foo/bar/example.txt");
176 TEST_CLEAN_FILE(path, "\\\\hostname\\share\\example.txt", "//hostname/share/example.txt");
177 TEST_CLEAN_FILE(path, "\\\\?\\c:\\very long path", "//?/c:/very long path");
178 TEST_CLEAN_FILE(path, "c:\\foo<>:\"|?*\t\r\nbar\\example.txt", "c:/foo__________bar/example.txt");
179 TEST_CLEAN_FILE(path, "c:\\example\\foo<>:\"|?*\t\r\nbar.txt", "c:/example/foo__________bar.txt");
180 TEST_CLEAN_FILE(path, "c:\\ foo\\ bar\\ example.txt", "c:/ foo/ bar/ example.txt");
181 TEST_CLEAN_FILE(path, "c:\\foo \\bar \\example.txt ", "c:/foo/bar/example.txt");
182 TEST_CLEAN_FILE(path, "c:\\foo bar\\exa mple.txt", "c:/foo bar/exa mple.txt");
183 TEST_CLEAN_FILE(path, "c:\\example\\NUL", "c:/example/___");
184 TEST_CLEAN_FILE(path, "c:\\example\\xNUL", "c:/example/xNUL");
185 TEST_CLEAN_FILE(path, "c:\\example\\NULx", "c:/example/NULx");
186 TEST_CLEAN_FILE(path, "c:\\example\\NUL.txt", "c:/example/___.txt");
187 TEST_CLEAN_FILE(path, "c:\\example\\xNUL.txt", "c:/example/xNUL.txt");
188 TEST_CLEAN_FILE(path, "c:\\example\\NULx.txt", "c:/example/NULx.txt");
191 //-----------------------------------------------------------------
192 // File Names
193 //-----------------------------------------------------------------
195 #define TEST_FILE_NAME(X, Y, ...) \
197 const QString workDir = makeTempFolder(__FUNCTION__); \
198 ASSERT_FALSE(workDir.isEmpty()); \
199 QSet<QString> test; \
200 const QRegExp pattern((Y)); \
201 for (int i = 0; i < 997; ++i) \
203 const QString name = MUtils::make_##X##_file(workDir, __VA_ARGS__); \
204 ASSERT_FALSE(name.isEmpty()); \
205 ASSERT_FALSE(test.contains(name)); \
206 ASSERT_GE(pattern.indexIn(name), 0); \
207 test.insert(name); \
208 QFile file(name); \
209 ASSERT_TRUE(file.open(QIODevice::ReadWrite)); \
210 ASSERT_GE(file.write(TEST_STRING), strlen(TEST_STRING)); \
211 file.close(); \
213 for (QSet<QString>::const_iterator iter = test.constBegin(); iter != test.constEnd(); iter++) \
215 ASSERT_TRUE(QFile::exists(*iter)); \
216 QFile::remove(*iter); \
220 TEST_F(GlobalTest, TempFileName)
222 TEST_FILE_NAME(temp, "/\\w+\\.txt$", "txt", true);
225 TEST_F(GlobalTest, UniqFileName)
227 TEST_FILE_NAME(unique, "/example.\\w+\\.txt$", "example", "txt");
230 #undef TEST_FILE_NAME
232 //-----------------------------------------------------------------
233 // Parity
234 //-----------------------------------------------------------------
236 TEST_F(GlobalTest, Parity)
238 ASSERT_EQ(MUtils::parity(0x00000000), false);
239 ASSERT_EQ(MUtils::parity(0x11111111), false);
240 ASSERT_EQ(MUtils::parity(0xFFFFFFFF), false);
241 ASSERT_EQ(MUtils::parity(0x00000001), true );
242 ASSERT_EQ(MUtils::parity(0x00000010), true );
243 ASSERT_EQ(MUtils::parity(0x00000100), true );
244 ASSERT_EQ(MUtils::parity(0x00001000), true );
245 ASSERT_EQ(MUtils::parity(0x00010000), true );
246 ASSERT_EQ(MUtils::parity(0x00100000), true );
247 ASSERT_EQ(MUtils::parity(0x01000000), true );
248 ASSERT_EQ(MUtils::parity(0x10000000), true );
249 ASSERT_EQ(MUtils::parity(0xEFFFFFFF), true );
250 ASSERT_EQ(MUtils::parity(0xFEFFFFFF), true );
251 ASSERT_EQ(MUtils::parity(0xFFEFFFFF), true );
252 ASSERT_EQ(MUtils::parity(0xFFFEFFFF), true );
253 ASSERT_EQ(MUtils::parity(0xFFFFEFFF), true );
254 ASSERT_EQ(MUtils::parity(0xFFFFFEFF), true );
255 ASSERT_EQ(MUtils::parity(0xFFFFFFEF), true );
256 ASSERT_EQ(MUtils::parity(0xFFFFFFFE), true );
257 ASSERT_EQ(MUtils::parity(0x10101010), false);
258 ASSERT_EQ(MUtils::parity(0x01010101), false);
259 ASSERT_EQ(MUtils::parity(0xC8A2CC96), false);
260 ASSERT_EQ(MUtils::parity(0x504928DD), true );
261 ASSERT_EQ(MUtils::parity(0x38BFB9EC), false);
262 ASSERT_EQ(MUtils::parity(0x73F42695), true );
263 ASSERT_EQ(MUtils::parity(0x9161E326), false);
264 ASSERT_EQ(MUtils::parity(0xB1C93AC2), true );
265 ASSERT_EQ(MUtils::parity(0xCA4B1193), false);
268 //-----------------------------------------------------------------
269 // Remove File/Dirrectory
270 //-----------------------------------------------------------------
272 #define MAKE_TEST_FILE(X) do \
274 ASSERT_TRUE((X).open(QIODevice::ReadWrite)); \
275 ASSERT_GE((X).write(TEST_STRING), strlen(TEST_STRING)); \
276 (X).setPermissions(QFile::ReadOwner|QFile::ExeOwner|QFile::ReadGroup|QFile::ExeGroup|QFile::ReadOther|QFile::ExeOther); \
278 while(0)
280 #define MAKE_SUB_DIR(X,Y) do \
282 ASSERT_TRUE((X).mkpath((Y))); \
283 ASSERT_TRUE((X).cd((Y))); \
285 while (0)
287 TEST_F(GlobalTest, RemoveFile)
289 const QString workDir = makeTempFolder(__FUNCTION__);
290 ASSERT_FALSE(workDir.isEmpty());
291 const QString fileName = QString("%1/example.txt").arg(workDir);
292 QFile test(fileName);
293 MAKE_TEST_FILE(test);
294 ASSERT_FALSE(MUtils::remove_file(fileName));
295 test.close();
296 ASSERT_TRUE(QFileInfo(fileName).exists());
297 ASSERT_TRUE(MUtils::remove_file(fileName));
298 ASSERT_FALSE(QFileInfo(fileName).exists());
301 TEST_F(GlobalTest, Directory)
303 const QString workDir = makeTempFolder(__FUNCTION__);
304 ASSERT_FALSE(workDir.isEmpty());
305 static const char *const DIR_NAMES[] = { "foo", "bar", NULL };
306 for (size_t i = 0; DIR_NAMES[i]; i++)
308 QDir dir(workDir);
309 MAKE_SUB_DIR(dir, QLatin1String(DIR_NAMES[i]));
310 for (size_t j = 0; DIR_NAMES[j]; j++)
312 QDir subdir(dir);
313 MAKE_SUB_DIR(subdir, QLatin1String(DIR_NAMES[j]));
314 QFile test(subdir.filePath("example.txt"));
315 MAKE_TEST_FILE(test);
316 test.close();
319 for (size_t i = 0; DIR_NAMES[i]; i++)
321 QDir dir(QString("%1/%2").arg(workDir, QLatin1String(DIR_NAMES[i])));
322 ASSERT_TRUE(dir.exists());
323 ASSERT_FALSE(MUtils::remove_directory(dir.absolutePath(), false));
324 dir.refresh();
325 ASSERT_TRUE(dir.exists());
326 ASSERT_TRUE(MUtils::remove_directory(dir.absolutePath(), true));
327 dir.refresh();
328 ASSERT_FALSE(dir.exists());
332 #undef MAKE_TEST_FILE
333 #undef MAKE_SUB_DIR
335 //-----------------------------------------------------------------
336 // Natural String Sort
337 //-----------------------------------------------------------------
339 TEST_F(GlobalTest, NaturalStrSort)
341 static const char *const TEST[] =
343 "z0.txt", "z1.txt", "z2.txt", "z3.txt", "z4.txt", "z5.txt", "z6.txt", "z7.txt", "z8.txt", "z9.txt",
344 "z10.txt", "z11.txt", "z12.txt", "z13.txt", "z14.txt", "z15.txt", "z16.txt", "z17.txt", "z18.txt", "z19.txt",
345 "z100.txt", "z101.txt", "z102.txt", "z103.txt", "z104.txt", "z105.txt", "z106.txt", "z107.txt", "z108.txt", "z109.txt",
346 NULL
349 QStringList test;
350 for (size_t i = 0; TEST[i]; i++)
352 test << QLatin1String(TEST[i]);
355 qsrand(time(NULL));
356 for (size_t q = 0; q < 97; q++)
358 for (size_t k = 0; k < 997; k++)
360 const size_t len = size_t(test.count());
361 for (size_t i = 0; i < len; i++)
363 test.swap(i, qrand() % len);
366 MUtils::natural_string_sort(test, true);
367 for (size_t i = 0; TEST[i]; i++)
369 ASSERT_QSTR(test[i], TEST[i]);
374 //-----------------------------------------------------------------
375 // RegExp Parser
376 //-----------------------------------------------------------------
378 #define TEST_REGEX_U32(X,Y,Z,...) do \
380 const QRegExp test(QLatin1String((X))); \
381 ASSERT_GE(test.indexIn(QLatin1String((Y))), 0); \
382 quint32 result[(Z)]; \
383 ASSERT_TRUE(MUtils::regexp_parse_uint32(test, result, (Z))); \
384 const quint32 expected[] = { __VA_ARGS__ }; \
385 for(size_t i = 0; i < (Z); i++) \
387 ASSERT_EQ(result[i], expected[i]); \
390 while(0)
392 TEST_F(GlobalTest, ParseRegExp)
394 TEST_REGEX_U32("(\\d+)", "42", 1, 42);
395 TEST_REGEX_U32("(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)", "4 8 15 16 23 42", 6, 4, 8, 15, 16, 23, 42);
396 TEST_REGEX_U32("x264\\s+(\\d+)\\.(\\d+)\\.(\\d+)\\s+\\w+", "x264 0.148.2744 b97ae06", 3, 0, 148, 2744);
397 TEST_REGEX_U32("HEVC\\s+encoder\\s+version\\s+(\\d+)\\.(\\d+)\\+(\\d+)-\\w+", "HEVC encoder version 2.1+70-78e1e1354a25", 3, 2, 1, 70);
400 #undef TEST_REGEX_U32