diff options
Diffstat (limited to 'tests/auto/corelib/io/qtemporaryfile')
3 files changed, 178 insertions, 62 deletions
diff --git a/tests/auto/corelib/io/qtemporaryfile/CMakeLists.txt b/tests/auto/corelib/io/qtemporaryfile/CMakeLists.txt index 11d4b991ce..9b453302c9 100644 --- a/tests/auto/corelib/io/qtemporaryfile/CMakeLists.txt +++ b/tests/auto/corelib/io/qtemporaryfile/CMakeLists.txt @@ -1,16 +1,23 @@ -# Generated from qtemporaryfile.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtemporaryfile Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtemporaryfile LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data list(APPEND test_data "tst_qtemporaryfile.cpp") qt_internal_add_test(tst_qtemporaryfile SOURCES tst_qtemporaryfile.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::TestPrivate TESTDATA ${test_data} ) @@ -31,7 +38,7 @@ qt_internal_add_resource(tst_qtemporaryfile "qtemporaryfile" ## Scopes: ##################################################################### -if(ANDROID AND NOT ANDROID_EMBEDDED) +if(ANDROID) # Resources: set(android_testdata_resource_files "resources/test.txt" @@ -45,3 +52,8 @@ if(ANDROID AND NOT ANDROID_EMBEDDED) ${android_testdata_resource_files} ) endif() + +qt_internal_extend_target(tst_qtemporaryfile CONDITION WIN32 + LIBRARIES + shlwapi +) diff --git a/tests/auto/corelib/io/qtemporaryfile/qtemporaryfile.qrc b/tests/auto/corelib/io/qtemporaryfile/qtemporaryfile.qrc deleted file mode 100644 index efadde8b4d..0000000000 --- a/tests/auto/corelib/io/qtemporaryfile/qtemporaryfile.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource> - <file>resources/test.txt</file> -</qresource> -</RCC>
\ No newline at end of file diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp index 331558255f..579e6d5511 100644 --- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp +++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp @@ -1,46 +1,23 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2017 Intel Corporation. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2017 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <qcoreapplication.h> -#include <qstring.h> -#include <qtemporarydir.h> -#include <qtemporaryfile.h> #include <qfile.h> #include <qdatetime.h> #include <qdir.h> #include <qset.h> +#include <qstandardpaths.h> +#include <qstring.h> +#include <qtemporarydir.h> +#include <qtemporaryfile.h> #include <QtTest/private/qtesthelpers_p.h> #if defined(Q_OS_WIN) -# include <windows.h> +# include <shlwapi.h> +# include <qt_windows.h> #endif #if defined(Q_OS_UNIX) # include <sys/types.h> @@ -50,11 +27,17 @@ # include <unistd.h> // close(2) #endif -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) +#ifdef Q_OS_ANDROID #include <QDirIterator> #include <QStandardPaths> #endif +#ifdef Q_OS_INTEGRITY +#include "qplatformdefs.h" +#endif + +using namespace Qt::StringLiterals; + class tst_QTemporaryFile : public QObject { Q_OBJECT @@ -81,6 +64,7 @@ private slots: void stressTest(); void rename(); void renameFdLeak(); + void moveToTrash(); void reOpenThroughQFile(); void keepOpenMode(); void resetTemplateAfterError(); @@ -91,6 +75,7 @@ private slots: void QTBUG_4796_data(); void QTBUG_4796(); void guaranteeUnique(); + void stdfilesystem(); private: QTemporaryDir m_temporaryDir; QString m_previousCurrent; @@ -98,6 +83,9 @@ private: void tst_QTemporaryFile::initTestCase() { + QStandardPaths::setTestModeEnabled(true); + QDir().mkpath(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)); + QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString())); m_previousCurrent = QDir::currentPath(); QVERIFY(QDir::setCurrent(m_temporaryDir.path())); @@ -106,15 +94,15 @@ void tst_QTemporaryFile::initTestCase() QVERIFY(QDir("test-XXXXXX").exists() || QDir().mkdir("test-XXXXXX")); QCoreApplication::setApplicationName("tst_qtemporaryfile"); -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) +#ifdef Q_OS_ANDROID QString sourceDir(":/android_testdata/"); QDirIterator it(sourceDir, QDirIterator::Subdirectories); while (it.hasNext()) { - it.next(); - - QFileInfo sourceFileInfo = it.fileInfo(); + QFileInfo sourceFileInfo = it.nextFileInfo(); if (!sourceFileInfo.isDir()) { - QFileInfo destinationFileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1Char('/') + sourceFileInfo.filePath().mid(sourceDir.length())); + QFileInfo destinationFileInfo( + QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1Char('/') + + sourceFileInfo.filePath().mid(sourceDir.length())); if (!destinationFileInfo.exists()) { QVERIFY(QDir().mkpath(destinationFileInfo.path())); @@ -206,6 +194,32 @@ void tst_QTemporaryFile::fileTemplate_data() prefix = "qt_" + hanTestText(); QTest::newRow("Chinese characters") << (prefix + "XXXXXX") << prefix << QString() << QString(); } + +#ifdef Q_OS_WIN + auto tmp = QDir::toNativeSeparators(QDir::tempPath()); + if (PathGetDriveNumber((const wchar_t *) tmp.utf16()) < 0) + return; // skip if we have no drive letter + + tmp.data()[1] = u'$'; + const auto tmpPath = tmp + uR"(\QTBUG-74291.XXXXXX.tmpFile)"_s; + + QTest::newRow("UNC-backslash") + << uR"(\\localhost\)"_s + tmpPath << "QTBUG-74291." + << ".tmpFile" + << ""; + QTest::newRow("UNC-prefix") + << uR"(\\?\UNC\localhost\)"_s + tmpPath << "QTBUG-74291." + << ".tmpFile" + << ""; + QTest::newRow("UNC-slash") + << u"//localhost/"_s + QDir::fromNativeSeparators(tmpPath) << "QTBUG-74291." + << ".tmpFile" + << ""; + QTest::newRow("UNC-prefix-slash") + << uR"(//?/UNC/localhost/)"_s + QDir::fromNativeSeparators(tmpPath) << "QTBUG-74291." + << ".tmpFile" + << ""; +#endif } void tst_QTemporaryFile::fileTemplate() @@ -222,11 +236,11 @@ void tst_QTemporaryFile::fileTemplate() QVERIFY2(file.open(), qPrintable(file.errorString())); QString fileName = QFileInfo(file).fileName(); - if (prefix.length()) - QCOMPARE(fileName.left(prefix.length()), prefix); + if (prefix.size()) + QCOMPARE(fileName.left(prefix.size()), prefix); - if (suffix.length()) - QCOMPARE(fileName.right(suffix.length()), suffix); + if (suffix.size()) + QCOMPARE(fileName.right(suffix.size()), suffix); } @@ -240,7 +254,7 @@ void tst_QTemporaryFile::fileName() QString absoluteTempPath = QDir(tempPath).absolutePath(); QTemporaryFile file; file.setAutoRemove(true); - file.open(); + QVERIFY(file.open()); QString fileName = file.fileName(); QVERIFY2(fileName.contains("/tst_qtemporaryfile."), qPrintable(fileName)); QVERIFY(QFile::exists(fileName)); @@ -355,7 +369,7 @@ void tst_QTemporaryFile::nonWritableCurrentDir() ChdirOnReturn cor(QDir::currentPath()); -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) +#ifdef Q_OS_ANDROID QDir::setCurrent("/data"); #else QDir::setCurrent("/home"); @@ -412,7 +426,7 @@ void tst_QTemporaryFile::io() file.reset(); QFile compare(file.fileName()); - compare.open(QIODevice::ReadOnly); + QVERIFY(compare.open(QIODevice::ReadOnly)); QCOMPARE(compare.readAll() , data); QCOMPARE(compare.fileTime(QFile::FileModificationTime), mtime); } @@ -446,7 +460,7 @@ void tst_QTemporaryFile::removeAndReOpen() QString fileName; { QTemporaryFile file; - file.open(); + QVERIFY(file.open()); fileName = file.fileName(); // materializes any unnamed file QVERIFY(QFile::exists(fileName)); @@ -466,7 +480,7 @@ void tst_QTemporaryFile::removeAndReOpen() void tst_QTemporaryFile::removeUnnamed() { QTemporaryFile file; - file.open(); + QVERIFY(file.open()); // we did not call fileName(), so the file name may not have a name QVERIFY(file.remove()); @@ -514,7 +528,8 @@ void tst_QTemporaryFile::openOnRootDrives() #endif // If it's possible to create a file in the root directory, it // must be possible to create a temp file there too. - foreach (QFileInfo driveInfo, QDir::drives()) { + const auto drives = QDir::drives(); + for (const QFileInfo &driveInfo : drives) { QFile testFile(driveInfo.filePath() + "XXXXXX.txt"); if (testFile.open(QIODevice::ReadWrite)) { testFile.remove(); @@ -613,6 +628,55 @@ void tst_QTemporaryFile::renameFdLeak() #endif } +void tst_QTemporaryFile::moveToTrash() +{ +#if defined(Q_OS_ANDROID) || defined(Q_OS_WEBOS) || defined(Q_OS_VXWORKS) + QSKIP("This platform doesn't implement a trash bin"); +#endif +#ifdef Q_OS_WIN + // QTemporaryFile won't really close the file with close(), so this is + // expected to fail with a sharing violation error. + constexpr bool expectSuccess = false; +#else + constexpr bool expectSuccess = true; +#endif + const QByteArrayView contents = "Hello, World\n"; + + QTemporaryFile f(QDir::homePath() + "/tst_qtemporaryfile.moveToTrash.XXXXXX"); + QString origFileName; + auto cleanup = qScopeGuard([&] { + if (!origFileName.isEmpty()) + QFile::remove(origFileName); + if (QString fn = f.fileName(); !fn.isEmpty() && fn != origFileName) + QFile::remove(fn); + }); + + if (!f.open()) + QSKIP("Failed to create temporary file"); + f.write(contents.data(), contents.size()); + + // we need an actual file name: + // 1) so we can delete it in the clean-up guard in case we fail to trash + // 2) so that the file exists on Linux in the first place (no sense in + // trashing an unnamed file) + origFileName = f.fileName(); + + if (expectSuccess) { + QVERIFY2(f.moveToTrash(), qPrintable(f.errorString())); + QCOMPARE_NE(f.fileName(), origFileName); // must have changed! + QCOMPARE_NE(f.fileName(), QString()); + QVERIFY(!QFile::exists(origFileName)); + QVERIFY(QFile::exists(f.fileName())); + QCOMPARE(QFileInfo(f.fileName()).size(), contents.size()); + } else { + QVERIFY(!f.moveToTrash()); + QCOMPARE(f.fileName(), origFileName); // mustn't have changed! + QCOMPARE_NE(f.error(), QFile::NoError); + QCOMPARE_NE(f.errorString(), "Unknown error"); + QVERIFY(QFile::exists(origFileName)); + } +} + void tst_QTemporaryFile::reOpenThroughQFile() { QByteArray data("abcdefghij"); @@ -781,8 +845,9 @@ void tst_QTemporaryFile::createNativeFile_data() QTest::addColumn<bool>("valid"); QTest::addColumn<QByteArray>("content"); -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) - const QString nativeFilePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QStringLiteral("/resources/test.txt"); +#ifdef Q_OS_ANDROID + const QString nativeFilePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + + QStringLiteral("/resources/test.txt"); #else const QString nativeFilePath = QFINDTESTDATA("resources/test.txt"); #endif @@ -805,7 +870,7 @@ void tst_QTemporaryFile::createNativeFile() QFile f(filePath); if (currentPos != -1) { - f.open(QIODevice::ReadOnly); + QVERIFY(f.open(QIODevice::ReadOnly)); f.seek(currentPos); } QTemporaryFile *tempFile = QTemporaryFile::createNativeFile(f); @@ -848,7 +913,7 @@ void tst_QTemporaryFile::QTBUG_4796() { ~CleanOnReturn() { - Q_FOREACH(QString tempName, tempNames) + for (const QString &tempName : std::as_const(tempNames)) QFile::remove(tempName); } @@ -936,7 +1001,7 @@ void tst_QTemporaryFile::QTBUG_4796() } } - Q_FOREACH(QString const &tempName, cleaner.tempNames) + for (const QString &tempName : std::as_const(cleaner.tempNames)) QVERIFY( !QFile::exists(tempName) ); cleaner.reset(); @@ -950,7 +1015,7 @@ void tst_QTemporaryFile::guaranteeUnique() // First pass. See which filename QTemporaryFile will try first. { QTemporaryFile tmpFile("testFile1.XXXXXX"); - tmpFile.open(); + QVERIFY(tmpFile.open()); takenFileName = tmpFile.fileName(); QVERIFY(QFile::exists(takenFileName)); } @@ -972,5 +1037,49 @@ void tst_QTemporaryFile::guaranteeUnique() QVERIFY(dir.rmdir(takenFileName)); } +void tst_QTemporaryFile::stdfilesystem() +{ +#if !QT_CONFIG(cxx17_filesystem) + QSKIP("std::filesystem not available"); +#else + // ctor + { + std::filesystem::path testFile("testFile1.XXXXXX"); + QTemporaryFile file(testFile); + QCOMPARE(file.fileTemplate(), QtPrivate::fromFilesystemPath(testFile)); + } + // rename + { + QTemporaryFile file("testFile1.XXXXXX"); + QVERIFY(file.open()); + QByteArray payload = "abc123 I am a string"; + file.write(payload); + QVERIFY(file.rename(std::filesystem::path("./test"))); + file.close(); + + QFile f(u"./test"_s); + QVERIFY(f.exists()); + QVERIFY(f.open(QFile::ReadOnly)); + QCOMPARE(f.readAll(), payload); + } + // createNativeFile + { + std::filesystem::path resource(":/resources/test.txt"); + std::unique_ptr<QTemporaryFile> tmp(QTemporaryFile::createNativeFile(resource)); + QVERIFY(tmp); + QFile file(resource); + QVERIFY(file.open(QFile::ReadOnly)); + QCOMPARE(tmp->readAll(), file.readAll()); + } + // setFileTemplate + { + QTemporaryFile file; + std::filesystem::path testFile("testFile1.XXXXXX"); + file.setFileTemplate(testFile); + QCOMPARE(file.fileTemplate(), QtPrivate::fromFilesystemPath(testFile)); + } +#endif +} + QTEST_MAIN(tst_QTemporaryFile) #include "tst_qtemporaryfile.moc" |