| 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 | |