qt5base-lts/tests/auto/qfileinfo/tst_qfileinfo.cpp
Qt by Nokia 38be0d1383 Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you
want to look at revision history older than this, please refer to the
Qt Git wiki for how to use Git history grafting. At the time of
writing, this wiki is located here:

http://qt.gitorious.org/qt/pages/GitIntroductionWithQt

If you have already performed the grafting and you don't see any
history beyond this commit, try running "git log" with the "--follow"
argument.

Branched from the monolithic repo, Qt master branch, at commit
896db169ea224deb96c59ce8af800d019de63f12
2011-04-27 12:05:43 +02:00

1811 lines
59 KiB
C++

/****************************************************************************
**
** 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$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $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
}
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";
#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)
QString 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
}
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);
#ifdef QT3_SUPPORT
QCOMPARE(fi.dir(true).path(), expected);
#endif
} else {
QCOMPARE(fi.path(), expected);
QCOMPARE(fi.dir().path(), expected);
#ifdef QT3_SUPPORT
QCOMPARE(fi.dir(false).path(), expected);
#endif
}
}
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::fromUtf16(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"