tests/auto/qdiriterator/tst_qdiriterator.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtTest/QtTest>
       
    44 
       
    45 #include <qcoreapplication.h>
       
    46 #include <qdebug.h>
       
    47 #include <qdiriterator.h>
       
    48 #include <qfileinfo.h>
       
    49 #include <qstringlist.h>
       
    50 
       
    51 #if defined(Q_OS_VXWORKS)
       
    52 #define Q_NO_SYMLINKS
       
    53 #endif
       
    54 
       
    55 #if defined(Q_OS_SYMBIAN)
       
    56 // Open C in Symbian doesn't support symbolic links to directories
       
    57 #define Q_NO_SYMLINKS_TO_DIRS
       
    58 #endif
       
    59 
       
    60 Q_DECLARE_METATYPE(QDirIterator::IteratorFlags)
       
    61 Q_DECLARE_METATYPE(QDir::Filters)
       
    62 
       
    63 //TESTED_CLASS=
       
    64 //TESTED_FILES=
       
    65 
       
    66 class tst_QDirIterator : public QObject
       
    67 {
       
    68     Q_OBJECT
       
    69 
       
    70 public:
       
    71     tst_QDirIterator();
       
    72     virtual ~tst_QDirIterator();
       
    73 
       
    74 private slots:
       
    75     void iterateRelativeDirectory_data();
       
    76     void iterateRelativeDirectory();
       
    77     void iterateResource_data();
       
    78     void iterateResource();
       
    79     void stopLinkLoop();
       
    80     void engineWithNoIterator();
       
    81     void absoluteFilePathsFromRelativeIteratorPath();
       
    82     void recurseWithFilters() const;
       
    83     void longPath();
       
    84     void task185502_dirorder();
       
    85     void relativePaths();
       
    86 };
       
    87 
       
    88 tst_QDirIterator::tst_QDirIterator()
       
    89 {
       
    90     QFile::remove("entrylist/entrylist1.lnk");
       
    91     QFile::remove("entrylist/entrylist2.lnk");
       
    92     QFile::remove("entrylist/entrylist3.lnk");
       
    93     QFile::remove("entrylist/entrylist4.lnk");
       
    94     QFile::remove("entrylist/directory/entrylist1.lnk");
       
    95     QFile::remove("entrylist/directory/entrylist2.lnk");
       
    96     QFile::remove("entrylist/directory/entrylist3.lnk");
       
    97     QFile::remove("entrylist/directory/entrylist4.lnk");
       
    98 
       
    99 #ifndef Q_NO_SYMLINKS
       
   100 #  if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
       
   101     // ### Sadly, this is a platform difference right now.
       
   102     QFile::link("entrylist/file", "entrylist/linktofile.lnk");
       
   103 #    ifndef Q_NO_SYMLINKS_TO_DIRS
       
   104     QFile::link("entrylist/directory", "entrylist/linktodirectory.lnk");
       
   105 #    endif
       
   106     QFile::link("entrylist/nothing", "entrylist/brokenlink.lnk");
       
   107 #  else
       
   108     QFile::link("file", "entrylist/linktofile.lnk");
       
   109 #    ifndef Q_NO_SYMLINKS_TO_DIRS
       
   110     QFile::link("directory", "entrylist/linktodirectory.lnk");
       
   111 #    endif
       
   112     QFile::link("nothing", "entrylist/brokenlink.lnk");
       
   113 #  endif
       
   114 #endif
       
   115     QFile("entrylist/writable").open(QIODevice::ReadWrite);
       
   116 }
       
   117 
       
   118 tst_QDirIterator::~tst_QDirIterator()
       
   119 {
       
   120     QFile::remove("entrylist/directory");
       
   121     QFile::remove("entrylist/linktofile.lnk");
       
   122     QFile::remove("entrylist/linktodirectory.lnk");
       
   123     QFile::remove("entrylist/brokenlink.lnk");
       
   124     QFile::remove("entrylist/brokenlink");
       
   125     QFile::remove("entrylist/writable");
       
   126     QFile::remove("entrylist/entrylist1.lnk");
       
   127     QFile::remove("entrylist/entrylist2.lnk");
       
   128     QFile::remove("entrylist/entrylist3.lnk");
       
   129     QFile::remove("entrylist/entrylist4.lnk");
       
   130     QFile::remove("entrylist/directory/entrylist1.lnk");
       
   131     QFile::remove("entrylist/directory/entrylist2.lnk");
       
   132     QFile::remove("entrylist/directory/entrylist3.lnk");
       
   133     QFile::remove("entrylist/directory/entrylist4.lnk");
       
   134 }
       
   135 
       
   136 void tst_QDirIterator::iterateRelativeDirectory_data()
       
   137 {
       
   138     QTest::addColumn<QString>("dirName"); // relative from current path or abs
       
   139     QTest::addColumn<QDirIterator::IteratorFlags>("flags");
       
   140     QTest::addColumn<QDir::Filters>("filters");
       
   141     QTest::addColumn<QStringList>("nameFilters");
       
   142     QTest::addColumn<QStringList>("entries");
       
   143 
       
   144     QTest::newRow("no flags")
       
   145         << QString("entrylist") << QDirIterator::IteratorFlags(0)
       
   146         << QDir::Filters(QDir::NoFilter) << QStringList("*")
       
   147         << QString(
       
   148 #if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
       
   149                   "entrylist/.,"
       
   150                    "entrylist/..,"
       
   151 #endif
       
   152                    "entrylist/file,"
       
   153 #ifndef Q_NO_SYMLINKS
       
   154                    "entrylist/linktofile.lnk,"
       
   155 #endif
       
   156                    "entrylist/directory,"
       
   157 #if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS)
       
   158                    "entrylist/linktodirectory.lnk,"
       
   159 #endif
       
   160                    "entrylist/writable").split(',');
       
   161 
       
   162     QTest::newRow("QDir::Subdirectories | QDir::FollowSymlinks")
       
   163         << QString("entrylist") << QDirIterator::IteratorFlags(QDirIterator::Subdirectories | QDirIterator::FollowSymlinks)
       
   164         << QDir::Filters(QDir::NoFilter) << QStringList("*")
       
   165         << QString(
       
   166 #if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
       
   167                    "entrylist/.,"
       
   168                    "entrylist/..,"
       
   169                    "entrylist/directory/.,"
       
   170                    "entrylist/directory/..,"
       
   171 #endif
       
   172                    "entrylist/file,"
       
   173 #ifndef Q_NO_SYMLINKS
       
   174                    "entrylist/linktofile.lnk,"
       
   175 #endif
       
   176                    "entrylist/directory,"
       
   177                    "entrylist/directory/dummy,"
       
   178 #if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS)
       
   179                    "entrylist/linktodirectory.lnk,"
       
   180 #endif
       
   181                    "entrylist/writable").split(',');
       
   182 
       
   183     QTest::newRow("QDir::Subdirectories / QDir::Files")
       
   184         << QString("entrylist") << QDirIterator::IteratorFlags(QDirIterator::Subdirectories)
       
   185         << QDir::Filters(QDir::Files) << QStringList("*")
       
   186         << QString("entrylist/directory/dummy,"
       
   187                    "entrylist/file,"
       
   188 #ifndef Q_NO_SYMLINKS
       
   189                    "entrylist/linktofile.lnk,"
       
   190 #endif
       
   191                    "entrylist/writable").split(',');
       
   192 
       
   193     QTest::newRow("QDir::Subdirectories | QDir::FollowSymlinks / QDir::Files")
       
   194         << QString("entrylist") << QDirIterator::IteratorFlags(QDirIterator::Subdirectories | QDirIterator::FollowSymlinks)
       
   195         << QDir::Filters(QDir::Files) << QStringList("*")
       
   196         << QString("entrylist/file,"
       
   197 #ifndef Q_NO_SYMLINKS
       
   198                    "entrylist/linktofile.lnk,"
       
   199 #endif
       
   200                    "entrylist/directory/dummy,"
       
   201                    "entrylist/writable").split(',');
       
   202 }
       
   203 
       
   204 void tst_QDirIterator::iterateRelativeDirectory()
       
   205 {
       
   206     QFETCH(QString, dirName);
       
   207     QFETCH(QDirIterator::IteratorFlags, flags);
       
   208     QFETCH(QDir::Filters, filters);
       
   209     QFETCH(QStringList, nameFilters);
       
   210     QFETCH(QStringList, entries);
       
   211 
       
   212     QDirIterator it(dirName, nameFilters, filters, flags);
       
   213     QStringList list;
       
   214     while (it.hasNext()) {
       
   215         QString next = it.next();
       
   216 
       
   217         QString fileName = it.fileName();
       
   218         QString filePath = it.filePath();
       
   219         QString path = it.path();
       
   220 
       
   221         QFileInfo info = it.fileInfo();
       
   222 
       
   223         QCOMPARE(path, dirName);
       
   224         QCOMPARE(next, filePath);
       
   225 
       
   226         QCOMPARE(info, QFileInfo(next));
       
   227         QCOMPARE(fileName, info.fileName());
       
   228         QCOMPARE(filePath, info.filePath());
       
   229 
       
   230         // Using canonical file paths for final comparison
       
   231         list << info.canonicalFilePath();
       
   232     }
       
   233 
       
   234     // The order of items returned by QDirIterator is not guaranteed.
       
   235     list.sort();
       
   236 
       
   237     QStringList sortedEntries;
       
   238     foreach(QString item, entries)
       
   239         sortedEntries.append(QFileInfo(item).canonicalFilePath());
       
   240     sortedEntries.sort();
       
   241 
       
   242     if (sortedEntries != list) {
       
   243         qDebug() << "EXPECTED:" << sortedEntries;
       
   244         qDebug() << "ACTUAL:  " << list;
       
   245     }
       
   246 
       
   247     QCOMPARE(list, sortedEntries);
       
   248 }
       
   249 
       
   250 void tst_QDirIterator::iterateResource_data()
       
   251 {
       
   252     QTest::addColumn<QString>("dirName"); // relative from current path or abs
       
   253     QTest::addColumn<QDirIterator::IteratorFlags>("flags");
       
   254     QTest::addColumn<QDir::Filters>("filters");
       
   255     QTest::addColumn<QStringList>("nameFilters");
       
   256     QTest::addColumn<QStringList>("entries");
       
   257 
       
   258     QTest::newRow("invalid") << QString::fromLatin1(":/burpaburpa") << QDirIterator::IteratorFlags(0)
       
   259                              << QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*"))
       
   260                              << QStringList();
       
   261     QTest::newRow(":/") << QString::fromLatin1(":/") << QDirIterator::IteratorFlags(0)
       
   262                                << QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*"))
       
   263                                << QString::fromLatin1(":/entrylist").split(QLatin1String(","));
       
   264     QTest::newRow(":/entrylist") << QString::fromLatin1(":/entrylist") << QDirIterator::IteratorFlags(0)
       
   265                                << QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*"))
       
   266                                << QString::fromLatin1(":/entrylist/directory,:/entrylist/file").split(QLatin1String(","));
       
   267     QTest::newRow(":/ recursive") << QString::fromLatin1(":/") << QDirIterator::IteratorFlags(QDirIterator::Subdirectories)
       
   268                                          << QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*"))
       
   269                                          << QString::fromLatin1(":/entrylist,:/entrylist/directory,:/entrylist/directory/dummy,:/entrylist/file").split(QLatin1String(","));
       
   270 }
       
   271 
       
   272 void tst_QDirIterator::iterateResource()
       
   273 {
       
   274     QFETCH(QString, dirName);
       
   275     QFETCH(QDirIterator::IteratorFlags, flags);
       
   276     QFETCH(QDir::Filters, filters);
       
   277     QFETCH(QStringList, nameFilters);
       
   278     QFETCH(QStringList, entries);
       
   279 
       
   280     QDirIterator it(dirName, nameFilters, filters, flags);
       
   281     QStringList list;
       
   282     while (it.hasNext())
       
   283         list << it.next();
       
   284 
       
   285     list.sort();
       
   286     QStringList sortedEntries = entries;
       
   287     sortedEntries.sort();
       
   288 
       
   289     if (sortedEntries != list) {
       
   290         qDebug() << "EXPECTED:" << sortedEntries;
       
   291         qDebug() << "ACTUAL:" << list;
       
   292     }
       
   293 
       
   294     QCOMPARE(list, sortedEntries);
       
   295 }
       
   296 
       
   297 void tst_QDirIterator::stopLinkLoop()
       
   298 {
       
   299 #ifdef Q_OS_WIN
       
   300     // ### Sadly, this is a platform difference right now.
       
   301     QFile::link(QDir::currentPath() + QLatin1String("/entrylist"), "entrylist/entrylist1.lnk");
       
   302     QFile::link("entrylist/.", "entrylist/entrylist2.lnk");
       
   303     QFile::link("entrylist/../entrylist/.", "entrylist/entrylist3.lnk");
       
   304     QFile::link("entrylist/..", "entrylist/entrylist4.lnk");
       
   305     QFile::link(QDir::currentPath() + QLatin1String("/entrylist"), "entrylist/directory/entrylist1.lnk");
       
   306     QFile::link("entrylist/.", "entrylist/directory/entrylist2.lnk");
       
   307     QFile::link("entrylist/../directory/.", "entrylist/directory/entrylist3.lnk");
       
   308     QFile::link("entrylist/..", "entrylist/directory/entrylist4.lnk");
       
   309 #else
       
   310     QFile::link(QDir::currentPath() + QLatin1String("/entrylist"), "entrylist/entrylist1.lnk");
       
   311     QFile::link(".", "entrylist/entrylist2.lnk");
       
   312     QFile::link("../entrylist/.", "entrylist/entrylist3.lnk");
       
   313     QFile::link("..", "entrylist/entrylist4.lnk");
       
   314     QFile::link(QDir::currentPath() + QLatin1String("/entrylist"), "entrylist/directory/entrylist1.lnk");
       
   315     QFile::link(".", "entrylist/directory/entrylist2.lnk");
       
   316     QFile::link("../directory/.", "entrylist/directory/entrylist3.lnk");
       
   317     QFile::link("..", "entrylist/directory/entrylist4.lnk");
       
   318 #endif
       
   319 
       
   320     QDirIterator it(QLatin1String("entrylist"), QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
       
   321     QStringList list;
       
   322     int max = 200;
       
   323     while (--max && it.hasNext())
       
   324         it.next();
       
   325     QVERIFY(max);
       
   326 
       
   327     // The goal of this test is only to ensure that the test above don't malfunction
       
   328 
       
   329 #ifdef Q_OS_WIN
       
   330     // ### Sadly, this is a platform difference right now.
       
   331     QFile::link(QDir::currentPath() + QLatin1String("/entrylist"), "entrylist/entrylist1.lnk");
       
   332     QFile::link("../../entrylist/.", "entrylist/entrylist2.lnk");
       
   333     QFile::link("entrylist/..", "entrylist/entrylist3.lnk");
       
   334 #else
       
   335     QFile::remove("entrylist/entrylist1.lnk");
       
   336     QFile::remove("entrylist/entrylist2.lnk");
       
   337     QFile::remove("entrylist/entrylist3.lnk");
       
   338     QFile::remove("entrylist/entrylist4.lnk");
       
   339     QFile::remove("entrylist/directory/entrylist1.lnk");
       
   340     QFile::remove("entrylist/directory/entrylist2.lnk");
       
   341     QFile::remove("entrylist/directory/entrylist3.lnk");
       
   342     QFile::remove("entrylist/directory/entrylist4.lnk");
       
   343 #endif
       
   344 }
       
   345 
       
   346 class EngineWithNoIterator : public QFSFileEngine
       
   347 {
       
   348 public:
       
   349     EngineWithNoIterator(const QString &fileName)
       
   350         : QFSFileEngine(fileName)
       
   351     { }
       
   352 
       
   353     QAbstractFileEngineIterator *beginEntryList(QDir::Filters, const QStringList &)
       
   354     { return 0; }
       
   355 };
       
   356 
       
   357 class EngineWithNoIteratorHandler : public QAbstractFileEngineHandler
       
   358 {
       
   359 public:
       
   360     QAbstractFileEngine *create(const QString &fileName) const
       
   361     {
       
   362         return new EngineWithNoIterator(fileName);
       
   363     }
       
   364 };
       
   365 
       
   366 void tst_QDirIterator::engineWithNoIterator()
       
   367 {
       
   368     EngineWithNoIteratorHandler handler;
       
   369 
       
   370     QDir("entrylist").entryList();
       
   371     QVERIFY(true); // test that the above line doesn't crash
       
   372 }
       
   373 
       
   374 void tst_QDirIterator::absoluteFilePathsFromRelativeIteratorPath()
       
   375 {
       
   376     QDirIterator it("entrylist/", QDir::NoDotAndDotDot);
       
   377     while (it.hasNext()) {
       
   378         it.next();
       
   379         QVERIFY(QFileInfo(it.filePath()).absoluteFilePath().contains("entrylist"));
       
   380     }
       
   381 }
       
   382 
       
   383 void tst_QDirIterator::recurseWithFilters() const
       
   384 {
       
   385     QStringList nameFilters;
       
   386     nameFilters.append("*.txt");
       
   387 
       
   388     QDirIterator it("recursiveDirs/", nameFilters, QDir::Files,
       
   389                     QDirIterator::Subdirectories);
       
   390 
       
   391     QSet<QString> actualEntries;
       
   392     QSet<QString> expectedEntries;
       
   393     expectedEntries.insert(QString::fromLatin1("recursiveDirs/dir1/textFileB.txt"));
       
   394     expectedEntries.insert(QString::fromLatin1("recursiveDirs/textFileA.txt"));
       
   395 
       
   396     QVERIFY(it.hasNext());
       
   397     it.next();
       
   398     actualEntries.insert(it.fileInfo().filePath());
       
   399     QVERIFY(it.hasNext());
       
   400     it.next();
       
   401     actualEntries.insert(it.fileInfo().filePath());
       
   402     QVERIFY(actualEntries == expectedEntries);
       
   403 
       
   404     QVERIFY(!it.hasNext());
       
   405 }
       
   406 
       
   407 void tst_QDirIterator::longPath()
       
   408 {
       
   409     QDir dir;
       
   410     dir.mkdir("longpaths");
       
   411     dir.cd("longpaths");
       
   412 
       
   413     QString dirName = "x";
       
   414     int n = 0;
       
   415     while (dir.exists(dirName) || dir.mkdir(dirName)) {
       
   416         ++n;
       
   417         dirName.append('x');
       
   418 #if defined(Q_OS_WINCE) && defined(WINCE_BROKEN_ITERATE)
       
   419         // Some Windows CE devices/emulators are broken.
       
   420         // though one can create directories of length <= 217,
       
   421         // FindNextFile only reports entries until ~ 214.
       
   422         if (n >= 210)
       
   423             break;
       
   424 #endif
       
   425     }
       
   426 
       
   427     QDirIterator it(dir.absolutePath(), QDir::NoDotAndDotDot|QDir::Dirs, QDirIterator::Subdirectories);
       
   428     int m = 0;
       
   429     while (it.hasNext()) {
       
   430         ++m;
       
   431         it.next();
       
   432     }
       
   433 
       
   434     QCOMPARE(n, m);
       
   435 
       
   436     dirName.chop(1);
       
   437     while (dirName.length() > 0 && dir.exists(dirName) && dir.rmdir(dirName)) {
       
   438         dirName.chop(1);
       
   439     }
       
   440     dir.cdUp();
       
   441     dir.rmdir("longpaths");
       
   442 }
       
   443 
       
   444 void tst_QDirIterator::task185502_dirorder()
       
   445 {
       
   446     QDirIterator iterator("foo", QDirIterator::Subdirectories);
       
   447     while (iterator.hasNext() && iterator.next() != "foo/bar")
       
   448     { }
       
   449 
       
   450     QCOMPARE(iterator.filePath(), QString("foo/bar"));
       
   451     QCOMPARE(iterator.fileInfo().filePath(), QString("foo/bar"));
       
   452 }
       
   453 
       
   454 void tst_QDirIterator::relativePaths()
       
   455 {
       
   456     QDirIterator iterator("*", QDirIterator::Subdirectories);
       
   457     while(iterator.hasNext()) {
       
   458         QCOMPARE(iterator.filePath(), QDir::cleanPath(iterator.filePath()));
       
   459     }
       
   460 }
       
   461 
       
   462 QTEST_MAIN(tst_QDirIterator)
       
   463 
       
   464 #include "tst_qdiriterator.moc"
       
   465