1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2016 LoRd_MuldeR <MuldeR2@GMX.de>
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.
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"
25 #include <MUtils/OSSupport.h>
30 //===========================================================================
32 //===========================================================================
34 class GlobalTest
: public Testbed
41 virtual void TearDown()
46 //===========================================================================
48 //===========================================================================
50 //-----------------------------------------------------------------
52 //-----------------------------------------------------------------
54 #define TEST_RANDOM_MAX 99991
55 #define TEST_RANDOM(X,Y) do \
57 MUtils::seed_rand(); \
60 while(test.count() != TEST_RANDOM_MAX) \
62 if(++attempts <= 64) \
66 MUtils::OS::sleep_ms(1); \
69 for (size_t i = 0; i < TEST_RANDOM_MAX; ++i) \
71 test.insert(MUtils::next_rand_##Y()); \
76 FAIL(); /*too many attempts!*/ \
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
);
100 //-----------------------------------------------------------------
102 //-----------------------------------------------------------------
104 #define TEST_TRIM_STR(X,Y,Z) do \
108 MUtils::trim_##X(test); \
109 ASSERT_QSTR(test, (Z)); \
112 const QString test((Y)); \
113 ASSERT_QSTR(MUtils::trim_##X(test), (Z)); \
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 !");
138 //-----------------------------------------------------------------
140 //-----------------------------------------------------------------
142 #define TEST_CLEAN_FILE(X,Y,Z) do \
144 ASSERT_QSTR(MUtils::clean_file_##X((Y)), (Z)); \
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 //-----------------------------------------------------------------
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); \
209 ASSERT_TRUE(file.open(QIODevice::ReadWrite)); \
210 ASSERT_GE(file.write(TEST_STRING), strlen(TEST_STRING)); \
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 //-----------------------------------------------------------------
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); \
280 #define MAKE_SUB_DIR(X,Y) do \
282 ASSERT_TRUE((X).mkpath((Y))); \
283 ASSERT_TRUE((X).cd((Y))); \
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
));
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
++)
309 MAKE_SUB_DIR(dir
, QLatin1String(DIR_NAMES
[i
]));
310 for (size_t j
= 0; DIR_NAMES
[j
]; j
++)
313 MAKE_SUB_DIR(subdir
, QLatin1String(DIR_NAMES
[j
]));
314 QFile
test(subdir
.filePath("example.txt"));
315 MAKE_TEST_FILE(test
);
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));
325 ASSERT_TRUE(dir
.exists());
326 ASSERT_TRUE(MUtils::remove_directory(dir
.absolutePath(), true));
328 ASSERT_FALSE(dir
.exists());
332 #undef MAKE_TEST_FILE
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",
350 for (size_t i
= 0; TEST
[i
]; i
++)
352 test
<< QLatin1String(TEST
[i
]);
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 //-----------------------------------------------------------------
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]); \
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