summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/io/qfileinfo
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/io/qfileinfo')
-rw-r--r--tests/auto/corelib/io/qfileinfo/CMakeLists.txt60
-rw-r--r--tests/auto/corelib/io/qfileinfo/qfileinfo.pro8
-rw-r--r--tests/auto/corelib/io/qfileinfo/qfileinfo.qrc5
-rw-r--r--tests/auto/corelib/io/qfileinfo/testdata.qrc8
-rw-r--r--tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp586
5 files changed, 433 insertions, 234 deletions
diff --git a/tests/auto/corelib/io/qfileinfo/CMakeLists.txt b/tests/auto/corelib/io/qfileinfo/CMakeLists.txt
new file mode 100644
index 0000000000..3b997e1bca
--- /dev/null
+++ b/tests/auto/corelib/io/qfileinfo/CMakeLists.txt
@@ -0,0 +1,60 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## tst_qfileinfo Test:
+#####################################################################
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qfileinfo LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qfileinfo
+ SOURCES
+ tst_qfileinfo.cpp
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::TestPrivate
+)
+
+# Resources:
+set(qfileinfo_resource_files
+ "resources/"
+)
+
+qt_internal_add_resource(tst_qfileinfo "qfileinfo"
+ PREFIX
+ "/tst_qfileinfo/"
+ FILES
+ ${qfileinfo_resource_files}
+)
+set(testdata_resource_files
+ "resources/file1"
+ "resources/file1.ext1"
+ "resources/file1.ext1.ext2"
+ "tst_qfileinfo.cpp"
+)
+
+qt_internal_add_resource(tst_qfileinfo "testdata"
+ PREFIX
+ "/testdata"
+ FILES
+ ${testdata_resource_files}
+)
+
+
+## Scopes:
+#####################################################################
+
+qt_internal_extend_target(tst_qfileinfo CONDITION WIN32
+ LIBRARIES
+ advapi32
+ netapi32
+)
+
+if (APPLE)
+ enable_language(OBJCXX)
+ set_source_files_properties(tst_qfileinfo.cpp PROPERTIES LANGUAGE OBJCXX)
+endif()
diff --git a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro
deleted file mode 100644
index d181d16a3e..0000000000
--- a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qfileinfo
-QT = core-private testlib
-SOURCES = tst_qfileinfo.cpp
-RESOURCES += qfileinfo.qrc \
- testdata.qrc
-
-win32:!winrt: QMAKE_USE += advapi32 netapi32
diff --git a/tests/auto/corelib/io/qfileinfo/qfileinfo.qrc b/tests/auto/corelib/io/qfileinfo/qfileinfo.qrc
deleted file mode 100644
index 2c63d8afeb..0000000000
--- a/tests/auto/corelib/io/qfileinfo/qfileinfo.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource prefix="/tst_qfileinfo/">
- <file>resources/</file>
-</qresource>
-</RCC>
diff --git a/tests/auto/corelib/io/qfileinfo/testdata.qrc b/tests/auto/corelib/io/qfileinfo/testdata.qrc
deleted file mode 100644
index d2974bae77..0000000000
--- a/tests/auto/corelib/io/qfileinfo/testdata.qrc
+++ /dev/null
@@ -1,8 +0,0 @@
-<RCC>
- <qresource prefix="/testdata">
- <file>resources/file1</file>
- <file>resources/file1.ext1</file>
- <file>resources/file1.ext1.ext2</file>
- <file>tst_qfileinfo.cpp</file>
- </qresource>
-</RCC>
diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
index ebb9a0a44c..563e4c2a83 100644
--- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
@@ -1,32 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QtTest>
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QTest>
+#include <QtTest/private/qcomparisontesthelper_p.h>
+#include <QStandardPaths>
+#include <QScopeGuard>
#include <qfile.h>
#include <qdir.h>
@@ -48,32 +26,28 @@
#endif
#ifdef Q_OS_WIN
#include <qt_windows.h>
-#if !defined(Q_OS_WINRT)
#include <private/qwinregistry_p.h>
#include <lm.h>
#endif
-#endif
#include <qplatformdefs.h>
#include <qdebug.h>
-#if defined(Q_OS_WIN)
-#include "../../../network-settings.h"
-#endif
#include <private/qfileinfo_p.h>
#include "../../../../shared/filesystem.h"
-#if defined(Q_OS_VXWORKS) || defined(Q_OS_WINRT)
+#if defined(Q_OS_MACOS)
+#include <Foundation/Foundation.h>
+#endif
+
+#if defined(Q_OS_VXWORKS)
#define Q_NO_SYMLINKS
#endif
#if defined(Q_OS_WIN)
-QT_BEGIN_NAMESPACE
-extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
-QT_END_NAMESPACE
-# ifndef Q_OS_WINRT
bool IsUserAdmin();
-# endif
#endif
+using namespace Qt::StringLiterals;
+
inline bool qIsLikelyToBeFat(const QString &path)
{
QByteArray name = QStorageInfo(path).fileSystemType().toLower();
@@ -96,37 +70,12 @@ inline bool qIsLikelyToBeNfs(const QString &path)
#endif
}
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
-# ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE // MinGW
-# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2)
-# endif
-
-static DWORD createSymbolicLink(const QString &symLinkName, const QString &target,
- QString *errorMessage)
-{
- DWORD result = ERROR_SUCCESS;
- const QString nativeSymLinkName = QDir::toNativeSeparators(symLinkName);
- const QString nativeTarget = QDir::toNativeSeparators(target);
- DWORD flags = 0;
- if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 14972))
- flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
- if (QFileInfo(target).isDir())
- flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
- if (CreateSymbolicLink(reinterpret_cast<const wchar_t*>(nativeSymLinkName.utf16()),
- reinterpret_cast<const wchar_t*>(nativeTarget.utf16()), flags) == FALSE) {
- result = GetLastError();
- QTextStream(errorMessage) << "CreateSymbolicLink(" << nativeSymLinkName << ", "
- << nativeTarget << ", 0x" << Qt::hex << flags << Qt::dec << ") failed with error " << result
- << ": " << qt_error_string(int(result));
- }
- return result;
-}
-
+#if defined(Q_OS_WIN)
static QByteArray msgInsufficientPrivileges(const QString &errorMessage)
{
return "Insufficient privileges (" + errorMessage.toLocal8Bit() + ')';
}
-#endif // Q_OS_WIN && !Q_OS_WINRT
+#endif // Q_OS_WIN
static QString seedAndTemplate()
{
@@ -224,6 +173,7 @@ private slots:
void systemFiles();
+ void compareCompiles();
void compare_data();
void compare();
@@ -232,6 +182,7 @@ private slots:
void fileTimes_data();
void fileTimes();
+ void setFileTimes();
void fakeFileTimes_data();
void fakeFileTimes();
@@ -244,12 +195,15 @@ private slots:
void isShortcut_data();
void isShortcut();
+ void isAlias_data();
+ void isAlias();
+
void link_data();
void link();
void isHidden_data();
void isHidden();
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
void isHiddenFromFinder();
#endif
@@ -261,7 +215,7 @@ private slots:
void refresh();
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN)
void ntfsJunctionPointsAndSymlinks_data();
void ntfsJunctionPointsAndSymlinks();
void brokenShortcut();
@@ -278,15 +232,16 @@ private slots:
void detachingOperations();
-#if !defined(Q_OS_WINRT)
void owner();
-#endif
void group();
void invalidState_data();
void invalidState();
void nonExistingFile();
+ void stdfilesystem();
+ void readSymLink();
+
private:
const QString m_currentDir;
QString m_sourceFile;
@@ -398,7 +353,7 @@ void tst_QFileInfo::isDir_data()
QFile::remove("brokenlink.lnk");
QFile::remove("dummyfile");
QFile file3("dummyfile");
- file3.open(QIODevice::WriteOnly);
+ QVERIFY(file3.open(QIODevice::WriteOnly));
if (file3.link("brokenlink.lnk")) {
file3.remove();
QFileInfo info3("brokenlink.lnk");
@@ -419,13 +374,13 @@ void tst_QFileInfo::isDir_data()
QTest::newRow("broken link") << "brokenlink.lnk" << false;
-#if (defined(Q_OS_WIN) && !defined(Q_OS_WINRT))
+#if defined(Q_OS_WIN)
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_WINRT)
- const QString uncRoot = QStringLiteral("//") + QtNetworkSettings::winServerName();
+#if defined(Q_OS_WIN)
+ const QString uncRoot = QStringLiteral("//") + QTest::uncServerName();
QTest::newRow("unc 1") << uncRoot << true;
QTest::newRow("unc 2") << uncRoot + QLatin1Char('/') << true;
QTest::newRow("unc 3") << uncRoot + "/testshare" << true;
@@ -461,14 +416,14 @@ void tst_QFileInfo::isRoot_data()
QTest::newRow("simple dir") << m_resourcesDir << false;
QTest::newRow("simple dir with slash") << (m_resourcesDir + QLatin1Char('/')) << false;
-#if (defined(Q_OS_WIN) && !defined(Q_OS_WINRT))
+#if defined(Q_OS_WIN)
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_WINRT)
- const QString uncRoot = QStringLiteral("//") + QtNetworkSettings::winServerName();
+#if defined(Q_OS_WIN)
+ const QString uncRoot = QStringLiteral("//") + QTest::uncServerName();
QTest::newRow("unc 1") << uncRoot << true;
QTest::newRow("unc 2") << uncRoot + QLatin1Char('/') << true;
QTest::newRow("unc 3") << uncRoot + "/testshare" << false;
@@ -505,19 +460,14 @@ void tst_QFileInfo::exists_data()
QTest::newRow("data8") << (m_resourcesDir + "/*.ext1") << false;
QTest::newRow("data9") << (m_resourcesDir + "/file?.ext1") << false;
QTest::newRow("data10") << "." << true;
-
- // Skip for the WinRT case, as GetFileAttributesEx removes _any_
- // trailing whitespace and "." is a valid entry as seen in data10
-#ifndef Q_OS_WINRT
QTest::newRow("data11") << ". " << false;
-#endif
QTest::newRow("empty") << "" << false;
QTest::newRow("simple dir") << m_resourcesDir << true;
QTest::newRow("simple dir with slash") << (m_resourcesDir + QLatin1Char('/')) << true;
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
- const QString uncRoot = QStringLiteral("//") + QtNetworkSettings::winServerName();
+#if defined(Q_OS_WIN)
+ const QString uncRoot = QStringLiteral("//") + QTest::uncServerName();
QTest::newRow("unc 1") << uncRoot << true;
QTest::newRow("unc 2") << uncRoot + QLatin1Char('/') << true;
QTest::newRow("unc 3") << uncRoot + "/testshare" << true;
@@ -551,7 +501,7 @@ void tst_QFileInfo::absolutePath_data()
QTest::addColumn<QString>("filename");
QString drivePrefix;
-#if (defined(Q_OS_WIN) && !defined(Q_OS_WINRT))
+#if defined(Q_OS_WIN)
drivePrefix = QDir::currentPath().left(2);
QString nonCurrentDrivePrefix =
drivePrefix.left(1).compare("X", Qt::CaseInsensitive) == 0 ? QString("Y:") : QString("X:");
@@ -561,8 +511,6 @@ void tst_QFileInfo::absolutePath_data()
QTest::newRow("<not current drive>:my.dll") << nonCurrentDrivePrefix + "my.dll"
<< nonCurrentDrivePrefix + "/"
<< "my.dll";
-#elif defined(Q_OS_WINRT)
- drivePrefix = QDir::currentPath().left(2);
#endif
QTest::newRow("0") << "/machine/share/dir1/" << drivePrefix + "/machine/share/dir1" << "";
QTest::newRow("1") << "/machine/share/dir1" << drivePrefix + "/machine/share" << "dir1";
@@ -570,7 +518,7 @@ void tst_QFileInfo::absolutePath_data()
QTest::newRow("3") << "/usr/local/bin/" << drivePrefix + "/usr/local/bin" << "";
QTest::newRow("/test") << "/test" << drivePrefix + "/" << "test";
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN)
QTest::newRow("c:\\autoexec.bat") << "c:\\autoexec.bat" << "C:/"
<< "autoexec.bat";
QTest::newRow("c:autoexec.bat") << QDir::currentPath().left(2) + "autoexec.bat" << QDir::currentPath()
@@ -710,7 +658,7 @@ void tst_QFileInfo::canonicalFilePath()
QFile file(QDir::currentPath());
if (file.link(link)) {
QFile tempfile("tempfile.txt");
- tempfile.open(QIODevice::ReadWrite);
+ QVERIFY(tempfile.open(QIODevice::ReadWrite));
tempfile.write("This file is generated by the QFileInfo autotest.");
QVERIFY(tempfile.flush());
tempfile.close();
@@ -746,14 +694,13 @@ void tst_QFileInfo::canonicalFilePath()
}
#endif
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN)
{
- QString errorMessage;
const QString linkTarget = QStringLiteral("res");
- const DWORD dwErr = createSymbolicLink(linkTarget, m_resourcesDir, &errorMessage);
- if (dwErr == ERROR_PRIVILEGE_NOT_HELD)
- QSKIP(msgInsufficientPrivileges(errorMessage));
- QVERIFY2(dwErr == ERROR_SUCCESS, qPrintable(errorMessage));
+ const auto result = FileSystem::createSymbolicLink(linkTarget, m_resourcesDir);
+ if (result.dwErr == ERROR_PRIVILEGE_NOT_HELD)
+ QSKIP(msgInsufficientPrivileges(result.errorMessage));
+ QVERIFY2(result.dwErr == ERROR_SUCCESS, qPrintable(result.errorMessage));
QString currentPath = QDir::currentPath();
QVERIFY(QDir::setCurrent(linkTarget));
const QString actualCanonicalPath = QFileInfo("file1").canonicalFilePath();
@@ -817,7 +764,7 @@ void tst_QFileInfo::bundleName_data()
QTest::newRow("root") << "/" << "";
QTest::newRow("etc") << "/etc" << "";
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
QTest::newRow("safari") << "/Applications/Safari.app" << "Safari";
#endif
}
@@ -844,7 +791,7 @@ void tst_QFileInfo::dir_data()
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";
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN)
QTest::newRow("driveWithSlash") << "C:/file1.ext1.ext2" << true << "C:/";
QTest::newRow("driveWithoutSlash") << QDir::currentPath().left(2) + "file1.ext1.ext2" << false << QDir::currentPath().left(2);
#endif
@@ -1035,7 +982,7 @@ void tst_QFileInfo::size()
void tst_QFileInfo::systemFiles()
{
-#if !defined(Q_OS_WIN) || defined(Q_OS_WINRT)
+#if !defined(Q_OS_WIN)
QSKIP("This is a Windows only test");
#endif
QFileInfo fi("c:\\pagefile.sys");
@@ -1046,9 +993,11 @@ void tst_QFileInfo::systemFiles()
QCOMPARE(fi.metadataChangeTime(), fi.lastModified()); // On Windows, they're the same
QVERIFY(fi.birthTime().isValid());
QVERIFY(fi.birthTime() <= fi.lastModified());
-#if QT_DEPRECATED_SINCE(5, 10)
- QCOMPARE(fi.created(), fi.birthTime()); // On Windows, they're the same
-#endif
+}
+
+void tst_QFileInfo::compareCompiles()
+{
+ QTestPrivate::testEqualityOperatorsCompile<QFileInfo>();
}
void tst_QFileInfo::compare_data()
@@ -1077,7 +1026,7 @@ void tst_QFileInfo::compare_data()
<< m_sourceFile
#if defined(Q_OS_WIN)
<< true;
-#elif defined(Q_OS_MAC)
+#elif defined(Q_OS_DARWIN)
<< !pathconf(QDir::currentPath().toLatin1().constData(), _PC_CASE_SENSITIVE);
#else
<< false;
@@ -1086,7 +1035,7 @@ void tst_QFileInfo::compare_data()
void tst_QFileInfo::compare()
{
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
if (qstrcmp(QTest::currentDataTag(), "casesense1") == 0)
QSKIP("Qt thinks all UNIX filesystems are case sensitive, see QTBUG-28246");
#endif
@@ -1095,7 +1044,7 @@ void tst_QFileInfo::compare()
QFETCH(QString, file2);
QFETCH(bool, same);
QFileInfo fi1(file1), fi2(file2);
- QCOMPARE(fi1 == fi2, same);
+ QT_TEST_EQUALITY_OPS(fi1, fi2, same);
}
void tst_QFileInfo::consistent_data()
@@ -1163,8 +1112,8 @@ void tst_QFileInfo::fileTimes()
{
// try to guess if file times on this filesystem round to the second
QFileInfo cwd(".");
- if (cwd.lastModified().toMSecsSinceEpoch() % 1000 == 0
- && cwd.lastRead().toMSecsSinceEpoch() % 1000 == 0) {
+ if (cwd.lastModified(QTimeZone::UTC).toMSecsSinceEpoch() % 1000 == 0
+ && cwd.lastRead(QTimeZone::UTC).toMSecsSinceEpoch() % 1000 == 0) {
fsClockSkew = sleepTime = 1000;
noAccessTime = qIsLikelyToBeFat(fileName);
@@ -1184,46 +1133,46 @@ void tst_QFileInfo::fileTimes()
QDateTime birthTime, writeTime, metadataChangeTime, readTime;
// --- Create file and write to it
- beforeBirth = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
+ beforeBirth = QDateTime::currentDateTimeUtc().addMSecs(-fsClockSkew);
{
QFile file(fileName);
QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
QFileInfo fileInfo(fileName);
- birthTime = fileInfo.birthTime();
+ birthTime = fileInfo.birthTime(QTimeZone::UTC);
QVERIFY2(!birthTime.isValid() || birthTime > beforeBirth,
datePairString(birthTime, beforeBirth));
QTest::qSleep(sleepTime);
- beforeWrite = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
+ beforeWrite = QDateTime::currentDateTimeUtc().addMSecs(-fsClockSkew);
QTextStream ts(&file);
ts << fileName << Qt::endl;
}
{
QFileInfo fileInfo(fileName);
- writeTime = fileInfo.lastModified();
+ writeTime = fileInfo.lastModified(QTimeZone::UTC);
QVERIFY2(writeTime > beforeWrite, datePairString(writeTime, beforeWrite));
- QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed
+ QCOMPARE(fileInfo.birthTime(QTimeZone::UTC), birthTime); // mustn't have changed
}
// --- Change the file's metadata
QTest::qSleep(sleepTime);
- beforeMetadataChange = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
+ beforeMetadataChange = QDateTime::currentDateTimeUtc().addMSecs(-fsClockSkew);
{
QFile file(fileName);
file.setPermissions(file.permissions());
}
{
QFileInfo fileInfo(fileName);
- metadataChangeTime = fileInfo.metadataChangeTime();
+ metadataChangeTime = fileInfo.metadataChangeTime(QTimeZone::UTC);
QVERIFY2(metadataChangeTime > beforeMetadataChange,
datePairString(metadataChangeTime, beforeMetadataChange));
QVERIFY(metadataChangeTime >= writeTime); // not all filesystems can store both times
- QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed
+ QCOMPARE(fileInfo.birthTime(QTimeZone::UTC), birthTime); // mustn't have changed
}
// --- Read the file
QTest::qSleep(sleepTime);
- beforeRead = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
+ beforeRead = QDateTime::currentDateTimeUtc().addMSecs(-fsClockSkew);
{
QFile file(fileName);
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
@@ -1233,12 +1182,12 @@ void tst_QFileInfo::fileTimes()
}
QFileInfo fileInfo(fileName);
- readTime = fileInfo.lastRead();
- QCOMPARE(fileInfo.lastModified(), writeTime); // mustn't have changed
- QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed
+ readTime = fileInfo.lastRead(QTimeZone::UTC);
+ QCOMPARE(fileInfo.lastModified(QTimeZone::UTC), writeTime); // mustn't have changed
+ QCOMPARE(fileInfo.birthTime(QTimeZone::UTC), birthTime); // mustn't have changed
QVERIFY(readTime.isValid());
-#if defined(Q_OS_WINRT) || defined(Q_OS_QNX) || (defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED))
+#if defined(Q_OS_QNX) || defined(Q_OS_ANDROID)
noAccessTime = true;
#elif defined(Q_OS_WIN)
//In Vista the last-access timestamp is not updated when the file is accessed/touched (by default).
@@ -1259,6 +1208,28 @@ void tst_QFileInfo::fileTimes()
QVERIFY(writeTime < beforeRead);
}
+void tst_QFileInfo::setFileTimes()
+{
+ QByteArray data("OLE\nOLE\nOLE");
+ QTemporaryFile file;
+
+ QVERIFY(file.open());
+ QCOMPARE(file.write(data), data.size());
+ QCOMPARE(file.size(), data.size());
+
+ QDateTime before = QDateTime::currentDateTimeUtc().addMSecs(-5000);
+
+ QVERIFY(file.setFileTime(before, QFile::FileModificationTime));
+ const QDateTime mtime = file.fileTime(QFile::FileModificationTime).toUTC();
+ if (mtime.time().msec() == 0)
+ {
+ const QTime beforeTime = before.time();
+ const QTime beforeTimeWithMSCutOff{beforeTime.hour(), beforeTime.minute(), beforeTime.second(), 0};
+ before.setTime(beforeTimeWithMSCutOff);
+ }
+ QCOMPARE(mtime, before);
+}
+
void tst_QFileInfo::fakeFileTimes_data()
{
QTest::addColumn<QDateTime>("when");
@@ -1276,7 +1247,7 @@ void tst_QFileInfo::fakeFileTimes()
QFETCH(QDateTime, when);
QFile file("faketimefile.txt");
- file.open(QIODevice::WriteOnly);
+ QVERIFY(file.open(QIODevice::WriteOnly));
file.write("\n", 1);
file.close();
@@ -1285,12 +1256,12 @@ void tst_QFileInfo::fakeFileTimes()
the file is open at the time. Of course, when writing, close() changes
modification time, so need to re-open for read in order to setFileTime().
*/
- file.open(QIODevice::ReadOnly);
+ QVERIFY(file.open(QIODevice::ReadOnly));
bool ok = file.setFileTime(when, QFileDevice::FileModificationTime);
file.close();
if (ok)
- QCOMPARE(QFileInfo(file.fileName()).lastModified(), when);
+ QCOMPARE(QFileInfo(file.fileName()).lastModified(QTimeZone::UTC), when);
else
QSKIP("Unable to set file metadata to contrived values");
}
@@ -1307,7 +1278,7 @@ void tst_QFileInfo::isSymLink_data()
QVERIFY(file1.link("link.lnk"));
QFile file2("dummyfile");
- file2.open(QIODevice::WriteOnly);
+ QVERIFY(file2.open(QIODevice::WriteOnly));
QVERIFY(file2.link("brokenlink.lnk"));
file2.remove();
@@ -1359,7 +1330,7 @@ void tst_QFileInfo::isShortcut_data()
<< regularFile.fileName() << false;
QTest::newRow("directory")
<< QDir::currentPath() << false;
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN)
// windows shortcuts
QVERIFY(regularFile.link("link.lnk"));
QTest::newRow("shortcut")
@@ -1382,6 +1353,57 @@ void tst_QFileInfo::isShortcut()
QCOMPARE(fi.isShortcut(), isShortcut);
}
+void tst_QFileInfo::isAlias_data()
+{
+ QFile::remove("symlink");
+ QFile::remove("file-alias");
+ QFile::remove("directory-alias");
+
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("isAlias");
+
+ QFile regularFile(m_sourceFile);
+ QTest::newRow("regular-file") << regularFile.fileName() << false;
+ QTest::newRow("directory") << QDir::currentPath() << false;
+
+#if defined(Q_OS_MACOS)
+ auto createAlias = [](const QString &target, const QString &alias) {
+ NSURL *targetUrl = [NSURL fileURLWithPath:target.toNSString()];
+ NSURL *aliasUrl = [NSURL fileURLWithPath:alias.toNSString()];
+ NSData *bookmarkData = [targetUrl bookmarkDataWithOptions:NSURLBookmarkCreationSuitableForBookmarkFile
+ includingResourceValuesForKeys:nil relativeToURL:nil error:nullptr];
+ Q_ASSERT(bookmarkData);
+
+ bool success = [NSURL writeBookmarkData:bookmarkData toURL:aliasUrl
+ options:NSURLBookmarkCreationSuitableForBookmarkFile error:nullptr];
+ Q_ASSERT(success);
+ };
+
+ regularFile.link("symlink");
+ QTest::newRow("symlink") << "symlink" << false;
+
+ createAlias(regularFile.fileName(), QDir::current().filePath("file-alias"));
+ QTest::newRow("file-alias") << "file-alias" << true;
+
+ createAlias(QDir::currentPath(), QDir::current().filePath("directory-alias"));
+ QTest::newRow("directory-alias") << "directory-alias" << true;
+
+ regularFile.copy("non-existing-file");
+ createAlias("non-existing-file", QDir::current().filePath("non-existing-file-alias"));
+ QDir::current().remove("non-existing-file");
+ QTest::newRow("non-existing-file-alias") << "non-existing-file-alias" << true;
+#endif
+}
+
+void tst_QFileInfo::isAlias()
+{
+ QFETCH(QString, path);
+ QFETCH(bool, isAlias);
+
+ QFileInfo fi(path);
+ QCOMPARE(fi.isAlias(), isAlias);
+}
+
void tst_QFileInfo::isSymbolicLink_data()
{
QTest::addColumn<QString>("path");
@@ -1395,17 +1417,14 @@ void tst_QFileInfo::isSymbolicLink_data()
#ifndef Q_NO_SYMLINKS
#if defined(Q_OS_WIN)
-#if !defined(Q_OS_WINRT)
- QString errorMessage;
- const DWORD creationResult = createSymbolicLink("symlink", m_sourceFile, &errorMessage);
- if (creationResult == ERROR_PRIVILEGE_NOT_HELD) {
- QWARN(msgInsufficientPrivileges(errorMessage));
+ const auto creationResult = FileSystem::createSymbolicLink("symlink", m_sourceFile);
+ if (creationResult.dwErr == ERROR_PRIVILEGE_NOT_HELD) {
+ qWarning() << qPrintable(msgInsufficientPrivileges(creationResult.errorMessage));
} else {
- QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
+ QVERIFY2(creationResult.dwErr == ERROR_SUCCESS, qPrintable(creationResult.errorMessage));
QTest::newRow("NTFS-symlink")
<< "symlink" << true;
}
-#endif // !Q_OS_WINRT
#else // Unix:
QVERIFY(regularFile.link("symlink.lnk"));
QTest::newRow("symlink.lnk")
@@ -1445,10 +1464,10 @@ void tst_QFileInfo::link_data()
QFile file1(m_sourceFile);
QFile file2("dummyfile");
- file2.open(QIODevice::WriteOnly);
+ QVERIFY(file2.open(QIODevice::WriteOnly));
QTest::newRow("existent file") << m_sourceFile << false << false << "";
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN)
// windows shortcuts
QVERIFY(file1.link("link.lnk"));
QTest::newRow("link.lnk")
@@ -1461,26 +1480,23 @@ void tst_QFileInfo::link_data()
#ifndef Q_NO_SYMLINKS
#if defined(Q_OS_WIN)
-#if !defined(Q_OS_WINRT)
- QString errorMessage;
- DWORD creationResult = createSymbolicLink("link", m_sourceFile, &errorMessage);
- if (creationResult == ERROR_PRIVILEGE_NOT_HELD) {
- QWARN(msgInsufficientPrivileges(errorMessage));
+ auto creationResult = FileSystem::createSymbolicLink("link", m_sourceFile);
+ if (creationResult.dwErr == ERROR_PRIVILEGE_NOT_HELD) {
+ qWarning() << qPrintable(msgInsufficientPrivileges(creationResult.errorMessage));
} else {
- QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
+ QVERIFY2(creationResult.dwErr == ERROR_SUCCESS, qPrintable(creationResult.errorMessage));
QTest::newRow("link")
<< "link" << false << true << QFileInfo(m_sourceFile).absoluteFilePath();
}
- creationResult = createSymbolicLink("brokenlink", "dummyfile", &errorMessage);
- if (creationResult == ERROR_PRIVILEGE_NOT_HELD) {
- QWARN(msgInsufficientPrivileges(errorMessage));
+ creationResult = FileSystem::createSymbolicLink("brokenlink", "dummyfile");
+ if (creationResult.dwErr == ERROR_PRIVILEGE_NOT_HELD) {
+ qWarning() << qPrintable(msgInsufficientPrivileges(creationResult.errorMessage));
} else {
- QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
+ QVERIFY2(creationResult.dwErr == ERROR_SUCCESS, qPrintable(creationResult.errorMessage));
QTest::newRow("broken link")
<< "brokenlink" << false << true << QFileInfo("dummyfile").absoluteFilePath();
}
-#endif // !Q_OS_WINRT
#else // Unix:
QVERIFY(file1.link("link"));
QTest::newRow("link")
@@ -1516,9 +1532,9 @@ void tst_QFileInfo::isHidden_data()
{
QTest::addColumn<QString>("path");
QTest::addColumn<bool>("isHidden");
- foreach (const QFileInfo& info, QDir::drives()) {
+ const auto drives = QDir::drives();
+ for (const QFileInfo& info : drives)
QTest::newRow(qPrintable("drive." + info.path())) << info.path() << false;
- }
#if defined(Q_OS_WIN)
QVERIFY(QDir("./hidden-directory").exists() || QDir().mkdir("./hidden-directory"));
@@ -1533,14 +1549,14 @@ void tst_QFileInfo::isHidden_data()
QTest::newRow("/path/to/.hidden-directory/..") << QDir::currentPath() + QString("/.hidden-directory/..") << true;
#endif
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
// /bin has the hidden attribute on OS X
QTest::newRow("/bin/") << QString::fromLatin1("/bin/") << true;
#elif !defined(Q_OS_WIN)
QTest::newRow("/bin/") << QString::fromLatin1("/bin/") << false;
#endif
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
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;
@@ -1556,7 +1572,7 @@ void tst_QFileInfo::isHidden()
QCOMPARE(fi.isHidden(), isHidden);
}
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
void tst_QFileInfo::isHiddenFromFinder()
{
const char *filename = "test_foobar.txt";
@@ -1582,7 +1598,7 @@ void tst_QFileInfo::isBundle_data()
QTest::addColumn<QString>("path");
QTest::addColumn<bool>("isBundle");
QTest::newRow("root") << QString::fromLatin1("/") << false;
-#ifdef Q_OS_MAC
+#ifdef Q_OS_DARWIN
QTest::newRow("mac_Applications") << QString::fromLatin1("/Applications") << false;
QTest::newRow("mac_Applications") << QString::fromLatin1("/Applications/Safari.app") << true;
#endif
@@ -1636,14 +1652,14 @@ void tst_QFileInfo::refresh()
file.flush();
QFileInfo info(file);
- QDateTime lastModified = info.lastModified();
+ QDateTime lastModified = info.lastModified(QTimeZone::UTC);
QCOMPARE(info.size(), qint64(7));
QTest::qSleep(sleepTime);
QCOMPARE(file.write("JOJOJO"), qint64(6));
file.flush();
- QCOMPARE(info.lastModified(), lastModified);
+ QCOMPARE(info.lastModified(QTimeZone::UTC), lastModified);
QCOMPARE(info.size(), qint64(7));
#if defined(Q_OS_WIN)
@@ -1651,7 +1667,7 @@ void tst_QFileInfo::refresh()
#endif
info.refresh();
QCOMPARE(info.size(), qint64(13));
- QVERIFY(info.lastModified() > lastModified);
+ QVERIFY(info.lastModified(QTimeZone::UTC) > lastModified);
QFileInfo info2 = info;
QCOMPARE(info2.size(), info.size());
@@ -1660,7 +1676,7 @@ void tst_QFileInfo::refresh()
QCOMPARE(info2.size(), info.size());
}
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN)
struct NtfsTestResource {
@@ -1680,7 +1696,6 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
{
QTest::addColumn<NtfsTestResource>("resource");
QTest::addColumn<QString>("path");
- QTest::addColumn<bool>("isSymLink");
QTest::addColumn<QString>("linkTarget");
QTest::addColumn<QString>("canonicalFilePath");
@@ -1708,13 +1723,13 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
QTest::newRow("absolute dir symlink")
<< NtfsTestResource(NtfsTestResource::SymLink, absSymlink, absTarget)
- << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath();
+ << absSymlink << QDir::fromNativeSeparators(absTarget) << target.canonicalPath();
QTest::newRow("relative dir symlink")
<< NtfsTestResource(NtfsTestResource::SymLink, relSymlink, relTarget)
- << relSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalPath();
+ << relSymlink << QDir::fromNativeSeparators(absTarget) << target.canonicalPath();
QTest::newRow("file in symlink dir")
<< NtfsTestResource()
- << fileInSymlink << false << "" << target.canonicalPath().append("/file");
+ << fileInSymlink << "" << target.canonicalPath().append("/file");
}
{
//File symlinks
@@ -1730,23 +1745,22 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
QTest::newRow("absolute file symlink")
<< NtfsTestResource(NtfsTestResource::SymLink, absSymlink, absTarget)
- << absSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
+ << absSymlink << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
QTest::newRow("relative file symlink")
<< NtfsTestResource(NtfsTestResource::SymLink, relSymlink, relTarget)
- << relSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
+ << relSymlink << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
QTest::newRow("relative to relative file symlink")
<< NtfsTestResource(NtfsTestResource::SymLink, relToRelSymlink, relToRelTarget)
- << relToRelSymlink << true << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
+ << relToRelSymlink << QDir::fromNativeSeparators(absTarget) << target.canonicalFilePath();
}
{
// Symlink to UNC share
pwd.mkdir("unc");
- QString errorMessage;
- QString uncTarget = QStringLiteral("//") + QtNetworkSettings::winServerName() + "/testshare";
+ QString uncTarget = QStringLiteral("//") + QTest::uncServerName() + "/testshare";
QString uncSymlink = QDir::toNativeSeparators(pwd.absolutePath().append("\\unc\\link_to_unc"));
QTest::newRow("UNC symlink")
<< NtfsTestResource(NtfsTestResource::SymLink, uncSymlink, uncTarget)
- << QDir::fromNativeSeparators(uncSymlink) << true << QDir::fromNativeSeparators(uncTarget) << uncTarget;
+ << QDir::fromNativeSeparators(uncSymlink) << QDir::fromNativeSeparators(uncTarget) << uncTarget;
}
//Junctions
@@ -1755,7 +1769,7 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
QFileInfo targetInfo(target);
QTest::newRow("junction_pwd")
<< NtfsTestResource(NtfsTestResource::Junction, junction, target)
- << junction << false << QString() << QString();
+ << junction << QString() << QString();
QFileInfo fileInJunction(targetInfo.absoluteFilePath().append("/file"));
QFile file(fileInJunction.absoluteFilePath());
@@ -1764,14 +1778,14 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
QVERIFY2(file.exists(), msgDoesNotExist(file.fileName()).constData());
QTest::newRow("file in junction")
<< NtfsTestResource()
- << fileInJunction.absoluteFilePath() << false << QString() << fileInJunction.canonicalFilePath();
+ << fileInJunction.absoluteFilePath() << QString() << fileInJunction.canonicalFilePath();
target = QDir::rootPath();
junction = "junction_root";
targetInfo.setFile(target);
QTest::newRow("junction_root")
<< NtfsTestResource(NtfsTestResource::Junction, junction, target)
- << junction << false << QString() << QString();
+ << junction << QString() << QString();
//Mountpoint
wchar_t buffer[MAX_PATH];
@@ -1782,35 +1796,37 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
rootVolume.replace("\\\\?\\","\\??\\");
QTest::newRow("mountpoint")
<< NtfsTestResource(NtfsTestResource::Junction, junction, rootVolume)
- << junction << false << QString() << QString();
+ << junction << QString() << QString();
}
void tst_QFileInfo::ntfsJunctionPointsAndSymlinks()
{
QFETCH(NtfsTestResource, resource);
QFETCH(QString, path);
- QFETCH(bool, isSymLink);
QFETCH(QString, linkTarget);
QFETCH(QString, canonicalFilePath);
- QString errorMessage;
- DWORD creationResult = ERROR_SUCCESS;
+ bool isSymLink = false;
+ bool isJunction = false;
+ FileSystem::Result creationResult;
switch (resource.type) {
case NtfsTestResource::None:
break;
case NtfsTestResource::SymLink:
- creationResult = createSymbolicLink(resource.source, resource.target, &errorMessage);
+ isSymLink = true;
+ creationResult = FileSystem::createSymbolicLink(resource.source, resource.target);
break;
case NtfsTestResource::Junction:
- creationResult = FileSystem::createNtfsJunction(resource.target, resource.source, &errorMessage);
- if (creationResult == ERROR_NOT_SUPPORTED) // Special value indicating non-NTFS drive
- QSKIP(qPrintable(errorMessage));
+ isJunction = true;
+ creationResult = FileSystem::createNtfsJunction(resource.target, resource.source);
+ if (creationResult.dwErr == ERROR_NOT_SUPPORTED) // Special value indicating non-NTFS drive
+ QSKIP(qPrintable(creationResult.errorMessage));
break;
}
- if (creationResult == ERROR_PRIVILEGE_NOT_HELD)
- QSKIP(msgInsufficientPrivileges(errorMessage));
- QVERIFY2(creationResult == ERROR_SUCCESS, qPrintable(errorMessage));
+ if (creationResult.dwErr == ERROR_PRIVILEGE_NOT_HELD)
+ QSKIP(msgInsufficientPrivileges(creationResult.errorMessage));
+ QVERIFY2(creationResult.dwErr == ERROR_SUCCESS, qPrintable(creationResult.errorMessage));
QFileInfo fi(path);
auto guard = qScopeGuard([&fi, this]() {
@@ -1825,14 +1841,36 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks()
}
}
});
- const QString actualSymLinkTarget = isSymLink ? fi.symLinkTarget() : QString();
- const QString actualCanonicalFilePath = isSymLink ? fi.canonicalFilePath() : QString();
- QCOMPARE(fi.isJunction(), resource.type == NtfsTestResource::Junction);
+ const QString actualCanonicalFilePath = fi.canonicalFilePath();
+ QCOMPARE(fi.isJunction(), isJunction);
QCOMPARE(fi.isSymbolicLink(), isSymLink);
if (isSymLink) {
- QCOMPARE(actualSymLinkTarget, linkTarget);
+ QCOMPARE(fi.symLinkTarget(), linkTarget);
QCOMPARE(actualCanonicalFilePath, canonicalFilePath);
}
+
+ if (isJunction) {
+ if (creationResult.target.startsWith(uR"(\??\)"))
+ creationResult.target = creationResult.target.sliced(4);
+
+ // resolve volume to drive letter
+ static const QRegularExpression matchVolumeRe(uR"(^Volume\{([a-z]|[0-9]|-)+\}\\)"_s,
+ QRegularExpression::CaseInsensitiveOption);
+ auto matchVolume = matchVolumeRe.match(creationResult.target);
+ if (matchVolume.hasMatch()) {
+ Q_ASSERT(matchVolume.capturedStart() == 0);
+ DWORD len;
+ wchar_t buffer[MAX_PATH];
+ const QString volumeName = uR"(\\?\)"_s + matchVolume.captured();
+ if (GetVolumePathNamesForVolumeName(reinterpret_cast<LPCWSTR>(volumeName.utf16()),
+ buffer, MAX_PATH, &len) != 0) {
+ creationResult.target.replace(0, matchVolume.capturedLength(),
+ QString::fromWCharArray(buffer));
+ }
+ }
+ QCOMPARE(fi.junctionTarget(), QDir::fromNativeSeparators(creationResult.target));
+ QCOMPARE(actualCanonicalFilePath, QFileInfo(creationResult.link).canonicalFilePath());
+ }
}
void tst_QFileInfo::brokenShortcut()
@@ -1863,42 +1901,48 @@ void tst_QFileInfo::brokenShortcut()
void tst_QFileInfo::isWritable()
{
QFile tempfile("tempfile.txt");
- tempfile.open(QIODevice::WriteOnly);
+ QVERIFY(tempfile.open(QIODevice::WriteOnly));
tempfile.write("This file is generated by the QFileInfo autotest.");
tempfile.close();
QVERIFY(QFileInfo("tempfile.txt").isWritable());
tempfile.remove();
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN)
QFileInfo fi("c:\\pagefile.sys");
QVERIFY2(fi.exists(), msgDoesNotExist(fi.absoluteFilePath()).constData());
QVERIFY(!fi.isWritable());
#endif
-#if defined (Q_OS_WIN) && !defined(Q_OS_WINRT)
- QScopedValueRollback<int> ntfsMode(qt_ntfs_permission_lookup);
- qt_ntfs_permission_lookup = 1;
+#if defined (Q_OS_WIN)
+ QNtfsPermissionCheckGuard permissionGuard;
QFileInfo fi2(QFile::decodeName(qgetenv("SystemRoot") + "/system.ini"));
QVERIFY(fi2.exists());
QCOMPARE(fi2.isWritable(), IsUserAdmin());
#endif
#if defined (Q_OS_QNX) // On QNX /etc is usually on a read-only filesystem
- QVERIFY(!QFileInfo("/etc/passwd").isWritable());
+ QCOMPARE(QFileInfo("/etc/passwd").isWritable(), (geteuid() == 0));
#elif defined (Q_OS_UNIX) && !defined(Q_OS_VXWORKS) // VxWorks does not have users/groups
- if (::getuid() == 0)
- QVERIFY(QFileInfo("/etc/passwd").isWritable());
- else
- QVERIFY(!QFileInfo("/etc/passwd").isWritable());
+ for (const char *attempt : { "/etc/passwd", "/etc/machine-id", "/proc/version" }) {
+ if (access(attempt, F_OK) == -1)
+ continue;
+ QCOMPARE(QFileInfo(attempt).isWritable(), ::access(attempt, W_OK) == 0);
+ }
#endif
}
void tst_QFileInfo::isExecutable()
{
QString appPath = QCoreApplication::applicationDirPath();
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
- appPath += "/libtst_qfileinfo.so";
+#ifdef Q_OS_ANDROID
+ QDir dir(appPath);
+ QVERIFY(dir.exists());
+ dir.setNameFilters({ "libtst_qfileinfo*.so" });
+ QStringList entries = dir.entryList();
+ QCOMPARE(entries.size(), 1);
+
+ appPath += "/" + entries[0];
#else
appPath += "/tst_qfileinfo";
# if defined(Q_OS_WIN)
@@ -1906,6 +1950,7 @@ void tst_QFileInfo::isExecutable()
# endif
#endif
QFileInfo fi(appPath);
+ QVERIFY(fi.exists());
QCOMPARE(fi.isExecutable(), true);
QCOMPARE(QFileInfo(m_proFile).isExecutable(), false);
@@ -1976,7 +2021,7 @@ private:
void tst_QFileInfo::testDecomposedUnicodeNames()
{
-#ifndef Q_OS_MAC
+#ifndef Q_OS_DARWIN
QSKIP("This is a OS X only test (unless you know more about filesystems, then maybe you should try it ;)");
#else
QFETCH(QString, filePath);
@@ -2056,7 +2101,7 @@ void tst_QFileInfo::detachingOperations()
QVERIFY(!info1.caching());
}
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+#if defined(Q_OS_WIN)
bool IsUserAdmin()
{
BOOL b;
@@ -2078,13 +2123,12 @@ bool IsUserAdmin()
return b != FALSE;
}
-#endif // Q_OS_WIN && !Q_OS_WINRT
+#endif // Q_OS_WIN
-#ifndef Q_OS_WINRT
void tst_QFileInfo::owner()
{
QString userName;
-#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
+#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS) && !defined(Q_OS_INTEGRITY)
{
passwd *user = getpwuid(geteuid());
QVERIFY(user);
@@ -2121,7 +2165,7 @@ void tst_QFileInfo::owner()
NetApiBufferFree(pBuf);
}
}
- qt_ntfs_permission_lookup = 1;
+ QNtfsPermissionCheckGuard permissionGuard;
#endif
if (userName.isEmpty())
QSKIP("Can't retrieve the user name");
@@ -2138,16 +2182,12 @@ void tst_QFileInfo::owner()
QCOMPARE(fi.owner(), userName);
QFile::remove(fileName);
-#if defined(Q_OS_WIN)
- qt_ntfs_permission_lookup = 0;
-#endif
}
-#endif // !Q_OS_WINRT
void tst_QFileInfo::group()
{
QString expected;
-#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
+#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS) && !defined(Q_OS_INTEGRITY)
struct group *gr;
gid_t gid = getegid();
@@ -2225,13 +2265,10 @@ static void stateCheck(const QFileInfo &info, const QString &dirname, const QStr
QCOMPARE(info.permissions(), QFile::Permissions());
-#if QT_DEPRECATED_SINCE(5, 10)
- QVERIFY(!info.created().isValid());
-#endif
- QVERIFY(!info.birthTime().isValid());
- QVERIFY(!info.metadataChangeTime().isValid());
- QVERIFY(!info.lastRead().isValid());
- QVERIFY(!info.lastModified().isValid());
+ QVERIFY(!info.birthTime(QTimeZone::UTC).isValid());
+ QVERIFY(!info.metadataChangeTime(QTimeZone::UTC).isValid());
+ QVERIFY(!info.lastRead(QTimeZone::UTC).isValid());
+ QVERIFY(!info.lastModified(QTimeZone::UTC).isValid());
};
void tst_QFileInfo::invalidState_data()
@@ -2269,6 +2306,129 @@ void tst_QFileInfo::nonExistingFile()
stateCheck(info, dirname, filename);
}
+void tst_QFileInfo::stdfilesystem()
+{
+#if QT_CONFIG(cxx17_filesystem)
+
+ namespace fs = std::filesystem;
+ // Verify constructing with fs::path leads to valid objects
+ {
+ // We compare using absoluteFilePath since QFileInfo::operator== ends up using
+ // canonicalFilePath which evaluates to empty-string for non-existent paths causing
+ // these tests to always succeed.
+ QDir base{ "../" }; // Used for the QFileInfo(QDir, <path>) ctor
+ auto doCompare = [&base](const char *filepath) {
+ QCOMPARE(QFileInfo(fs::path(filepath)).absoluteFilePath(),
+ QFileInfo(QString::fromLocal8Bit(filepath)).absoluteFilePath());
+ QCOMPARE(QFileInfo(base, fs::path(filepath)).absoluteFilePath(),
+ QFileInfo(base, QString::fromLocal8Bit(filepath)).absoluteFilePath());
+ };
+#define COMPARE_CONSTRUCTION(filepath) \
+ doCompare(filepath); if (QTest::currentTestFailed()) return
+
+ COMPARE_CONSTRUCTION("./file");
+
+#ifdef Q_OS_WIN32
+ COMPARE_CONSTRUCTION("C:\\path\\to\\file.txt");
+ COMPARE_CONSTRUCTION("x:\\path/to\\file.txt");
+ COMPARE_CONSTRUCTION("D:/path/TO/file.txt");
+ COMPARE_CONSTRUCTION("//sharename/folder/file.txt");
+#endif
+ COMPARE_CONSTRUCTION("/path/TO/file.txt");
+ COMPARE_CONSTRUCTION("./path/TO/file.txt");
+ COMPARE_CONSTRUCTION("../file.txt");
+#if !(defined(__GLIBCXX__) && defined(Q_OS_WIN32))
+ // libstdc++ bug on Windows - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111244
+ COMPARE_CONSTRUCTION("./filæ.txt");
+#endif
+
+ // Test unicode strings
+ QCOMPARE(QFileInfo(fs::path(u"./filæ.txt")).absoluteFilePath(),
+ QFileInfo(u"./filæ.txt"_s).absoluteFilePath());
+ QCOMPARE(QFileInfo(base, fs::path(u"./filæ.txt")).absoluteFilePath(),
+ QFileInfo(base, u"./filæ.txt"_s).absoluteFilePath());
+#ifdef __cpp_char8_t
+ QCOMPARE(QFileInfo(fs::path(u8"./filæ.txt")).absoluteFilePath(),
+ QFileInfo(u8"./filæ.txt").absoluteFilePath());
+ QCOMPARE(QFileInfo(base, fs::path(u8"./filæ.txt")).absoluteFilePath(),
+ QFileInfo(base, u8"./filæ.txt").absoluteFilePath());
+#endif
+
+#undef COMPARE_CONSTRUCTION
+ {
+ // One proper comparison with operator== for each ctor
+ QFile file(QStringLiteral("./filesystem_test_file.txt"));
+ if (!file.open(QFile::NewOnly))
+ QVERIFY(file.exists());
+ file.close();
+
+ QFileInfo pinfo{ fs::path{ "./filesystem_test_file.txt" } };
+ QFileInfo info{ QStringLiteral("./filesystem_test_file.txt") };
+ QCOMPARE(pinfo, info);
+ }
+
+ {
+ // And once more for QFileInfo(QDir, <path>)
+ const QString &subdir = QStringLiteral("./filesystem_test_dir/");
+ base = QDir(QStringLiteral("."));
+ if (!base.exists(subdir))
+ QVERIFY(base.mkdir(subdir));
+ base.cd(subdir);
+ QFile file{ base.filePath(QStringLiteral("./filesystem_test_file.txt")) };
+ if (!file.open(QFile::NewOnly))
+ QVERIFY(file.exists());
+ file.close();
+ QFileInfo pinfo{ base, fs::path{ "filesystem_test_file.txt" } };
+ QFileInfo info{ base, QStringLiteral("filesystem_test_file.txt") };
+ QCOMPARE(pinfo, info);
+ }
+ }
+
+ // Verify that functions returning path all point to the same place
+ {
+#define COMPARE_PATHS(actual, expected) \
+ QCOMPARE(QString::fromStdU16String(actual.u16string()), expected)
+
+ QFile file(QStringLiteral("./orig"));
+ if (!file.open(QFile::NewOnly))
+ QVERIFY(file.exists());
+ file.close();
+
+ QFileInfo info{ QStringLiteral("./orig") };
+ COMPARE_PATHS(info.filesystemPath(), info.path());
+ COMPARE_PATHS(info.filesystemAbsolutePath(), info.absolutePath());
+ COMPARE_PATHS(info.filesystemCanonicalPath(), info.canonicalPath());
+ COMPARE_PATHS(info.filesystemFilePath(), info.filePath());
+ COMPARE_PATHS(info.filesystemAbsoluteFilePath(), info.absoluteFilePath());
+ COMPARE_PATHS(info.filesystemCanonicalFilePath(), info.canonicalFilePath());
+
+ QVERIFY(file.link(QStringLiteral("./filesystem_test_symlink.lnk")));
+ info = QFileInfo{ "./filesystem_test_symlink.lnk" };
+
+ COMPARE_PATHS(info.filesystemSymLinkTarget(), info.symLinkTarget());
+#undef COMPARE_PATHS
+ }
+
+#else
+ QSKIP("Not supported");
+#endif
+}
+
+void tst_QFileInfo::readSymLink()
+{
+ QString symLinkName("./a.link");
+ const auto tidier = qScopeGuard([symLinkName]() { QFile::remove(symLinkName); });
+
+#ifdef Q_OS_WIN
+ QVERIFY2(CreateSymbolicLink(L"a.link", L"..\\..\\a", SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)
+ != 0,
+ "Failed to create symlink for test");
+#else
+ QVERIFY2(QFile::link("../../a", symLinkName), "Failed to create symlink for test");
+#endif
+ QFileInfo info(symLinkName);
+ QCOMPARE(info.readSymLink(), QString("../../a"));
+}
QTEST_MAIN(tst_QFileInfo)
#include "tst_qfileinfo.moc"