mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-02 23:35:28 +08:00
qt 6.5.1 original
This commit is contained in:
15
tests/auto/corelib/io/qsavefile/CMakeLists.txt
Normal file
15
tests/auto/corelib/io/qsavefile/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qsavefile Test:
|
||||
#####################################################################
|
||||
|
||||
# Collect test data
|
||||
list(APPEND test_data "tst_qsavefile.cpp")
|
||||
|
||||
qt_internal_add_test(tst_qsavefile
|
||||
SOURCES
|
||||
tst_qsavefile.cpp
|
||||
TESTDATA ${test_data}
|
||||
)
|
556
tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp
Normal file
556
tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp
Normal file
@ -0,0 +1,556 @@
|
||||
// Copyright (C) 2012 David Faure <faure@kde.org>
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <QTest>
|
||||
#include <QSaveFile>
|
||||
#include <qcoreapplication.h>
|
||||
#include <qstring.h>
|
||||
#include <qtemporaryfile.h>
|
||||
#include <qfile.h>
|
||||
#include <qdir.h>
|
||||
#include <qset.h>
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
|
||||
#include <unistd.h> // for geteuid
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
# include <qt_windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_INTEGRITY
|
||||
#include "qplatformdefs.h"
|
||||
#endif
|
||||
|
||||
// Restore permissions so that the QTemporaryDir cleanup can happen
|
||||
class PermissionRestorer
|
||||
{
|
||||
Q_DISABLE_COPY(PermissionRestorer)
|
||||
public:
|
||||
explicit PermissionRestorer(const QString& path) : m_path(path) {}
|
||||
~PermissionRestorer() { restore(); }
|
||||
|
||||
inline void restore()
|
||||
{
|
||||
QFile file(m_path);
|
||||
#ifdef Q_OS_UNIX
|
||||
file.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner));
|
||||
#else
|
||||
file.setPermissions(QFile::WriteOwner);
|
||||
file.remove();
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
const QString m_path;
|
||||
};
|
||||
|
||||
class tst_QSaveFile : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public slots:
|
||||
|
||||
private slots:
|
||||
void transactionalWrite();
|
||||
void retryTransactionalWrite();
|
||||
void textStreamManualFlush();
|
||||
void textStreamAutoFlush();
|
||||
void saveTwice();
|
||||
void transactionalWriteNoPermissionsOnDir_data();
|
||||
void transactionalWriteNoPermissionsOnDir();
|
||||
void transactionalWriteNoPermissionsOnFile();
|
||||
void transactionalWriteCanceled();
|
||||
void transactionalWriteErrorRenaming();
|
||||
void symlink();
|
||||
void directory();
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
void alternateDataStream_data();
|
||||
void alternateDataStream();
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline QByteArray msgCannotOpen(const QFileDevice &f)
|
||||
{
|
||||
QString result = QStringLiteral("Cannot open ") + QDir::toNativeSeparators(f.fileName())
|
||||
+ QStringLiteral(": ") + f.errorString();
|
||||
return result.toLocal8Bit();
|
||||
}
|
||||
|
||||
void tst_QSaveFile::transactionalWrite()
|
||||
{
|
||||
QTemporaryDir dir;
|
||||
QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
|
||||
const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
|
||||
QFile::remove(targetFile);
|
||||
QSaveFile file(targetFile);
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData());
|
||||
QVERIFY(file.isOpen());
|
||||
QCOMPARE(file.fileName(), targetFile);
|
||||
QVERIFY(!QFile::exists(targetFile));
|
||||
|
||||
QCOMPARE(file.write("Hello"), Q_INT64_C(5));
|
||||
QCOMPARE(file.error(), QFile::NoError);
|
||||
QVERIFY(!QFile::exists(targetFile));
|
||||
|
||||
QVERIFY(file.commit());
|
||||
QVERIFY(QFile::exists(targetFile));
|
||||
QCOMPARE(file.fileName(), targetFile);
|
||||
|
||||
QFile reader(targetFile);
|
||||
QVERIFY(reader.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("Hello"));
|
||||
|
||||
// check that permissions are the same as for QFile
|
||||
const QString otherFile = dir.path() + QString::fromLatin1("/otherfile");
|
||||
QFile::remove(otherFile);
|
||||
QFile other(otherFile);
|
||||
other.open(QIODevice::WriteOnly);
|
||||
other.close();
|
||||
QCOMPARE(QFile::permissions(targetFile), QFile::permissions(otherFile));
|
||||
}
|
||||
|
||||
// QTBUG-77007: Simulate the case of an application with a loop prompting
|
||||
// to retry saving on failure. Create a read-only file first (Unix only)
|
||||
void tst_QSaveFile::retryTransactionalWrite()
|
||||
{
|
||||
#ifndef Q_OS_UNIX
|
||||
QSKIP("This test is Unix only");
|
||||
#else
|
||||
// root can open the read-only file for writing...
|
||||
if (geteuid() == 0)
|
||||
QSKIP("This test does not work as the root user");
|
||||
#endif
|
||||
QTemporaryDir dir;
|
||||
QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
|
||||
|
||||
QString targetFile = dir.path() + QLatin1String("/outfile");
|
||||
const QString readOnlyName = targetFile + QLatin1String(".ro");
|
||||
{
|
||||
QFile readOnlyFile(readOnlyName);
|
||||
QVERIFY2(readOnlyFile.open(QIODevice::WriteOnly), msgCannotOpen(readOnlyFile).constData());
|
||||
readOnlyFile.write("Hello");
|
||||
readOnlyFile.close();
|
||||
auto permissions = readOnlyFile.permissions();
|
||||
permissions &= ~(QFileDevice::WriteOwner | QFileDevice::WriteGroup | QFileDevice::WriteUser);
|
||||
QVERIFY(readOnlyFile.setPermissions(permissions));
|
||||
}
|
||||
|
||||
QSaveFile file(readOnlyName);
|
||||
QVERIFY(!file.open(QIODevice::WriteOnly));
|
||||
|
||||
file.setFileName(targetFile);
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData());
|
||||
QVERIFY(file.isOpen());
|
||||
QCOMPARE(file.write("Hello"), Q_INT64_C(5));
|
||||
QCOMPARE(file.error(), QFile::NoError);
|
||||
QVERIFY(file.commit());
|
||||
}
|
||||
|
||||
void tst_QSaveFile::saveTwice()
|
||||
{
|
||||
// Check that we can reuse a QSaveFile object
|
||||
// (and test the case of an existing target file)
|
||||
QTemporaryDir dir;
|
||||
QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
|
||||
const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
|
||||
QSaveFile file(targetFile);
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData());
|
||||
QCOMPARE(file.write("Hello"), Q_INT64_C(5));
|
||||
QVERIFY2(file.commit(), qPrintable(file.errorString()));
|
||||
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData());
|
||||
QCOMPARE(file.write("World"), Q_INT64_C(5));
|
||||
QVERIFY2(file.commit(), qPrintable(file.errorString()));
|
||||
|
||||
QFile reader(targetFile);
|
||||
QVERIFY2(reader.open(QIODevice::ReadOnly), msgCannotOpen(reader).constData());
|
||||
QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("World"));
|
||||
}
|
||||
|
||||
void tst_QSaveFile::textStreamManualFlush()
|
||||
{
|
||||
QTemporaryDir dir;
|
||||
QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
|
||||
const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
|
||||
QSaveFile file(targetFile);
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData());
|
||||
|
||||
QTextStream ts(&file);
|
||||
ts << "Manual flush";
|
||||
ts.flush();
|
||||
QCOMPARE(file.error(), QFile::NoError);
|
||||
QVERIFY(!QFile::exists(targetFile));
|
||||
|
||||
QVERIFY(file.commit());
|
||||
QFile reader(targetFile);
|
||||
QVERIFY(reader.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(QString::fromLatin1(reader.readAll().constData()), QString::fromLatin1("Manual flush"));
|
||||
QFile::remove(targetFile);
|
||||
}
|
||||
|
||||
void tst_QSaveFile::textStreamAutoFlush()
|
||||
{
|
||||
QTemporaryDir dir;
|
||||
QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
|
||||
const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
|
||||
QSaveFile file(targetFile);
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData());
|
||||
|
||||
QTextStream ts(&file);
|
||||
ts << "Auto-flush.";
|
||||
// no flush
|
||||
QVERIFY(file.commit()); // QIODevice::close will emit aboutToClose, which will flush the stream
|
||||
QFile reader(targetFile);
|
||||
QVERIFY(reader.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(QString::fromLatin1(reader.readAll().constData()), QString::fromLatin1("Auto-flush."));
|
||||
QFile::remove(targetFile);
|
||||
}
|
||||
|
||||
void tst_QSaveFile::transactionalWriteNoPermissionsOnDir_data()
|
||||
{
|
||||
QTest::addColumn<bool>("directWriteFallback");
|
||||
|
||||
QTest::newRow("default") << false;
|
||||
QTest::newRow("directWriteFallback") << true;
|
||||
}
|
||||
|
||||
void tst_QSaveFile::transactionalWriteNoPermissionsOnDir()
|
||||
{
|
||||
#ifdef Q_OS_UNIX
|
||||
#if !defined(Q_OS_VXWORKS)
|
||||
if (::geteuid() == 0)
|
||||
QSKIP("Test is not applicable with root privileges");
|
||||
#endif
|
||||
QFETCH(bool, directWriteFallback);
|
||||
QTemporaryDir dir;
|
||||
QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
|
||||
QVERIFY(QFile(dir.path()).setPermissions(QFile::ReadOwner | QFile::ExeOwner));
|
||||
PermissionRestorer permissionRestorer(dir.path());
|
||||
|
||||
const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
|
||||
QSaveFile firstTry(targetFile);
|
||||
QVERIFY(!firstTry.open(QIODevice::WriteOnly));
|
||||
QCOMPARE((int)firstTry.error(), (int)QFile::OpenError);
|
||||
QVERIFY(!firstTry.commit());
|
||||
|
||||
// Now make an existing writable file
|
||||
permissionRestorer.restore();
|
||||
QFile f(targetFile);
|
||||
QVERIFY(f.open(QIODevice::WriteOnly));
|
||||
QCOMPARE(f.write("Hello"), Q_INT64_C(5));
|
||||
f.close();
|
||||
|
||||
// Make the directory non-writable again
|
||||
QVERIFY(QFile(dir.path()).setPermissions(QFile::ReadOwner | QFile::ExeOwner));
|
||||
|
||||
// And write to it again using QSaveFile; only works if directWriteFallback is enabled
|
||||
QSaveFile file(targetFile);
|
||||
file.setDirectWriteFallback(directWriteFallback);
|
||||
QCOMPARE(file.directWriteFallback(), directWriteFallback);
|
||||
if (directWriteFallback) {
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData());
|
||||
QCOMPARE((int)file.error(), (int)QFile::NoError);
|
||||
QCOMPARE(file.write("World"), Q_INT64_C(5));
|
||||
QVERIFY(file.commit());
|
||||
|
||||
QFile reader(targetFile);
|
||||
QVERIFY(reader.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("World"));
|
||||
reader.close();
|
||||
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData());
|
||||
QCOMPARE((int)file.error(), (int)QFile::NoError);
|
||||
QCOMPARE(file.write("W"), Q_INT64_C(1));
|
||||
file.cancelWriting(); // no effect, as per the documentation
|
||||
QVERIFY(file.commit());
|
||||
|
||||
QVERIFY(reader.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("W"));
|
||||
} else {
|
||||
QVERIFY(!file.open(QIODevice::WriteOnly));
|
||||
QCOMPARE((int)file.error(), (int)QFile::OpenError);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QSaveFile::transactionalWriteNoPermissionsOnFile()
|
||||
{
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
|
||||
if (::geteuid() == 0)
|
||||
QSKIP("Test is not applicable with root privileges");
|
||||
#endif
|
||||
// Setup an existing but readonly file
|
||||
QTemporaryDir dir;
|
||||
QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
|
||||
const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
|
||||
QFile file(targetFile);
|
||||
PermissionRestorer permissionRestorer(targetFile);
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData());
|
||||
QCOMPARE(file.write("Hello"), Q_INT64_C(5));
|
||||
file.close();
|
||||
file.setPermissions(QFile::ReadOwner);
|
||||
QVERIFY(!file.open(QIODevice::WriteOnly));
|
||||
|
||||
// Try saving into it
|
||||
{
|
||||
QSaveFile saveFile(targetFile);
|
||||
QVERIFY(!saveFile.open(QIODevice::WriteOnly)); // just like QFile
|
||||
}
|
||||
QVERIFY(file.exists());
|
||||
}
|
||||
|
||||
void tst_QSaveFile::transactionalWriteCanceled()
|
||||
{
|
||||
QTemporaryDir dir;
|
||||
QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
|
||||
const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
|
||||
QFile::remove(targetFile);
|
||||
QSaveFile file(targetFile);
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData());
|
||||
|
||||
QTextStream ts(&file);
|
||||
ts << "This writing operation will soon be canceled.\n";
|
||||
ts.flush();
|
||||
QCOMPARE(file.error(), QFile::NoError);
|
||||
QVERIFY(!QFile::exists(targetFile));
|
||||
|
||||
// We change our mind, let's abort writing
|
||||
file.cancelWriting();
|
||||
|
||||
QVERIFY(!file.commit());
|
||||
|
||||
QVERIFY(!QFile::exists(targetFile)); // temp file was discarded
|
||||
QCOMPARE(file.fileName(), targetFile);
|
||||
}
|
||||
|
||||
void tst_QSaveFile::transactionalWriteErrorRenaming()
|
||||
{
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
|
||||
if (::geteuid() == 0)
|
||||
QSKIP("Test is not applicable with root privileges");
|
||||
#endif
|
||||
QTemporaryDir dir;
|
||||
QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
|
||||
const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
|
||||
QSaveFile file(targetFile);
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData());
|
||||
QCOMPARE(file.write("Hello"), qint64(5));
|
||||
QVERIFY(!QFile::exists(targetFile));
|
||||
#ifdef Q_OS_UNIX
|
||||
// Make rename() fail for lack of permissions in the directory
|
||||
QFile dirAsFile(dir.path()); // yay, I have to use QFile to change a dir's permissions...
|
||||
QVERIFY(dirAsFile.setPermissions(QFile::Permissions{})); // no permissions
|
||||
PermissionRestorer permissionRestorer(dir.path());
|
||||
#else
|
||||
// Windows: Make rename() fail for lack of permissions on an existing target file
|
||||
QFile existingTargetFile(targetFile);
|
||||
QVERIFY2(existingTargetFile.open(QIODevice::WriteOnly), msgCannotOpen(existingTargetFile).constData());
|
||||
QCOMPARE(file.write("Target"), qint64(6));
|
||||
existingTargetFile.close();
|
||||
QVERIFY(existingTargetFile.setPermissions(QFile::ReadOwner));
|
||||
PermissionRestorer permissionRestorer(targetFile);
|
||||
#endif
|
||||
|
||||
// The saving should fail.
|
||||
QVERIFY(!file.commit());
|
||||
#ifdef Q_OS_UNIX
|
||||
QVERIFY(!QFile::exists(targetFile)); // renaming failed
|
||||
#endif
|
||||
QCOMPARE(file.error(), QFile::RenameError);
|
||||
}
|
||||
|
||||
void tst_QSaveFile::symlink()
|
||||
{
|
||||
#ifdef Q_OS_UNIX
|
||||
QByteArray someData = "some data";
|
||||
QTemporaryDir dir;
|
||||
QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
|
||||
|
||||
const QString targetFile = dir.path() + QLatin1String("/outfile");
|
||||
const QString linkFile = dir.path() + QLatin1String("/linkfile");
|
||||
{
|
||||
QFile file(targetFile);
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), msgCannotOpen(file).constData());
|
||||
QCOMPARE(file.write("Hello"), Q_INT64_C(5));
|
||||
file.close();
|
||||
}
|
||||
|
||||
QVERIFY(QFile::link(targetFile, linkFile));
|
||||
|
||||
QString canonical = QFileInfo(linkFile).canonicalFilePath();
|
||||
QCOMPARE(canonical, QFileInfo(targetFile).canonicalFilePath());
|
||||
|
||||
// Try saving into it
|
||||
{
|
||||
QSaveFile saveFile(linkFile);
|
||||
QVERIFY(saveFile.open(QIODevice::WriteOnly));
|
||||
QCOMPARE(saveFile.write(someData), someData.size());
|
||||
saveFile.commit();
|
||||
|
||||
//Check that the linkFile is still a link and still has the same canonical path
|
||||
QFileInfo info(linkFile);
|
||||
QVERIFY(info.isSymLink());
|
||||
QCOMPARE(QFileInfo(linkFile).canonicalFilePath(), canonical);
|
||||
|
||||
QFile file(targetFile);
|
||||
QVERIFY2(file.open(QIODevice::ReadOnly), msgCannotOpen(file).constData());
|
||||
QCOMPARE(file.readAll(), someData);
|
||||
file.remove();
|
||||
}
|
||||
|
||||
// Save into a symbolic link that point to a removed file
|
||||
someData = "more stuff";
|
||||
{
|
||||
QSaveFile saveFile(linkFile);
|
||||
QVERIFY(saveFile.open(QIODevice::WriteOnly));
|
||||
QCOMPARE(saveFile.write(someData), someData.size());
|
||||
saveFile.commit();
|
||||
|
||||
QFileInfo info(linkFile);
|
||||
QVERIFY(info.isSymLink());
|
||||
QCOMPARE(QFileInfo(linkFile).canonicalFilePath(), canonical);
|
||||
|
||||
QFile file(targetFile);
|
||||
QVERIFY2(file.open(QIODevice::ReadOnly), msgCannotOpen(file).constData());
|
||||
QCOMPARE(file.readAll(), someData);
|
||||
}
|
||||
|
||||
// link to a link in another directory
|
||||
QTemporaryDir dir2;
|
||||
QVERIFY2(dir2.isValid(), qPrintable(dir2.errorString()));
|
||||
|
||||
const QString linkFile2 = dir2.path() + QLatin1String("/linkfile");
|
||||
QVERIFY(QFile::link(linkFile, linkFile2));
|
||||
QCOMPARE(QFileInfo(linkFile2).canonicalFilePath(), canonical);
|
||||
|
||||
|
||||
someData = "hello everyone";
|
||||
|
||||
{
|
||||
QSaveFile saveFile(linkFile2);
|
||||
QVERIFY(saveFile.open(QIODevice::WriteOnly));
|
||||
QCOMPARE(saveFile.write(someData), someData.size());
|
||||
saveFile.commit();
|
||||
|
||||
QFile file(targetFile);
|
||||
QVERIFY2(file.open(QIODevice::ReadOnly), msgCannotOpen(file).constData());
|
||||
QCOMPARE(file.readAll(), someData);
|
||||
}
|
||||
|
||||
//cyclic link
|
||||
const QString cyclicLink = dir.path() + QLatin1String("/cyclic");
|
||||
QVERIFY(QFile::link(cyclicLink, cyclicLink));
|
||||
{
|
||||
QSaveFile saveFile(cyclicLink);
|
||||
QVERIFY(saveFile.open(QIODevice::WriteOnly));
|
||||
QCOMPARE(saveFile.write(someData), someData.size());
|
||||
saveFile.commit();
|
||||
|
||||
QFile file(cyclicLink);
|
||||
QVERIFY2(file.open(QIODevice::ReadOnly), msgCannotOpen(file).constData());
|
||||
QCOMPARE(file.readAll(), someData);
|
||||
}
|
||||
|
||||
//cyclic link2
|
||||
QVERIFY(QFile::link(cyclicLink + QLatin1Char('1'), cyclicLink + QLatin1Char('2')));
|
||||
QVERIFY(QFile::link(cyclicLink + QLatin1Char('2'), cyclicLink + QLatin1Char('1')));
|
||||
|
||||
{
|
||||
QSaveFile saveFile(cyclicLink + QLatin1Char('1'));
|
||||
QVERIFY(saveFile.open(QIODevice::WriteOnly));
|
||||
QCOMPARE(saveFile.write(someData), someData.size());
|
||||
saveFile.commit();
|
||||
|
||||
// the explicit file becomes a file instead of a link
|
||||
QVERIFY(!QFileInfo(cyclicLink + QLatin1Char('1')).isSymLink());
|
||||
QVERIFY(QFileInfo(cyclicLink + QLatin1Char('2')).isSymLink());
|
||||
|
||||
QFile file(cyclicLink + QLatin1Char('1'));
|
||||
QVERIFY2(file.open(QIODevice::ReadOnly), msgCannotOpen(file).constData());
|
||||
QCOMPARE(file.readAll(), someData);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QSaveFile::directory()
|
||||
{
|
||||
QTemporaryDir dir;
|
||||
QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
|
||||
|
||||
const QString subdir = dir.path() + QLatin1String("/subdir");
|
||||
QVERIFY(QDir(dir.path()).mkdir(QStringLiteral("subdir")));
|
||||
{
|
||||
QFile sf(subdir);
|
||||
QVERIFY(!sf.open(QIODevice::WriteOnly));
|
||||
}
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
//link to a directory
|
||||
const QString linkToDir = dir.path() + QLatin1String("/linkToDir");
|
||||
QVERIFY(QFile::link(subdir, linkToDir));
|
||||
|
||||
{
|
||||
QFile sf(linkToDir);
|
||||
QVERIFY(!sf.open(QIODevice::WriteOnly));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
void tst_QSaveFile::alternateDataStream_data()
|
||||
{
|
||||
QTest::addColumn<bool>("directWriteFallback");
|
||||
QTest::addColumn<bool>("success");
|
||||
|
||||
QTest::newRow("default") << false << false;
|
||||
QTest::newRow("directWriteFallback") << true << true;
|
||||
}
|
||||
|
||||
void tst_QSaveFile::alternateDataStream()
|
||||
{
|
||||
QFETCH(bool, directWriteFallback);
|
||||
QFETCH(bool, success);
|
||||
static const char newContent[] = "New content\r\n";
|
||||
|
||||
QTemporaryDir dir;
|
||||
QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
|
||||
QString baseName = dir.path() + QLatin1String("/base");
|
||||
{
|
||||
QFile baseFile(baseName);
|
||||
QVERIFY2(baseFile.open(QIODevice::ReadWrite), qPrintable(baseFile.errorString()));
|
||||
}
|
||||
|
||||
// First, create a file with old content
|
||||
QString adsName = baseName + QLatin1String(":outfile");
|
||||
{
|
||||
QFile targetFile(adsName);
|
||||
if (!targetFile.open(QIODevice::ReadWrite))
|
||||
QSKIP("Failed to ceate ADS file (" + targetFile.errorString().toUtf8()
|
||||
+ "). Temp dir is FAT?");
|
||||
targetFile.write("Old content\r\n");
|
||||
}
|
||||
|
||||
// And write to it again using QSaveFile; only works if directWriteFallback is enabled
|
||||
QSaveFile file(adsName);
|
||||
file.setDirectWriteFallback(directWriteFallback);
|
||||
QCOMPARE(file.directWriteFallback(), directWriteFallback);
|
||||
|
||||
if (success) {
|
||||
QVERIFY2(file.open(QIODevice::WriteOnly), qPrintable(file.errorString()));
|
||||
file.write(newContent);
|
||||
QVERIFY2(file.commit(), qPrintable(file.errorString()));
|
||||
|
||||
// check the contents
|
||||
QFile targetFile(adsName);
|
||||
QVERIFY2(targetFile.open(QIODevice::ReadOnly), qPrintable(targetFile.errorString()));
|
||||
QByteArray contents = targetFile.readAll();
|
||||
QCOMPARE(contents, QByteArray(newContent));
|
||||
} else {
|
||||
QVERIFY(!file.open(QIODevice::WriteOnly));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QTEST_MAIN(tst_QSaveFile)
|
||||
#include "tst_qsavefile.moc"
|
Reference in New Issue
Block a user