OSDN Git Service

a6160f38faab758899704fd237150c91b086b6dd
[mutilities/MUtilities.git] / test / src / GlobalTest.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2019 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.
14 //
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
18 //
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
21
22 #include "MUtilsTest.h"
23
24 //MUtils
25 #include <MUtils/OSSupport.h>
26
27 //Qt
28 #include <QSet>
29
30 //===========================================================================
31 // TESTBED CLASS
32 //===========================================================================
33
34 class GlobalTest : public Testbed
35 {
36 protected:
37         virtual void SetUp()
38         {
39         }
40
41         virtual void TearDown()
42         {
43         }
44 };
45
46 //===========================================================================
47 // TEST METHODS
48 //===========================================================================
49
50 //-----------------------------------------------------------------
51 // Random
52 //-----------------------------------------------------------------
53
54 #define TEST_RANDOM_MAX 29989
55 #define TEST_RANDOM(X,Y) do \
56 { \
57         QSet<X> test; \
58         for (size_t i = 0; i < TEST_RANDOM_MAX; ++i)  \
59         {  \
60                 test.insert(MUtils::next_rand_##Y()); \
61         } \
62         ASSERT_EQ(test.count(), TEST_RANDOM_MAX); \
63 } \
64 while(0)
65
66 TEST_F(GlobalTest, RandomU32)
67 {
68         TEST_RANDOM(quint32, u32);
69 }
70
71 TEST_F(GlobalTest, RandomU64)
72 {
73         TEST_RANDOM(quint64, u64);
74 }
75
76 TEST_F(GlobalTest, RandomStr)
77 {
78         TEST_RANDOM(QString, str);
79 }
80
81 #undef TEST_RANDOM
82 #undef RND_LIMIT
83
84 //-----------------------------------------------------------------
85 // Trim String
86 //-----------------------------------------------------------------
87
88 #define TEST_TRIM_STR(X,Y,Z) do \
89 { \
90         { \
91                 QString test((Y)); \
92                 MUtils::trim_##X(test); \
93                 ASSERT_QSTR(test, (Z)); \
94         } \
95         { \
96                 const QString test((Y)); \
97                 ASSERT_QSTR(MUtils::trim_##X(test), (Z)); \
98         } \
99 } \
100 while(0)
101
102 TEST_F(GlobalTest, TrimStringLeft)
103 {
104         TEST_TRIM_STR(left, "", "");
105         TEST_TRIM_STR(left, "   ", "");
106         TEST_TRIM_STR(left, "!   test   !", "!   test   !");
107         TEST_TRIM_STR(left, "   test   ", "test   ");
108         TEST_TRIM_STR(left, "   !   test   !   ", "!   test   !   ");
109 }
110
111 TEST_F(GlobalTest, TrimStringRight)
112 {
113         TEST_TRIM_STR(right, "", "");
114         TEST_TRIM_STR(right, "   ", "");
115         TEST_TRIM_STR(right, "!   test   !", "!   test   !");
116         TEST_TRIM_STR(right, "   test   ", "   test");
117         TEST_TRIM_STR(right, "   !   test   !   ", "   !   test   !");
118 }
119
120 #undef TEST_TRIM_STR
121
122 //-----------------------------------------------------------------
123 // Clean File Path
124 //-----------------------------------------------------------------
125
126 #define TEST_CLEAN_FILE(X,Y,Z) do \
127 { \
128         ASSERT_QSTR(MUtils::clean_file_##X((Y), false), (Z)); \
129 } \
130 while(0)
131
132 static const char *const VALID_FILENAME_CHARS = "!#$%&'()+,-.0123456789;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{}~";
133
134 TEST_F(GlobalTest, CleanFileName)
135 {
136         TEST_CLEAN_FILE(name, "", "");
137         TEST_CLEAN_FILE(name, VALID_FILENAME_CHARS, VALID_FILENAME_CHARS);
138         TEST_CLEAN_FILE(name, "example.txt", "example.txt");
139         TEST_CLEAN_FILE(name, " example.txt", " example.txt");
140         TEST_CLEAN_FILE(name, "example.txt ", "example.txt");
141         TEST_CLEAN_FILE(name, ".example.txt", ".example.txt");
142         TEST_CLEAN_FILE(name, "example.txt.", "example.txt");
143         TEST_CLEAN_FILE(name, "foo<>:\"/\\|?*\t\r\nbar", "foo____________bar");
144         TEST_CLEAN_FILE(name, "NUL", "___");
145         TEST_CLEAN_FILE(name, "xNUL", "xNUL");
146         TEST_CLEAN_FILE(name, "NULx", "NULx");
147         TEST_CLEAN_FILE(name, "NUL.txt", "___.txt");
148         TEST_CLEAN_FILE(name, "NULx.txt", "NULx.txt");
149         TEST_CLEAN_FILE(name, "xNUL.txt", "xNUL.txt");
150 }
151
152 TEST_F(GlobalTest, CleanFilePath)
153 {
154         TEST_CLEAN_FILE(path, "", "");
155         TEST_CLEAN_FILE(path, VALID_FILENAME_CHARS, VALID_FILENAME_CHARS);
156         TEST_CLEAN_FILE(path, "c:\\foo\\bar\\example.txt", "c:/foo/bar/example.txt");
157         TEST_CLEAN_FILE(path, "c:/foo/bar/example.txt", "c:/foo/bar/example.txt");
158         TEST_CLEAN_FILE(path, "foo\\bar\\example.txt", "foo/bar/example.txt");
159         TEST_CLEAN_FILE(path, "\\foo\\bar\\example.txt", "/foo/bar/example.txt");
160         TEST_CLEAN_FILE(path, "\\\\hostname\\share\\example.txt", "//hostname/share/example.txt");
161         TEST_CLEAN_FILE(path, "\\\\?\\c:\\very long path", "//?/c:/very long path");
162         TEST_CLEAN_FILE(path, "c:\\foo<>:\"|?*\t\r\nbar\\example.txt", "c:/foo__________bar/example.txt");
163         TEST_CLEAN_FILE(path, "c:\\example\\foo<>:\"|?*\t\r\nbar.txt", "c:/example/foo__________bar.txt");
164         TEST_CLEAN_FILE(path, "c:\\ foo\\ bar\\ example.txt", "c:/ foo/ bar/ example.txt");
165         TEST_CLEAN_FILE(path, "c:\\foo \\bar \\example.txt ", "c:/foo/bar/example.txt");
166         TEST_CLEAN_FILE(path, "c:\\foo   bar\\exa   mple.txt", "c:/foo   bar/exa   mple.txt");
167         TEST_CLEAN_FILE(path, "c:\\example\\NUL", "c:/example/___");
168         TEST_CLEAN_FILE(path, "c:\\example\\xNUL", "c:/example/xNUL");
169         TEST_CLEAN_FILE(path, "c:\\example\\NULx", "c:/example/NULx");
170         TEST_CLEAN_FILE(path, "c:\\example\\NUL.txt", "c:/example/___.txt");
171         TEST_CLEAN_FILE(path, "c:\\example\\xNUL.txt", "c:/example/xNUL.txt");
172         TEST_CLEAN_FILE(path, "c:\\example\\NULx.txt", "c:/example/NULx.txt");
173 }
174
175 //-----------------------------------------------------------------
176 // File Names
177 //-----------------------------------------------------------------
178
179 #define TEST_FILE_NAME(X, Y, ...) \
180 { \
181         const QString workDir = makeTempFolder(__FUNCTION__); \
182         ASSERT_FALSE(workDir.isEmpty()); \
183         QSet<QString> test; \
184         const QRegExp pattern((Y)); \
185         for (int i = 0; i < 997; ++i) \
186         { \
187                 const QString name = MUtils::make_##X##_file(workDir, __VA_ARGS__); \
188                 ASSERT_FALSE(name.isEmpty()); \
189                 ASSERT_FALSE(test.contains(name)); \
190                 ASSERT_GE(pattern.indexIn(name), 0); \
191                 test.insert(name); \
192                 QFile file(name); \
193                 ASSERT_TRUE(file.open(QIODevice::ReadWrite)); \
194                 ASSERT_GE(file.write(TEST_STRING), strlen(TEST_STRING)); \
195                 file.close(); \
196         } \
197         for (QSet<QString>::const_iterator iter = test.constBegin(); iter != test.constEnd(); iter++) \
198         { \
199                 ASSERT_TRUE(QFile::exists(*iter)); \
200                 QFile::remove(*iter); \
201         } \
202 }
203
204 TEST_F(GlobalTest, TempFileName)
205 {
206         TEST_FILE_NAME(temp, "/\\w+\\.txt$", "txt", true);
207 }
208
209 TEST_F(GlobalTest, UniqFileName)
210 {
211         TEST_FILE_NAME(unique, "/example.\\w+\\.txt$", "example", "txt");
212 }
213
214 #undef TEST_FILE_NAME
215
216 //-----------------------------------------------------------------
217 // Parity
218 //-----------------------------------------------------------------
219
220 TEST_F(GlobalTest, Parity)
221 {
222         ASSERT_EQ(MUtils::parity(0x00000000), false);
223         ASSERT_EQ(MUtils::parity(0x11111111), false);
224         ASSERT_EQ(MUtils::parity(0xFFFFFFFF), false);
225         ASSERT_EQ(MUtils::parity(0x00000001), true );
226         ASSERT_EQ(MUtils::parity(0x00000010), true );
227         ASSERT_EQ(MUtils::parity(0x00000100), true );
228         ASSERT_EQ(MUtils::parity(0x00001000), true );
229         ASSERT_EQ(MUtils::parity(0x00010000), true );
230         ASSERT_EQ(MUtils::parity(0x00100000), true );
231         ASSERT_EQ(MUtils::parity(0x01000000), true );
232         ASSERT_EQ(MUtils::parity(0x10000000), true );
233         ASSERT_EQ(MUtils::parity(0xEFFFFFFF), true );
234         ASSERT_EQ(MUtils::parity(0xFEFFFFFF), true );
235         ASSERT_EQ(MUtils::parity(0xFFEFFFFF), true );
236         ASSERT_EQ(MUtils::parity(0xFFFEFFFF), true );
237         ASSERT_EQ(MUtils::parity(0xFFFFEFFF), true );
238         ASSERT_EQ(MUtils::parity(0xFFFFFEFF), true );
239         ASSERT_EQ(MUtils::parity(0xFFFFFFEF), true );
240         ASSERT_EQ(MUtils::parity(0xFFFFFFFE), true );
241         ASSERT_EQ(MUtils::parity(0x10101010), false);
242         ASSERT_EQ(MUtils::parity(0x01010101), false);
243         ASSERT_EQ(MUtils::parity(0xC8A2CC96), false);
244         ASSERT_EQ(MUtils::parity(0x504928DD), true );
245         ASSERT_EQ(MUtils::parity(0x38BFB9EC), false);
246         ASSERT_EQ(MUtils::parity(0x73F42695), true );
247         ASSERT_EQ(MUtils::parity(0x9161E326), false);
248         ASSERT_EQ(MUtils::parity(0xB1C93AC2), true );
249         ASSERT_EQ(MUtils::parity(0xCA4B1193), false);
250 }
251
252 //-----------------------------------------------------------------
253 // Remove File/Dirrectory
254 //-----------------------------------------------------------------
255
256 #define MAKE_TEST_FILE(X) do \
257 { \
258         ASSERT_TRUE((X).open(QIODevice::ReadWrite)); \
259         ASSERT_GE((X).write(TEST_STRING), strlen(TEST_STRING)); \
260         (X).setPermissions(QFile::ReadOwner|QFile::ExeOwner|QFile::ReadGroup|QFile::ExeGroup|QFile::ReadOther|QFile::ExeOther); \
261 } \
262 while(0)
263
264 #define MAKE_SUB_DIR(X,Y) do \
265 { \
266         ASSERT_TRUE((X).mkpath((Y))); \
267         ASSERT_TRUE((X).cd((Y))); \
268 } \
269 while (0)
270
271 TEST_F(GlobalTest, RemoveFile)
272 {
273         const QString workDir = makeTempFolder(__FUNCTION__);
274         ASSERT_FALSE(workDir.isEmpty());
275         const QString fileName = QString("%1/example.txt").arg(workDir);
276         QFile test(fileName);
277         MAKE_TEST_FILE(test);
278         ASSERT_FALSE(MUtils::remove_file(fileName));
279         test.close();
280         ASSERT_TRUE(QFileInfo(fileName).exists());
281         ASSERT_TRUE(MUtils::remove_file(fileName));
282         ASSERT_FALSE(QFileInfo(fileName).exists());
283 }
284
285 TEST_F(GlobalTest, Directory)
286 {
287         const QString workDir = makeTempFolder(__FUNCTION__);
288         ASSERT_FALSE(workDir.isEmpty());
289         static const char *const DIR_NAMES[] = { "foo", "bar", NULL };
290         for (size_t i = 0; DIR_NAMES[i]; i++)
291         {
292                 QDir dir(workDir);
293                 MAKE_SUB_DIR(dir, QLatin1String(DIR_NAMES[i]));
294                 for (size_t j = 0; DIR_NAMES[j]; j++)
295                 {
296                         QDir subdir(dir);
297                         MAKE_SUB_DIR(subdir, QLatin1String(DIR_NAMES[j]));
298                         QFile test(subdir.filePath("example.txt"));
299                         MAKE_TEST_FILE(test);
300                         test.close();
301                 }
302         }
303         for (size_t i = 0; DIR_NAMES[i]; i++)
304         {
305                 QDir dir(QString("%1/%2").arg(workDir, QLatin1String(DIR_NAMES[i])));
306                 ASSERT_TRUE(dir.exists());
307                 ASSERT_FALSE(MUtils::remove_directory(dir.absolutePath(), false));
308                 dir.refresh();
309                 ASSERT_TRUE(dir.exists());
310                 ASSERT_TRUE(MUtils::remove_directory(dir.absolutePath(), true));
311                 dir.refresh();
312                 ASSERT_FALSE(dir.exists());
313         }
314 }
315
316 #undef MAKE_TEST_FILE
317 #undef MAKE_SUB_DIR
318
319 //-----------------------------------------------------------------
320 // Natural String Sort
321 //-----------------------------------------------------------------
322
323 TEST_F(GlobalTest, NaturalStrSort)
324 {
325         static const char *const TEST[] =
326         {
327                 "z0.txt",   "z1.txt",   "z2.txt",   "z3.txt",   "z4.txt",   "z5.txt",   "z6.txt",   "z7.txt",   "z8.txt",   "z9.txt",
328                 "z10.txt",  "z11.txt",  "z12.txt",  "z13.txt",  "z14.txt",  "z15.txt",  "z16.txt",  "z17.txt",  "z18.txt",  "z19.txt",
329                 "z100.txt", "z101.txt", "z102.txt", "z103.txt", "z104.txt", "z105.txt", "z106.txt", "z107.txt", "z108.txt", "z109.txt",
330                 NULL
331         };
332
333         QStringList test;
334         for (size_t i = 0; TEST[i]; i++)
335         {
336                 test << QLatin1String(TEST[i]);
337         }
338
339         qsrand(time(NULL));
340         for (size_t q = 0; q < 97; q++)
341         {
342                 for (size_t k = 0; k < 997; k++)
343                 {
344                         const size_t len = size_t(test.count());
345                         for (size_t i = 0; i < len; i++)
346                         {
347                                 test.swap(i, qrand() % len);
348                         }
349                 }
350                 MUtils::natural_string_sort(test, true);
351                 for (size_t i = 0; TEST[i]; i++)
352                 {
353                         ASSERT_QSTR(test[i], TEST[i]);
354                 }
355         }
356 }
357
358 //-----------------------------------------------------------------
359 // RegExp Parser
360 //-----------------------------------------------------------------
361
362 #define TEST_REGEX_U32(X,Y,Z,...) do \
363 { \
364         const QRegExp test(QLatin1String((X))); \
365         ASSERT_GE(test.indexIn(QLatin1String((Y))), 0); \
366         quint32 result[(Z)]; \
367         ASSERT_TRUE(MUtils::regexp_parse_uint32(test, result, (Z))); \
368         const quint32 expected[] = { __VA_ARGS__ }; \
369         for(size_t i = 0; i < (Z); i++) \
370         { \
371                 ASSERT_EQ(result[i], expected[i]); \
372         } \
373 } \
374 while(0)
375
376 TEST_F(GlobalTest, ParseRegExp)
377 {
378         TEST_REGEX_U32("(\\d+)", "42", 1, 42);
379         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);
380         TEST_REGEX_U32("x264\\s+(\\d+)\\.(\\d+)\\.(\\d+)\\s+\\w+", "x264 0.148.2744 b97ae06", 3, 0, 148, 2744);
381         TEST_REGEX_U32("HEVC\\s+encoder\\s+version\\s+(\\d+)\\.(\\d+)\\+(\\d+)-\\w+", "HEVC encoder version 2.1+70-78e1e1354a25", 3, 2, 1, 70);
382 }
383
384 #undef TEST_REGEX_U32