diff options
Diffstat (limited to 'tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp')
-rw-r--r-- | tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp | 1811 |
1 files changed, 1811 insertions, 0 deletions
diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp new file mode 100644 index 0000000000..1eb59ac96a --- /dev/null +++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp @@ -0,0 +1,1811 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include <qfile.h> +#include <qdir.h> +#include <qcoreapplication.h> +#include <qlibrary.h> +#include <qtemporaryfile.h> +#include <qdir.h> +#include <qfileinfo.h> +#ifdef Q_OS_UNIX +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <pwd.h> +#endif +#ifdef Q_OS_WIN +#define _WIN32_WINNT 0x500 +#include <qt_windows.h> +#include <qlibrary.h> +#include <lm.h> +#endif +#include <qplatformdefs.h> +#include <qdebug.h> +#ifdef Q_OS_SYMBIAN +#include <f32file.h> +#include <private/qcore_symbian_p.h> +#endif +#include "../../../network-settings.h" +#include <private/qfileinfo_p.h> +#include "../../../../shared/filesystem.h" + +#if defined(Q_OS_SYMBIAN) +# define SRCDIR "" +# define NO_SYMLINKS +#endif + +QT_BEGIN_NAMESPACE +extern Q_AUTOTEST_EXPORT bool qIsLikelyToBeNfs(int /* handle */); +QT_END_NAMESPACE + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QFileInfo : public QObject +{ +Q_OBJECT + +public: + tst_QFileInfo(); + ~tst_QFileInfo(); + +private slots: + void getSetCheck(); + + void copy(); + + void isFile_data(); + void isFile(); + + void isDir_data(); + void isDir(); + + void isRoot_data(); + void isRoot(); + + void exists_data(); + void exists(); + + void absolutePath_data(); + void absolutePath(); + + void absFilePath_data(); + void absFilePath(); + + void canonicalPath(); + void canonicalFilePath(); + + void fileName_data(); + void fileName(); + + void bundleName_data(); + void bundleName(); + + void dir_data(); + void dir(); + + void suffix_data(); + void suffix(); + + void completeSuffix_data(); + void completeSuffix(); + + void baseName_data(); + void baseName(); + + void completeBaseName_data(); + void completeBaseName(); + + void permission_data(); + void permission(); + + void size_data(); + void size(); + + void systemFiles(); + + void compare_data(); + void compare(); + + void consistent_data(); + void consistent(); + + void fileTimes_data(); + void fileTimes(); + void fileTimes_oldFile(); + + void isSymLink_data(); + void isSymLink(); + + void isHidden_data(); + void isHidden(); +#if defined(Q_OS_MAC) + void isHiddenFromFinder(); +#endif + + void isBundle_data(); + void isBundle(); + + void isLocalFs_data(); + void isLocalFs(); + + void refresh(); + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + void ntfsJunctionPointsAndSymlinks_data(); + void ntfsJunctionPointsAndSymlinks(); + void brokenShortcut(); +#endif + + void isWritable(); + void isExecutable(); + void testDecomposedUnicodeNames_data(); + void testDecomposedUnicodeNames(); + + void equalOperator() const; + void equalOperatorWithDifferentSlashes() const; + void notEqualOperator() const; + + void detachingOperations(); + +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) + void owner(); +#endif + void group(); + + void invalidState(); +}; + +tst_QFileInfo::tst_QFileInfo() +{ +} + +tst_QFileInfo::~tst_QFileInfo() +{ + QFile::remove("brokenlink.lnk"); + QFile::remove("link.lnk"); + QFile::remove("file1"); + QFile::remove("dummyfile"); + QFile::remove("simplefile.txt"); + QFile::remove("longFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileName.txt"); +#ifdef Q_OS_SYMBIAN + QFile::remove("hidden.txt"); + QFile::remove("nothidden.txt"); +#else + QFile::remove("tempfile.txt"); +#endif + +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) + QDir().rmdir("./.hidden-directory"); + QFile::remove("link_to_tst_qfileinfo"); +#endif +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + QDir().rmdir("./hidden-directory"); + QDir().rmdir("abs_symlink"); + QDir().rmdir("rel_symlink"); + QDir().rmdir("junction_pwd"); + QDir().rmdir("junction_root"); + QDir().rmdir("mountpoint"); + QFile::remove("abs_symlink.cpp"); + QFile::remove("rel_symlink.cpp"); +#endif +} + +// Testing get/set functions +void tst_QFileInfo::getSetCheck() +{ + QFileInfo obj1; + // bool QFileInfo::caching() + // void QFileInfo::setCaching(bool) + obj1.setCaching(false); + QCOMPARE(false, obj1.caching()); + obj1.setCaching(true); + QCOMPARE(true, obj1.caching()); +} + +static QFileInfoPrivate* getPrivate(QFileInfo &info) +{ + return (*reinterpret_cast<QFileInfoPrivate**>(&info)); +} + +void tst_QFileInfo::copy() +{ + QTemporaryFile *t; + t = new QTemporaryFile; + t->open(); + QFileInfo info(t->fileName()); + QVERIFY(info.exists()); + + //copy constructor + QFileInfo info2(info); + QFileInfoPrivate *privateInfo = getPrivate(info); + QFileInfoPrivate *privateInfo2 = getPrivate(info2); + QCOMPARE(privateInfo, privateInfo2); + + //operator = + QFileInfo info3 = info; + QFileInfoPrivate *privateInfo3 = getPrivate(info3); + QCOMPARE(privateInfo, privateInfo3); + QCOMPARE(privateInfo2, privateInfo3); + + //refreshing info3 will detach it + QFile file(info.absoluteFilePath()); + QVERIFY(file.open(QFile::WriteOnly)); + QCOMPARE(file.write("JAJAJAA"), qint64(7)); + file.flush(); + + QTest::qWait(250); +#if defined(Q_OS_WIN) || defined(Q_OS_WINCE) + if (QSysInfo::windowsVersion() & QSysInfo::WV_VISTA || + QSysInfo::windowsVersion() & QSysInfo::WV_CE_based) + file.close(); +#endif +#if defined(Q_OS_WINCE) + // On Windows CE we need to close the file. + // Otherwise the content will be cached and not + // flushed to the storage, although we flushed it + // manually!!! CE has interim cache, we cannot influence. + QTest::qWait(5000); +#endif + info3.refresh(); + privateInfo3 = getPrivate(info3); + QVERIFY(privateInfo != privateInfo3); + QVERIFY(privateInfo2 != privateInfo3); + QCOMPARE(privateInfo, privateInfo2); +} + +void tst_QFileInfo::isFile_data() +{ + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("expected"); + + QTest::newRow("data0") << QDir::currentPath() << false; + QTest::newRow("data1") << SRCDIR "tst_qfileinfo.cpp" << true; + QTest::newRow("data2") << ":/tst_qfileinfo/resources/" << false; + QTest::newRow("data3") << ":/tst_qfileinfo/resources/file1" << true; + QTest::newRow("data4") << ":/tst_qfileinfo/resources/afilethatshouldnotexist" << false; +} + +void tst_QFileInfo::isFile() +{ + QFETCH(QString, path); + QFETCH(bool, expected); + + QFileInfo fi(path); + QCOMPARE(fi.isFile(), expected); +} + + +void tst_QFileInfo::isDir_data() +{ + // create a broken symlink + QFile::remove("brokenlink.lnk"); + QFile::remove("dummyfile"); + QFile file3("dummyfile"); + file3.open(QIODevice::WriteOnly); + if (file3.link("brokenlink.lnk")) { + file3.remove(); + QFileInfo info3("brokenlink.lnk"); + QVERIFY( info3.isSymLink() ); + } + + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("expected"); + + QTest::newRow("data0") << QDir::currentPath() << true; + QTest::newRow("data1") << SRCDIR "tst_qfileinfo.cpp" << false; + QTest::newRow("data2") << ":/tst_qfileinfo/resources/" << true; + QTest::newRow("data3") << ":/tst_qfileinfo/resources/file1" << false; + QTest::newRow("data4") << ":/tst_qfileinfo/resources/afilethatshouldnotexist" << false; + + QTest::newRow("simple dir") << SRCDIR "resources" << true; + QTest::newRow("simple dir with slash") << SRCDIR "resources/" << true; + + QTest::newRow("broken link") << "brokenlink.lnk" << false; + +#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN) + QTest::newRow("drive 1") << "c:" << true; + QTest::newRow("drive 2") << "c:/" << true; + //QTest::newRow("drive 2") << "t:s" << false; +#endif +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << true; + QTest::newRow("unc 2") << "//" + QtNetworkSettings::winServerName() + "/" << true; + QTest::newRow("unc 3") << "//" + QtNetworkSettings::winServerName() + "/testshare" << true; + QTest::newRow("unc 4") << "//" + QtNetworkSettings::winServerName() + "/testshare/" << true; + QTest::newRow("unc 5") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp" << true; + QTest::newRow("unc 6") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp/" << true; + QTest::newRow("unc 7") << "//" + QtNetworkSettings::winServerName() + "/testshare/adirthatshouldnotexist" << false; +#endif +} + +void tst_QFileInfo::isDir() +{ + QFETCH(QString, path); + QFETCH(bool, expected); + + QFileInfo fi(path); + QCOMPARE(fi.isDir(), expected); +} + +void tst_QFileInfo::isRoot_data() +{ + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("expected"); + QTest::newRow("data0") << QDir::currentPath() << false; + QTest::newRow("data1") << "/" << true; + QTest::newRow("data2") << "*" << false; + QTest::newRow("data3") << "/*" << false; + QTest::newRow("data4") << ":/tst_qfileinfo/resources/" << false; + QTest::newRow("data5") << ":/" << true; + + QTest::newRow("simple dir") << SRCDIR "resources" << false; + QTest::newRow("simple dir with slash") << SRCDIR "resources/" << false; +#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN) + QTest::newRow("drive 1") << "c:" << false; + QTest::newRow("drive 2") << "c:/" << true; + QTest::newRow("drive 3") << "p:/" << false; +#endif + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << true; + QTest::newRow("unc 2") << "//" + QtNetworkSettings::winServerName() + "/" << true; + QTest::newRow("unc 3") << "//" + QtNetworkSettings::winServerName() + "/testshare" << false; + QTest::newRow("unc 4") << "//" + QtNetworkSettings::winServerName() + "/testshare/" << false; + QTest::newRow("unc 7") << "//ahostthatshouldnotexist" << false; +#endif +} + +void tst_QFileInfo::isRoot() +{ + QFETCH(QString, path); + QFETCH(bool, expected); + + QFileInfo fi(path); + QCOMPARE(fi.isRoot(), expected); +} + +void tst_QFileInfo::exists_data() +{ + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("expected"); + + QTest::newRow("data0") << QDir::currentPath() << true; + QTest::newRow("data1") << SRCDIR "tst_qfileinfo.cpp" << true; + QTest::newRow("data2") << "/I/do_not_expect_this_path_to_exist/" << false; + QTest::newRow("data3") << ":/tst_qfileinfo/resources/" << true; + QTest::newRow("data4") << ":/tst_qfileinfo/resources/file1" << true; + QTest::newRow("data5") << ":/I/do_not_expect_this_path_to_exist/" << false; + QTest::newRow("data6") << SRCDIR "resources/*" << false; + QTest::newRow("data7") << SRCDIR "resources/*.foo" << false; + QTest::newRow("data8") << SRCDIR "resources/*.ext1" << false; + QTest::newRow("data9") << SRCDIR "resources/file?.ext1" << false; + QTest::newRow("data10") << "." << true; + QTest::newRow("data11") << ". " << false; + QTest::newRow("empty") << "" << false; + + QTest::newRow("simple dir") << SRCDIR "resources" << true; + QTest::newRow("simple dir with slash") << SRCDIR "resources/" << true; + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << true; + QTest::newRow("unc 2") << "//" + QtNetworkSettings::winServerName() + "/" << true; + QTest::newRow("unc 3") << "//" + QtNetworkSettings::winServerName() + "/testshare" << true; + QTest::newRow("unc 4") << "//" + QtNetworkSettings::winServerName() + "/testshare/" << true; + QTest::newRow("unc 5") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp" << true; + QTest::newRow("unc 6") << "//" + QtNetworkSettings::winServerName() + "/testshare/tmp/" << true; + QTest::newRow("unc 7") << "//" + QtNetworkSettings::winServerName() + "/testshare/adirthatshouldnotexist" << false; + QTest::newRow("unc 8") << "//" + QtNetworkSettings::winServerName() + "/asharethatshouldnotexist" << false; + QTest::newRow("unc 9") << "//ahostthatshouldnotexist" << false; +#endif +} + +void tst_QFileInfo::exists() +{ + QFETCH(QString, path); + QFETCH(bool, expected); + + QFileInfo fi(path); + QCOMPARE(fi.exists(), expected); +} + +void tst_QFileInfo::absolutePath_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("path"); + QTest::addColumn<QString>("filename"); + + QString drivePrefix; +#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN) + drivePrefix = QDir::currentPath().left(2); + QString nonCurrentDrivePrefix = + drivePrefix.left(1).compare("X", Qt::CaseInsensitive) == 0 ? QString("Y:") : QString("X:"); + + // Make sure drive-relative paths return correct absolute paths (task 255326) + QTest::newRow("<current drive>:my.dll") << drivePrefix + "my.dll" << QDir::currentPath() << "my.dll"; + QTest::newRow("<not current drive>:my.dll") << nonCurrentDrivePrefix + "my.dll" + << nonCurrentDrivePrefix + "/" + << "my.dll"; +#endif + QTest::newRow("0") << "/machine/share/dir1/" << drivePrefix + "/machine/share/dir1" << ""; + QTest::newRow("1") << "/machine/share/dir1" << drivePrefix + "/machine/share" << "dir1"; + QTest::newRow("2") << "/usr/local/bin" << drivePrefix + "/usr/local" << "bin"; + QTest::newRow("3") << "/usr/local/bin/" << drivePrefix + "/usr/local/bin" << ""; + QTest::newRow("/test") << "/test" << drivePrefix + "/" << "test"; + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + // see task 102898 + QTest::newRow("c:\\autoexec.bat") << "c:\\autoexec.bat" << "C:/" + << "autoexec.bat"; +#endif + QTest::newRow("QTBUG-19995.1") << drivePrefix + "/System/Library/StartupItems/../Frameworks" + << drivePrefix + "/System/Library" + << "Frameworks"; + QTest::newRow("QTBUG-19995.2") << drivePrefix + "/System/Library/StartupItems/../Frameworks/" + << drivePrefix + "/System/Library/Frameworks" << ""; +} + +void tst_QFileInfo::absolutePath() +{ + QFETCH(QString, file); + QFETCH(QString, path); + QFETCH(QString, filename); + + QFileInfo fi(file); + + QCOMPARE(fi.absolutePath(), path); + QCOMPARE(fi.fileName(), filename); +} + +void tst_QFileInfo::absFilePath_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("relativeFile") << "tmp.txt" << QDir::currentPath() + "/tmp.txt"; + QTest::newRow("relativeFileInSubDir") << "temp/tmp.txt" << QDir::currentPath() + "/" + "temp/tmp.txt"; + QString drivePrefix; +#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN) + QString curr = QDir::currentPath(); + + curr.remove(0, 2); // Make it a absolute path with no drive specifier: \depot\qt-4.2\tests\auto\qfileinfo + QTest::newRow(".") << curr << QDir::currentPath(); + QTest::newRow("absFilePath") << "c:\\home\\andy\\tmp.txt" << "C:/home/andy/tmp.txt"; + + // Make sure drive-relative paths return correct absolute paths (task 255326) + drivePrefix = QDir::currentPath().left(2); + QString nonCurrentDrivePrefix = + drivePrefix.left(1).compare("X", Qt::CaseInsensitive) == 0 ? QString("Y:") : QString("X:"); + + QTest::newRow("<current drive>:my.dll") << drivePrefix + "temp/my.dll" << QDir::currentPath() + "/temp/my.dll"; + QTest::newRow("<not current drive>:my.dll") << nonCurrentDrivePrefix + "temp/my.dll" + << nonCurrentDrivePrefix + "/temp/my.dll"; +#else + QTest::newRow("absFilePath") << "/home/andy/tmp.txt" << "/home/andy/tmp.txt"; +#endif + QTest::newRow("QTBUG-19995") << drivePrefix + "/System/Library/StartupItems/../Frameworks" + << drivePrefix + "/System/Library/Frameworks"; +} + +void tst_QFileInfo::absFilePath() +{ + QFETCH(QString, file); + QFETCH(QString, expected); + + QFileInfo fi(file); +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + QVERIFY(QString::compare(fi.absoluteFilePath(), expected, Qt::CaseInsensitive) == 0); +#else + QCOMPARE(fi.absoluteFilePath(), expected); +#endif +} + +void tst_QFileInfo::canonicalPath() +{ + QTemporaryFile tempFile; + tempFile.setAutoRemove(true); + tempFile.open(); + QFileInfo fi(tempFile.fileName()); + QCOMPARE(fi.canonicalPath(), QFileInfo(QDir::tempPath()).canonicalFilePath()); +} + +void tst_QFileInfo::canonicalFilePath() +{ + const QString fileName("tmp.canon"); + QFile tempFile(fileName); + QVERIFY(tempFile.open(QFile::WriteOnly)); + QFileInfo fi(tempFile.fileName()); + QCOMPARE(fi.canonicalFilePath(), QDir::currentPath() + "/" + fileName); + tempFile.remove(); + + // This used to crash on Mac, verify that it doesn't anymore. + QFileInfo info("/tmp/../../../../../../../../../../../../../../../../../"); + info.canonicalFilePath(); + +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) + // This used to crash on Mac + QFileInfo dontCrash(QLatin1String("/")); + QCOMPARE(dontCrash.canonicalFilePath(), QLatin1String("/")); +#endif + +#ifndef Q_OS_WIN + // test symlinks + QFile::remove("link.lnk"); + { + QFile file(SRCDIR "tst_qfileinfo.cpp"); + if (file.link("link.lnk")) { + QFileInfo info1(file); + QFileInfo info2("link.lnk"); + QCOMPARE(info1.canonicalFilePath(), info2.canonicalFilePath()); + } + } +# if !defined(Q_OS_SYMBIAN) + // Symbian doesn't support links to directories + { + const QString link(QDir::tempPath() + QDir::separator() + "tst_qfileinfo"); + QFile::remove(link); + QFile file(QDir::currentPath()); + if (file.link(link)) { + QFile tempfile("tempfile.txt"); + tempfile.open(QIODevice::ReadWrite); + tempfile.write("This file is generated by the QFileInfo autotest."); + QVERIFY(tempfile.flush()); + tempfile.close(); + + QFileInfo info1("tempfile.txt"); + QFileInfo info2(link + QDir::separator() + "tempfile.txt"); + + QVERIFY(info1.exists()); + QVERIFY(info2.exists()); + QCOMPARE(info1.canonicalFilePath(), info2.canonicalFilePath()); + + QFileInfo info3(link + QDir::separator() + "link.lnk"); + QFileInfo info4(SRCDIR "tst_qfileinfo.cpp"); + QVERIFY(!info3.canonicalFilePath().isEmpty()); + QCOMPARE(info4.canonicalFilePath(), info3.canonicalFilePath()); + + tempfile.remove(); + } + } + { + QString link(QDir::tempPath() + QDir::separator() + "tst_qfileinfo" + + QDir::separator() + "link_to_tst_qfileinfo"); + QFile::remove(link); + + QFile file(QDir::tempPath() + QDir::separator() + "tst_qfileinfo" + + QDir::separator() + "tst_qfileinfo.cpp"); + if (file.link(link)) + { + QFileInfo info1("tst_qfileinfo.cpp"); + QFileInfo info2(link); + QCOMPARE(info1.canonicalFilePath(), info2.canonicalFilePath()); + } + } +# endif +#endif + +#ifdef Q_OS_WIN + typedef BOOL (WINAPI *PtrCreateSymbolicLink)(LPTSTR, LPTSTR, DWORD); + PtrCreateSymbolicLink ptrCreateSymbolicLink = + (PtrCreateSymbolicLink)QLibrary::resolve(QLatin1String("kernel32"), "CreateSymbolicLinkW"); + + if (!ptrCreateSymbolicLink) { + QSKIP("Symbolic links aren't supported by FS", SkipAll); + } else { + // CreateSymbolicLink can return TRUE & still fail to create the link, + // the error code in that case is ERROR_PRIVILEGE_NOT_HELD (1314) + SetLastError(0); + BOOL ret = ptrCreateSymbolicLink((wchar_t*)QString("res").utf16(), (wchar_t*)QString("resources").utf16(), 1); + DWORD dwErr = GetLastError(); + if (!ret) + QSKIP("Symbolic links aren't supported by FS", SkipAll); + QString currentPath = QDir::currentPath(); + bool is_res_Current = QDir::setCurrent("res"); + if (!is_res_Current && dwErr == 1314) + QSKIP("Not enough privilages to create Symbolic links", SkipAll); + QCOMPARE(is_res_Current, true); + + QCOMPARE(QFileInfo("file1").canonicalFilePath(), currentPath + "/resources/file1"); + + QCOMPARE(QDir::setCurrent(currentPath), true); + QDir::current().rmdir("res"); + } +#endif +} + +void tst_QFileInfo::fileName_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("relativeFile") << "tmp.txt" << "tmp.txt"; + QTest::newRow("relativeFileInSubDir") << "temp/tmp.txt" << "tmp.txt"; +#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN) + QTest::newRow("absFilePath") << "c:\\home\\andy\\tmp.txt" << "tmp.txt"; +#else + QTest::newRow("absFilePath") << "/home/andy/tmp.txt" << "tmp.txt"; +#endif + QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << "file1.ext1"; + QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1.ext2" << "file1.ext1.ext2"; + + QTest::newRow("ending slash [small]") << QString::fromLatin1("/a/") << QString::fromLatin1(""); + QTest::newRow("no ending slash [small]") << QString::fromLatin1("/a") << QString::fromLatin1("a"); + + QTest::newRow("ending slash") << QString::fromLatin1("/somedir/") << QString::fromLatin1(""); + QTest::newRow("no ending slash") << QString::fromLatin1("/somedir") << QString::fromLatin1("somedir"); +} + +void tst_QFileInfo::fileName() +{ + QFETCH(QString, file); + QFETCH(QString, expected); + + QFileInfo fi(file); + QCOMPARE(fi.fileName(), expected); +} + +void tst_QFileInfo::bundleName_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("root") << "/" << ""; + QTest::newRow("etc") << "/etc" << ""; +#ifdef Q_OS_MAC + QTest::newRow("safari") << "/Applications/Safari.app" << "Safari"; +#endif +} + +void tst_QFileInfo::bundleName() +{ + QFETCH(QString, file); + QFETCH(QString, expected); + + QFileInfo fi(file); + QCOMPARE(fi.bundleName(), expected); +} + +void tst_QFileInfo::dir_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<bool>("absPath"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("relativeFile") << "tmp.txt" << false << "."; + QTest::newRow("relativeFileAbsPath") << "tmp.txt" << true << QDir::currentPath(); + QTest::newRow("relativeFileInSubDir") << "temp/tmp.txt" << false << "temp"; + QTest::newRow("relativeFileInSubDirAbsPath") << "temp/tmp.txt" << true << QDir::currentPath() + "/temp"; + QTest::newRow("absFilePath") << QDir::currentPath() + "/tmp.txt" << false << QDir::currentPath(); + QTest::newRow("absFilePathAbsPath") << QDir::currentPath() + "/tmp.txt" << true << QDir::currentPath(); + QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << true << ":/tst_qfileinfo/resources"; +} + +void tst_QFileInfo::dir() +{ + QFETCH(QString, file); + QFETCH(bool, absPath); + QFETCH(QString, expected); + + QFileInfo fi(file); + if (absPath) { + QCOMPARE(fi.absolutePath(), expected); + QCOMPARE(fi.absoluteDir().path(), expected); + } else { + QCOMPARE(fi.path(), expected); + QCOMPARE(fi.dir().path(), expected); + } +} + + +void tst_QFileInfo::suffix_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("noextension0") << "file" << ""; + QTest::newRow("noextension1") << "/path/to/file" << ""; + QTest::newRow("data0") << "file.tar" << "tar"; + QTest::newRow("data1") << "file.tar.gz" << "gz"; + QTest::newRow("data2") << "/path/file/file.tar.gz" << "gz"; + QTest::newRow("data3") << "/path/file.tar" << "tar"; + QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << "ext1"; + QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1.ext2" << "ext2"; + QTest::newRow("hidden1") << ".ext1" << "ext1"; + QTest::newRow("hidden1") << ".ext" << "ext"; + QTest::newRow("hidden1") << ".ex" << "ex"; + QTest::newRow("hidden1") << ".e" << "e"; + QTest::newRow("hidden2") << ".ext1.ext2" << "ext2"; + QTest::newRow("hidden2") << ".ext.ext2" << "ext2"; + QTest::newRow("hidden2") << ".ex.ext2" << "ext2"; + QTest::newRow("hidden2") << ".e.ext2" << "ext2"; + QTest::newRow("hidden2") << "..ext2" << "ext2"; +} + +void tst_QFileInfo::suffix() +{ + QFETCH(QString, file); + QFETCH(QString, expected); + + QFileInfo fi(file); + QCOMPARE(fi.suffix(), expected); +} + + +void tst_QFileInfo::completeSuffix_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("noextension0") << "file" << ""; + QTest::newRow("noextension1") << "/path/to/file" << ""; + QTest::newRow("data0") << "file.tar" << "tar"; + QTest::newRow("data1") << "file.tar.gz" << "tar.gz"; + QTest::newRow("data2") << "/path/file/file.tar.gz" << "tar.gz"; + QTest::newRow("data3") << "/path/file.tar" << "tar"; + QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << "ext1"; + QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1.ext2" << "ext1.ext2"; +} + +void tst_QFileInfo::completeSuffix() +{ + QFETCH(QString, file); + QFETCH(QString, expected); + + QFileInfo fi(file); + QCOMPARE(fi.completeSuffix(), expected); +} + +void tst_QFileInfo::baseName_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("data0") << "file.tar" << "file"; + QTest::newRow("data1") << "file.tar.gz" << "file"; + QTest::newRow("data2") << "/path/file/file.tar.gz" << "file"; + QTest::newRow("data3") << "/path/file.tar" << "file"; + QTest::newRow("data4") << "/path/file" << "file"; + QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << "file1"; + QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1.ext2" << "file1"; +} + +void tst_QFileInfo::baseName() +{ + QFETCH(QString, file); + QFETCH(QString, expected); + + QFileInfo fi(file); + QCOMPARE(fi.baseName(), expected); +} + +void tst_QFileInfo::completeBaseName_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("expected"); + + QTest::newRow("data0") << "file.tar" << "file"; + QTest::newRow("data1") << "file.tar.gz" << "file.tar"; + QTest::newRow("data2") << "/path/file/file.tar.gz" << "file.tar"; + QTest::newRow("data3") << "/path/file.tar" << "file"; + QTest::newRow("data4") << "/path/file" << "file"; + QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << "file1"; + QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1.ext2" << "file1.ext1"; +} + +void tst_QFileInfo::completeBaseName() +{ + QFETCH(QString, file); + QFETCH(QString, expected); + + QFileInfo fi(file); + QCOMPARE(fi.completeBaseName(), expected); +} + +void tst_QFileInfo::permission_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<int>("perms"); + QTest::addColumn<bool>("expected"); + + QTest::newRow("data0") << QCoreApplication::instance()->applicationFilePath() << int(QFile::ExeUser) << true; + QTest::newRow("data1") << SRCDIR "tst_qfileinfo.cpp" << int(QFile::ReadUser) << true; +// QTest::newRow("data2") << "tst_qfileinfo.cpp" << int(QFile::WriteUser) << false; + QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::ReadUser) << true; + QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::WriteUser) << false; + QTest::newRow("resource3") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::ExeUser) << false; +} + +void tst_QFileInfo::permission() +{ + QFETCH(QString, file); + QFETCH(int, perms); + QFETCH(bool, expected); +#ifdef Q_OS_SYMBIAN + QSKIP("No user based rights in Symbian OS - SOS needs platform security tests instead", SkipAll); +#endif + QFileInfo fi(file); + QCOMPARE(fi.permission(QFile::Permissions(perms)), expected); +} + +void tst_QFileInfo::size_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<int>("size"); + + QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << 0; + QFile::remove("file1"); + QFile file("file1"); + QVERIFY(file.open(QFile::WriteOnly)); + QCOMPARE(file.write("JAJAJAA"), qint64(7)); + QTest::newRow("created-file") << "file1" << 7; + + QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1.ext2" << 0; +} + +void tst_QFileInfo::size() +{ + QFETCH(QString, file); + + QFileInfo fi(file); + (void)fi.permissions(); // see task 104198 + QTEST(int(fi.size()), "size"); +} + +void tst_QFileInfo::systemFiles() +{ +#if !defined(Q_OS_WIN) || defined(Q_OS_WINCE) + QSKIP("This is a Windows only test", SkipAll); +#endif + QFileInfo fi("c:\\pagefile.sys"); + QVERIFY(fi.exists()); // task 167099 + QVERIFY(fi.size() > 0); // task 189202 + QVERIFY(fi.lastModified().isValid()); +} + +void tst_QFileInfo::compare_data() +{ + QTest::addColumn<QString>("file1"); + QTest::addColumn<QString>("file2"); + QTest::addColumn<bool>("same"); + +#if defined(Q_OS_MAC) + // Since 10.6 we use realpath() in qfsfileengine, and it properly handles + // file system case sensitivity. However here in the autotest we don't + // check if the file system is case sensitive, so to make it pass in the + // default OS X installation we assume we are running on a case insensitive + // file system if on 10.6 and on a case sensitive file system if on 10.5 + bool caseSensitiveOnMac = true; + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) + caseSensitiveOnMac = false; +#endif + + QTest::newRow("data0") + << QString::fromLatin1(SRCDIR "tst_qfileinfo.cpp") + << QString::fromLatin1(SRCDIR "tst_qfileinfo.cpp") + << true; + QTest::newRow("data1") + << QString::fromLatin1(SRCDIR "tst_qfileinfo.cpp") + << QString::fromLatin1("/tst_qfileinfo.cpp") + << false; + QTest::newRow("data2") + << QString::fromLatin1("tst_qfileinfo.cpp") + << QDir::currentPath() + QString::fromLatin1("/tst_qfileinfo.cpp") + << true; + QTest::newRow("casesense1") + << QString::fromLatin1(SRCDIR "tst_qfileInfo.cpp") + << QString::fromLatin1(SRCDIR "tst_qfileinfo.cpp") +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + << true; +#elif defined(Q_OS_MAC) + << !caseSensitiveOnMac; +#else + << false; +#endif +} + +void tst_QFileInfo::compare() +{ + QFETCH(QString, file1); + QFETCH(QString, file2); + QFETCH(bool, same); + QFileInfo fi1(file1), fi2(file2); + QCOMPARE(fi1 == fi2, same); +} + +void tst_QFileInfo::consistent_data() +{ + QTest::addColumn<QString>("file"); + QTest::addColumn<QString>("expected"); + +#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN) + QTest::newRow("slashes") << QString::fromLatin1("\\a\\a\\a\\a") << QString::fromLatin1("/a/a/a/a"); +#endif + QTest::newRow("ending slash") << QString::fromLatin1("/a/somedir/") << QString::fromLatin1("/a/somedir/"); + QTest::newRow("no ending slash") << QString::fromLatin1("/a/somedir") << QString::fromLatin1("/a/somedir"); +} + +void tst_QFileInfo::consistent() +{ + QFETCH(QString, file); + QFETCH(QString, expected); + + QFileInfo fi(file); + QCOMPARE(fi.filePath(), expected); + QCOMPARE(fi.dir().path() + "/" + fi.fileName(), expected); +} + + +void tst_QFileInfo::fileTimes_data() +{ + QTest::addColumn<QString>("fileName"); + QTest::newRow("simple") << QString::fromLatin1("simplefile.txt"); + QTest::newRow( "longfile" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName" + "longFileNamelongFileNamelongFileNamelongFileName" + "longFileNamelongFileNamelongFileNamelongFileName" + "longFileNamelongFileNamelongFileNamelongFileName" + "longFileNamelongFileNamelongFileNamelongFileName.txt"); + QTest::newRow( "longfile absolutepath" ) << QFileInfo(QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName" + "longFileNamelongFileNamelongFileNamelongFileName" + "longFileNamelongFileNamelongFileNamelongFileName" + "longFileNamelongFileNamelongFileNamelongFileName" + "longFileNamelongFileNamelongFileNamelongFileName.txt")).absoluteFilePath(); +} + +void tst_QFileInfo::fileTimes() +{ +#if defined(Q_OS_WINCE) + int sleepTime = 3000; +#else + int sleepTime = 2000; +#endif + QFETCH(QString, fileName); + if (QFile::exists(fileName)) { + QVERIFY(QFile::remove(fileName)); + } + QTest::qSleep(sleepTime); + { + QFile file(fileName); +#if defined(Q_OS_WINCE) + QEXPECT_FAIL("longfile", "No long filenames on WinCE", Abort); + QEXPECT_FAIL("longfile absolutepath", "No long filenames on WinCE", Abort); +#elif defined(Q_OS_SYMBIAN) + QEXPECT_FAIL("longfile", "Maximum total filepath cannot exceed 256 characters in Symbian", Abort); + QEXPECT_FAIL("longfile absolutepath", "Maximum total filepath cannot exceed 256 characters in Symbian", Abort); +#endif + QVERIFY(file.open(QFile::WriteOnly | QFile::Text)); +#ifdef Q_OS_UNIX + if (qIsLikelyToBeNfs(file.handle())) + QSKIP("This Test doesn't work on NFS", SkipAll); +#endif + QTextStream ts(&file); + ts << fileName << endl; + } + QTest::qSleep(sleepTime); + QDateTime beforeWrite = QDateTime::currentDateTime(); + QTest::qSleep(sleepTime); + { + QFileInfo fileInfo(fileName); + QVERIFY(fileInfo.created() < beforeWrite); + QFile file(fileName); + QVERIFY(file.open(QFile::ReadWrite | QFile::Text)); + QTextStream ts(&file); + ts << fileName << endl; + } + QTest::qSleep(sleepTime); + QDateTime beforeRead = QDateTime::currentDateTime(); + QTest::qSleep(sleepTime); + { + QFileInfo fileInfo(fileName); +// On unix created() returns the same as lastModified(). +#if !defined(Q_OS_UNIX) && !defined(Q_OS_WINCE) + QVERIFY(fileInfo.created() < beforeWrite); +#endif + QVERIFY(fileInfo.lastModified() > beforeWrite); + QFile file(fileName); + QVERIFY(file.open(QFile::ReadOnly | QFile::Text)); + QTextStream ts(&file); + QString line = ts.readLine(); + QCOMPARE(line, fileName); + } + + QFileInfo fileInfo(fileName); +#if !defined(Q_OS_UNIX) && !defined(Q_OS_WINCE) + QVERIFY(fileInfo.created() < beforeWrite); +#endif + //In Vista the last-access timestamp is not updated when the file is accessed/touched (by default). + //To enable this the HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisableLastAccessUpdate + //is set to 0, in the test machine. +#ifdef Q_OS_WINCE + QEXPECT_FAIL("simple", "WinCE only stores date of access data, not the time", Continue); +#endif +#ifdef Q_OS_SYMBIAN + QEXPECT_FAIL("simple", "Symbian implementation of stat doesn't return read time right", Abort); +#endif + QVERIFY(fileInfo.lastRead() > beforeRead); + QVERIFY(fileInfo.lastModified() > beforeWrite); + QVERIFY(fileInfo.lastModified() < beforeRead); +} + +void tst_QFileInfo::fileTimes_oldFile() +{ + // This is not supported on WinCE +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + // All files are opened in share mode (both read and write). + DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + + // All files on Windows can be read; there's no such thing as an + // unreadable file. Add GENERIC_WRITE if WriteOnly is passed. + int accessRights = GENERIC_READ | GENERIC_WRITE; + + SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + + // Regular file mode. In Unbuffered mode, pass the no-buffering flag. + DWORD flagsAndAtts = FILE_ATTRIBUTE_NORMAL; + + // WriteOnly can create files, ReadOnly cannot. + DWORD creationDisp = OPEN_ALWAYS; + + // Create the file handle. + HANDLE fileHandle = CreateFile(L"oldfile.txt", + accessRights, + shareMode, + &securityAtts, + creationDisp, + flagsAndAtts, + NULL); + + // Set file times back to 1601. + SYSTEMTIME stime; + stime.wYear = 1601; + stime.wMonth = 1; + stime.wDayOfWeek = 1; + stime.wDay = 1; + stime.wHour = 1; + stime.wMinute = 0; + stime.wSecond = 0; + stime.wMilliseconds = 0; + + FILETIME ctime; + QVERIFY(SystemTimeToFileTime(&stime, &ctime)); + FILETIME atime = ctime; + FILETIME mtime = atime; + QVERIFY(fileHandle); + QVERIFY(SetFileTime(fileHandle, &ctime, &atime, &mtime) != 0); + + CloseHandle(fileHandle); + + QFileInfo info("oldfile.txt"); + QCOMPARE(info.lastModified(), QDateTime(QDate(1601, 1, 1), QTime(1, 0), Qt::UTC).toLocalTime()); +#endif +} + +void tst_QFileInfo::isSymLink_data() +{ +#ifndef NO_SYMLINKS + QFile::remove("link.lnk"); + QFile::remove("brokenlink.lnk"); + QFile::remove("dummyfile"); + + QFile file1(SRCDIR "tst_qfileinfo.cpp"); + QVERIFY(file1.link("link.lnk")); + + QFile file2("dummyfile"); + file2.open(QIODevice::WriteOnly); + QVERIFY(file2.link("brokenlink.lnk")); + file2.remove(); + + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("isSymLink"); + QTest::addColumn<QString>("linkTarget"); + + QTest::newRow("existent file") << SRCDIR "tst_qfileinfo.cpp" << false << ""; + QTest::newRow("link") << "link.lnk" << true << QFileInfo(SRCDIR "tst_qfileinfo.cpp").absoluteFilePath(); + QTest::newRow("broken link") << "brokenlink.lnk" << true << QFileInfo("dummyfile").absoluteFilePath(); +#endif +} + +void tst_QFileInfo::isSymLink() +{ +#ifndef NO_SYMLINKS + QFETCH(QString, path); + QFETCH(bool, isSymLink); + QFETCH(QString, linkTarget); + + QFileInfo fi(path); + QCOMPARE(fi.isSymLink(), isSymLink); + QCOMPARE(fi.symLinkTarget(), linkTarget); +#else + QSKIP("no symbolic link support on this platform", SkipAll); +#endif +} + +void tst_QFileInfo::isHidden_data() +{ + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("isHidden"); + foreach (const QFileInfo& info, QDir::drives()) { + QTest::newRow(qPrintable("drive." + info.path())) << info.path() << false; + } + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + QVERIFY(QDir("./hidden-directory").exists() || QDir().mkdir("./hidden-directory")); + QVERIFY(SetFileAttributesW(reinterpret_cast<LPCWSTR>(QString("./hidden-directory").utf16()),FILE_ATTRIBUTE_HIDDEN)); + QTest::newRow("C:/path/to/hidden-directory") << QDir::currentPath() + QString::fromLatin1("/hidden-directory") << true; + QTest::newRow("C:/path/to/hidden-directory/.") << QDir::currentPath() + QString::fromLatin1("/hidden-directory/.") << true; +#endif +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) + QVERIFY(QDir("./.hidden-directory").exists() || QDir().mkdir("./.hidden-directory")); + QTest::newRow("/path/to/.hidden-directory") << QDir::currentPath() + QString("/.hidden-directory") << true; + QTest::newRow("/path/to/.hidden-directory/.") << QDir::currentPath() + QString("/.hidden-directory/.") << true; + QTest::newRow("/path/to/.hidden-directory/..") << QDir::currentPath() + QString("/.hidden-directory/..") << true; +#endif + +#if defined(Q_OS_MAC) + // /bin has the hidden attribute on Mac OS X + QTest::newRow("/bin/") << QString::fromLatin1("/bin/") << true; +#elif !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN) + QTest::newRow("/bin/") << QString::fromLatin1("/bin/") << false; +#endif + +#ifdef Q_OS_MAC + QTest::newRow("mac_etc") << QString::fromLatin1("/etc") << true; + QTest::newRow("mac_private_etc") << QString::fromLatin1("/private/etc") << false; + QTest::newRow("mac_Applications") << QString::fromLatin1("/Applications") << false; +#endif + +#ifdef Q_OS_SYMBIAN + // No guaranteed hidden file knows to exist in Symbian filesystem, so make one. + QString hiddenFileName("hidden.txt"); + QString notHiddenFileName("nothidden.txt"); + QTest::newRow("hidden file") << hiddenFileName << true; + QTest::newRow("non-hidden file") << notHiddenFileName << false; + + { + QFile file(hiddenFileName); + QVERIFY(file.open(QIODevice::WriteOnly)); + QTextStream t(&file); + t << "foobar"; + + QFile file2(notHiddenFileName); + QVERIFY(file2.open(QIODevice::WriteOnly)); + QTextStream t2(&file2); + t2 << "foobar"; + } + + RFs rfs; + TInt err = rfs.Connect(); + QCOMPARE(err, KErrNone); + HBufC* symFile = qt_QString2HBufC(hiddenFileName); + err = rfs.SetAtt(*symFile, KEntryAttHidden, 0); + rfs.Close(); + delete symFile; + QCOMPARE(err, KErrNone); +#endif +} + +void tst_QFileInfo::isHidden() +{ + QFETCH(QString, path); + QFETCH(bool, isHidden); + QFileInfo fi(path); + + QCOMPARE(fi.isHidden(), isHidden); +} + +#if defined(Q_OS_MAC) +void tst_QFileInfo::isHiddenFromFinder() +{ + const char *filename = "test_foobar.txt"; + + QFile testFile(filename); + testFile.open(QIODevice::WriteOnly | QIODevice::Append); + testFile.write(QByteArray("world")); + testFile.close(); + + struct stat buf; + stat(filename, &buf); + chflags(filename, buf.st_flags | UF_HIDDEN); + + QFileInfo fi(filename); + QCOMPARE(fi.isHidden(), true); + + testFile.remove(); +} +#endif + +void tst_QFileInfo::isBundle_data() +{ + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("isBundle"); + QTest::newRow("root") << QString::fromLatin1("/") << false; +#ifdef Q_OS_MAC + QTest::newRow("mac_Applications") << QString::fromLatin1("/Applications") << false; + QTest::newRow("mac_Applications") << QString::fromLatin1("/Applications/Safari.app") << true; +#endif +} + +void tst_QFileInfo::isBundle() +{ + QFETCH(QString, path); + QFETCH(bool, isBundle); + QFileInfo fi(path); + QCOMPARE(fi.isBundle(), isBundle); +} + +void tst_QFileInfo::isLocalFs_data() +{ + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("isLocalFs"); + + QTest::newRow("local root") << QString::fromLatin1("/") << true; + QTest::newRow("local non-existent file") << QString::fromLatin1("/abrakadabra.boo") << true; + + QTest::newRow("qresource root") << QString::fromLatin1(":/") << false; +} + +void tst_QFileInfo::isLocalFs() +{ + QFETCH(QString, path); + QFETCH(bool, isLocalFs); + + QFileInfo info(path); + QFileInfoPrivate *privateInfo = getPrivate(info); + QCOMPARE((privateInfo->fileEngine == 0), isLocalFs); + if (privateInfo->fileEngine) + QCOMPARE(bool(privateInfo->fileEngine->fileFlags(QAbstractFileEngine::LocalDiskFlag) + & QAbstractFileEngine::LocalDiskFlag), isLocalFs); +} + +void tst_QFileInfo::refresh() +{ +#if defined(Q_OS_WINCE) || defined(Q_OS_WIN) + int sleepTime = 3000; +#else + int sleepTime = 2000; +#endif + + QFile::remove("file1"); + QFile file("file1"); + QVERIFY(file.open(QFile::WriteOnly)); + QCOMPARE(file.write("JAJAJAA"), qint64(7)); + file.flush(); + + QFileInfo info(file); + QDateTime lastModified = info.lastModified(); + QCOMPARE(info.size(), qint64(7)); + + QTest::qSleep(sleepTime); + + QCOMPARE(file.write("JOJOJO"), qint64(6)); + file.flush(); + QVERIFY(info.lastModified() == lastModified); + + QCOMPARE(info.size(), qint64(7)); +#if defined(Q_OS_WIN) || defined(Q_OS_WINCE) + if (QSysInfo::windowsVersion() & QSysInfo::WV_VISTA || + QSysInfo::windowsVersion() & QSysInfo::WV_CE_based) + file.close(); +#endif +#if defined(Q_OS_WINCE) + // On Windows CE we need to close the file. + // Otherwise the content will be cached and not + // flushed to the storage, although we flushed it + // manually!!! CE has interim cache, we cannot influence. + QTest::qWait(5000); +#endif + info.refresh(); + QCOMPARE(info.size(), qint64(13)); + QVERIFY(info.lastModified() > lastModified); + + QFileInfo info2 = info; + QCOMPARE(info2.size(), info.size()); + + info2.refresh(); + QCOMPARE(info2.size(), info.size()); +} + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data() +{ + QTest::addColumn<QString>("path"); + QTest::addColumn<bool>("isSymLink"); + QTest::addColumn<QString>("linkTarget"); + QTest::addColumn<QString>("canonicalFilePath"); + + QDir pwd; + pwd.mkdir("target"); + + QLibrary kernel32("kernel32"); + typedef BOOLEAN (WINAPI *PtrCreateSymbolicLink)(LPCWSTR, LPCWSTR, DWORD); + PtrCreateSymbolicLink createSymbolicLinkW = 0; + createSymbolicLinkW = (PtrCreateSymbolicLink) kernel32.resolve("CreateSymbolicLinkW"); + if (!createSymbolicLinkW) { + //we need at least one data set for the test not to fail when skipping _data function + QDir target("target"); + QTest::newRow("dummy") << target.path() << false << "" << target.canonicalPath(); + QSKIP("symbolic links not supported by operating system",SkipSingle); + } + { + //Directory symlinks + QDir target("target"); + QVERIFY(target.exists()); + + QString absTarget = QDir::toNativeSeparators(target.absolutePath()); + QString absSymlink = QDir::toNativeSeparators(pwd.absolutePath()).append("\\abs_symlink"); + QString relTarget = "target"; + QString relSymlink = "rel_symlink"; + QString fileInTarget(absTarget); + fileInTarget.append("\\file"); + QString fileInSymlink(absSymlink); + fileInSymlink.append("\\file"); + QFile file(fileInTarget); + file.open(QIODevice::ReadWrite); + file.close(); + + DWORD err = ERROR_SUCCESS ; + if (!pwd.exists("abs_symlink")) + if (!createSymbolicLinkW((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x1)) + err = GetLastError(); + if (err == ERROR_SUCCESS && !pwd.exists(relSymlink)) + if (!createSymbolicLinkW((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x1)) + err = GetLastError(); + if (err != ERROR_SUCCESS) { + wchar_t errstr[0x100]; + DWORD count = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, + 0, err, 0, errstr, 0x100, 0); + QString error(QString::fromWCharArray(errstr, count)); + qWarning() << error; + //we need at least one data set for the test not to assert fail when skipping _data function + QDir target("target"); + QTest::newRow("dummy") << target.path() << false << "" << target.canonicalPath(); + QSKIP("link not supported by FS or insufficient privilege", SkipSingle); + } + QVERIFY(file.exists()); + + QTest::newRow("absolute dir symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath(); + QTest::newRow("relative dir symlink") << relSymlink << true << QDir::fromNativeSeparators(relTarget) << target.canonicalPath(); + QTest::newRow("file in symlink dir") << fileInSymlink << false << "" << target.canonicalPath().append("/file"); + } + { + //File symlinks + QFileInfo target(SRCDIR "tst_qfileinfo.cpp"); + QString absTarget = QDir::toNativeSeparators(target.absoluteFilePath()); + QString absSymlink = QDir::toNativeSeparators(pwd.absolutePath()).append("\\abs_symlink.cpp"); + QString relTarget = QDir::toNativeSeparators(pwd.relativeFilePath(target.absoluteFilePath())); + QString relSymlink = "rel_symlink.cpp"; + QVERIFY(pwd.exists("abs_symlink.cpp") || createSymbolicLinkW((wchar_t*)absSymlink.utf16(),(wchar_t*)absTarget.utf16(),0x0)); + QVERIFY(pwd.exists(relSymlink) || createSymbolicLinkW((wchar_t*)relSymlink.utf16(),(wchar_t*)relTarget.utf16(),0x0)); + + QTest::newRow("absolute file symlink") << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath(); + QTest::newRow("relative file symlink") << relSymlink << true << QDir::fromNativeSeparators(relTarget) << target.canonicalFilePath(); + } + + //Junctions + QString target = "target"; + QString junction = "junction_pwd"; + FileSystem::createNtfsJunction(target, junction); + QFileInfo targetInfo(target); + QTest::newRow("junction_pwd") << junction << true << targetInfo.absoluteFilePath() << targetInfo.canonicalFilePath(); + + QFileInfo fileInJunction(targetInfo.absoluteFilePath().append("/file")); + QFile file(fileInJunction.absoluteFilePath()); + file.open(QIODevice::ReadWrite); + file.close(); + QVERIFY(file.exists()); + QTest::newRow("file in junction") << fileInJunction.absoluteFilePath() << false << "" << fileInJunction.canonicalFilePath(); + + target = QDir::rootPath(); + junction = "junction_root"; + FileSystem::createNtfsJunction(target, junction); + targetInfo.setFile(target); + QTest::newRow("junction_root") << junction << true << targetInfo.absoluteFilePath() << targetInfo.canonicalFilePath(); + + //Mountpoint + typedef BOOLEAN (WINAPI *PtrGetVolumeNameForVolumeMountPointW)(LPCWSTR, LPWSTR, DWORD); + PtrGetVolumeNameForVolumeMountPointW getVolumeNameForVolumeMountPointW = 0; + getVolumeNameForVolumeMountPointW = (PtrGetVolumeNameForVolumeMountPointW) kernel32.resolve("GetVolumeNameForVolumeMountPointW"); + if(getVolumeNameForVolumeMountPointW) + { + wchar_t buffer[MAX_PATH]; + QString rootPath = QDir::toNativeSeparators(QDir::rootPath()); + QVERIFY(getVolumeNameForVolumeMountPointW((wchar_t*)rootPath.utf16(), buffer, MAX_PATH)); + QString rootVolume = QString::fromWCharArray(buffer); + junction = "mountpoint"; + rootVolume.replace("\\\\?\\","\\??\\"); + FileSystem::createNtfsJunction(rootVolume, junction); + QTest::newRow("mountpoint") << junction << true << QDir::fromNativeSeparators(rootPath) << QDir::rootPath(); + } +} + +void tst_QFileInfo::ntfsJunctionPointsAndSymlinks() +{ + QFETCH(QString, path); + QFETCH(bool, isSymLink); + QFETCH(QString, linkTarget); + QFETCH(QString, canonicalFilePath); + + QFileInfo fi(path); + QCOMPARE(fi.isSymLink(), isSymLink); + QCOMPARE(fi.symLinkTarget(), linkTarget); + QCOMPARE(fi.canonicalFilePath(), canonicalFilePath); +} + +void tst_QFileInfo::brokenShortcut() +{ + QString linkName("borkenlink.lnk"); + QFile::remove(linkName); + QFile file(linkName); + file.open(QFile::WriteOnly); + file.write("b0rk"); + file.close(); + + QFileInfo info(linkName); + QVERIFY(info.isSymLink()); + QVERIFY(!info.exists()); + QFile::remove(linkName); +} +#endif + +void tst_QFileInfo::isWritable() +{ + QFile tempfile("tempfile.txt"); + tempfile.open(QIODevice::WriteOnly); + tempfile.write("This file is generated by the QFileInfo autotest."); + tempfile.close(); + + QVERIFY(QFileInfo("tempfile.txt").isWritable()); + tempfile.remove(); + +#ifdef Q_OS_WIN +#ifdef Q_OS_WINCE + QFileInfo fi("\\Windows\\wince.nls"); +#else + QFileInfo fi("c:\\pagefile.sys"); +#endif + QVERIFY(fi.exists()); + QVERIFY(!fi.isWritable()); +#endif +#if defined (Q_OS_UNIX) && !defined (Q_OS_SYMBIAN) + if (::getuid() == 0) + QVERIFY(QFileInfo("/etc/passwd").isWritable()); + else + QVERIFY(!QFileInfo("/etc/passwd").isWritable()); +#endif +} + +void tst_QFileInfo::isExecutable() +{ +#ifdef Q_OS_SYMBIAN + QString appPath = "c:/sys/bin/tst_qfileinfo.exe"; +#else + QString appPath = QCoreApplication::applicationDirPath(); + appPath += "/tst_qfileinfo"; +# if defined(Q_OS_WIN) + appPath += ".exe"; +# endif +#endif + QFileInfo fi(appPath); + QCOMPARE(fi.isExecutable(), true); + + QCOMPARE(QFileInfo("qfileinfo.pro").isExecutable(), false); +} + + +void tst_QFileInfo::testDecomposedUnicodeNames_data() +{ + QTest::addColumn<QString>("filePath"); + QTest::addColumn<QString>("fileName"); + QTest::addColumn<bool>("exists"); + QString currPath = QDir::currentPath(); + QTest::newRow("latin-only") << currPath + "/4.pdf" << "4.pdf" << true; + QTest::newRow("one-decomposed uni") << currPath + QString::fromUtf8("/4 ä.pdf") << QString::fromUtf8("4 ä.pdf") << true; + QTest::newRow("many-decomposed uni") << currPath + QString::fromUtf8("/4 äääcopy.pdf") << QString::fromUtf8("4 äääcopy.pdf") << true; + QTest::newRow("no decomposed") << currPath + QString::fromUtf8("/4 øøøcopy.pdf") << QString::fromUtf8("4 øøøcopy.pdf") << true; +} + +static void createFileNative(const QString &filePath) +{ +#ifdef Q_OS_UNIX + int fd = open(filePath.normalized(QString::NormalizationForm_D).toUtf8().constData(), O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); + if (fd < 0) { + QFAIL("couldn't create file"); + } else { + close(fd); + } +#else + Q_UNUSED(filePath); +#endif +} + +static void removeFileNative(const QString &filePath) +{ +#ifdef Q_OS_UNIX + unlink(filePath.normalized(QString::NormalizationForm_D).toUtf8().constData()); +#else + Q_UNUSED(filePath); +#endif +} + +void tst_QFileInfo::testDecomposedUnicodeNames() +{ +#ifndef Q_OS_MAC + QSKIP("This is a OS X only test (unless you know more about filesystems, then maybe you should try it ;)", SkipAll); +#endif + QFETCH(QString, filePath); + createFileNative(filePath); + + QFileInfo file(filePath); + QTEST(file.fileName(), "fileName"); + QTEST(file.exists(), "exists"); + removeFileNative(filePath); +} + +void tst_QFileInfo::equalOperator() const +{ + /* Compare two default constructed values. Yes, to me it seems it should be the opposite too, but + * this is how the code was written. */ + QVERIFY(!(QFileInfo() == QFileInfo())); +} + + +void tst_QFileInfo::equalOperatorWithDifferentSlashes() const +{ + const QFileInfo fi1("/usr"); + const QFileInfo fi2("/usr/"); + + QCOMPARE(fi1, fi2); +} + +void tst_QFileInfo::notEqualOperator() const +{ + /* Compare two default constructed values. Yes, to me it seems it should be the opposite too, but + * this is how the code was written. */ + QVERIFY(QFileInfo() != QFileInfo()); +} + +void tst_QFileInfo::detachingOperations() +{ + QFileInfo info1; + QVERIFY(info1.caching()); + info1.setCaching(false); + + { + QFileInfo info2 = info1; + + QVERIFY(!info1.caching()); + QVERIFY(!info2.caching()); + + info2.setCaching(true); + QVERIFY(info2.caching()); + + info1.setFile("foo"); + QVERIFY(!info1.caching()); + } + + { + QFile file("foo"); + info1.setFile(file); + QVERIFY(!info1.caching()); + } + + info1.setFile(QDir(), "foo"); + QVERIFY(!info1.caching()); + + { + QFileInfo info3; + QVERIFY(info3.caching()); + + info3 = info1; + QVERIFY(!info3.caching()); + } + + info1.refresh(); + QVERIFY(!info1.caching()); + + QVERIFY(info1.makeAbsolute()); + QVERIFY(!info1.caching()); + + info1.detach(); + QVERIFY(!info1.caching()); +} + +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) +#if defined (Q_OS_WIN) +BOOL IsUserAdmin() +{ + BOOL b; + SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; + PSID AdministratorsGroup; + b = AllocateAndInitializeSid( + &NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &AdministratorsGroup); + if (b) { + if (!CheckTokenMembership( NULL, AdministratorsGroup, &b)) + b = FALSE; + FreeSid(AdministratorsGroup); + } + + return(b); +} +#endif + +void tst_QFileInfo::owner() +{ + QString userName; +#if defined(Q_OS_UNIX) + { + passwd *user = getpwuid(geteuid()); + QVERIFY(user); + char *usernameBuf = user->pw_name; + userName = QString::fromLocal8Bit(usernameBuf); + } +#endif +#if defined(Q_OS_WIN) + wchar_t usernameBuf[1024]; + DWORD bufSize = 1024; + if (GetUserNameW(usernameBuf, &bufSize)) { + userName = QString::fromWCharArray(usernameBuf); + if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && IsUserAdmin()) { + // Special case : If the user is a member of Administrators group, all files + // created by the current user are owned by the Administrators group. + LPLOCALGROUP_USERS_INFO_0 pBuf = NULL; + DWORD dwLevel = 0; + DWORD dwFlags = LG_INCLUDE_INDIRECT ; + DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH; + DWORD dwEntriesRead = 0; + DWORD dwTotalEntries = 0; + NET_API_STATUS nStatus; + nStatus = NetUserGetLocalGroups(0, usernameBuf, dwLevel, dwFlags, (LPBYTE *) &pBuf, + dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries); + // Check if the current user is a member of Administrators group + if (nStatus == NERR_Success && pBuf){ + for (int i = 0; i < dwEntriesRead; i++) { + QString groupName = QString::fromWCharArray(pBuf[i].lgrui0_name); + if (!groupName.compare(QLatin1String("Administrators"))) + userName = groupName; + } + } + if (pBuf != NULL) + NetApiBufferFree(pBuf); + } + } + extern Q_CORE_EXPORT int qt_ntfs_permission_lookup; + qt_ntfs_permission_lookup = 1; +#endif + if (userName.isEmpty()) + QSKIP("Can't retrieve the user name", SkipAll); + QString fileName("ownertest.txt"); + QVERIFY(!QFile::exists(fileName) || QFile::remove(fileName)); + { + QFile testFile(fileName); + QVERIFY(testFile.open(QIODevice::WriteOnly | QIODevice::Text)); + QByteArray testData("testfile"); + QVERIFY(testFile.write(testData) != -1); + } + QFileInfo fi(fileName); + QVERIFY(fi.exists()); + QCOMPARE(fi.owner(), userName); + + QFile::remove(fileName); +#if defined(Q_OS_WIN) + qt_ntfs_permission_lookup = 0; +#endif +} +#endif + +void tst_QFileInfo::group() +{ + QString expected; +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) + struct group *gr; + gid_t gid = getegid(); + gr = getgrgid(gid); + expected = QString::fromLocal8Bit(gr->gr_name); +#endif + + QString fileName("ownertest.txt"); + if (QFile::exists(fileName)) + QFile::remove(fileName); + QFile testFile(fileName); + QVERIFY(testFile.open(QIODevice::WriteOnly | QIODevice::Text)); + QByteArray testData("testfile"); + QVERIFY(testFile.write(testData) != -1); + testFile.close(); + QFileInfo fi(fileName); + QVERIFY(fi.exists()); + + QCOMPARE(fi.group(), expected); +} + +void tst_QFileInfo::invalidState() +{ + // Shouldn't crash; + + { + QFileInfo info; + QCOMPARE(info.size(), qint64(0)); + QVERIFY(!info.exists()); + + info.setCaching(false); + + info.created(); + info.lastRead(); + info.lastModified(); + } + + { + QFileInfo info(""); + QCOMPARE(info.size(), qint64(0)); + QVERIFY(!info.exists()); + + info.setCaching(false); + + info.created(); + info.lastRead(); + info.lastModified(); + } + + { + QFileInfo info("file-doesn't-really-exist.txt"); + QCOMPARE(info.size(), qint64(0)); + QVERIFY(!info.exists()); + + info.setCaching(false); + + info.created(); + info.lastRead(); + info.lastModified(); + } + + QVERIFY(true); +} + +QTEST_MAIN(tst_QFileInfo) +#include "tst_qfileinfo.moc" |