1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | |
30 | #include <QtTest/QtTest> |
31 | |
32 | #include <qcoreapplication.h> |
33 | #include <qdebug.h> |
34 | #include <qdiriterator.h> |
35 | #include <qfileinfo.h> |
36 | #include <qstringlist.h> |
37 | |
38 | #include <QtCore/private/qfsfileengine_p.h> |
39 | |
40 | #if defined(Q_OS_VXWORKS) || defined(Q_OS_WINRT) |
41 | #define Q_NO_SYMLINKS |
42 | #endif |
43 | |
44 | #if defined(Q_OS_WIN) |
45 | # include "../../../network-settings.h" |
46 | #endif |
47 | |
48 | Q_DECLARE_METATYPE(QDirIterator::IteratorFlags) |
49 | Q_DECLARE_METATYPE(QDir::Filters) |
50 | |
51 | class tst_QDirIterator : public QObject |
52 | { |
53 | Q_OBJECT |
54 | |
55 | private: // convenience functions |
56 | QStringList createdDirectories; |
57 | QStringList createdFiles; |
58 | |
59 | QDir currentDir; |
60 | bool createDirectory(const QString &dirName) |
61 | { |
62 | if (currentDir.mkdir(dirName)) { |
63 | createdDirectories.prepend(t: dirName); |
64 | return true; |
65 | } |
66 | return false; |
67 | } |
68 | |
69 | enum Cleanup { DoDelete, DontDelete }; |
70 | bool createFile(const QString &fileName, Cleanup cleanup = DoDelete) |
71 | { |
72 | QFile file(fileName); |
73 | if (file.open(flags: QIODevice::WriteOnly)) { |
74 | if (cleanup == DoDelete) |
75 | createdFiles << fileName; |
76 | return true; |
77 | } |
78 | return false; |
79 | } |
80 | |
81 | bool createLink(const QString &destination, const QString &linkName) |
82 | { |
83 | if (QFile::link(oldname: destination, newName: linkName)) { |
84 | createdFiles << linkName; |
85 | return true; |
86 | } |
87 | return false; |
88 | } |
89 | |
90 | private slots: |
91 | void initTestCase(); |
92 | void cleanupTestCase(); |
93 | void iterateRelativeDirectory_data(); |
94 | void iterateRelativeDirectory(); |
95 | void iterateResource_data(); |
96 | void iterateResource(); |
97 | void stopLinkLoop(); |
98 | #ifdef QT_BUILD_INTERNAL |
99 | void engineWithNoIterator(); |
100 | #endif |
101 | void absoluteFilePathsFromRelativeIteratorPath(); |
102 | void recurseWithFilters() const; |
103 | void longPath(); |
104 | void dirorder(); |
105 | void relativePaths(); |
106 | #if defined(Q_OS_WIN) |
107 | void uncPaths_data(); |
108 | void uncPaths(); |
109 | #endif |
110 | #ifndef Q_OS_WIN |
111 | void hiddenDirs_hiddenFiles(); |
112 | #endif |
113 | #ifdef BUILTIN_TESTDATA |
114 | private: |
115 | QSharedPointer<QTemporaryDir> m_dataDir; |
116 | #endif |
117 | }; |
118 | |
119 | void tst_QDirIterator::initTestCase() |
120 | { |
121 | #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) |
122 | QString testdata_dir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); |
123 | QString resourceSourcePath = QStringLiteral(":/testdata" ); |
124 | QDirIterator it(resourceSourcePath, QDirIterator::Subdirectories); |
125 | while (it.hasNext()) { |
126 | it.next(); |
127 | |
128 | QFileInfo fileInfo = it.fileInfo(); |
129 | |
130 | if (!fileInfo.isDir()) { |
131 | QString destination = testdata_dir + QLatin1Char('/') + fileInfo.filePath().mid(resourceSourcePath.length()); |
132 | QFileInfo destinationFileInfo(destination); |
133 | if (!destinationFileInfo.exists()) { |
134 | QDir().mkpath(destinationFileInfo.path()); |
135 | if (!QFile::copy(fileInfo.filePath(), destination)) |
136 | qWarning("Failed to copy %s" , qPrintable(fileInfo.filePath())); |
137 | } |
138 | } |
139 | |
140 | } |
141 | |
142 | testdata_dir += QStringLiteral("/entrylist" ); |
143 | #elif defined(BUILTIN_TESTDATA) |
144 | m_dataDir = QEXTRACTTESTDATA("/testdata" ); |
145 | QVERIFY2(!m_dataDir.isNull(), qPrintable("Could not extract test data" )); |
146 | QString testdata_dir = m_dataDir->path(); |
147 | #else |
148 | |
149 | // chdir into testdata directory, then find testdata by relative paths. |
150 | QString testdata_dir = QFileInfo(QFINDTESTDATA("entrylist" )).absolutePath(); |
151 | #endif |
152 | |
153 | QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir)); |
154 | |
155 | QFile::remove(fileName: "entrylist/entrylist1.lnk" ); |
156 | QFile::remove(fileName: "entrylist/entrylist2.lnk" ); |
157 | QFile::remove(fileName: "entrylist/entrylist3.lnk" ); |
158 | QFile::remove(fileName: "entrylist/entrylist4.lnk" ); |
159 | QFile::remove(fileName: "entrylist/directory/entrylist1.lnk" ); |
160 | QFile::remove(fileName: "entrylist/directory/entrylist2.lnk" ); |
161 | QFile::remove(fileName: "entrylist/directory/entrylist3.lnk" ); |
162 | QFile::remove(fileName: "entrylist/directory/entrylist4.lnk" ); |
163 | |
164 | createDirectory(dirName: "entrylist" ); |
165 | createDirectory(dirName: "entrylist/directory" ); |
166 | createFile(fileName: "entrylist/file" , cleanup: DontDelete); |
167 | createFile(fileName: "entrylist/writable" ); |
168 | createFile(fileName: "entrylist/directory/dummy" , cleanup: DontDelete); |
169 | |
170 | createDirectory(dirName: "recursiveDirs" ); |
171 | createDirectory(dirName: "recursiveDirs/dir1" ); |
172 | createFile(fileName: "recursiveDirs/textFileA.txt" ); |
173 | createFile(fileName: "recursiveDirs/dir1/aPage.html" ); |
174 | createFile(fileName: "recursiveDirs/dir1/textFileB.txt" ); |
175 | |
176 | createDirectory(dirName: "foo" ); |
177 | createDirectory(dirName: "foo/bar" ); |
178 | createFile(fileName: "foo/bar/readme.txt" ); |
179 | |
180 | createDirectory(dirName: "empty" ); |
181 | |
182 | #ifndef Q_NO_SYMLINKS |
183 | # if defined(Q_OS_WIN) |
184 | // ### Sadly, this is a platform difference right now. |
185 | createLink("entrylist/file" , "entrylist/linktofile.lnk" ); |
186 | # ifndef Q_NO_SYMLINKS_TO_DIRS |
187 | createLink("entrylist/directory" , "entrylist/linktodirectory.lnk" ); |
188 | # endif |
189 | createLink("entrylist/nothing" , "entrylist/brokenlink.lnk" ); |
190 | # else |
191 | createLink(destination: "file" , linkName: "entrylist/linktofile.lnk" ); |
192 | # ifndef Q_NO_SYMLINKS_TO_DIRS |
193 | createLink(destination: "directory" , linkName: "entrylist/linktodirectory.lnk" ); |
194 | # endif |
195 | createLink(destination: "nothing" , linkName: "entrylist/brokenlink.lnk" ); |
196 | # endif |
197 | #endif |
198 | |
199 | #if !defined(Q_OS_WIN) |
200 | createDirectory(dirName: "hiddenDirs_hiddenFiles" ); |
201 | createFile(fileName: "hiddenDirs_hiddenFiles/normalFile" ); |
202 | createFile(fileName: "hiddenDirs_hiddenFiles/.hiddenFile" ); |
203 | createDirectory(dirName: "hiddenDirs_hiddenFiles/normalDirectory" ); |
204 | createDirectory(dirName: "hiddenDirs_hiddenFiles/.hiddenDirectory" ); |
205 | createFile(fileName: "hiddenDirs_hiddenFiles/normalDirectory/normalFile" ); |
206 | createFile(fileName: "hiddenDirs_hiddenFiles/normalDirectory/.hiddenFile" ); |
207 | createFile(fileName: "hiddenDirs_hiddenFiles/.hiddenDirectory/normalFile" ); |
208 | createFile(fileName: "hiddenDirs_hiddenFiles/.hiddenDirectory/.hiddenFile" ); |
209 | createDirectory(dirName: "hiddenDirs_hiddenFiles/normalDirectory/normalDirectory" ); |
210 | createDirectory(dirName: "hiddenDirs_hiddenFiles/normalDirectory/.hiddenDirectory" ); |
211 | createDirectory(dirName: "hiddenDirs_hiddenFiles/.hiddenDirectory/normalDirectory" ); |
212 | createDirectory(dirName: "hiddenDirs_hiddenFiles/.hiddenDirectory/.hiddenDirectory" ); |
213 | #endif |
214 | } |
215 | |
216 | void tst_QDirIterator::cleanupTestCase() |
217 | { |
218 | Q_FOREACH(QString fileName, createdFiles) |
219 | QFile::remove(fileName); |
220 | |
221 | Q_FOREACH(QString dirName, createdDirectories) |
222 | currentDir.rmdir(dirName); |
223 | |
224 | #ifdef Q_OS_WINRT |
225 | QDir::setCurrent(QCoreApplication::applicationDirPath()); |
226 | #endif // Q_OS_WINRT |
227 | |
228 | } |
229 | |
230 | void tst_QDirIterator::iterateRelativeDirectory_data() |
231 | { |
232 | QTest::addColumn<QString>(name: "dirName" ); // relative from current path or abs |
233 | QTest::addColumn<QDirIterator::IteratorFlags>(name: "flags" ); |
234 | QTest::addColumn<QDir::Filters>(name: "filters" ); |
235 | QTest::addColumn<QStringList>(name: "nameFilters" ); |
236 | QTest::addColumn<QStringList>(name: "entries" ); |
237 | |
238 | QTest::newRow(dataTag: "no flags" ) |
239 | << QString("entrylist" ) << QDirIterator::IteratorFlags{} |
240 | << QDir::Filters(QDir::NoFilter) << QStringList("*" ) |
241 | << QString( |
242 | "entrylist/.," |
243 | "entrylist/..," |
244 | "entrylist/file," |
245 | #ifndef Q_NO_SYMLINKS |
246 | "entrylist/linktofile.lnk," |
247 | #endif |
248 | "entrylist/directory," |
249 | #if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS) |
250 | "entrylist/linktodirectory.lnk," |
251 | #endif |
252 | "entrylist/writable" ).split(sep: ','); |
253 | |
254 | QTest::newRow(dataTag: "NoDot" ) |
255 | << QString("entrylist" ) << QDirIterator::IteratorFlags{} |
256 | << QDir::Filters(QDir::AllEntries | QDir::NoDot) << QStringList("*" ) |
257 | << QString( |
258 | "entrylist/..," |
259 | "entrylist/file," |
260 | #ifndef Q_NO_SYMLINKS |
261 | "entrylist/linktofile.lnk," |
262 | #endif |
263 | "entrylist/directory," |
264 | #if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS) |
265 | "entrylist/linktodirectory.lnk," |
266 | #endif |
267 | "entrylist/writable" ).split(sep: ','); |
268 | |
269 | QTest::newRow(dataTag: "NoDotDot" ) |
270 | << QString("entrylist" ) << QDirIterator::IteratorFlags{} |
271 | << QDir::Filters(QDir::AllEntries | QDir::NoDotDot) << QStringList("*" ) |
272 | << QString( |
273 | "entrylist/.," |
274 | "entrylist/file," |
275 | #ifndef Q_NO_SYMLINKS |
276 | "entrylist/linktofile.lnk," |
277 | #endif |
278 | "entrylist/directory," |
279 | #if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS) |
280 | "entrylist/linktodirectory.lnk," |
281 | #endif |
282 | "entrylist/writable" ).split(sep: ','); |
283 | |
284 | QTest::newRow(dataTag: "NoDotAndDotDot" ) |
285 | << QString("entrylist" ) << QDirIterator::IteratorFlags{} |
286 | << QDir::Filters(QDir::AllEntries | QDir::NoDotAndDotDot) << QStringList("*" ) |
287 | << QString( |
288 | "entrylist/file," |
289 | #ifndef Q_NO_SYMLINKS |
290 | "entrylist/linktofile.lnk," |
291 | #endif |
292 | "entrylist/directory," |
293 | #if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS) |
294 | "entrylist/linktodirectory.lnk," |
295 | #endif |
296 | "entrylist/writable" ).split(sep: ','); |
297 | |
298 | QTest::newRow(dataTag: "QDir::Subdirectories | QDir::FollowSymlinks" ) |
299 | << QString("entrylist" ) << QDirIterator::IteratorFlags(QDirIterator::Subdirectories | QDirIterator::FollowSymlinks) |
300 | << QDir::Filters(QDir::NoFilter) << QStringList("*" ) |
301 | << QString( |
302 | "entrylist/.," |
303 | "entrylist/..," |
304 | "entrylist/directory/.," |
305 | "entrylist/directory/..," |
306 | "entrylist/file," |
307 | #ifndef Q_NO_SYMLINKS |
308 | "entrylist/linktofile.lnk," |
309 | #endif |
310 | "entrylist/directory," |
311 | "entrylist/directory/dummy," |
312 | #if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS) |
313 | "entrylist/linktodirectory.lnk," |
314 | #endif |
315 | "entrylist/writable" ).split(sep: ','); |
316 | |
317 | QTest::newRow(dataTag: "QDir::Subdirectories / QDir::Files" ) |
318 | << QString("entrylist" ) << QDirIterator::IteratorFlags(QDirIterator::Subdirectories) |
319 | << QDir::Filters(QDir::Files) << QStringList("*" ) |
320 | << QString("entrylist/directory/dummy," |
321 | "entrylist/file," |
322 | #ifndef Q_NO_SYMLINKS |
323 | "entrylist/linktofile.lnk," |
324 | #endif |
325 | "entrylist/writable" ).split(sep: ','); |
326 | |
327 | QTest::newRow(dataTag: "QDir::Subdirectories | QDir::FollowSymlinks / QDir::Files" ) |
328 | << QString("entrylist" ) << QDirIterator::IteratorFlags(QDirIterator::Subdirectories | QDirIterator::FollowSymlinks) |
329 | << QDir::Filters(QDir::Files) << QStringList("*" ) |
330 | << QString("entrylist/file," |
331 | #ifndef Q_NO_SYMLINKS |
332 | "entrylist/linktofile.lnk," |
333 | #endif |
334 | "entrylist/directory/dummy," |
335 | "entrylist/writable" ).split(sep: ','); |
336 | |
337 | QTest::newRow(dataTag: "empty, default" ) |
338 | << QString("empty" ) << QDirIterator::IteratorFlags{} |
339 | << QDir::Filters(QDir::NoFilter) << QStringList("*" ) |
340 | << QString("empty/.,empty/.." ).split(sep: ','); |
341 | |
342 | QTest::newRow(dataTag: "empty, QDir::NoDotAndDotDot" ) |
343 | << QString("empty" ) << QDirIterator::IteratorFlags{} |
344 | << QDir::Filters(QDir::NoDotAndDotDot) << QStringList("*" ) |
345 | << QStringList(); |
346 | } |
347 | |
348 | void tst_QDirIterator::iterateRelativeDirectory() |
349 | { |
350 | QFETCH(QString, dirName); |
351 | QFETCH(QDirIterator::IteratorFlags, flags); |
352 | QFETCH(QDir::Filters, filters); |
353 | QFETCH(QStringList, nameFilters); |
354 | QFETCH(QStringList, entries); |
355 | |
356 | QDirIterator it(dirName, nameFilters, filters, flags); |
357 | QStringList list; |
358 | while (it.hasNext()) { |
359 | QString next = it.next(); |
360 | |
361 | QString fileName = it.fileName(); |
362 | QString filePath = it.filePath(); |
363 | QString path = it.path(); |
364 | |
365 | QFileInfo info = it.fileInfo(); |
366 | |
367 | QCOMPARE(path, dirName); |
368 | QCOMPARE(next, filePath); |
369 | |
370 | QCOMPARE(info, QFileInfo(next)); |
371 | QCOMPARE(fileName, info.fileName()); |
372 | QCOMPARE(filePath, info.filePath()); |
373 | |
374 | // Using canonical file paths for final comparison |
375 | list << info.canonicalFilePath(); |
376 | } |
377 | |
378 | // The order of items returned by QDirIterator is not guaranteed. |
379 | list.sort(); |
380 | |
381 | QStringList sortedEntries; |
382 | foreach(QString item, entries) |
383 | sortedEntries.append(t: QFileInfo(item).canonicalFilePath()); |
384 | sortedEntries.sort(); |
385 | |
386 | if (sortedEntries != list) { |
387 | qDebug() << "EXPECTED:" << sortedEntries; |
388 | qDebug() << "ACTUAL: " << list; |
389 | } |
390 | |
391 | QCOMPARE(list, sortedEntries); |
392 | } |
393 | |
394 | void tst_QDirIterator::iterateResource_data() |
395 | { |
396 | QTest::addColumn<QString>(name: "dirName" ); // relative from current path or abs |
397 | QTest::addColumn<QDirIterator::IteratorFlags>(name: "flags" ); |
398 | QTest::addColumn<QDir::Filters>(name: "filters" ); |
399 | QTest::addColumn<QStringList>(name: "nameFilters" ); |
400 | QTest::addColumn<QStringList>(name: "entries" ); |
401 | |
402 | QTest::newRow(dataTag: "invalid" ) << QString::fromLatin1(str: ":/testdata/burpaburpa" ) << QDirIterator::IteratorFlags{} |
403 | << QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*" )) |
404 | << QStringList(); |
405 | QTest::newRow(dataTag: ":/testdata" ) << QString::fromLatin1(str: ":/testdata/" ) << QDirIterator::IteratorFlags{} |
406 | << QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*" )) |
407 | << QString::fromLatin1(str: ":/testdata/entrylist" ).split(sep: QLatin1String("," )); |
408 | QTest::newRow(dataTag: ":/testdata/entrylist" ) << QString::fromLatin1(str: ":/testdata/entrylist" ) << QDirIterator::IteratorFlags{} |
409 | << QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*" )) |
410 | << QString::fromLatin1(str: ":/testdata/entrylist/directory,:/testdata/entrylist/file" ).split(sep: QLatin1String("," )); |
411 | QTest::newRow(dataTag: ":/testdata recursive" ) << QString::fromLatin1(str: ":/testdata" ) << QDirIterator::IteratorFlags(QDirIterator::Subdirectories) |
412 | << QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*" )) |
413 | << QString::fromLatin1(str: ":/testdata/entrylist,:/testdata/entrylist/directory,:/testdata/entrylist/directory/dummy,:/testdata/entrylist/file" ).split(sep: QLatin1String("," )); |
414 | } |
415 | |
416 | void tst_QDirIterator::iterateResource() |
417 | { |
418 | QFETCH(QString, dirName); |
419 | QFETCH(QDirIterator::IteratorFlags, flags); |
420 | QFETCH(QDir::Filters, filters); |
421 | QFETCH(QStringList, nameFilters); |
422 | QFETCH(QStringList, entries); |
423 | |
424 | QDirIterator it(dirName, nameFilters, filters, flags); |
425 | QStringList list; |
426 | while (it.hasNext()) { |
427 | const QString dir = it.next(); |
428 | if (!dir.startsWith(s: ":/qt-project.org" )) |
429 | list << dir; |
430 | } |
431 | |
432 | list.sort(); |
433 | QStringList sortedEntries = entries; |
434 | sortedEntries.sort(); |
435 | |
436 | if (sortedEntries != list) { |
437 | qDebug() << "EXPECTED:" << sortedEntries; |
438 | qDebug() << "ACTUAL:" << list; |
439 | } |
440 | |
441 | QCOMPARE(list, sortedEntries); |
442 | } |
443 | |
444 | void tst_QDirIterator::stopLinkLoop() |
445 | { |
446 | #ifdef Q_OS_WIN |
447 | // ### Sadly, this is a platform difference right now. |
448 | createLink(QDir::currentPath() + QLatin1String("/entrylist" ), "entrylist/entrylist1.lnk" ); |
449 | createLink("entrylist/." , "entrylist/entrylist2.lnk" ); |
450 | createLink("entrylist/../entrylist/." , "entrylist/entrylist3.lnk" ); |
451 | createLink("entrylist/.." , "entrylist/entrylist4.lnk" ); |
452 | createLink(QDir::currentPath() + QLatin1String("/entrylist" ), "entrylist/directory/entrylist1.lnk" ); |
453 | createLink("entrylist/." , "entrylist/directory/entrylist2.lnk" ); |
454 | createLink("entrylist/../directory/." , "entrylist/directory/entrylist3.lnk" ); |
455 | createLink("entrylist/.." , "entrylist/directory/entrylist4.lnk" ); |
456 | #else |
457 | createLink(destination: QDir::currentPath() + QLatin1String("/entrylist" ), linkName: "entrylist/entrylist1.lnk" ); |
458 | createLink(destination: "." , linkName: "entrylist/entrylist2.lnk" ); |
459 | createLink(destination: "../entrylist/." , linkName: "entrylist/entrylist3.lnk" ); |
460 | createLink(destination: ".." , linkName: "entrylist/entrylist4.lnk" ); |
461 | createLink(destination: QDir::currentPath() + QLatin1String("/entrylist" ), linkName: "entrylist/directory/entrylist1.lnk" ); |
462 | createLink(destination: "." , linkName: "entrylist/directory/entrylist2.lnk" ); |
463 | createLink(destination: "../directory/." , linkName: "entrylist/directory/entrylist3.lnk" ); |
464 | createLink(destination: ".." , linkName: "entrylist/directory/entrylist4.lnk" ); |
465 | #endif |
466 | |
467 | QDirIterator it(QLatin1String("entrylist" ), QDirIterator::Subdirectories | QDirIterator::FollowSymlinks); |
468 | QStringList list; |
469 | int max = 200; |
470 | while (--max && it.hasNext()) |
471 | it.next(); |
472 | QVERIFY(max); |
473 | |
474 | // The goal of this test is only to ensure that the test above don't malfunction |
475 | } |
476 | |
477 | #ifdef QT_BUILD_INTERNAL |
478 | class EngineWithNoIterator : public QFSFileEngine |
479 | { |
480 | public: |
481 | EngineWithNoIterator(const QString &fileName) |
482 | : QFSFileEngine(fileName) |
483 | { } |
484 | |
485 | QAbstractFileEngineIterator *beginEntryList(QDir::Filters, const QStringList &) |
486 | { return 0; } |
487 | }; |
488 | |
489 | class EngineWithNoIteratorHandler : public QAbstractFileEngineHandler |
490 | { |
491 | public: |
492 | QAbstractFileEngine *create(const QString &fileName) const |
493 | { |
494 | return new EngineWithNoIterator(fileName); |
495 | } |
496 | }; |
497 | #endif |
498 | |
499 | #ifdef QT_BUILD_INTERNAL |
500 | void tst_QDirIterator::engineWithNoIterator() |
501 | { |
502 | EngineWithNoIteratorHandler handler; |
503 | |
504 | QDir("entrylist" ).entryList(); |
505 | QVERIFY(true); // test that the above line doesn't crash |
506 | } |
507 | #endif |
508 | |
509 | void tst_QDirIterator::absoluteFilePathsFromRelativeIteratorPath() |
510 | { |
511 | QDirIterator it("entrylist/" , QDir::NoDotAndDotDot); |
512 | while (it.hasNext()) { |
513 | it.next(); |
514 | QVERIFY(QFileInfo(it.filePath()).absoluteFilePath().contains("entrylist" )); |
515 | } |
516 | } |
517 | |
518 | void tst_QDirIterator::recurseWithFilters() const |
519 | { |
520 | QStringList nameFilters; |
521 | nameFilters.append(t: "*.txt" ); |
522 | |
523 | QDirIterator it("recursiveDirs/" , nameFilters, QDir::Files, |
524 | QDirIterator::Subdirectories); |
525 | |
526 | QSet<QString> actualEntries; |
527 | QSet<QString> expectedEntries; |
528 | expectedEntries.insert(value: QString::fromLatin1(str: "recursiveDirs/dir1/textFileB.txt" )); |
529 | expectedEntries.insert(value: QString::fromLatin1(str: "recursiveDirs/textFileA.txt" )); |
530 | |
531 | QVERIFY(it.hasNext()); |
532 | it.next(); |
533 | actualEntries.insert(value: it.fileInfo().filePath()); |
534 | QVERIFY(it.hasNext()); |
535 | it.next(); |
536 | actualEntries.insert(value: it.fileInfo().filePath()); |
537 | QCOMPARE(actualEntries, expectedEntries); |
538 | |
539 | QVERIFY(!it.hasNext()); |
540 | } |
541 | |
542 | void tst_QDirIterator::longPath() |
543 | { |
544 | QDir dir; |
545 | dir.mkdir(dirName: "longpaths" ); |
546 | dir.cd(dirName: "longpaths" ); |
547 | |
548 | QString dirName = "x" ; |
549 | int n = 0; |
550 | while (dir.exists(name: dirName) || dir.mkdir(dirName)) { |
551 | ++n; |
552 | dirName.append(c: 'x'); |
553 | } |
554 | |
555 | QDirIterator it(dir.absolutePath(), QDir::NoDotAndDotDot|QDir::Dirs, QDirIterator::Subdirectories); |
556 | int m = 0; |
557 | while (it.hasNext()) { |
558 | ++m; |
559 | it.next(); |
560 | } |
561 | |
562 | QCOMPARE(n, m); |
563 | |
564 | dirName.chop(n: 1); |
565 | while (dirName.length() > 0 && dir.exists(name: dirName) && dir.rmdir(dirName)) { |
566 | dirName.chop(n: 1); |
567 | } |
568 | dir.cdUp(); |
569 | dir.rmdir(dirName: "longpaths" ); |
570 | } |
571 | |
572 | void tst_QDirIterator::dirorder() |
573 | { |
574 | QDirIterator iterator("foo" , QDirIterator::Subdirectories); |
575 | while (iterator.hasNext() && iterator.next() != "foo/bar" ) |
576 | { } |
577 | |
578 | QCOMPARE(iterator.filePath(), QString("foo/bar" )); |
579 | QCOMPARE(iterator.fileInfo().filePath(), QString("foo/bar" )); |
580 | } |
581 | |
582 | void tst_QDirIterator::relativePaths() |
583 | { |
584 | QDirIterator iterator("*" , QDirIterator::Subdirectories); |
585 | while(iterator.hasNext()) { |
586 | QCOMPARE(iterator.filePath(), QDir::cleanPath(iterator.filePath())); |
587 | } |
588 | } |
589 | |
590 | #if defined(Q_OS_WIN) |
591 | void tst_QDirIterator::uncPaths_data() |
592 | { |
593 | QTest::addColumn<QString>("dirName" ); |
594 | QTest::newRow("uncserver" ) |
595 | <<QString("//" + QtNetworkSettings::winServerName()); |
596 | QTest::newRow("uncserver/testshare" ) |
597 | <<QString("//" + QtNetworkSettings::winServerName() + "/testshare" ); |
598 | QTest::newRow("uncserver/testshare/tmp" ) |
599 | <<QString("//" + QtNetworkSettings::winServerName() + "/testshare/tmp" ); |
600 | } |
601 | void tst_QDirIterator::uncPaths() |
602 | { |
603 | QFETCH(QString, dirName); |
604 | QDirIterator iterator(dirName, QDir::AllEntries|QDir::NoDotAndDotDot, QDirIterator::Subdirectories); |
605 | while(iterator.hasNext()) { |
606 | iterator.next(); |
607 | QCOMPARE(iterator.filePath(), QDir::cleanPath(iterator.filePath())); |
608 | } |
609 | } |
610 | #endif |
611 | |
612 | #ifndef Q_OS_WIN |
613 | // In Unix it is easy to create hidden files, but in Windows it requires |
614 | // a special call since hidden files need to be "marked" while in Unix |
615 | // anything starting by a '.' is a hidden file. |
616 | // For that reason this test is not run in Windows. |
617 | void tst_QDirIterator::hiddenDirs_hiddenFiles() |
618 | { |
619 | // Only files |
620 | { |
621 | int matches = 0; |
622 | int failures = 0; |
623 | QDirIterator di("hiddenDirs_hiddenFiles" , QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); |
624 | while (di.hasNext()) { |
625 | ++matches; |
626 | QString filename = di.next(); |
627 | if (QFileInfo(filename).isDir()) |
628 | ++failures; // search was only supposed to find files |
629 | } |
630 | QCOMPARE(matches, 6); |
631 | QCOMPARE(failures, 0); |
632 | } |
633 | // Only directories |
634 | { |
635 | int matches = 0; |
636 | int failures = 0; |
637 | QDirIterator di("hiddenDirs_hiddenFiles" , QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); |
638 | while (di.hasNext()) { |
639 | ++matches; |
640 | QString filename = di.next(); |
641 | if (!QFileInfo(filename).isDir()) |
642 | ++failures; // search was only supposed to find files |
643 | } |
644 | QCOMPARE(matches, 6); |
645 | QCOMPARE(failures, 0); |
646 | } |
647 | } |
648 | #endif // Q_OS_WIN |
649 | |
650 | QTEST_MAIN(tst_QDirIterator) |
651 | |
652 | #include "tst_qdiriterator.moc" |
653 | |
654 | |