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:
66
tests/auto/corelib/io/CMakeLists.txt
Normal file
66
tests/auto/corelib/io/CMakeLists.txt
Normal file
@ -0,0 +1,66 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# There is no mounted filesystem for IO testing on INTEGRITY yet.
|
||||
if(INTEGRITY)
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(QT_FEATURE_private_tests)
|
||||
add_subdirectory(qabstractfileengine)
|
||||
add_subdirectory(qfileinfo)
|
||||
add_subdirectory(qipaddress)
|
||||
add_subdirectory(qloggingregistry)
|
||||
add_subdirectory(qurlinternal)
|
||||
endif()
|
||||
add_subdirectory(qbuffer)
|
||||
add_subdirectory(qdataurl)
|
||||
add_subdirectory(qdiriterator)
|
||||
add_subdirectory(qfile)
|
||||
add_subdirectory(largefile)
|
||||
add_subdirectory(qfileselector)
|
||||
add_subdirectory(qfilesystemmetadata)
|
||||
add_subdirectory(qloggingcategory)
|
||||
add_subdirectory(qnodebug)
|
||||
add_subdirectory(qsavefile)
|
||||
add_subdirectory(qstandardpaths)
|
||||
if(NOT QNX)
|
||||
add_subdirectory(qstorageinfo)
|
||||
endif()
|
||||
add_subdirectory(qtemporarydir)
|
||||
add_subdirectory(qtemporaryfile)
|
||||
add_subdirectory(qurlquery)
|
||||
add_subdirectory(qurluts46)
|
||||
if(TARGET Qt::Concurrent)
|
||||
if(NOT INTEGRITY)
|
||||
add_subdirectory(qdebug)
|
||||
endif()
|
||||
add_subdirectory(qlockfile)
|
||||
add_subdirectory(qurl)
|
||||
endif()
|
||||
if(NOT ANDROID)
|
||||
add_subdirectory(qdir)
|
||||
add_subdirectory(qresourceengine)
|
||||
endif()
|
||||
if(QT_FEATURE_private_tests)
|
||||
add_subdirectory(qfilesystementry)
|
||||
endif()
|
||||
# QTBUG-88508
|
||||
if(QT_FEATURE_filesystemwatcher AND NOT ANDROID)
|
||||
add_subdirectory(qfilesystemwatcher)
|
||||
endif()
|
||||
if(TARGET Qt::Network)
|
||||
add_subdirectory(qiodevice)
|
||||
endif()
|
||||
if(QT_FEATURE_process AND TARGET Qt::Network AND NOT ANDROID)
|
||||
add_subdirectory(qprocess)
|
||||
endif()
|
||||
if(QT_FEATURE_process)
|
||||
add_subdirectory(qprocess-noapplication)
|
||||
endif()
|
||||
if(QT_FEATURE_processenvironment)
|
||||
add_subdirectory(qprocessenvironment)
|
||||
endif()
|
||||
if(QT_FEATURE_settings AND TARGET Qt::Gui)
|
||||
add_subdirectory(qsettings)
|
||||
endif()
|
13
tests/auto/corelib/io/largefile/CMakeLists.txt
Normal file
13
tests/auto/corelib/io/largefile/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_largefile Test:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_test(tst_largefile
|
||||
SOURCES
|
||||
tst_largefile.cpp
|
||||
LIBRARIES
|
||||
Qt::TestPrivate
|
||||
)
|
530
tests/auto/corelib/io/largefile/tst_largefile.cpp
Normal file
530
tests/auto/corelib/io/largefile/tst_largefile.cpp
Normal file
@ -0,0 +1,530 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <QTest>
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QRandomGenerator>
|
||||
#include <qplatformdefs.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# include <qt_windows.h>
|
||||
# include <io.h>
|
||||
# ifndef FSCTL_SET_SPARSE
|
||||
// MinGW doesn't define this.
|
||||
# define FSCTL_SET_SPARSE (0x900C4)
|
||||
# endif
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
#include <QtTest/private/qemulationdetector_p.h>
|
||||
|
||||
class tst_LargeFile
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
tst_LargeFile()
|
||||
: blockSize(1 << 12)
|
||||
, maxSizeBits()
|
||||
, fd_(-1)
|
||||
, stream_(0)
|
||||
{
|
||||
#if defined(QT_LARGEFILE_SUPPORT) && !defined(Q_OS_MAC) && !defined(Q_OS_QNX)
|
||||
maxSizeBits = 36; // 64 GiB
|
||||
#elif defined(Q_OS_MAC)
|
||||
// HFS+ does not support sparse files, so we limit file size for the test
|
||||
// on Mac OS.
|
||||
maxSizeBits = 24; // 16 MiB
|
||||
#elif defined(Q_OS_QNX)
|
||||
// Many of the filesystems that QNX supports use a 32-bit format.
|
||||
// This means that files are limited to 2 GB − 1 bytes.
|
||||
// Limit max size to 256MB
|
||||
maxSizeBits = 28; // 256 MiB
|
||||
#else
|
||||
maxSizeBits = 24; // 16 MiB
|
||||
#endif
|
||||
|
||||
// QEMU only supports < 4GB files
|
||||
if (QTestPrivate::isRunningArmOnX86())
|
||||
maxSizeBits = qMin(maxSizeBits, 28);
|
||||
}
|
||||
|
||||
private:
|
||||
void sparseFileData();
|
||||
QByteArray const &getDataBlock(int index, qint64 position);
|
||||
|
||||
private slots:
|
||||
// The LargeFile test case was designed to be run in order as a single unit
|
||||
|
||||
void initTestCase();
|
||||
void cleanupTestCase();
|
||||
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
// Create and fill large file
|
||||
void createSparseFile();
|
||||
void fillFileSparsely();
|
||||
void closeSparseFile();
|
||||
|
||||
// Verify file was created
|
||||
void fileCreated();
|
||||
|
||||
// Positioning in large files
|
||||
void filePositioning();
|
||||
void fdPositioning();
|
||||
void streamPositioning();
|
||||
|
||||
// Read data from file
|
||||
void openFileForReading();
|
||||
void readFile();
|
||||
|
||||
// Map/unmap large file
|
||||
void mapFile();
|
||||
void mapOffsetOverflow();
|
||||
|
||||
void closeFile() { largeFile.close(); }
|
||||
|
||||
// Test data
|
||||
void fillFileSparsely_data() { sparseFileData(); }
|
||||
void filePositioning_data() { sparseFileData(); }
|
||||
void fdPositioning_data() { sparseFileData(); }
|
||||
void streamPositioning_data() { sparseFileData(); }
|
||||
void readFile_data() { sparseFileData(); }
|
||||
void mapFile_data() { sparseFileData(); }
|
||||
|
||||
private:
|
||||
const int blockSize;
|
||||
int maxSizeBits;
|
||||
|
||||
QFile largeFile;
|
||||
|
||||
QByteArrayList generatedBlocks;
|
||||
|
||||
int fd_;
|
||||
FILE *stream_;
|
||||
|
||||
QSharedPointer<QTemporaryDir> m_tempDir;
|
||||
QString m_previousCurrent;
|
||||
};
|
||||
|
||||
/*
|
||||
Convenience function to hide reinterpret_cast when copying a POD directly
|
||||
into a QByteArray.
|
||||
*/
|
||||
template <class T>
|
||||
static inline void appendRaw(QByteArray &array, T data)
|
||||
{
|
||||
array.append(reinterpret_cast<char *>(&data), sizeof(T));
|
||||
}
|
||||
|
||||
/*
|
||||
Pad array with filler up to size. On return, array.size() returns size.
|
||||
*/
|
||||
static inline void topUpWith(QByteArray &array, QByteArray filler, int size)
|
||||
{
|
||||
for (int i = (size - array.size()) / filler.size(); i > 0; --i)
|
||||
array.append(filler);
|
||||
|
||||
if (array.size() < size) {
|
||||
array.append(filler.left(size - array.size()));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Generate a unique data block containing identifiable data. Unaligned,
|
||||
overlapping and partial blocks should not compare equal.
|
||||
*/
|
||||
static inline QByteArray generateDataBlock(int blockSize, QString text, qint64 userBits = -1)
|
||||
{
|
||||
QByteArray block;
|
||||
block.reserve(blockSize);
|
||||
|
||||
// Use of counter and randomBits means content of block will be dependent
|
||||
// on the generation order. For (file-)systems that do not support sparse
|
||||
// files, these can be removed so the test file can be reused and doesn't
|
||||
// have to be generated for every run.
|
||||
|
||||
static qint64 counter = 0;
|
||||
|
||||
qint64 randomBits = QRandomGenerator::global()->generate64();
|
||||
|
||||
appendRaw(block, randomBits);
|
||||
appendRaw(block, userBits);
|
||||
appendRaw(block, counter);
|
||||
appendRaw(block, (qint32)0xdeadbeef);
|
||||
appendRaw(block, blockSize);
|
||||
|
||||
QByteArray userContent = text.toUtf8();
|
||||
appendRaw(block, userContent.size());
|
||||
block.append(userContent);
|
||||
appendRaw(block, (qint64)0);
|
||||
|
||||
// size, so far
|
||||
appendRaw(block, block.size());
|
||||
|
||||
QByteArray filler("0123456789");
|
||||
block.append(filler.right(10 - block.size() % 10));
|
||||
topUpWith(block, filler, blockSize - 3 * sizeof(qint64));
|
||||
|
||||
appendRaw(block, counter);
|
||||
appendRaw(block, userBits);
|
||||
appendRaw(block, randomBits);
|
||||
|
||||
++counter;
|
||||
return block;
|
||||
}
|
||||
|
||||
/*
|
||||
Generates data blocks the first time they are requested. Keeps copies for reuse.
|
||||
*/
|
||||
QByteArray const &tst_LargeFile::getDataBlock(int index, qint64 position)
|
||||
{
|
||||
if (index >= generatedBlocks.size())
|
||||
generatedBlocks.resize(index + 1);
|
||||
|
||||
if (generatedBlocks[index].isNull()) {
|
||||
QString text = QString("Current %1-byte block (index = %2) "
|
||||
"starts %3 bytes into the file '%4'.")
|
||||
.arg(blockSize)
|
||||
.arg(index)
|
||||
.arg(position)
|
||||
.arg("qt_largefile.tmp");
|
||||
|
||||
generatedBlocks[index] = generateDataBlock(blockSize, text, (qint64)1 << index);
|
||||
}
|
||||
|
||||
return generatedBlocks[index];
|
||||
}
|
||||
|
||||
void tst_LargeFile::initTestCase()
|
||||
{
|
||||
m_previousCurrent = QDir::currentPath();
|
||||
m_tempDir = QSharedPointer<QTemporaryDir>::create();
|
||||
QVERIFY2(!m_tempDir.isNull(), qPrintable("Could not create temporary directory."));
|
||||
QVERIFY2(QDir::setCurrent(m_tempDir->path()), qPrintable("Could not switch current directory"));
|
||||
|
||||
QFile file("qt_largefile.tmp");
|
||||
QVERIFY( !file.exists() || file.remove() );
|
||||
}
|
||||
|
||||
void tst_LargeFile::cleanupTestCase()
|
||||
{
|
||||
if (largeFile.isOpen())
|
||||
largeFile.close();
|
||||
|
||||
QFile file("qt_largefile.tmp");
|
||||
QVERIFY( !file.exists() || file.remove() );
|
||||
|
||||
QDir::setCurrent(m_previousCurrent);
|
||||
}
|
||||
|
||||
void tst_LargeFile::init()
|
||||
{
|
||||
fd_ = -1;
|
||||
stream_ = 0;
|
||||
}
|
||||
|
||||
void tst_LargeFile::cleanup()
|
||||
{
|
||||
if (-1 != fd_)
|
||||
QT_CLOSE(fd_);
|
||||
if (stream_)
|
||||
::fclose(stream_);
|
||||
}
|
||||
|
||||
void tst_LargeFile::sparseFileData()
|
||||
{
|
||||
QTest::addColumn<int>("index");
|
||||
QTest::addColumn<qint64>("position");
|
||||
QTest::addColumn<QByteArray>("block");
|
||||
|
||||
QTest::newRow(QString("block[%1] @%2)")
|
||||
.arg(0).arg(0)
|
||||
.toLocal8Bit().constData())
|
||||
<< 0 << (qint64)0 << getDataBlock(0, 0);
|
||||
|
||||
// While on Linux sparse files scale well, on Windows, testing at every
|
||||
// power of 2 leads to very large files. i += 4 gives us a good coverage
|
||||
// without taxing too much on resources.
|
||||
for (int index = 12; index <= maxSizeBits; index += 4) {
|
||||
qint64 position = (qint64)1 << index;
|
||||
QByteArray block = getDataBlock(index, position);
|
||||
|
||||
QTest::newRow(
|
||||
QString("block[%1] @%2)")
|
||||
.arg(index).arg(position)
|
||||
.toLocal8Bit().constData())
|
||||
<< index << position << block;
|
||||
}
|
||||
}
|
||||
|
||||
void tst_LargeFile::createSparseFile()
|
||||
{
|
||||
#if defined(Q_OS_WIN32)
|
||||
// On Windows platforms, we must explicitly set the file to be sparse,
|
||||
// so disk space is not allocated for the full file when writing to it.
|
||||
HANDLE handle = ::CreateFileA("qt_largefile.tmp",
|
||||
GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
||||
QVERIFY( INVALID_HANDLE_VALUE != handle );
|
||||
|
||||
DWORD bytes;
|
||||
if (!::DeviceIoControl(handle, FSCTL_SET_SPARSE, NULL, 0, NULL, 0,
|
||||
&bytes, NULL)) {
|
||||
qWarning("Unable to set test file as sparse. "
|
||||
"Limiting test file to 16MiB.");
|
||||
maxSizeBits = 24;
|
||||
}
|
||||
|
||||
int fd = ::_open_osfhandle((intptr_t)handle, 0);
|
||||
QVERIFY( -1 != fd );
|
||||
QVERIFY( largeFile.open(fd, QIODevice::WriteOnly | QIODevice::Unbuffered) );
|
||||
#else // !Q_OS_WIN32
|
||||
largeFile.setFileName("qt_largefile.tmp");
|
||||
QVERIFY( largeFile.open(QIODevice::WriteOnly | QIODevice::Unbuffered) );
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_LargeFile::closeSparseFile()
|
||||
{
|
||||
#if defined(Q_OS_WIN32)
|
||||
int fd = largeFile.handle();
|
||||
#endif
|
||||
|
||||
largeFile.close();
|
||||
|
||||
#if defined(Q_OS_WIN32)
|
||||
if (-1 != fd)
|
||||
::_close(fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_LargeFile::fillFileSparsely()
|
||||
{
|
||||
QFETCH( qint64, position );
|
||||
QFETCH( QByteArray, block );
|
||||
QCOMPARE( block.size(), blockSize );
|
||||
|
||||
static int lastKnownGoodIndex = 0;
|
||||
struct ScopeGuard {
|
||||
ScopeGuard(tst_LargeFile* test)
|
||||
: this_(test)
|
||||
, failed(true)
|
||||
{
|
||||
QFETCH( int, index );
|
||||
index_ = index;
|
||||
}
|
||||
|
||||
~ScopeGuard()
|
||||
{
|
||||
if (failed) {
|
||||
this_->maxSizeBits = lastKnownGoodIndex;
|
||||
qWarning("QFile::error %d: '%s'. Maximum size bits reset to %d.",
|
||||
this_->largeFile.error(),
|
||||
qPrintable(this_->largeFile.errorString()),
|
||||
this_->maxSizeBits);
|
||||
} else
|
||||
lastKnownGoodIndex = qMax<int>(index_, lastKnownGoodIndex);
|
||||
}
|
||||
|
||||
private:
|
||||
tst_LargeFile * const this_;
|
||||
int index_;
|
||||
|
||||
public:
|
||||
bool failed;
|
||||
};
|
||||
|
||||
ScopeGuard resetMaxSizeBitsOnFailure(this);
|
||||
|
||||
QVERIFY( largeFile.seek(position) );
|
||||
QCOMPARE( largeFile.pos(), position );
|
||||
|
||||
QCOMPARE( largeFile.write(block), (qint64)blockSize );
|
||||
QCOMPARE( largeFile.pos(), position + blockSize );
|
||||
QVERIFY( largeFile.flush() );
|
||||
|
||||
resetMaxSizeBitsOnFailure.failed = false;
|
||||
}
|
||||
|
||||
void tst_LargeFile::fileCreated()
|
||||
{
|
||||
QFileInfo info("qt_largefile.tmp");
|
||||
|
||||
QVERIFY( info.exists() );
|
||||
QVERIFY( info.isFile() );
|
||||
QVERIFY( info.size() >= ((qint64)1 << maxSizeBits) + blockSize );
|
||||
}
|
||||
|
||||
void tst_LargeFile::filePositioning()
|
||||
{
|
||||
QFETCH( qint64, position );
|
||||
|
||||
QFile file("qt_largefile.tmp");
|
||||
QVERIFY( file.open(QIODevice::ReadOnly) );
|
||||
|
||||
QVERIFY( file.seek(position) );
|
||||
QCOMPARE( file.pos(), position );
|
||||
}
|
||||
|
||||
void tst_LargeFile::fdPositioning()
|
||||
{
|
||||
QFETCH( qint64, position );
|
||||
|
||||
fd_ = QT_OPEN("qt_largefile.tmp",
|
||||
QT_OPEN_RDONLY | QT_OPEN_LARGEFILE);
|
||||
QVERIFY( -1 != fd_ );
|
||||
|
||||
QFile file;
|
||||
QVERIFY( file.open(fd_, QIODevice::ReadOnly) );
|
||||
QCOMPARE( file.pos(), (qint64)0 );
|
||||
QVERIFY( file.seek(position) );
|
||||
QCOMPARE( file.pos(), position );
|
||||
|
||||
file.close();
|
||||
|
||||
QCOMPARE( QT_OFF_T(QT_LSEEK(fd_, QT_OFF_T(0), SEEK_SET)), QT_OFF_T(0) );
|
||||
QCOMPARE( QT_OFF_T(QT_LSEEK(fd_, QT_OFF_T(position), SEEK_SET)), QT_OFF_T(position) );
|
||||
|
||||
QVERIFY( file.open(fd_, QIODevice::ReadOnly) );
|
||||
QCOMPARE( QT_OFF_T(QT_LSEEK(fd_, QT_OFF_T(0), SEEK_CUR)), QT_OFF_T(position) );
|
||||
QCOMPARE( file.pos(), position );
|
||||
QVERIFY( file.seek(0) );
|
||||
QCOMPARE( file.pos(), (qint64)0 );
|
||||
|
||||
file.close();
|
||||
|
||||
QVERIFY( !QT_CLOSE(fd_) );
|
||||
fd_ = -1;
|
||||
}
|
||||
|
||||
void tst_LargeFile::streamPositioning()
|
||||
{
|
||||
QFETCH( qint64, position );
|
||||
|
||||
stream_ = QT_FOPEN("qt_largefile.tmp", "rb");
|
||||
QVERIFY( 0 != stream_ );
|
||||
|
||||
QFile file;
|
||||
QVERIFY( file.open(stream_, QIODevice::ReadOnly) );
|
||||
QCOMPARE( file.pos(), (qint64)0 );
|
||||
QVERIFY( file.seek(position) );
|
||||
QCOMPARE( file.pos(), position );
|
||||
|
||||
file.close();
|
||||
|
||||
QVERIFY( !QT_FSEEK(stream_, QT_OFF_T(0), SEEK_SET) );
|
||||
QCOMPARE( QT_OFF_T(QT_FTELL(stream_)), QT_OFF_T(0) );
|
||||
QVERIFY( !QT_FSEEK(stream_, QT_OFF_T(position), SEEK_SET) );
|
||||
QCOMPARE( QT_OFF_T(QT_FTELL(stream_)), QT_OFF_T(position) );
|
||||
|
||||
QVERIFY( file.open(stream_, QIODevice::ReadOnly) );
|
||||
QCOMPARE( QT_OFF_T(QT_FTELL(stream_)), QT_OFF_T(position) );
|
||||
QCOMPARE( file.pos(), position );
|
||||
QVERIFY( file.seek(0) );
|
||||
QCOMPARE( file.pos(), (qint64)0 );
|
||||
|
||||
file.close();
|
||||
|
||||
QVERIFY( !::fclose(stream_) );
|
||||
stream_ = 0;
|
||||
}
|
||||
|
||||
void tst_LargeFile::openFileForReading()
|
||||
{
|
||||
largeFile.setFileName("qt_largefile.tmp");
|
||||
QVERIFY( largeFile.open(QIODevice::ReadOnly) );
|
||||
}
|
||||
|
||||
void tst_LargeFile::readFile()
|
||||
{
|
||||
QFETCH( qint64, position );
|
||||
QFETCH( QByteArray, block );
|
||||
QCOMPARE( block.size(), blockSize );
|
||||
|
||||
QVERIFY( largeFile.size() >= position + blockSize );
|
||||
|
||||
QVERIFY( largeFile.seek(position) );
|
||||
QCOMPARE( largeFile.pos(), position );
|
||||
|
||||
QCOMPARE( largeFile.read(blockSize), block );
|
||||
QCOMPARE( largeFile.pos(), position + blockSize );
|
||||
}
|
||||
|
||||
void tst_LargeFile::mapFile()
|
||||
{
|
||||
QFETCH( qint64, position );
|
||||
QFETCH( QByteArray, block );
|
||||
QCOMPARE( block.size(), blockSize );
|
||||
|
||||
// Keep full block mapped to facilitate OS and/or internal reuse by Qt.
|
||||
uchar *baseAddress = largeFile.map(position, blockSize);
|
||||
QVERIFY( baseAddress );
|
||||
QVERIFY( std::equal(block.begin(), block.end(), reinterpret_cast<char*>(baseAddress)) );
|
||||
|
||||
for (int offset = 1; offset < blockSize; ++offset) {
|
||||
uchar *address = largeFile.map(position + offset, blockSize - offset);
|
||||
|
||||
QVERIFY( address );
|
||||
if ( !std::equal(block.begin() + offset, block.end(), reinterpret_cast<char*>(address)) ) {
|
||||
qDebug() << "Expected:" << block.toHex();
|
||||
qDebug() << "Actual :" << QByteArray(reinterpret_cast<char*>(address), blockSize).toHex();
|
||||
QVERIFY(false);
|
||||
}
|
||||
|
||||
QVERIFY( largeFile.unmap( address ) );
|
||||
}
|
||||
|
||||
QVERIFY( largeFile.unmap( baseAddress ) );
|
||||
}
|
||||
|
||||
//Mac: memory-mapping beyond EOF may succeed but it could generate bus error on access
|
||||
//FreeBSD: same
|
||||
//Linux: memory-mapping beyond EOF usually succeeds, but depends on the filesystem
|
||||
// 32-bit: limited to 44-bit offsets (when sizeof(off_t) == 8)
|
||||
//Windows: memory-mapping beyond EOF is not allowed
|
||||
void tst_LargeFile::mapOffsetOverflow()
|
||||
{
|
||||
enum {
|
||||
#ifdef Q_OS_WIN
|
||||
Succeeds = false,
|
||||
MaxOffset = 63
|
||||
#else
|
||||
Succeeds = true,
|
||||
# if (defined(Q_OS_LINUX) || defined(Q_OS_ANDROID)) && Q_PROCESSOR_WORDSIZE == 4
|
||||
MaxOffset = sizeof(QT_OFF_T) > 4 ? 43 : 30
|
||||
# else
|
||||
MaxOffset = 8 * sizeof(QT_OFF_T) - 1
|
||||
# endif
|
||||
#endif
|
||||
};
|
||||
|
||||
QByteArray zeroPage(blockSize, '\0');
|
||||
for (int i = maxSizeBits + 1; i < 63; ++i) {
|
||||
bool succeeds = Succeeds && (i <= MaxOffset);
|
||||
uchar *address = 0;
|
||||
qint64 offset = Q_INT64_C(1) << i;
|
||||
|
||||
if (succeeds)
|
||||
QTest::ignoreMessage(QtWarningMsg, "QFSFileEngine::map: Mapping a file beyond its size is not portable");
|
||||
address = largeFile.map(offset, blockSize);
|
||||
QCOMPARE(!!address, succeeds);
|
||||
|
||||
if (succeeds)
|
||||
QTest::ignoreMessage(QtWarningMsg, "QFSFileEngine::map: Mapping a file beyond its size is not portable");
|
||||
address = largeFile.map(offset + blockSize, blockSize);
|
||||
QCOMPARE(!!address, succeeds);
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_LargeFile)
|
||||
#include "tst_largefile.moc"
|
||||
|
26
tests/auto/corelib/io/qabstractfileengine/CMakeLists.txt
Normal file
26
tests/auto/corelib/io/qabstractfileengine/CMakeLists.txt
Normal file
@ -0,0 +1,26 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qabstractfileengine Test:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_test(tst_qabstractfileengine
|
||||
SOURCES
|
||||
tst_qabstractfileengine.cpp
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(qabstractfileengine_resource_files
|
||||
"resources/"
|
||||
)
|
||||
|
||||
qt_internal_add_resource(tst_qabstractfileengine "qabstractfileengine"
|
||||
PREFIX
|
||||
"/tst_qabstractfileengine/"
|
||||
FILES
|
||||
${qabstractfileengine_resource_files}
|
||||
)
|
||||
|
@ -0,0 +1 @@
|
||||
This is a simple text file.
|
@ -0,0 +1,836 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <QtCore/private/qabstractfileengine_p.h>
|
||||
#include <QtCore/private/qfsfileengine_p.h>
|
||||
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QMutexLocker>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QScopedPointer>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QDirIterator>
|
||||
|
||||
#include <QtTest/QTest>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include "../../../../shared/filesystem.h"
|
||||
|
||||
class tst_QAbstractFileEngine
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public slots:
|
||||
void initTestCase();
|
||||
void cleanupTestCase();
|
||||
|
||||
private slots:
|
||||
void customHandler();
|
||||
|
||||
void fileIO_data();
|
||||
void fileIO();
|
||||
|
||||
void mounting_data();
|
||||
void mounting();
|
||||
private:
|
||||
QStringList filesForRemoval;
|
||||
QSharedPointer<QTemporaryDir> m_currentDir;
|
||||
QString m_previousCurrent;
|
||||
};
|
||||
|
||||
class ReferenceFileEngine
|
||||
: public QAbstractFileEngine
|
||||
{
|
||||
public:
|
||||
ReferenceFileEngine(const QString &fileName)
|
||||
: fileName_(QDir::cleanPath(fileName))
|
||||
, position_(-1)
|
||||
, openForRead_(false)
|
||||
, openForWrite_(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool open(QIODevice::OpenMode openMode, std::optional<QFile::Permissions> permissions) override
|
||||
{
|
||||
Q_UNUSED(permissions);
|
||||
|
||||
if (openForRead_ || openForWrite_) {
|
||||
qWarning("%s: file is already open for %s",
|
||||
Q_FUNC_INFO,
|
||||
(openForRead_ ? "reading" : "writing"));
|
||||
return false;
|
||||
}
|
||||
|
||||
openFile_ = resolveFile(openMode & QIODevice::WriteOnly);
|
||||
if (!openFile_)
|
||||
return false;
|
||||
|
||||
position_ = 0;
|
||||
if (openMode & QIODevice::ReadOnly)
|
||||
openForRead_ = true;
|
||||
|
||||
if (openMode & QIODevice::WriteOnly) {
|
||||
openForWrite_ = true;
|
||||
|
||||
QMutexLocker lock(&openFile_->mutex);
|
||||
if (openMode & QIODevice::Truncate
|
||||
|| !(openForRead_ || openMode & QIODevice::Append))
|
||||
openFile_->content.clear();
|
||||
|
||||
if (openMode & QIODevice::Append)
|
||||
position_ = openFile_->content.size();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool close() override
|
||||
{
|
||||
openFile_.clear();
|
||||
|
||||
openForRead_ = false;
|
||||
openForWrite_ = false;
|
||||
position_ = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qint64 size() const override
|
||||
{
|
||||
QSharedPointer<File> file = resolveFile(false);
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
QMutexLocker lock(&file->mutex);
|
||||
return file->content.size();
|
||||
}
|
||||
|
||||
qint64 pos() const override
|
||||
{
|
||||
if (!openForRead_ && !openForWrite_) {
|
||||
qWarning("%s: file is not open", Q_FUNC_INFO);
|
||||
return -1;
|
||||
}
|
||||
return position_;
|
||||
}
|
||||
|
||||
bool seek(qint64 pos) override
|
||||
{
|
||||
if (!openForRead_ && !openForWrite_) {
|
||||
qWarning("%s: file is not open", Q_FUNC_INFO);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pos >= 0) {
|
||||
position_ = pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool flush() override
|
||||
{
|
||||
if (!openForRead_ && !openForWrite_) {
|
||||
qWarning("%s: file is not open", Q_FUNC_INFO);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool remove() override
|
||||
{
|
||||
QMutexLocker lock(&fileSystemMutex);
|
||||
int count = fileSystem.remove(fileName_);
|
||||
|
||||
return (count == 1);
|
||||
}
|
||||
|
||||
bool copy(const QString &newName) override
|
||||
{
|
||||
QMutexLocker lock(&fileSystemMutex);
|
||||
if (!fileSystem.contains(fileName_)
|
||||
|| fileSystem.contains(newName))
|
||||
return false;
|
||||
|
||||
fileSystem.insert(newName, fileSystem.value(fileName_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rename(const QString &newName) override
|
||||
{
|
||||
QMutexLocker lock(&fileSystemMutex);
|
||||
if (!fileSystem.contains(fileName_)
|
||||
|| fileSystem.contains(newName))
|
||||
return false;
|
||||
|
||||
fileSystem.insert(newName, fileSystem.take(fileName_));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setSize(qint64 size) override
|
||||
{
|
||||
if (size < 0)
|
||||
return false;
|
||||
|
||||
QSharedPointer<File> file = resolveFile(false);
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
QMutexLocker lock(&file->mutex);
|
||||
file->content.resize(size);
|
||||
|
||||
if (openForRead_ || openForWrite_)
|
||||
if (position_ > size)
|
||||
position_ = size;
|
||||
|
||||
return (file->content.size() == size);
|
||||
}
|
||||
|
||||
FileFlags fileFlags(FileFlags type) const override
|
||||
{
|
||||
QSharedPointer<File> file = resolveFile(false);
|
||||
if (file) {
|
||||
QMutexLocker lock(&file->mutex);
|
||||
return (file->fileFlags & type);
|
||||
}
|
||||
|
||||
return FileFlags();
|
||||
}
|
||||
|
||||
QString fileName(FileName file) const override
|
||||
{
|
||||
switch (file) {
|
||||
case DefaultName:
|
||||
return QLatin1String("DefaultName");
|
||||
case BaseName:
|
||||
return QLatin1String("BaseName");
|
||||
case PathName:
|
||||
return QLatin1String("PathName");
|
||||
case AbsoluteName:
|
||||
return QLatin1String("AbsoluteName");
|
||||
case AbsolutePathName:
|
||||
return QLatin1String("AbsolutePathName");
|
||||
case AbsoluteLinkTarget:
|
||||
return QLatin1String("AbsoluteLinkTarget");
|
||||
case CanonicalName:
|
||||
return QLatin1String("CanonicalName");
|
||||
case CanonicalPathName:
|
||||
return QLatin1String("CanonicalPathName");
|
||||
case BundleName:
|
||||
return QLatin1String("BundleName");
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
uint ownerId(FileOwner owner) const override
|
||||
{
|
||||
QSharedPointer<File> file = resolveFile(false);
|
||||
if (file) {
|
||||
switch (owner) {
|
||||
case OwnerUser:
|
||||
{
|
||||
QMutexLocker lock(&file->mutex);
|
||||
return file->userId;
|
||||
}
|
||||
case OwnerGroup:
|
||||
{
|
||||
QMutexLocker lock(&file->mutex);
|
||||
return file->groupId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
QString owner(FileOwner owner) const override
|
||||
{
|
||||
QSharedPointer<File> file = resolveFile(false);
|
||||
if (file) {
|
||||
uint ownerId;
|
||||
switch (owner) {
|
||||
case OwnerUser:
|
||||
{
|
||||
QMutexLocker lock(&file->mutex);
|
||||
ownerId = file->userId;
|
||||
}
|
||||
|
||||
{
|
||||
QMutexLocker lock(&fileSystemMutex);
|
||||
return fileSystemUsers.value(ownerId);
|
||||
}
|
||||
|
||||
case OwnerGroup:
|
||||
{
|
||||
QMutexLocker lock(&file->mutex);
|
||||
ownerId = file->groupId;
|
||||
}
|
||||
|
||||
{
|
||||
QMutexLocker lock(&fileSystemMutex);
|
||||
return fileSystemGroups.value(ownerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QDateTime fileTime(FileTime time) const override
|
||||
{
|
||||
QSharedPointer<File> file = resolveFile(false);
|
||||
if (file) {
|
||||
QMutexLocker lock(&file->mutex);
|
||||
switch (time) {
|
||||
case BirthTime:
|
||||
return file->birth;
|
||||
case MetadataChangeTime:
|
||||
return file->change;
|
||||
case ModificationTime:
|
||||
return file->modification;
|
||||
case AccessTime:
|
||||
return file->access;
|
||||
}
|
||||
}
|
||||
|
||||
return QDateTime();
|
||||
}
|
||||
|
||||
void setFileName(const QString &file) override
|
||||
{
|
||||
if (openForRead_ || openForWrite_)
|
||||
qWarning("%s: Can't set file name while file is open", Q_FUNC_INFO);
|
||||
else
|
||||
fileName_ = file;
|
||||
}
|
||||
|
||||
qint64 read(char *data, qint64 maxLen) override
|
||||
{
|
||||
if (!openForRead_) {
|
||||
qWarning("%s: file must be open for reading", Q_FUNC_INFO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (openFile_.isNull()) {
|
||||
qWarning("%s: file must not be null", Q_FUNC_INFO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
QMutexLocker lock(&openFile_->mutex);
|
||||
qint64 readSize = qMin(openFile_->content.size() - position_, maxLen);
|
||||
if (readSize < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(data, openFile_->content.constData() + position_, readSize);
|
||||
position_ += readSize;
|
||||
|
||||
return readSize;
|
||||
}
|
||||
|
||||
qint64 write(const char *data, qint64 length) override
|
||||
{
|
||||
if (!openForWrite_) {
|
||||
qWarning("%s: file must be open for writing", Q_FUNC_INFO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (openFile_.isNull()) {
|
||||
qWarning("%s: file must not be null", Q_FUNC_INFO);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (length < 0)
|
||||
return -1;
|
||||
|
||||
QMutexLocker lock(&openFile_->mutex);
|
||||
if (openFile_->content.size() == position_)
|
||||
openFile_->content.append(data, length);
|
||||
else {
|
||||
if (position_ + length > openFile_->content.size())
|
||||
openFile_->content.resize(position_ + length);
|
||||
openFile_->content.replace(position_, length, data, length);
|
||||
}
|
||||
|
||||
qint64 writeSize = qMin(length, openFile_->content.size() - position_);
|
||||
position_ += writeSize;
|
||||
|
||||
return writeSize;
|
||||
}
|
||||
|
||||
protected:
|
||||
// void setError(QFile::FileError error, const QString &str);
|
||||
|
||||
struct File
|
||||
{
|
||||
File()
|
||||
: userId(0)
|
||||
, groupId(0)
|
||||
, fileFlags(
|
||||
ReadOwnerPerm | WriteOwnerPerm | ExeOwnerPerm
|
||||
| ReadUserPerm | WriteUserPerm | ExeUserPerm
|
||||
| ReadGroupPerm | WriteGroupPerm | ExeGroupPerm
|
||||
| ReadOtherPerm | WriteOtherPerm | ExeOtherPerm
|
||||
| FileType | ExistsFlag)
|
||||
{
|
||||
}
|
||||
|
||||
QMutex mutex;
|
||||
|
||||
uint userId, groupId;
|
||||
QAbstractFileEngine::FileFlags fileFlags;
|
||||
QDateTime birth, change, modification, access;
|
||||
|
||||
QByteArray content;
|
||||
};
|
||||
|
||||
QSharedPointer<File> resolveFile(bool create) const
|
||||
{
|
||||
if (openForRead_ || openForWrite_) {
|
||||
if (!openFile_)
|
||||
qWarning("%s: file should not be null", Q_FUNC_INFO);
|
||||
return openFile_;
|
||||
}
|
||||
|
||||
QMutexLocker lock(&fileSystemMutex);
|
||||
if (create) {
|
||||
QSharedPointer<File> &p = fileSystem[fileName_];
|
||||
if (p.isNull())
|
||||
p = QSharedPointer<File>::create();
|
||||
return p;
|
||||
}
|
||||
|
||||
return fileSystem.value(fileName_);
|
||||
}
|
||||
|
||||
static QMutex fileSystemMutex;
|
||||
static QHash<uint, QString> fileSystemUsers, fileSystemGroups;
|
||||
static QHash<QString, QSharedPointer<File> > fileSystem;
|
||||
|
||||
private:
|
||||
QString fileName_;
|
||||
qint64 position_;
|
||||
bool openForRead_;
|
||||
bool openForWrite_;
|
||||
|
||||
mutable QSharedPointer<File> openFile_;
|
||||
};
|
||||
|
||||
class MountingFileEngine : public QFSFileEngine
|
||||
{
|
||||
public:
|
||||
class Iterator : public QAbstractFileEngineIterator
|
||||
{
|
||||
public:
|
||||
Iterator(QDir::Filters filters, const QStringList &filterNames)
|
||||
: QAbstractFileEngineIterator(filters, filterNames)
|
||||
{
|
||||
names.append("foo");
|
||||
names.append("bar");
|
||||
index = -1;
|
||||
}
|
||||
QString currentFileName() const override
|
||||
{
|
||||
return names.at(index);
|
||||
}
|
||||
bool hasNext() const override
|
||||
{
|
||||
return index < names.size() - 1;
|
||||
}
|
||||
QString next() override
|
||||
{
|
||||
if (!hasNext())
|
||||
return QString();
|
||||
++index;
|
||||
return currentFilePath();
|
||||
}
|
||||
QStringList names;
|
||||
int index;
|
||||
};
|
||||
MountingFileEngine(QString fileName)
|
||||
: QFSFileEngine(fileName)
|
||||
{
|
||||
}
|
||||
Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override
|
||||
{
|
||||
return new Iterator(filters, filterNames);
|
||||
}
|
||||
FileFlags fileFlags(FileFlags type) const override
|
||||
{
|
||||
if (fileName(DefaultName).endsWith(".tar")) {
|
||||
FileFlags ret = QFSFileEngine::fileFlags(type);
|
||||
//make this file in file system appear to be a directory
|
||||
ret &= ~FileType;
|
||||
ret |= DirectoryType;
|
||||
return ret;
|
||||
} else {
|
||||
//file inside the archive
|
||||
return ExistsFlag | FileType;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
QMutex ReferenceFileEngine::fileSystemMutex;
|
||||
QHash<uint, QString> ReferenceFileEngine::fileSystemUsers, ReferenceFileEngine::fileSystemGroups;
|
||||
QHash<QString, QSharedPointer<ReferenceFileEngine::File> > ReferenceFileEngine::fileSystem;
|
||||
|
||||
class FileEngineHandler
|
||||
: QAbstractFileEngineHandler
|
||||
{
|
||||
QAbstractFileEngine *create(const QString &fileName) const override
|
||||
{
|
||||
if (fileName.endsWith(".tar") || fileName.contains(".tar/"))
|
||||
return new MountingFileEngine(fileName);
|
||||
if (fileName.startsWith("QFSFileEngine:"))
|
||||
return new QFSFileEngine(fileName.mid(14));
|
||||
if (fileName.startsWith("reference-file-engine:"))
|
||||
return new ReferenceFileEngine(fileName.mid(22));
|
||||
if (fileName.startsWith("resource:"))
|
||||
return QAbstractFileEngine::create(QLatin1String(":/tst_qabstractfileengine/resources/") + fileName.mid(9));
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
void tst_QAbstractFileEngine::initTestCase()
|
||||
{
|
||||
m_previousCurrent = QDir::currentPath();
|
||||
m_currentDir = QSharedPointer<QTemporaryDir>::create();
|
||||
QVERIFY2(!m_currentDir.isNull(), qPrintable("Could not create current directory."));
|
||||
QDir::setCurrent(m_currentDir->path());
|
||||
}
|
||||
|
||||
void tst_QAbstractFileEngine::cleanupTestCase()
|
||||
{
|
||||
bool failed = false;
|
||||
|
||||
FileEngineHandler handler;
|
||||
Q_FOREACH(QString file, filesForRemoval)
|
||||
if (!QFile::remove(file)
|
||||
|| QFile::exists(file)) {
|
||||
failed = true;
|
||||
qDebug() << "Couldn't remove file:" << file;
|
||||
}
|
||||
|
||||
QVERIFY(!failed);
|
||||
|
||||
QDir::setCurrent(m_previousCurrent);
|
||||
}
|
||||
|
||||
void tst_QAbstractFileEngine::customHandler()
|
||||
{
|
||||
QScopedPointer<QAbstractFileEngine> file;
|
||||
{
|
||||
file.reset(QAbstractFileEngine::create("resource:file.txt"));
|
||||
|
||||
QVERIFY(file);
|
||||
}
|
||||
|
||||
{
|
||||
FileEngineHandler handler;
|
||||
|
||||
QFile file("resource:file.txt");
|
||||
QVERIFY(file.exists());
|
||||
}
|
||||
|
||||
{
|
||||
QFile file("resource:file.txt");
|
||||
QVERIFY(!file.exists());
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QAbstractFileEngine::fileIO_data()
|
||||
{
|
||||
QTest::addColumn<QString>("fileName");
|
||||
QTest::addColumn<QByteArray>("readContent");
|
||||
QTest::addColumn<QByteArray>("writeContent");
|
||||
QTest::addColumn<bool>("fileExists");
|
||||
|
||||
QString resourceTxtFile(":/tst_qabstractfileengine/resources/file.txt");
|
||||
QByteArray readContent("This is a simple text file.\n");
|
||||
QByteArray writeContent("This contains two lines of text.\n");
|
||||
|
||||
QTest::newRow("resource") << resourceTxtFile << readContent << QByteArray() << true;
|
||||
QTest::newRow("native") << "native-file.txt" << readContent << writeContent << false;
|
||||
QTest::newRow("Forced QFSFileEngine") << "QFSFileEngine:QFSFileEngine-file.txt" << readContent << writeContent << false;
|
||||
QTest::newRow("Custom FE") << "reference-file-engine:file.txt" << readContent << writeContent << false;
|
||||
|
||||
QTest::newRow("Forced QFSFileEngine (native)") << "QFSFileEngine:native-file.txt" << readContent << writeContent << true;
|
||||
QTest::newRow("native (Forced QFSFileEngine)") << "QFSFileEngine-file.txt" << readContent << writeContent << true;
|
||||
QTest::newRow("Custom FE (2)") << "reference-file-engine:file.txt" << readContent << writeContent << true;
|
||||
}
|
||||
|
||||
void tst_QAbstractFileEngine::fileIO()
|
||||
{
|
||||
QFETCH(QString, fileName);
|
||||
QFETCH(QByteArray, readContent);
|
||||
QFETCH(QByteArray, writeContent);
|
||||
QFETCH(bool, fileExists);
|
||||
|
||||
FileEngineHandler handler;
|
||||
|
||||
|
||||
{
|
||||
QFile file(fileName);
|
||||
QCOMPARE(file.exists(), fileExists);
|
||||
|
||||
if (!fileExists) {
|
||||
QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Unbuffered));
|
||||
filesForRemoval.append(fileName);
|
||||
|
||||
QCOMPARE(file.write(readContent), qint64(readContent.size()));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// File content is: readContent
|
||||
//
|
||||
|
||||
qint64 fileSize = readContent.size();
|
||||
{
|
||||
// Reading
|
||||
QFile file(fileName);
|
||||
QVERIFY(!file.isOpen());
|
||||
|
||||
/* For an exact match, this test requires the repository to
|
||||
* be checked out with UNIX-style line endings on Windows.
|
||||
* Try to succeed also for the common case of checking out with autocrlf
|
||||
* by reading the file as text and checking if the size matches
|
||||
* the original size + the '\r' characters added by autocrlf. */
|
||||
|
||||
QFile::OpenMode openMode = QIODevice::ReadOnly | QIODevice::Unbuffered;
|
||||
#ifdef Q_OS_WIN
|
||||
openMode |= QIODevice::Text;
|
||||
#endif
|
||||
QVERIFY(file.open(openMode));
|
||||
QVERIFY(file.isOpen());
|
||||
#ifdef Q_OS_WIN
|
||||
const qint64 convertedSize = fileSize + readContent.count('\n');
|
||||
if (file.size() == convertedSize)
|
||||
fileSize = convertedSize;
|
||||
#endif
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
QCOMPARE(file.pos(), qint64(0));
|
||||
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
QCOMPARE(file.readAll(), readContent);
|
||||
QCOMPARE(file.pos(), fileSize);
|
||||
|
||||
file.close();
|
||||
QVERIFY(!file.isOpen());
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
}
|
||||
|
||||
if (writeContent.isEmpty())
|
||||
return;
|
||||
|
||||
{
|
||||
// Writing / appending
|
||||
QFile file(fileName);
|
||||
|
||||
QVERIFY(!file.isOpen());
|
||||
QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Unbuffered));
|
||||
|
||||
QVERIFY(file.isOpen());
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
QCOMPARE(file.pos(), fileSize);
|
||||
|
||||
QCOMPARE(file.write(writeContent), qint64(writeContent.size()));
|
||||
|
||||
fileSize += writeContent.size();
|
||||
QCOMPARE(file.pos(), fileSize);
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
file.close();
|
||||
QVERIFY(!file.isOpen());
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
}
|
||||
|
||||
//
|
||||
// File content is: readContent + writeContent
|
||||
//
|
||||
|
||||
{
|
||||
// Reading and Writing
|
||||
QFile file(fileName);
|
||||
|
||||
QVERIFY(!file.isOpen());
|
||||
QVERIFY(file.open(QIODevice::ReadWrite | QIODevice::Unbuffered));
|
||||
|
||||
QVERIFY(file.isOpen());
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
QCOMPARE(file.pos(), qint64(0));
|
||||
|
||||
QCOMPARE(file.readAll(), readContent + writeContent);
|
||||
QCOMPARE(file.pos(), fileSize);
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
QVERIFY(file.seek(writeContent.size()));
|
||||
QCOMPARE(file.pos(), qint64(writeContent.size()));
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
QCOMPARE(file.write(readContent), qint64(readContent.size()));
|
||||
QCOMPARE(file.pos(), fileSize);
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
QVERIFY(file.seek(0));
|
||||
QCOMPARE(file.pos(), qint64(0));
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
QCOMPARE(file.write(writeContent), qint64(writeContent.size()));
|
||||
QCOMPARE(file.pos(), qint64(writeContent.size()));
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
QVERIFY(file.seek(0));
|
||||
QCOMPARE(file.read(writeContent.size()), writeContent);
|
||||
QCOMPARE(file.pos(), qint64(writeContent.size()));
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
QCOMPARE(file.readAll(), readContent);
|
||||
QCOMPARE(file.pos(), fileSize);
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
file.close();
|
||||
QVERIFY(!file.isOpen());
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
}
|
||||
|
||||
//
|
||||
// File content is: writeContent + readContent
|
||||
//
|
||||
|
||||
{
|
||||
// Writing
|
||||
QFile file(fileName);
|
||||
|
||||
QVERIFY(!file.isOpen());
|
||||
QVERIFY(file.open(QIODevice::ReadWrite | QIODevice::Unbuffered));
|
||||
|
||||
QVERIFY(file.isOpen());
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
QCOMPARE(file.pos(), qint64(0));
|
||||
|
||||
QCOMPARE(file.write(writeContent), qint64(writeContent.size()));
|
||||
QCOMPARE(file.pos(), qint64(writeContent.size()));
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
QVERIFY(file.resize(writeContent.size()));
|
||||
QCOMPARE(file.size(), qint64(writeContent.size()));
|
||||
|
||||
file.close();
|
||||
QVERIFY(!file.isOpen());
|
||||
QCOMPARE(file.size(), qint64(writeContent.size()));
|
||||
|
||||
QVERIFY(file.resize(fileSize));
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
}
|
||||
|
||||
//
|
||||
// File content is: writeContent + <undefined>
|
||||
// File size is : (readContent + writeContent).size()
|
||||
//
|
||||
|
||||
{
|
||||
// Writing / extending
|
||||
QFile file(fileName);
|
||||
|
||||
QVERIFY(!file.isOpen());
|
||||
QVERIFY(file.open(QIODevice::ReadWrite | QIODevice::Unbuffered));
|
||||
|
||||
QVERIFY(file.isOpen());
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
QCOMPARE(file.pos(), qint64(0));
|
||||
|
||||
QVERIFY(file.seek(1024));
|
||||
QCOMPARE(file.pos(), qint64(1024));
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
fileSize = 1024 + writeContent.size();
|
||||
QCOMPARE(file.write(writeContent), qint64(writeContent.size()));
|
||||
QCOMPARE(file.pos(), fileSize);
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
QVERIFY(file.seek(1028));
|
||||
QCOMPARE(file.pos(), qint64(1028));
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
fileSize = 1028 + writeContent.size();
|
||||
QCOMPARE(file.write(writeContent), qint64(writeContent.size()));
|
||||
QCOMPARE(file.pos(), fileSize);
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
file.close();
|
||||
QVERIFY(!file.isOpen());
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
}
|
||||
|
||||
//
|
||||
// File content is: writeContent + <undefined> + writeContent
|
||||
// File size is : 1024 + writeContent.size()
|
||||
//
|
||||
|
||||
{
|
||||
// Writing / truncating
|
||||
QFile file(fileName);
|
||||
|
||||
QVERIFY(!file.isOpen());
|
||||
QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Unbuffered));
|
||||
|
||||
QVERIFY(file.isOpen());
|
||||
QCOMPARE(file.size(), qint64(0));
|
||||
QCOMPARE(file.pos(), qint64(0));
|
||||
|
||||
fileSize = readContent.size();
|
||||
QCOMPARE(file.write(readContent), fileSize);
|
||||
QCOMPARE(file.pos(), fileSize);
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
|
||||
file.close();
|
||||
QVERIFY(!file.isOpen());
|
||||
QCOMPARE(file.size(), fileSize);
|
||||
}
|
||||
|
||||
//
|
||||
// File content is: readContent
|
||||
//
|
||||
}
|
||||
|
||||
void tst_QAbstractFileEngine::mounting_data()
|
||||
{
|
||||
QTest::addColumn<QString>("fileName");
|
||||
QTest::newRow("native") << "test.tar";
|
||||
QTest::newRow("Forced QFSFileEngine") << "QFSFileEngine:test.tar";
|
||||
}
|
||||
|
||||
void tst_QAbstractFileEngine::mounting()
|
||||
{
|
||||
FileSystem fs;
|
||||
QVERIFY(fs.createFile("test.tar"));
|
||||
FileEngineHandler handler;
|
||||
|
||||
QFETCH(QString, fileName);
|
||||
const QString absName = fs.absoluteFilePath(fileName);
|
||||
|
||||
QVERIFY(QFileInfo(absName).isDir());
|
||||
QDir dir(absName);
|
||||
QCOMPARE(dir.entryList(), (QStringList() << "bar" << "foo"));
|
||||
QDir dir2(fs.path());
|
||||
bool found = false;
|
||||
foreach (QFileInfo info, dir2.entryInfoList()) {
|
||||
if (info.fileName() == QLatin1String("test.tar")) {
|
||||
QVERIFY(!found);
|
||||
found = true;
|
||||
QVERIFY(info.isDir());
|
||||
}
|
||||
}
|
||||
QVERIFY(found);
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QAbstractFileEngine)
|
||||
#include "tst_qabstractfileengine.moc"
|
||||
|
11
tests/auto/corelib/io/qbuffer/CMakeLists.txt
Normal file
11
tests/auto/corelib/io/qbuffer/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qbuffer Test:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_test(tst_qbuffer
|
||||
SOURCES
|
||||
tst_qbuffer.cpp
|
||||
)
|
704
tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
Normal file
704
tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
Normal file
@ -0,0 +1,704 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include <QTest>
|
||||
#include <QTestEventLoop>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QByteArray>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#include <string>
|
||||
|
||||
class tst_QBuffer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private slots:
|
||||
void open();
|
||||
void openWriteOnlyDoesNotTruncate();
|
||||
void getSetCheck();
|
||||
void readBlock();
|
||||
void readBlockPastEnd();
|
||||
void writeBlock_data();
|
||||
void writeBlock();
|
||||
void seek();
|
||||
void invalidSeeks();
|
||||
void seekTest_data();
|
||||
void seekTest();
|
||||
void read_rawdata();
|
||||
void isSequential();
|
||||
void signalTest_data();
|
||||
void signalTest();
|
||||
void isClosedAfterClose();
|
||||
void readLine_data();
|
||||
void readLine();
|
||||
void canReadLine_data();
|
||||
void canReadLine();
|
||||
void atEnd();
|
||||
void readLineBoundaries();
|
||||
void getAndUngetChar();
|
||||
void writeAfterQByteArrayResize();
|
||||
void writeOfMoreThan2GiB();
|
||||
void read_null();
|
||||
|
||||
protected slots:
|
||||
void readyReadSlot();
|
||||
void bytesWrittenSlot(qint64 written);
|
||||
|
||||
private:
|
||||
qint64 totalBytesWritten;
|
||||
bool gotReadyRead;
|
||||
};
|
||||
|
||||
// Testing get/set functions
|
||||
void tst_QBuffer::getSetCheck()
|
||||
{
|
||||
QBuffer obj1;
|
||||
// const QByteArray & QBuffer::data()
|
||||
// void QBuffer::setData(const QByteArray &)
|
||||
QByteArray var1("Bogus data");
|
||||
obj1.setData(var1);
|
||||
QCOMPARE(var1, obj1.data());
|
||||
obj1.setData(QByteArray());
|
||||
QCOMPARE(QByteArray(), obj1.data());
|
||||
}
|
||||
|
||||
void tst_QBuffer::open()
|
||||
{
|
||||
QByteArray data(10, 'f');
|
||||
|
||||
QBuffer b;
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "QBuffer::open: Buffer access not specified");
|
||||
QVERIFY(!b.open(QIODevice::NotOpen));
|
||||
QVERIFY(!b.isOpen());
|
||||
b.close();
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "QBuffer::open: Buffer access not specified");
|
||||
QVERIFY(!b.open(QIODevice::Text));
|
||||
QVERIFY(!b.isOpen());
|
||||
b.close();
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "QBuffer::open: Buffer access not specified");
|
||||
QVERIFY(!b.open(QIODevice::Unbuffered));
|
||||
QVERIFY(!b.isOpen());
|
||||
b.close();
|
||||
|
||||
QVERIFY(b.open(QIODevice::ReadOnly));
|
||||
QVERIFY(b.isReadable());
|
||||
b.close();
|
||||
|
||||
QVERIFY(b.open(QIODevice::WriteOnly));
|
||||
QVERIFY(b.isWritable());
|
||||
b.close();
|
||||
|
||||
b.setData(data);
|
||||
QVERIFY(b.open(QIODevice::Append));
|
||||
QVERIFY(b.isWritable());
|
||||
QCOMPARE(b.size(), qint64(10));
|
||||
QCOMPARE(b.pos(), b.size());
|
||||
b.close();
|
||||
|
||||
b.setData(data);
|
||||
QVERIFY(b.open(QIODevice::Truncate));
|
||||
QVERIFY(b.isWritable());
|
||||
QCOMPARE(b.size(), qint64(0));
|
||||
QCOMPARE(b.pos(), qint64(0));
|
||||
b.close();
|
||||
|
||||
QVERIFY(b.open(QIODevice::ReadWrite));
|
||||
QVERIFY(b.isReadable());
|
||||
QVERIFY(b.isWritable());
|
||||
b.close();
|
||||
}
|
||||
|
||||
void tst_QBuffer::openWriteOnlyDoesNotTruncate()
|
||||
{
|
||||
QBuffer b;
|
||||
const auto data = QByteArrayLiteral("Hey, presto!");
|
||||
|
||||
{
|
||||
QVERIFY(b.open(QIODevice::WriteOnly));
|
||||
b.write(data);
|
||||
b.close();
|
||||
}
|
||||
{
|
||||
QVERIFY(b.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(b.readAll(), data);
|
||||
b.close();
|
||||
}
|
||||
{
|
||||
QVERIFY(b.open(QIODevice::WriteOnly));
|
||||
QCOMPARE(b.size(), data.size());
|
||||
QCOMPARE(b.pos(), 0);
|
||||
b.close();
|
||||
}
|
||||
}
|
||||
|
||||
// some status() tests, too
|
||||
void tst_QBuffer::readBlock()
|
||||
{
|
||||
const int arraySize = 10;
|
||||
char a[arraySize];
|
||||
QBuffer b;
|
||||
QCOMPARE(b.bytesAvailable(), (qint64) 0); // no data
|
||||
QCOMPARE(b.read(a, arraySize), (qint64) -1); // not opened
|
||||
QVERIFY(b.atEnd());
|
||||
|
||||
QByteArray ba;
|
||||
ba.resize(arraySize);
|
||||
b.setBuffer(&ba);
|
||||
QCOMPARE(b.bytesAvailable(), (qint64) arraySize);
|
||||
b.open(QIODevice::WriteOnly);
|
||||
QCOMPARE(b.bytesAvailable(), (qint64) arraySize);
|
||||
QTest::ignoreMessage(QtWarningMsg, "QIODevice::read (QBuffer): WriteOnly device");
|
||||
QCOMPARE(b.read(a, arraySize), (qint64) -1); // no read access
|
||||
b.close();
|
||||
|
||||
b.open(QIODevice::ReadOnly);
|
||||
QCOMPARE(b.bytesAvailable(), (qint64) arraySize);
|
||||
QCOMPARE(b.read(a, arraySize), (qint64) arraySize);
|
||||
QVERIFY(b.atEnd());
|
||||
QCOMPARE(b.bytesAvailable(), (qint64) 0);
|
||||
|
||||
// up to 3.0.x reading beyond the end was an error while ok
|
||||
// this has been made consistent with other QIODevice sub classes in 3.1
|
||||
QCOMPARE(b.read(a, 1), qint64(0));
|
||||
QVERIFY(b.atEnd());
|
||||
|
||||
// read in two chunks
|
||||
b.close();
|
||||
b.open(QIODevice::ReadOnly);
|
||||
QCOMPARE(b.bytesAvailable(), (qint64) arraySize);
|
||||
QCOMPARE(b.read(a, arraySize/2), (qint64) arraySize/2);
|
||||
QCOMPARE(b.bytesAvailable(), (qint64) arraySize/2);
|
||||
QCOMPARE(b.read(a + arraySize/2, arraySize - arraySize/2),
|
||||
(qint64)(arraySize - arraySize/2));
|
||||
QVERIFY(b.atEnd());
|
||||
QCOMPARE(b.bytesAvailable(), (qint64) 0);
|
||||
}
|
||||
|
||||
void tst_QBuffer::readBlockPastEnd()
|
||||
{
|
||||
QByteArray arr(4096 + 3616, 'd');
|
||||
QBuffer buf(&arr);
|
||||
|
||||
buf.open(QIODevice::ReadOnly);
|
||||
char dummy[4096];
|
||||
|
||||
buf.read(1);
|
||||
|
||||
QCOMPARE(buf.read(dummy, 4096), qint64(4096));
|
||||
QCOMPARE(buf.read(dummy, 4096), qint64(3615));
|
||||
QVERIFY(buf.atEnd());
|
||||
}
|
||||
|
||||
void tst_QBuffer::writeBlock_data()
|
||||
{
|
||||
QTest::addColumn<QString>("str");
|
||||
|
||||
QTest::newRow( "small_bytearray" ) << QString("Test");
|
||||
QTest::newRow( "large_bytearray" ) << QString(
|
||||
"The QBuffer class is an I/O device that operates on a QByteArray.\n"
|
||||
"QBuffer is used to read and write to a memory buffer. It is normally "
|
||||
"used with a QTextStream or a QDataStream. QBuffer has an associated "
|
||||
"QByteArray which holds the buffer data. The size() of the buffer is "
|
||||
"automatically adjusted as data is written.\n"
|
||||
"The constructor QBuffer(QByteArray) creates a QBuffer using an existing "
|
||||
"byte array. The byte array can also be set with setBuffer(). Writing to "
|
||||
"the QBuffer will modify the original byte array because QByteArray is "
|
||||
"explicitly shared.\n"
|
||||
"Use open() to open the buffer before use and to set the mode (read-only, "
|
||||
"write-only, etc.). close() closes the buffer. The buffer must be closed "
|
||||
"before reopening or calling setBuffer().\n"
|
||||
"A common way to use QBuffer is through QDataStream or QTextStream, which "
|
||||
"have constructors that take a QBuffer parameter. For convenience, there "
|
||||
"are also QDataStream and QTextStream constructors that take a QByteArray "
|
||||
"parameter. These constructors create and open an internal QBuffer.\n"
|
||||
"Note that QTextStream can also operate on a QString (a Unicode string); a "
|
||||
"QBuffer cannot.\n"
|
||||
"You can also use QBuffer directly through the standard QIODevice functions "
|
||||
"readBlock(), writeBlock() readLine(), at(), getch(), putch() and ungetch().\n"
|
||||
"See also QFile, QDataStream, QTextStream, QByteArray, Shared Classes, Collection "
|
||||
"Classes and Input/Output and Networking.\n\n"
|
||||
"The QBuffer class is an I/O device that operates on a QByteArray.\n"
|
||||
"QBuffer is used to read and write to a memory buffer. It is normally "
|
||||
"used with a QTextStream or a QDataStream. QBuffer has an associated "
|
||||
"QByteArray which holds the buffer data. The size() of the buffer is "
|
||||
"automatically adjusted as data is written.\n"
|
||||
"The constructor QBuffer(QByteArray) creates a QBuffer using an existing "
|
||||
"byte array. The byte array can also be set with setBuffer(). Writing to "
|
||||
"the QBuffer will modify the original byte array because QByteArray is "
|
||||
"explicitly shared.\n"
|
||||
"Use open() to open the buffer before use and to set the mode (read-only, "
|
||||
"write-only, etc.). close() closes the buffer. The buffer must be closed "
|
||||
"before reopening or calling setBuffer().\n"
|
||||
"A common way to use QBuffer is through QDataStream or QTextStream, which "
|
||||
"have constructors that take a QBuffer parameter. For convenience, there "
|
||||
"are also QDataStream and QTextStream constructors that take a QByteArray "
|
||||
"parameter. These constructors create and open an internal QBuffer.\n"
|
||||
"Note that QTextStream can also operate on a QString (a Unicode string); a "
|
||||
"QBuffer cannot.\n"
|
||||
"You can also use QBuffer directly through the standard QIODevice functions "
|
||||
"readBlock(), writeBlock() readLine(), at(), getch(), putch() and ungetch().\n"
|
||||
"See also QFile, QDataStream, QTextStream, QByteArray, Shared Classes, Collection "
|
||||
"Classes and Input/Output and Networking.\n\n"
|
||||
"The QBuffer class is an I/O device that operates on a QByteArray.\n"
|
||||
"QBuffer is used to read and write to a memory buffer. It is normally "
|
||||
"used with a QTextStream or a QDataStream. QBuffer has an associated "
|
||||
"QByteArray which holds the buffer data. The size() of the buffer is "
|
||||
"automatically adjusted as data is written.\n"
|
||||
"The constructor QBuffer(QByteArray) creates a QBuffer using an existing "
|
||||
"byte array. The byte array can also be set with setBuffer(). Writing to "
|
||||
"the QBuffer will modify the original byte array because QByteArray is "
|
||||
"explicitly shared.\n"
|
||||
"Use open() to open the buffer before use and to set the mode (read-only, "
|
||||
"write-only, etc.). close() closes the buffer. The buffer must be closed "
|
||||
"before reopening or calling setBuffer().\n"
|
||||
"A common way to use QBuffer is through QDataStream or QTextStream, which "
|
||||
"have constructors that take a QBuffer parameter. For convenience, there "
|
||||
"are also QDataStream and QTextStream constructors that take a QByteArray "
|
||||
"parameter. These constructors create and open an internal QBuffer.\n"
|
||||
"Note that QTextStream can also operate on a QString (a Unicode string); a "
|
||||
"QBuffer cannot.\n"
|
||||
"You can also use QBuffer directly through the standard QIODevice functions "
|
||||
"readBlock(), writeBlock() readLine(), at(), getch(), putch() and ungetch().\n"
|
||||
"See also QFile, QDataStream, QTextStream, QByteArray, Shared Classes, Collection "
|
||||
"Classes and Input/Output and Networking.");
|
||||
}
|
||||
|
||||
void tst_QBuffer::writeBlock()
|
||||
{
|
||||
QFETCH( QString, str );
|
||||
|
||||
QByteArray ba;
|
||||
QBuffer buf( &ba );
|
||||
buf.open(QIODevice::ReadWrite);
|
||||
QByteArray data = str.toLatin1();
|
||||
QCOMPARE(buf.write( data.constData(), data.size() ), qint64(data.size()));
|
||||
|
||||
QCOMPARE(buf.data(), str.toLatin1());
|
||||
}
|
||||
|
||||
void tst_QBuffer::seek()
|
||||
{
|
||||
QBuffer buffer;
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QCOMPARE(buffer.size(), qint64(0));
|
||||
QCOMPARE(buffer.pos(), qint64(0));
|
||||
const qint64 pos = 10;
|
||||
QVERIFY(buffer.seek(pos));
|
||||
QCOMPARE(buffer.size(), pos);
|
||||
}
|
||||
|
||||
void tst_QBuffer::invalidSeeks()
|
||||
{
|
||||
if constexpr (sizeof(qsizetype) == sizeof(qint64)) {
|
||||
// sizeof(qsizetype) == sizeof(qint64), so +1 would overflow
|
||||
QSKIP("This is a 32-bit-only test.");
|
||||
} else {
|
||||
QBuffer buffer;
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QCOMPARE(buffer.buffer().size(), qsizetype(0));
|
||||
QCOMPARE(buffer.pos(), qint64(0));
|
||||
constexpr qint64 MaxQByteArrayCapacity = (std::numeric_limits<qsizetype>::max)();
|
||||
// this should fail fast, not after trying to allocate nearly 2 GiB of data,
|
||||
// potentially crashing in the process:
|
||||
QVERIFY(!buffer.seek(2 * MaxQByteArrayCapacity - 1));
|
||||
QCOMPARE(buffer.buffer().size(), qsizetype(0));
|
||||
QCOMPARE(buffer.pos(), qint64(0));
|
||||
// ditto:
|
||||
QVERIFY(!buffer.seek(MaxQByteArrayCapacity + 1));
|
||||
QCOMPARE(buffer.buffer().size(), qsizetype(0));
|
||||
QCOMPARE(buffer.pos(), qint64(0));
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QBuffer::seekTest_data()
|
||||
{
|
||||
writeBlock_data();
|
||||
}
|
||||
|
||||
#define DO_VALID_SEEK(position) { \
|
||||
char c; \
|
||||
QVERIFY(buf.seek(qint64(position))); \
|
||||
QCOMPARE(buf.pos(), qint64(position)); \
|
||||
QVERIFY(buf.getChar(&c)); \
|
||||
QCOMPARE(QChar(c), str.at(qint64(position))); \
|
||||
}
|
||||
#define DO_INVALID_SEEK(position) { \
|
||||
qint64 prev_pos = buf.pos(); \
|
||||
QVERIFY(!buf.seek(qint64(position))); \
|
||||
QCOMPARE(buf.pos(), prev_pos); /* position should not be changed */ \
|
||||
}
|
||||
|
||||
void tst_QBuffer::seekTest()
|
||||
{
|
||||
QFETCH(QString, str);
|
||||
|
||||
QByteArray ba;
|
||||
QBuffer buf(&ba);
|
||||
QCOMPARE(buf.pos(), qint64(0));
|
||||
|
||||
buf.open(QIODevice::ReadWrite);
|
||||
QCOMPARE(buf.pos(), qint64(0));
|
||||
QCOMPARE(buf.bytesAvailable(), qint64(0));
|
||||
|
||||
QByteArray data = str.toLatin1();
|
||||
QCOMPARE(buf.write( data.constData(), data.size() ), qint64(data.size()));
|
||||
QCOMPARE(buf.bytesAvailable(), qint64(0)); // we're at the end
|
||||
QCOMPARE(buf.size(), qint64(data.size()));
|
||||
|
||||
QTest::ignoreMessage(QtWarningMsg, "QBuffer::seek: Invalid pos: -1");
|
||||
DO_INVALID_SEEK(-1);
|
||||
|
||||
DO_VALID_SEEK(0);
|
||||
DO_VALID_SEEK(str.size() - 1);
|
||||
QVERIFY(buf.atEnd());
|
||||
DO_VALID_SEEK(str.size() / 2);
|
||||
|
||||
// Special case: valid to seek one position past the buffer.
|
||||
// Its then legal to write, but not read.
|
||||
{
|
||||
char c = 'a';
|
||||
QVERIFY(buf.seek(qint64(str.size())));
|
||||
QCOMPARE(buf.bytesAvailable(), qint64(0));
|
||||
QCOMPARE(buf.read(&c, qint64(1)), qint64(0));
|
||||
QCOMPARE(c, 'a');
|
||||
QCOMPARE(buf.write(&c, qint64(1)), qint64(1));
|
||||
}
|
||||
|
||||
// Special case 2: seeking to an arbitrary position beyond the buffer auto-expands it
|
||||
{
|
||||
char c;
|
||||
const int offset = 1; // any positive integer will do
|
||||
const qint64 pos = buf.size() + offset;
|
||||
QVERIFY(buf.seek(pos));
|
||||
QCOMPARE(buf.bytesAvailable(), qint64(0));
|
||||
QCOMPARE(buf.pos(), pos);
|
||||
QVERIFY(!buf.getChar(&c));
|
||||
QVERIFY(buf.seek(pos - 1));
|
||||
QVERIFY(buf.getChar(&c));
|
||||
QCOMPARE(c, buf.data().at(pos - 1));
|
||||
QVERIFY(buf.seek(pos));
|
||||
QVERIFY(buf.putChar(c));
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QBuffer::read_rawdata()
|
||||
{
|
||||
static const unsigned char mydata[] = {
|
||||
0x01, 0x00, 0x03, 0x84, 0x78, 0x9c, 0x3b, 0x76,
|
||||
0xec, 0x18, 0xc3, 0x31, 0x0a, 0xf1, 0xcc, 0x99,
|
||||
0x6d, 0x5b
|
||||
};
|
||||
|
||||
QByteArray data = QByteArray::fromRawData((const char *)mydata, sizeof(mydata));
|
||||
QBuffer buffer(&data);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
QDataStream in(&buffer);
|
||||
quint8 ch;
|
||||
for (int i = 0; i < (int)sizeof(mydata); ++i) {
|
||||
QVERIFY(!buffer.atEnd());
|
||||
in >> ch;
|
||||
QCOMPARE(ch, (quint8)mydata[i]);
|
||||
}
|
||||
QVERIFY(buffer.atEnd());
|
||||
}
|
||||
|
||||
void tst_QBuffer::isSequential()
|
||||
{
|
||||
QBuffer buf;
|
||||
QVERIFY(!buf.isSequential());
|
||||
}
|
||||
|
||||
void tst_QBuffer::signalTest_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("sample");
|
||||
|
||||
QTest::newRow("empty") << QByteArray();
|
||||
QTest::newRow("size 1") << QByteArray("1");
|
||||
QTest::newRow("size 2") << QByteArray("11");
|
||||
QTest::newRow("size 100") << QByteArray(100, '1');
|
||||
}
|
||||
|
||||
void tst_QBuffer::signalTest()
|
||||
{
|
||||
QFETCH(QByteArray, sample);
|
||||
|
||||
totalBytesWritten = 0;
|
||||
|
||||
QBuffer buf;
|
||||
buf.open(QIODevice::WriteOnly);
|
||||
|
||||
buf.buffer().resize(sample.size() * 10);
|
||||
connect(&buf, SIGNAL(readyRead()), this, SLOT(readyReadSlot()));
|
||||
connect(&buf, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWrittenSlot(qint64)));
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
gotReadyRead = false;
|
||||
QCOMPARE(buf.write(sample), qint64(sample.size()));
|
||||
if (sample.size() > 0) {
|
||||
QTestEventLoop::instance().enterLoop(5);
|
||||
if (QTestEventLoop::instance().timeout())
|
||||
QFAIL("Timed out when waiting for readyRead()");
|
||||
QCOMPARE(totalBytesWritten, qint64(sample.size() * (i + 1)));
|
||||
QVERIFY(gotReadyRead);
|
||||
} else {
|
||||
QCOMPARE(totalBytesWritten, qint64(0));
|
||||
QVERIFY(!gotReadyRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QBuffer::readyReadSlot()
|
||||
{
|
||||
gotReadyRead = true;
|
||||
QTestEventLoop::instance().exitLoop();
|
||||
}
|
||||
|
||||
void tst_QBuffer::bytesWrittenSlot(qint64 written)
|
||||
{
|
||||
totalBytesWritten += written;
|
||||
}
|
||||
|
||||
void tst_QBuffer::isClosedAfterClose()
|
||||
{
|
||||
QBuffer buffer;
|
||||
buffer.open(QBuffer::ReadOnly);
|
||||
QVERIFY(buffer.isOpen());
|
||||
buffer.close();
|
||||
QVERIFY(!buffer.isOpen());
|
||||
}
|
||||
|
||||
void tst_QBuffer::readLine_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("src");
|
||||
QTest::addColumn<int>("maxlen");
|
||||
QTest::addColumn<QByteArray>("expected");
|
||||
|
||||
QTest::newRow("1") << QByteArray("line1\nline2\n") << 1024
|
||||
<< QByteArray("line1\n");
|
||||
QTest::newRow("2") << QByteArray("hi there") << 1024
|
||||
<< QByteArray("hi there");
|
||||
QTest::newRow("3") << QByteArray("l\n") << 3 << QByteArray("l\n");
|
||||
QTest::newRow("4") << QByteArray("l\n") << 2 << QByteArray("l");
|
||||
}
|
||||
|
||||
void tst_QBuffer::readLine()
|
||||
{
|
||||
QFETCH(QByteArray, src);
|
||||
QFETCH(int, maxlen);
|
||||
QFETCH(QByteArray, expected);
|
||||
|
||||
QBuffer buf;
|
||||
buf.setBuffer(&src);
|
||||
char *result = new char[maxlen + 1];
|
||||
result[maxlen] = '\0';
|
||||
|
||||
QVERIFY(buf.open(QIODevice::ReadOnly));
|
||||
|
||||
qint64 bytes_read = buf.readLine(result, maxlen);
|
||||
|
||||
QCOMPARE(bytes_read, qint64(expected.size()));
|
||||
QCOMPARE(QByteArray(result), expected);
|
||||
|
||||
buf.close();
|
||||
delete[] result;
|
||||
|
||||
}
|
||||
|
||||
void tst_QBuffer::canReadLine_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("src");
|
||||
QTest::addColumn<bool>("expected");
|
||||
|
||||
QTest::newRow("1") << QByteArray("no newline") << false;
|
||||
QTest::newRow("2") << QByteArray("two \n lines\n") << true;
|
||||
QTest::newRow("3") << QByteArray("\n") << true;
|
||||
QTest::newRow("4") << QByteArray() << false;
|
||||
}
|
||||
|
||||
void tst_QBuffer::canReadLine()
|
||||
{
|
||||
QFETCH(QByteArray, src);
|
||||
QFETCH(bool, expected);
|
||||
|
||||
QBuffer buf;
|
||||
buf.setBuffer(&src);
|
||||
QVERIFY(!buf.canReadLine());
|
||||
QVERIFY(buf.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(buf.canReadLine(), expected);
|
||||
}
|
||||
|
||||
void tst_QBuffer::atEnd()
|
||||
{
|
||||
QBuffer buffer;
|
||||
buffer.open(QBuffer::Append);
|
||||
buffer.write("heisann");
|
||||
buffer.close();
|
||||
|
||||
buffer.open(QBuffer::ReadOnly);
|
||||
buffer.seek(buffer.size());
|
||||
char c;
|
||||
QVERIFY(!buffer.getChar(&c));
|
||||
QCOMPARE(buffer.read(&c, 1), qint64(0));
|
||||
}
|
||||
|
||||
// Test that reading data out of a QBuffer a line at a time gives the same
|
||||
// result as reading the whole buffer at once.
|
||||
void tst_QBuffer::readLineBoundaries()
|
||||
{
|
||||
QByteArray line = "This is a line\n";
|
||||
QBuffer buffer;
|
||||
buffer.open(QIODevice::ReadWrite);
|
||||
while (buffer.size() < 16384)
|
||||
buffer.write(line);
|
||||
|
||||
buffer.seek(0);
|
||||
QByteArray lineByLine;
|
||||
while (!buffer.atEnd())
|
||||
lineByLine.append(buffer.readLine());
|
||||
|
||||
buffer.seek(0);
|
||||
QCOMPARE(buffer.bytesAvailable(), lineByLine.size());
|
||||
|
||||
QByteArray all = buffer.readAll();
|
||||
QCOMPARE(all.size(), lineByLine.size());
|
||||
QCOMPARE(all, lineByLine);
|
||||
}
|
||||
|
||||
// Test that any character in a buffer can be read and pushed back.
|
||||
void tst_QBuffer::getAndUngetChar()
|
||||
{
|
||||
// Create some data in a buffer
|
||||
QByteArray line = "This is a line\n";
|
||||
QBuffer buffer;
|
||||
buffer.open(QIODevice::ReadWrite);
|
||||
while (buffer.size() < 16384)
|
||||
buffer.write(line);
|
||||
|
||||
// Take a copy of the data held in the buffer
|
||||
buffer.seek(0);
|
||||
QCOMPARE(buffer.bytesAvailable(), buffer.size());
|
||||
QByteArray data = buffer.readAll();
|
||||
QCOMPARE(buffer.bytesAvailable(), qint64(0));
|
||||
|
||||
// Get and unget each character in order
|
||||
for (qint64 i = 0; i < buffer.size(); ++i) {
|
||||
buffer.seek(i);
|
||||
char c;
|
||||
QVERIFY(buffer.getChar(&c));
|
||||
QCOMPARE(c, data.at((uint)i));
|
||||
buffer.ungetChar(c);
|
||||
}
|
||||
|
||||
// Get and unget each character in reverse order
|
||||
for (qint64 i = buffer.size() - 1; i >= 0; --i) {
|
||||
buffer.seek(i);
|
||||
char c;
|
||||
QVERIFY(buffer.getChar(&c));
|
||||
QCOMPARE(c, data.at((uint)i));
|
||||
buffer.ungetChar(c);
|
||||
}
|
||||
|
||||
// Verify that the state of the buffer still matches the original data.
|
||||
buffer.seek(0);
|
||||
QCOMPARE(buffer.bytesAvailable(), data.size());
|
||||
QCOMPARE(buffer.readAll(), data);
|
||||
QCOMPARE(buffer.bytesAvailable(), qint64(0));
|
||||
}
|
||||
|
||||
void tst_QBuffer::writeAfterQByteArrayResize()
|
||||
{
|
||||
QBuffer buffer;
|
||||
QVERIFY(buffer.open(QIODevice::WriteOnly));
|
||||
|
||||
buffer.write(QByteArray().fill('a', 1000));
|
||||
QCOMPARE(buffer.buffer().size(), 1000);
|
||||
|
||||
// resize the QByteArray behind QBuffer's back
|
||||
buffer.buffer().clear();
|
||||
buffer.seek(0);
|
||||
QCOMPARE(buffer.buffer().size(), 0);
|
||||
|
||||
buffer.write(QByteArray().fill('b', 1000));
|
||||
QCOMPARE(buffer.buffer().size(), 1000);
|
||||
}
|
||||
|
||||
void tst_QBuffer::writeOfMoreThan2GiB()
|
||||
{
|
||||
if constexpr (sizeof(void*) == 4)
|
||||
QSKIP("This is a 64-bit-only test");
|
||||
|
||||
[[maybe_unused]] constexpr size_t GiB = 1024 * 1024 * 1024;
|
||||
|
||||
#ifndef QT_NO_EXCEPTIONS
|
||||
|
||||
try {
|
||||
//
|
||||
// GIVEN: an empty QBuffer open for writing
|
||||
//
|
||||
QBuffer buffer;
|
||||
QVERIFY(buffer.open(QIODevice::WriteOnly));
|
||||
|
||||
//
|
||||
// WHEN: writing more than 2GiB in a singe chunk:
|
||||
//
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
const std::string input(2 * GiB + 1, 42);
|
||||
|
||||
qDebug("created dataset in %lld ms", timer.restart());
|
||||
|
||||
const auto inputSize = qint64(input.size());
|
||||
|
||||
QCOMPARE(buffer.write(input.data(), inputSize), inputSize);
|
||||
|
||||
qDebug("performed write in %lld ms", timer.restart());
|
||||
|
||||
//
|
||||
// THEN: the buffer contains the written data
|
||||
//
|
||||
QCOMPARE(buffer.buffer().size(), inputSize);
|
||||
QVERIFY(buffer.buffer() == QByteArrayView{input});
|
||||
|
||||
qDebug("verified result in %lld ms", timer.elapsed());
|
||||
|
||||
} catch (const std::bad_alloc &) {
|
||||
QSKIP("Cannot allocate enough memory for this test");
|
||||
}
|
||||
|
||||
#else
|
||||
QSKIP("This test requires exceptions enabled.");
|
||||
#endif // QT_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
void tst_QBuffer::read_null()
|
||||
{
|
||||
QByteArray buffer;
|
||||
buffer.resize(32000);
|
||||
for (int i = 0; i < buffer.size(); ++i)
|
||||
buffer[i] = char(i & 0xff);
|
||||
|
||||
QBuffer in(&buffer);
|
||||
in.open(QIODevice::ReadOnly);
|
||||
|
||||
QByteArray chunk;
|
||||
|
||||
chunk.resize(16380);
|
||||
in.read(chunk.data(), 16380);
|
||||
|
||||
QCOMPARE(chunk, buffer.mid(0, chunk.size()));
|
||||
|
||||
in.read(chunk.data(), 0);
|
||||
|
||||
chunk.resize(8);
|
||||
in.read(chunk.data(), chunk.size());
|
||||
|
||||
QCOMPARE(chunk, buffer.mid(16380, chunk.size()));
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QBuffer)
|
||||
#include "tst_qbuffer.moc"
|
13
tests/auto/corelib/io/qdataurl/CMakeLists.txt
Normal file
13
tests/auto/corelib/io/qdataurl/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qdataurl Test:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_test(tst_qdataurl
|
||||
SOURCES
|
||||
tst_qdataurl.cpp
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
)
|
59
tests/auto/corelib/io/qdataurl/tst_qdataurl.cpp
Normal file
59
tests/auto/corelib/io/qdataurl/tst_qdataurl.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "private/qdataurl_p.h"
|
||||
#include <QTest>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace Qt::Literals;
|
||||
|
||||
class tst_QDataUrl : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void decode_data();
|
||||
void decode();
|
||||
};
|
||||
|
||||
void tst_QDataUrl::decode_data()
|
||||
{
|
||||
QTest::addColumn<QString>("input");
|
||||
QTest::addColumn<bool>("result");
|
||||
QTest::addColumn<QString>("mimeType");
|
||||
QTest::addColumn<QByteArray>("payload");
|
||||
|
||||
auto row = [](const char *tag, const char *url, bool success, QString mimeType = {}, QByteArray payload = {}) {
|
||||
QTest::newRow(tag) << url << success <<mimeType << payload;
|
||||
};
|
||||
|
||||
row("nonData", "http://test.com", false);
|
||||
row("emptyData", "data:text/plain", true,
|
||||
"text/plain;charset=US-ASCII"_L1);
|
||||
row("alreadyPercentageEncoded", "data:text/plain,%E2%88%9A", true,
|
||||
"text/plain"_L1, QByteArray::fromPercentEncoding("%E2%88%9A"));
|
||||
row("everythingIsCaseInsensitive", "Data:texT/PlaiN;charSet=iSo-8859-1;Base64,SGVsbG8=", true,
|
||||
"texT/PlaiN;charSet=iSo-8859-1"_L1, QByteArrayLiteral("Hello"));
|
||||
}
|
||||
|
||||
void tst_QDataUrl::decode()
|
||||
{
|
||||
QFETCH(const QString, input);
|
||||
QFETCH(const bool, result);
|
||||
QFETCH(const QString, mimeType);
|
||||
QFETCH(const QByteArray, payload);
|
||||
|
||||
QString actualMimeType;
|
||||
QByteArray actualPayload;
|
||||
|
||||
QUrl url(input);
|
||||
const bool actualResult = qDecodeDataUrl(url, actualMimeType, actualPayload);
|
||||
|
||||
QCOMPARE(actualResult, result);
|
||||
QCOMPARE(actualMimeType, mimeType);
|
||||
QCOMPARE(actualPayload, payload);
|
||||
QCOMPARE(actualPayload.isNull(), payload.isNull()); // assume nullness is significant
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QDataUrl)
|
||||
#include "tst_qdataurl.moc"
|
17
tests/auto/corelib/io/qdebug/CMakeLists.txt
Normal file
17
tests/auto/corelib/io/qdebug/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qdebug Test:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_test(tst_qdebug
|
||||
SOURCES
|
||||
tst_qdebug.cpp
|
||||
LIBRARIES
|
||||
Qt::Concurrent
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
set_source_files_properties(tst_qdebug.cpp PROPERTIES LANGUAGE OBJCXX)
|
||||
endif()
|
1293
tests/auto/corelib/io/qdebug/tst_qdebug.cpp
Normal file
1293
tests/auto/corelib/io/qdebug/tst_qdebug.cpp
Normal file
File diff suppressed because it is too large
Load Diff
96
tests/auto/corelib/io/qdir/CMakeLists.txt
Normal file
96
tests/auto/corelib/io/qdir/CMakeLists.txt
Normal file
@ -0,0 +1,96 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qdir Test:
|
||||
#####################################################################
|
||||
|
||||
# Collect test data
|
||||
list(APPEND test_data "testdir")
|
||||
list(APPEND test_data "testData")
|
||||
list(APPEND test_data "searchdir")
|
||||
list(APPEND test_data "resources")
|
||||
list(APPEND test_data "entrylist")
|
||||
list(APPEND test_data "types")
|
||||
list(APPEND test_data "tst_qdir.cpp")
|
||||
|
||||
qt_internal_add_test(tst_qdir
|
||||
SOURCES
|
||||
tst_qdir.cpp
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
TESTDATA ${test_data}
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(qdir_resource_files
|
||||
"resources/entryList/"
|
||||
)
|
||||
|
||||
qt_internal_add_resource(tst_qdir "qdir"
|
||||
PREFIX
|
||||
"/tst_qdir/"
|
||||
FILES
|
||||
${qdir_resource_files}
|
||||
)
|
||||
|
||||
## Scopes:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_extend_target(tst_qdir CONDITION CONFIG___contains___builtin_testdata
|
||||
DEFINES
|
||||
BUILTIN_TESTDATA
|
||||
)
|
||||
|
||||
if(ANDROID)
|
||||
# Resources:
|
||||
set(android_testdata_resource_files
|
||||
"entrylist/directory/dummy"
|
||||
"entrylist/file"
|
||||
"resources/entryList/file1.data"
|
||||
"resources/entryList/file2.data"
|
||||
"resources/entryList/file3.data"
|
||||
"resources/entryList/file4.nothing"
|
||||
"searchdir/subdir1/picker.png"
|
||||
"searchdir/subdir2/picker.png"
|
||||
"testData/empty"
|
||||
"testdir/dir/qdir.pro"
|
||||
"testdir/dir/qrc_qdir.cpp"
|
||||
"testdir/dir/tmp/empty"
|
||||
"testdir/dir/tst_qdir.cpp"
|
||||
"testdir/spaces/foo. bar"
|
||||
"testdir/spaces/foo.bar"
|
||||
"tst_qdir.cpp"
|
||||
"types/a"
|
||||
"types/a.a"
|
||||
"types/a.b"
|
||||
"types/a.c"
|
||||
"types/b"
|
||||
"types/b.a"
|
||||
"types/b.b"
|
||||
"types/b.c"
|
||||
"types/c"
|
||||
"types/c.a"
|
||||
"types/c.b"
|
||||
"types/c.c"
|
||||
"types/d.a/dummy"
|
||||
"types/d.b/dummy"
|
||||
"types/d.c/dummy"
|
||||
"types/d/dummy"
|
||||
"types/e.a/dummy"
|
||||
"types/e.b/dummy"
|
||||
"types/e.c/dummy"
|
||||
"types/e/dummy"
|
||||
"types/f.a/dummy"
|
||||
"types/f.b/dummy"
|
||||
"types/f.c/dummy"
|
||||
"types/f/dummy"
|
||||
)
|
||||
|
||||
qt_internal_add_resource(tst_qdir "android_testdata"
|
||||
PREFIX
|
||||
"/android_testdata"
|
||||
FILES
|
||||
${android_testdata_resource_files}
|
||||
)
|
||||
endif()
|
39
tests/auto/corelib/io/qdir/Info.plist
Normal file
39
tests/auto/corelib/io/qdir/Info.plist
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>${ASSETCATALOG_COMPILER_APPICON_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>${QMAKE_SHORT_VERSION}</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>${QMAKE_PKGINFO_TYPEINFO}</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${QMAKE_FULL_VERSION}</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>${IPHONEOS_DEPLOYMENT_TARGET}</string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Enables use of assets file engine</string>
|
||||
</dict>
|
||||
</plist>
|
44
tests/auto/corelib/io/qdir/android_testdata.qrc
Normal file
44
tests/auto/corelib/io/qdir/android_testdata.qrc
Normal file
@ -0,0 +1,44 @@
|
||||
<RCC>
|
||||
<qresource prefix="/android_testdata">
|
||||
<file>tst_qdir.cpp</file>
|
||||
<file>entrylist/file</file>
|
||||
<file>entrylist/directory/dummy</file>
|
||||
<file>searchdir/subdir1/picker.png</file>
|
||||
<file>searchdir/subdir2/picker.png</file>
|
||||
<file>testData/empty</file>
|
||||
<file>testdir/dir/tmp/empty</file>
|
||||
<file>testdir/dir/qdir.pro</file>
|
||||
<file>testdir/dir/qrc_qdir.cpp</file>
|
||||
<file>testdir/dir/tst_qdir.cpp</file>
|
||||
<file>testdir/spaces/foo. bar</file>
|
||||
<file>testdir/spaces/foo.bar</file>
|
||||
<file>types/a</file>
|
||||
<file>types/a.a</file>
|
||||
<file>types/a.b</file>
|
||||
<file>types/a.c</file>
|
||||
<file>types/b</file>
|
||||
<file>types/b.a</file>
|
||||
<file>types/b.b</file>
|
||||
<file>types/b.c</file>
|
||||
<file>types/c</file>
|
||||
<file>types/c.a</file>
|
||||
<file>types/c.b</file>
|
||||
<file>types/c.c</file>
|
||||
<file>types/d/dummy</file>
|
||||
<file>types/d.a/dummy</file>
|
||||
<file>types/d.c/dummy</file>
|
||||
<file>types/d.b/dummy</file>
|
||||
<file>types/e/dummy</file>
|
||||
<file>types/e.a/dummy</file>
|
||||
<file>types/e.c/dummy</file>
|
||||
<file>types/f/dummy</file>
|
||||
<file>types/f.a/dummy</file>
|
||||
<file>types/f.b/dummy</file>
|
||||
<file>types/f.c/dummy</file>
|
||||
<file>types/e.b/dummy</file>
|
||||
<file>resources/entryList/file1.data</file>
|
||||
<file>resources/entryList/file2.data</file>
|
||||
<file>resources/entryList/file3.data</file>
|
||||
<file>resources/entryList/file4.nothing</file>
|
||||
</qresource>
|
||||
</RCC>
|
0
tests/auto/corelib/io/qdir/entrylist/file
Normal file
0
tests/auto/corelib/io/qdir/entrylist/file
Normal file
1
tests/auto/corelib/io/qdir/searchdir/subdir1/picker.png
Normal file
1
tests/auto/corelib/io/qdir/searchdir/subdir1/picker.png
Normal file
@ -0,0 +1 @@
|
||||
mostly empty
|
1
tests/auto/corelib/io/qdir/searchdir/subdir2/picker.png
Normal file
1
tests/auto/corelib/io/qdir/searchdir/subdir2/picker.png
Normal file
@ -0,0 +1 @@
|
||||
mostly empty
|
1
tests/auto/corelib/io/qdir/testData/empty
Normal file
1
tests/auto/corelib/io/qdir/testData/empty
Normal file
@ -0,0 +1 @@
|
||||
this is just so QDir has something to dive into.
|
12
tests/auto/corelib/io/qdir/testdir/dir/CMakeLists.txt
Normal file
12
tests/auto/corelib/io/qdir/testdir/dir/CMakeLists.txt
Normal file
@ -0,0 +1,12 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## qdir Binary:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_executable(qdir
|
||||
GUI
|
||||
LIBRARIES
|
||||
Qt::Gui
|
||||
)
|
0
tests/auto/corelib/io/qdir/testdir/dir/qdir.pro
Normal file
0
tests/auto/corelib/io/qdir/testdir/dir/qdir.pro
Normal file
4
tests/auto/corelib/io/qdir/testdir/dir/qrc_qdir.cpp
Normal file
4
tests/auto/corelib/io/qdir/testdir/dir/qrc_qdir.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
|
0
tests/auto/corelib/io/qdir/testdir/dir/tmp/empty
Normal file
0
tests/auto/corelib/io/qdir/testdir/dir/tmp/empty
Normal file
4
tests/auto/corelib/io/qdir/testdir/dir/tst_qdir.cpp
Normal file
4
tests/auto/corelib/io/qdir/testdir/dir/tst_qdir.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
|
0
tests/auto/corelib/io/qdir/testdir/spaces/foo. bar
Normal file
0
tests/auto/corelib/io/qdir/testdir/spaces/foo. bar
Normal file
0
tests/auto/corelib/io/qdir/testdir/spaces/foo.bar
Normal file
0
tests/auto/corelib/io/qdir/testdir/spaces/foo.bar
Normal file
2490
tests/auto/corelib/io/qdir/tst_qdir.cpp
Normal file
2490
tests/auto/corelib/io/qdir/tst_qdir.cpp
Normal file
File diff suppressed because it is too large
Load Diff
0
tests/auto/corelib/io/qdir/types/a
Normal file
0
tests/auto/corelib/io/qdir/types/a
Normal file
1
tests/auto/corelib/io/qdir/types/a.a
Normal file
1
tests/auto/corelib/io/qdir/types/a.a
Normal file
@ -0,0 +1 @@
|
||||
a
|
1
tests/auto/corelib/io/qdir/types/a.b
Normal file
1
tests/auto/corelib/io/qdir/types/a.b
Normal file
@ -0,0 +1 @@
|
||||
aa
|
1
tests/auto/corelib/io/qdir/types/a.c
Normal file
1
tests/auto/corelib/io/qdir/types/a.c
Normal file
@ -0,0 +1 @@
|
||||
aaa
|
0
tests/auto/corelib/io/qdir/types/b
Normal file
0
tests/auto/corelib/io/qdir/types/b
Normal file
1
tests/auto/corelib/io/qdir/types/b.a
Normal file
1
tests/auto/corelib/io/qdir/types/b.a
Normal file
@ -0,0 +1 @@
|
||||
aaaaaa
|
1
tests/auto/corelib/io/qdir/types/b.b
Normal file
1
tests/auto/corelib/io/qdir/types/b.b
Normal file
@ -0,0 +1 @@
|
||||
aaaa
|
1
tests/auto/corelib/io/qdir/types/b.c
Normal file
1
tests/auto/corelib/io/qdir/types/b.c
Normal file
@ -0,0 +1 @@
|
||||
aaaaa
|
0
tests/auto/corelib/io/qdir/types/c
Normal file
0
tests/auto/corelib/io/qdir/types/c
Normal file
1
tests/auto/corelib/io/qdir/types/c.a
Normal file
1
tests/auto/corelib/io/qdir/types/c.a
Normal file
@ -0,0 +1 @@
|
||||
aaaaaaaaa
|
1
tests/auto/corelib/io/qdir/types/c.b
Normal file
1
tests/auto/corelib/io/qdir/types/c.b
Normal file
@ -0,0 +1 @@
|
||||
aaaaaaaa
|
1
tests/auto/corelib/io/qdir/types/c.c
Normal file
1
tests/auto/corelib/io/qdir/types/c.c
Normal file
@ -0,0 +1 @@
|
||||
aaaaaaa
|
0
tests/auto/corelib/io/qdir/types/d.a/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/d.a/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/d.b/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/d.b/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/d.c/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/d.c/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/d/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/d/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/e.a/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/e.a/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/e.b/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/e.b/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/e.c/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/e.c/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/e/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/e/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/f.a/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/f.a/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/f.b/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/f.b/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/f.c/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/f.c/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/f/dummy
Normal file
0
tests/auto/corelib/io/qdir/types/f/dummy
Normal file
39
tests/auto/corelib/io/qdiriterator/CMakeLists.txt
Normal file
39
tests/auto/corelib/io/qdiriterator/CMakeLists.txt
Normal file
@ -0,0 +1,39 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qdiriterator Test:
|
||||
#####################################################################
|
||||
|
||||
# Collect test data
|
||||
list(APPEND test_data "entrylist")
|
||||
|
||||
qt_internal_add_test(tst_qdiriterator
|
||||
SOURCES
|
||||
tst_qdiriterator.cpp
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
TESTDATA ${test_data}
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(qdiriterator_resource_files
|
||||
"entrylist/directory/dummy"
|
||||
"entrylist/file"
|
||||
)
|
||||
|
||||
qt_internal_add_resource(tst_qdiriterator "qdiriterator"
|
||||
PREFIX
|
||||
"/testdata/"
|
||||
FILES
|
||||
${qdiriterator_resource_files}
|
||||
)
|
||||
|
||||
|
||||
## Scopes:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_extend_target(tst_qdiriterator CONDITION CONFIG___contains___builtin_testdata
|
||||
DEFINES
|
||||
BUILTIN_TESTDATA
|
||||
)
|
0
tests/auto/corelib/io/qdiriterator/entrylist/file
Normal file
0
tests/auto/corelib/io/qdiriterator/entrylist/file
Normal file
620
tests/auto/corelib/io/qdiriterator/tst_qdiriterator.cpp
Normal file
620
tests/auto/corelib/io/qdiriterator/tst_qdiriterator.cpp
Normal file
@ -0,0 +1,620 @@
|
||||
// Copyright (C) 2021 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
|
||||
#include <QTest>
|
||||
|
||||
#include <qcoreapplication.h>
|
||||
#include <qdebug.h>
|
||||
#include <qdiriterator.h>
|
||||
#include <qfileinfo.h>
|
||||
#include <qstringlist.h>
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
|
||||
#include <QtCore/private/qfsfileengine_p.h>
|
||||
|
||||
#if defined(Q_OS_VXWORKS)
|
||||
#define Q_NO_SYMLINKS
|
||||
#endif
|
||||
|
||||
#include "../../../../shared/filesystem.h"
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
#include <QStandardPaths>
|
||||
#endif
|
||||
|
||||
Q_DECLARE_METATYPE(QDirIterator::IteratorFlags)
|
||||
Q_DECLARE_METATYPE(QDir::Filters)
|
||||
|
||||
class tst_QDirIterator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private: // convenience functions
|
||||
QStringList createdDirectories;
|
||||
QStringList createdFiles;
|
||||
|
||||
QDir currentDir;
|
||||
bool createDirectory(const QString &dirName)
|
||||
{
|
||||
if (currentDir.mkdir(dirName)) {
|
||||
createdDirectories.prepend(dirName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
enum Cleanup { DoDelete, DontDelete };
|
||||
bool createFile(const QString &fileName, Cleanup cleanup = DoDelete)
|
||||
{
|
||||
QFile file(fileName);
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
if (cleanup == DoDelete)
|
||||
createdFiles << fileName;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool createLink(const QString &destination, const QString &linkName)
|
||||
{
|
||||
if (QFile::link(destination, linkName)) {
|
||||
createdFiles << linkName;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void cleanupTestCase();
|
||||
void iterateRelativeDirectory_data();
|
||||
void iterateRelativeDirectory();
|
||||
void iterateResource_data();
|
||||
void iterateResource();
|
||||
void stopLinkLoop();
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
void engineWithNoIterator();
|
||||
#endif
|
||||
void absoluteFilePathsFromRelativeIteratorPath();
|
||||
void recurseWithFilters() const;
|
||||
void longPath();
|
||||
void dirorder();
|
||||
void relativePaths();
|
||||
#if defined(Q_OS_WIN)
|
||||
void uncPaths_data();
|
||||
void uncPaths();
|
||||
#endif
|
||||
#ifndef Q_OS_WIN
|
||||
void hiddenDirs_hiddenFiles();
|
||||
#endif
|
||||
#ifdef BUILTIN_TESTDATA
|
||||
private:
|
||||
QSharedPointer<QTemporaryDir> m_dataDir;
|
||||
#endif
|
||||
};
|
||||
|
||||
void tst_QDirIterator::initTestCase()
|
||||
{
|
||||
#ifdef Q_OS_ANDROID
|
||||
QString testdata_dir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
|
||||
QString resourceSourcePath = QStringLiteral(":/testdata");
|
||||
QDirIterator it(resourceSourcePath, QDirIterator::Subdirectories);
|
||||
while (it.hasNext()) {
|
||||
QFileInfo fileInfo = it.nextFileInfo();
|
||||
|
||||
if (!fileInfo.isDir()) {
|
||||
QString destination = testdata_dir + QLatin1Char('/')
|
||||
+ fileInfo.filePath().mid(resourceSourcePath.length());
|
||||
QFileInfo destinationFileInfo(destination);
|
||||
if (!destinationFileInfo.exists()) {
|
||||
QDir().mkpath(destinationFileInfo.path());
|
||||
if (!QFile::copy(fileInfo.filePath(), destination))
|
||||
qWarning("Failed to copy %s", qPrintable(fileInfo.filePath()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
testdata_dir += QStringLiteral("/entrylist");
|
||||
#elif defined(BUILTIN_TESTDATA)
|
||||
m_dataDir = QEXTRACTTESTDATA("/testdata");
|
||||
QVERIFY2(!m_dataDir.isNull(), qPrintable("Could not extract test data"));
|
||||
QString testdata_dir = m_dataDir->path();
|
||||
#else
|
||||
|
||||
// chdir into testdata directory, then find testdata by relative paths.
|
||||
QString testdata_dir = QFileInfo(QFINDTESTDATA("entrylist")).absolutePath();
|
||||
#endif
|
||||
|
||||
QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir));
|
||||
|
||||
QFile::remove("entrylist/entrylist1.lnk");
|
||||
QFile::remove("entrylist/entrylist2.lnk");
|
||||
QFile::remove("entrylist/entrylist3.lnk");
|
||||
QFile::remove("entrylist/entrylist4.lnk");
|
||||
QFile::remove("entrylist/directory/entrylist1.lnk");
|
||||
QFile::remove("entrylist/directory/entrylist2.lnk");
|
||||
QFile::remove("entrylist/directory/entrylist3.lnk");
|
||||
QFile::remove("entrylist/directory/entrylist4.lnk");
|
||||
|
||||
createDirectory("entrylist");
|
||||
createDirectory("entrylist/directory");
|
||||
createFile("entrylist/file", DontDelete);
|
||||
createFile("entrylist/writable");
|
||||
createFile("entrylist/directory/dummy", DontDelete);
|
||||
|
||||
createDirectory("recursiveDirs");
|
||||
createDirectory("recursiveDirs/dir1");
|
||||
createFile("recursiveDirs/textFileA.txt");
|
||||
createFile("recursiveDirs/dir1/aPage.html");
|
||||
createFile("recursiveDirs/dir1/textFileB.txt");
|
||||
|
||||
createDirectory("foo");
|
||||
createDirectory("foo/bar");
|
||||
createFile("foo/bar/readme.txt");
|
||||
|
||||
createDirectory("empty");
|
||||
|
||||
#ifndef Q_NO_SYMLINKS
|
||||
# if defined(Q_OS_WIN)
|
||||
// ### Sadly, this is a platform difference right now.
|
||||
createLink("entrylist/file", "entrylist/linktofile.lnk");
|
||||
# ifndef Q_NO_SYMLINKS_TO_DIRS
|
||||
createLink("entrylist/directory", "entrylist/linktodirectory.lnk");
|
||||
# endif
|
||||
createLink("entrylist/nothing", "entrylist/brokenlink.lnk");
|
||||
# else
|
||||
createLink("file", "entrylist/linktofile.lnk");
|
||||
# ifndef Q_NO_SYMLINKS_TO_DIRS
|
||||
createLink("directory", "entrylist/linktodirectory.lnk");
|
||||
# endif
|
||||
createLink("nothing", "entrylist/brokenlink.lnk");
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(Q_OS_WIN)
|
||||
createDirectory("hiddenDirs_hiddenFiles");
|
||||
createFile("hiddenDirs_hiddenFiles/normalFile");
|
||||
createFile("hiddenDirs_hiddenFiles/.hiddenFile");
|
||||
createDirectory("hiddenDirs_hiddenFiles/normalDirectory");
|
||||
createDirectory("hiddenDirs_hiddenFiles/.hiddenDirectory");
|
||||
createFile("hiddenDirs_hiddenFiles/normalDirectory/normalFile");
|
||||
createFile("hiddenDirs_hiddenFiles/normalDirectory/.hiddenFile");
|
||||
createFile("hiddenDirs_hiddenFiles/.hiddenDirectory/normalFile");
|
||||
createFile("hiddenDirs_hiddenFiles/.hiddenDirectory/.hiddenFile");
|
||||
createDirectory("hiddenDirs_hiddenFiles/normalDirectory/normalDirectory");
|
||||
createDirectory("hiddenDirs_hiddenFiles/normalDirectory/.hiddenDirectory");
|
||||
createDirectory("hiddenDirs_hiddenFiles/.hiddenDirectory/normalDirectory");
|
||||
createDirectory("hiddenDirs_hiddenFiles/.hiddenDirectory/.hiddenDirectory");
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QDirIterator::cleanupTestCase()
|
||||
{
|
||||
Q_FOREACH(QString fileName, createdFiles)
|
||||
QFile::remove(fileName);
|
||||
|
||||
Q_FOREACH(QString dirName, createdDirectories)
|
||||
currentDir.rmdir(dirName);
|
||||
}
|
||||
|
||||
void tst_QDirIterator::iterateRelativeDirectory_data()
|
||||
{
|
||||
QTest::addColumn<QString>("dirName"); // relative from current path or abs
|
||||
QTest::addColumn<QDirIterator::IteratorFlags>("flags");
|
||||
QTest::addColumn<QDir::Filters>("filters");
|
||||
QTest::addColumn<QStringList>("nameFilters");
|
||||
QTest::addColumn<QStringList>("entries");
|
||||
|
||||
QTest::newRow("no flags")
|
||||
<< QString("entrylist") << QDirIterator::IteratorFlags{}
|
||||
<< QDir::Filters(QDir::NoFilter) << QStringList("*")
|
||||
<< QString(
|
||||
"entrylist/.,"
|
||||
"entrylist/..,"
|
||||
"entrylist/file,"
|
||||
#ifndef Q_NO_SYMLINKS
|
||||
"entrylist/linktofile.lnk,"
|
||||
#endif
|
||||
"entrylist/directory,"
|
||||
#if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS)
|
||||
"entrylist/linktodirectory.lnk,"
|
||||
#endif
|
||||
"entrylist/writable").split(',');
|
||||
|
||||
QTest::newRow("NoDot")
|
||||
<< QString("entrylist") << QDirIterator::IteratorFlags{}
|
||||
<< QDir::Filters(QDir::AllEntries | QDir::NoDot) << QStringList("*")
|
||||
<< QString(
|
||||
"entrylist/..,"
|
||||
"entrylist/file,"
|
||||
#ifndef Q_NO_SYMLINKS
|
||||
"entrylist/linktofile.lnk,"
|
||||
#endif
|
||||
"entrylist/directory,"
|
||||
#if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS)
|
||||
"entrylist/linktodirectory.lnk,"
|
||||
#endif
|
||||
"entrylist/writable").split(',');
|
||||
|
||||
QTest::newRow("NoDotDot")
|
||||
<< QString("entrylist") << QDirIterator::IteratorFlags{}
|
||||
<< QDir::Filters(QDir::AllEntries | QDir::NoDotDot) << QStringList("*")
|
||||
<< QString(
|
||||
"entrylist/.,"
|
||||
"entrylist/file,"
|
||||
#ifndef Q_NO_SYMLINKS
|
||||
"entrylist/linktofile.lnk,"
|
||||
#endif
|
||||
"entrylist/directory,"
|
||||
#if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS)
|
||||
"entrylist/linktodirectory.lnk,"
|
||||
#endif
|
||||
"entrylist/writable").split(',');
|
||||
|
||||
QTest::newRow("NoDotAndDotDot")
|
||||
<< QString("entrylist") << QDirIterator::IteratorFlags{}
|
||||
<< QDir::Filters(QDir::AllEntries | QDir::NoDotAndDotDot) << QStringList("*")
|
||||
<< QString(
|
||||
"entrylist/file,"
|
||||
#ifndef Q_NO_SYMLINKS
|
||||
"entrylist/linktofile.lnk,"
|
||||
#endif
|
||||
"entrylist/directory,"
|
||||
#if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS)
|
||||
"entrylist/linktodirectory.lnk,"
|
||||
#endif
|
||||
"entrylist/writable").split(',');
|
||||
|
||||
QTest::newRow("QDir::Subdirectories | QDir::FollowSymlinks")
|
||||
<< QString("entrylist") << QDirIterator::IteratorFlags(QDirIterator::Subdirectories | QDirIterator::FollowSymlinks)
|
||||
<< QDir::Filters(QDir::NoFilter) << QStringList("*")
|
||||
<< QString(
|
||||
"entrylist/.,"
|
||||
"entrylist/..,"
|
||||
"entrylist/directory/.,"
|
||||
"entrylist/directory/..,"
|
||||
"entrylist/file,"
|
||||
#ifndef Q_NO_SYMLINKS
|
||||
"entrylist/linktofile.lnk,"
|
||||
#endif
|
||||
"entrylist/directory,"
|
||||
"entrylist/directory/dummy,"
|
||||
#if !defined(Q_NO_SYMLINKS) && !defined(Q_NO_SYMLINKS_TO_DIRS)
|
||||
"entrylist/linktodirectory.lnk,"
|
||||
#endif
|
||||
"entrylist/writable").split(',');
|
||||
|
||||
QTest::newRow("QDir::Subdirectories / QDir::Files")
|
||||
<< QString("entrylist") << QDirIterator::IteratorFlags(QDirIterator::Subdirectories)
|
||||
<< QDir::Filters(QDir::Files) << QStringList("*")
|
||||
<< QString("entrylist/directory/dummy,"
|
||||
"entrylist/file,"
|
||||
#ifndef Q_NO_SYMLINKS
|
||||
"entrylist/linktofile.lnk,"
|
||||
#endif
|
||||
"entrylist/writable").split(',');
|
||||
|
||||
QTest::newRow("QDir::Subdirectories | QDir::FollowSymlinks / QDir::Files")
|
||||
<< QString("entrylist") << QDirIterator::IteratorFlags(QDirIterator::Subdirectories | QDirIterator::FollowSymlinks)
|
||||
<< QDir::Filters(QDir::Files) << QStringList("*")
|
||||
<< QString("entrylist/file,"
|
||||
#ifndef Q_NO_SYMLINKS
|
||||
"entrylist/linktofile.lnk,"
|
||||
#endif
|
||||
"entrylist/directory/dummy,"
|
||||
"entrylist/writable").split(',');
|
||||
|
||||
QTest::newRow("empty, default")
|
||||
<< QString("empty") << QDirIterator::IteratorFlags{}
|
||||
<< QDir::Filters(QDir::NoFilter) << QStringList("*")
|
||||
<< QString("empty/.,empty/..").split(',');
|
||||
|
||||
QTest::newRow("empty, QDir::NoDotAndDotDot")
|
||||
<< QString("empty") << QDirIterator::IteratorFlags{}
|
||||
<< QDir::Filters(QDir::NoDotAndDotDot) << QStringList("*")
|
||||
<< QStringList();
|
||||
}
|
||||
|
||||
void tst_QDirIterator::iterateRelativeDirectory()
|
||||
{
|
||||
QFETCH(QString, dirName);
|
||||
QFETCH(QDirIterator::IteratorFlags, flags);
|
||||
QFETCH(QDir::Filters, filters);
|
||||
QFETCH(QStringList, nameFilters);
|
||||
QFETCH(QStringList, entries);
|
||||
|
||||
QDirIterator it(dirName, nameFilters, filters, flags);
|
||||
QStringList list;
|
||||
while (it.hasNext()) {
|
||||
QString next = it.next();
|
||||
|
||||
QString fileName = it.fileName();
|
||||
QString filePath = it.filePath();
|
||||
QString path = it.path();
|
||||
|
||||
QFileInfo info = it.fileInfo();
|
||||
|
||||
QCOMPARE(path, dirName);
|
||||
QCOMPARE(next, filePath);
|
||||
|
||||
QCOMPARE(info, QFileInfo(next));
|
||||
QCOMPARE(fileName, info.fileName());
|
||||
QCOMPARE(filePath, info.filePath());
|
||||
|
||||
// Using canonical file paths for final comparison
|
||||
list << info.canonicalFilePath();
|
||||
}
|
||||
|
||||
// The order of items returned by QDirIterator is not guaranteed.
|
||||
list.sort();
|
||||
|
||||
QStringList sortedEntries;
|
||||
foreach(QString item, entries)
|
||||
sortedEntries.append(QFileInfo(item).canonicalFilePath());
|
||||
sortedEntries.sort();
|
||||
|
||||
if (sortedEntries != list) {
|
||||
qDebug() << "EXPECTED:" << sortedEntries;
|
||||
qDebug() << "ACTUAL: " << list;
|
||||
}
|
||||
|
||||
QCOMPARE(list, sortedEntries);
|
||||
}
|
||||
|
||||
void tst_QDirIterator::iterateResource_data()
|
||||
{
|
||||
QTest::addColumn<QString>("dirName"); // relative from current path or abs
|
||||
QTest::addColumn<QDirIterator::IteratorFlags>("flags");
|
||||
QTest::addColumn<QDir::Filters>("filters");
|
||||
QTest::addColumn<QStringList>("nameFilters");
|
||||
QTest::addColumn<QStringList>("entries");
|
||||
|
||||
QTest::newRow("invalid") << QString::fromLatin1(":/testdata/burpaburpa") << QDirIterator::IteratorFlags{}
|
||||
<< QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*"))
|
||||
<< QStringList();
|
||||
QTest::newRow(":/testdata") << QString::fromLatin1(":/testdata/") << QDirIterator::IteratorFlags{}
|
||||
<< QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*"))
|
||||
<< QString::fromLatin1(":/testdata/entrylist").split(QLatin1String(","));
|
||||
QTest::newRow(":/testdata/entrylist") << QString::fromLatin1(":/testdata/entrylist") << QDirIterator::IteratorFlags{}
|
||||
<< QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*"))
|
||||
<< QString::fromLatin1(":/testdata/entrylist/directory,:/testdata/entrylist/file").split(QLatin1String(","));
|
||||
QTest::newRow(":/testdata recursive") << QString::fromLatin1(":/testdata") << QDirIterator::IteratorFlags(QDirIterator::Subdirectories)
|
||||
<< QDir::Filters(QDir::NoFilter) << QStringList(QLatin1String("*"))
|
||||
<< QString::fromLatin1(":/testdata/entrylist,:/testdata/entrylist/directory,:/testdata/entrylist/directory/dummy,:/testdata/entrylist/file").split(QLatin1String(","));
|
||||
}
|
||||
|
||||
void tst_QDirIterator::iterateResource()
|
||||
{
|
||||
QFETCH(QString, dirName);
|
||||
QFETCH(QDirIterator::IteratorFlags, flags);
|
||||
QFETCH(QDir::Filters, filters);
|
||||
QFETCH(QStringList, nameFilters);
|
||||
QFETCH(QStringList, entries);
|
||||
|
||||
QDirIterator it(dirName, nameFilters, filters, flags);
|
||||
QStringList list;
|
||||
while (it.hasNext()) {
|
||||
const QString dir = it.next();
|
||||
if (!dir.startsWith(":/qt-project.org"))
|
||||
list << dir;
|
||||
}
|
||||
|
||||
list.sort();
|
||||
QStringList sortedEntries = entries;
|
||||
sortedEntries.sort();
|
||||
|
||||
if (sortedEntries != list) {
|
||||
qDebug() << "EXPECTED:" << sortedEntries;
|
||||
qDebug() << "ACTUAL:" << list;
|
||||
}
|
||||
|
||||
QCOMPARE(list, sortedEntries);
|
||||
}
|
||||
|
||||
void tst_QDirIterator::stopLinkLoop()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
// ### Sadly, this is a platform difference right now.
|
||||
createLink(QDir::currentPath() + QLatin1String("/entrylist"), "entrylist/entrylist1.lnk");
|
||||
createLink("entrylist/.", "entrylist/entrylist2.lnk");
|
||||
createLink("entrylist/../entrylist/.", "entrylist/entrylist3.lnk");
|
||||
createLink("entrylist/..", "entrylist/entrylist4.lnk");
|
||||
createLink(QDir::currentPath() + QLatin1String("/entrylist"), "entrylist/directory/entrylist1.lnk");
|
||||
createLink("entrylist/.", "entrylist/directory/entrylist2.lnk");
|
||||
createLink("entrylist/../directory/.", "entrylist/directory/entrylist3.lnk");
|
||||
createLink("entrylist/..", "entrylist/directory/entrylist4.lnk");
|
||||
#else
|
||||
createLink(QDir::currentPath() + QLatin1String("/entrylist"), "entrylist/entrylist1.lnk");
|
||||
createLink(".", "entrylist/entrylist2.lnk");
|
||||
createLink("../entrylist/.", "entrylist/entrylist3.lnk");
|
||||
createLink("..", "entrylist/entrylist4.lnk");
|
||||
createLink(QDir::currentPath() + QLatin1String("/entrylist"), "entrylist/directory/entrylist1.lnk");
|
||||
createLink(".", "entrylist/directory/entrylist2.lnk");
|
||||
createLink("../directory/.", "entrylist/directory/entrylist3.lnk");
|
||||
createLink("..", "entrylist/directory/entrylist4.lnk");
|
||||
#endif
|
||||
|
||||
QDirIterator it(QLatin1String("entrylist"), QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
|
||||
QStringList list;
|
||||
int max = 200;
|
||||
while (--max && it.hasNext())
|
||||
it.nextFileInfo();
|
||||
QVERIFY(max);
|
||||
|
||||
// The goal of this test is only to ensure that the test above don't malfunction
|
||||
}
|
||||
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
class EngineWithNoIterator : public QFSFileEngine
|
||||
{
|
||||
public:
|
||||
EngineWithNoIterator(const QString &fileName)
|
||||
: QFSFileEngine(fileName)
|
||||
{ }
|
||||
|
||||
QAbstractFileEngineIterator *beginEntryList(QDir::Filters, const QStringList &) override
|
||||
{ return 0; }
|
||||
};
|
||||
|
||||
class EngineWithNoIteratorHandler : public QAbstractFileEngineHandler
|
||||
{
|
||||
public:
|
||||
QAbstractFileEngine *create(const QString &fileName) const override
|
||||
{
|
||||
return new EngineWithNoIterator(fileName);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
void tst_QDirIterator::engineWithNoIterator()
|
||||
{
|
||||
EngineWithNoIteratorHandler handler;
|
||||
|
||||
QDir("entrylist").entryList();
|
||||
QVERIFY(true); // test that the above line doesn't crash
|
||||
}
|
||||
#endif
|
||||
|
||||
void tst_QDirIterator::absoluteFilePathsFromRelativeIteratorPath()
|
||||
{
|
||||
QDirIterator it("entrylist/", QDir::NoDotAndDotDot);
|
||||
while (it.hasNext())
|
||||
QVERIFY(it.nextFileInfo().absoluteFilePath().contains("entrylist"));
|
||||
}
|
||||
|
||||
void tst_QDirIterator::recurseWithFilters() const
|
||||
{
|
||||
QStringList nameFilters;
|
||||
nameFilters.append("*.txt");
|
||||
|
||||
QDirIterator it("recursiveDirs/", nameFilters, QDir::Files,
|
||||
QDirIterator::Subdirectories);
|
||||
|
||||
QSet<QString> actualEntries;
|
||||
QSet<QString> expectedEntries;
|
||||
expectedEntries.insert(QString::fromLatin1("recursiveDirs/dir1/textFileB.txt"));
|
||||
expectedEntries.insert(QString::fromLatin1("recursiveDirs/textFileA.txt"));
|
||||
|
||||
QVERIFY(it.hasNext());
|
||||
actualEntries.insert(it.next());
|
||||
QVERIFY(it.hasNext());
|
||||
actualEntries.insert(it.next());
|
||||
QCOMPARE(actualEntries, expectedEntries);
|
||||
|
||||
QVERIFY(!it.hasNext());
|
||||
}
|
||||
|
||||
void tst_QDirIterator::longPath()
|
||||
{
|
||||
QDir dir;
|
||||
dir.mkdir("longpaths");
|
||||
dir.cd("longpaths");
|
||||
|
||||
QString dirName = "x";
|
||||
int n = 0;
|
||||
while (dir.exists(dirName) || dir.mkdir(dirName)) {
|
||||
++n;
|
||||
dirName.append('x');
|
||||
}
|
||||
|
||||
QDirIterator it(dir.absolutePath(), QDir::NoDotAndDotDot|QDir::Dirs, QDirIterator::Subdirectories);
|
||||
int m = 0;
|
||||
while (it.hasNext()) {
|
||||
++m;
|
||||
it.nextFileInfo();
|
||||
}
|
||||
|
||||
QCOMPARE(n, m);
|
||||
|
||||
dirName.chop(1);
|
||||
while (dirName.size() > 0 && dir.exists(dirName) && dir.rmdir(dirName)) {
|
||||
dirName.chop(1);
|
||||
}
|
||||
dir.cdUp();
|
||||
dir.rmdir("longpaths");
|
||||
}
|
||||
|
||||
void tst_QDirIterator::dirorder()
|
||||
{
|
||||
QDirIterator iterator("foo", QDirIterator::Subdirectories);
|
||||
while (iterator.hasNext() && iterator.next() != "foo/bar")
|
||||
{ }
|
||||
|
||||
QCOMPARE(iterator.filePath(), QString("foo/bar"));
|
||||
QCOMPARE(iterator.fileInfo().filePath(), QString("foo/bar"));
|
||||
}
|
||||
|
||||
void tst_QDirIterator::relativePaths()
|
||||
{
|
||||
QDirIterator iterator("*", QDirIterator::Subdirectories);
|
||||
while(iterator.hasNext()) {
|
||||
QCOMPARE(iterator.filePath(), QDir::cleanPath(iterator.filePath()));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
void tst_QDirIterator::uncPaths_data()
|
||||
{
|
||||
QTest::addColumn<QString>("dirName");
|
||||
QTest::newRow("uncserver")
|
||||
<<QString("//" + QTest::uncServerName());
|
||||
QTest::newRow("uncserver/testshare")
|
||||
<<QString("//" + QTest::uncServerName() + "/testshare");
|
||||
QTest::newRow("uncserver/testshare/tmp")
|
||||
<<QString("//" + QTest::uncServerName() + "/testshare/tmp");
|
||||
}
|
||||
void tst_QDirIterator::uncPaths()
|
||||
{
|
||||
QFETCH(QString, dirName);
|
||||
QDirIterator iterator(dirName, QDir::AllEntries|QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
|
||||
while(iterator.hasNext()) {
|
||||
iterator.next();
|
||||
QCOMPARE(iterator.filePath(), QDir::cleanPath(iterator.filePath()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
// In Unix it is easy to create hidden files, but in Windows it requires
|
||||
// a special call since hidden files need to be "marked" while in Unix
|
||||
// anything starting by a '.' is a hidden file.
|
||||
// For that reason this test is not run in Windows.
|
||||
void tst_QDirIterator::hiddenDirs_hiddenFiles()
|
||||
{
|
||||
// Only files
|
||||
{
|
||||
int matches = 0;
|
||||
int failures = 0;
|
||||
QDirIterator di("hiddenDirs_hiddenFiles", QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
|
||||
while (di.hasNext()) {
|
||||
++matches;
|
||||
if (di.nextFileInfo().isDir())
|
||||
++failures; // search was only supposed to find files
|
||||
}
|
||||
QCOMPARE(matches, 6);
|
||||
QCOMPARE(failures, 0);
|
||||
}
|
||||
// Only directories
|
||||
{
|
||||
int matches = 0;
|
||||
int failures = 0;
|
||||
QDirIterator di("hiddenDirs_hiddenFiles", QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
|
||||
while (di.hasNext()) {
|
||||
++matches;
|
||||
if (!di.nextFileInfo().isDir())
|
||||
++failures; // search was only supposed to find files
|
||||
}
|
||||
QCOMPARE(matches, 6);
|
||||
QCOMPARE(failures, 0);
|
||||
}
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
QTEST_MAIN(tst_QDirIterator)
|
||||
|
||||
#include "tst_qdiriterator.moc"
|
||||
|
87
tests/auto/corelib/io/qfile/CMakeLists.txt
Normal file
87
tests/auto/corelib/io/qfile/CMakeLists.txt
Normal file
@ -0,0 +1,87 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qfile Test:
|
||||
#####################################################################
|
||||
|
||||
# Collect test data
|
||||
list(APPEND test_data "dosfile.txt")
|
||||
list(APPEND test_data "noendofline.txt")
|
||||
list(APPEND test_data "testfile.txt")
|
||||
list(APPEND test_data "testlog.txt")
|
||||
list(APPEND test_data "two.dots.file")
|
||||
list(APPEND test_data "tst_qfile.cpp")
|
||||
list(APPEND test_data "forCopying.txt")
|
||||
list(APPEND test_data "forRenaming.txt")
|
||||
list(APPEND test_data "resources/file1.ext1")
|
||||
|
||||
qt_internal_add_test(tst_qfile
|
||||
SOURCES
|
||||
tst_qfile.cpp
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
Qt::TestPrivate
|
||||
TESTDATA ${test_data}
|
||||
)
|
||||
|
||||
# Resources:
|
||||
set(qfile_resource_files
|
||||
"resources/"
|
||||
)
|
||||
|
||||
qt_internal_add_resource(tst_qfile "qfile"
|
||||
PREFIX
|
||||
"/tst_qfileinfo/"
|
||||
FILES
|
||||
${qfile_resource_files}
|
||||
)
|
||||
set(rename-fallback_resource_files
|
||||
"rename-fallback.qrc"
|
||||
)
|
||||
|
||||
qt_internal_add_resource(tst_qfile "rename-fallback"
|
||||
PREFIX
|
||||
"/"
|
||||
FILES
|
||||
${rename-fallback_resource_files}
|
||||
)
|
||||
set(copy-fallback_resource_files
|
||||
"copy-fallback.qrc"
|
||||
)
|
||||
|
||||
qt_internal_add_resource(tst_qfile "copy-fallback"
|
||||
PREFIX
|
||||
"/"
|
||||
FILES
|
||||
${copy-fallback_resource_files}
|
||||
)
|
||||
|
||||
|
||||
## Scopes:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_extend_target(tst_qfile CONDITION TARGET Qt::Network
|
||||
LIBRARIES
|
||||
Qt::Network
|
||||
)
|
||||
|
||||
qt_internal_extend_target(tst_qfile CONDITION NOT TARGET Qt::Network
|
||||
DEFINES
|
||||
QT_NO_NETWORK
|
||||
)
|
||||
|
||||
qt_internal_extend_target(tst_qfile CONDITION CONFIG___contains___builtin_testdata
|
||||
DEFINES
|
||||
BUILTIN_TESTDATA
|
||||
)
|
||||
|
||||
qt_internal_extend_target(tst_qfile CONDITION WIN32
|
||||
LIBRARIES
|
||||
ole32
|
||||
uuid
|
||||
)
|
||||
add_subdirectory(stdinprocess)
|
||||
if(QT_FEATURE_process)
|
||||
add_dependencies(tst_qfile stdinprocess_helper)
|
||||
endif()
|
5
tests/auto/corelib/io/qfile/copy-fallback.qrc
Normal file
5
tests/auto/corelib/io/qfile/copy-fallback.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>copy-fallback.qrc</file>
|
||||
</qresource>
|
||||
</RCC>
|
14
tests/auto/corelib/io/qfile/dosfile.txt
Normal file
14
tests/auto/corelib/io/qfile/dosfile.txt
Normal file
@ -0,0 +1,14 @@
|
||||
/dev/system/root / reiserfs acl,user_xattr 1 1
|
||||
/dev/sda1 /boot ext3 acl,user_xattr 1 2
|
||||
/dev/system/home /home reiserfs acl,user_xattr 1 2
|
||||
/dev/system/temp /tmp reiserfs acl,user_xattr 1 2
|
||||
/dev/sda2 swap swap pri=42 0 0
|
||||
devpts /dev/pts devpts mode=0620,gid=5 0 0
|
||||
proc /proc proc defaults 0 0
|
||||
usbfs /proc/bus/usb usbfs noauto 0 0
|
||||
sysfs /sys sysfs noauto 0 0
|
||||
/dev/dvd /media/dvd subfs noauto,fs=cdfss,ro,procuid,nosuid,nodev,exec,iocharset=utf8 0 0
|
||||
/dev/fd0 /media/floppy subfs noauto,fs=floppyfss,procuid,nodev,nosuid,sync 0 0
|
||||
/dev/sdb2 /media/ipod subfs noauto,rw,noexec,nosuid,nodev,sync,procuid,user,iocharset=utf8 1 2
|
||||
/dev/sdc1 /media/usbkey vfat rw,nosuid,nodev,sync,procuid,user 1 2
|
||||
|
1
tests/auto/corelib/io/qfile/forCopying.txt
Normal file
1
tests/auto/corelib/io/qfile/forCopying.txt
Normal file
@ -0,0 +1 @@
|
||||
A basic file for copying.
|
7
tests/auto/corelib/io/qfile/forRenaming.txt
Normal file
7
tests/auto/corelib/io/qfile/forRenaming.txt
Normal file
File diff suppressed because one or more lines are too long
3
tests/auto/corelib/io/qfile/noendofline.txt
Normal file
3
tests/auto/corelib/io/qfile/noendofline.txt
Normal file
@ -0,0 +1,3 @@
|
||||
Do not touch the content of this file.
|
||||
It shows a text file
|
||||
with no end-of-line-character on the last line
|
5
tests/auto/corelib/io/qfile/rename-fallback.qrc
Normal file
5
tests/auto/corelib/io/qfile/rename-fallback.qrc
Normal file
@ -0,0 +1,5 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>rename-fallback.qrc</file>
|
||||
</qresource>
|
||||
</RCC>
|
1
tests/auto/corelib/io/qfile/resources/file1.ext1
Normal file
1
tests/auto/corelib/io/qfile/resources/file1.ext1
Normal file
@ -0,0 +1 @@
|
||||
12345
|
11
tests/auto/corelib/io/qfile/stdinprocess/CMakeLists.txt
Normal file
11
tests/auto/corelib/io/qfile/stdinprocess/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## stdinprocess_helper Binary:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_test_helper(stdinprocess_helper
|
||||
SOURCES
|
||||
main.cpp
|
||||
)
|
35
tests/auto/corelib/io/qfile/stdinprocess/main.cpp
Normal file
35
tests/auto/corelib/io/qfile/stdinprocess/main.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QFile>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("usage: stdinprocess_helper <all|line <0|1>>\n");
|
||||
printf("echos all its input to its output.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
QFile file;
|
||||
|
||||
if (strcmp(argv[1], "all") == 0) {
|
||||
file.open(stdin, QFile::ReadWrite);
|
||||
printf("%s", file.readAll().constData());
|
||||
} else if (strcmp(argv[1], "line") == 0) {
|
||||
if (strcmp(argv[2], "0") == 0) {
|
||||
file.open(stdin, QFile::ReadWrite);
|
||||
} else {
|
||||
file.open(0, QFile::ReadWrite);
|
||||
}
|
||||
|
||||
char line[1024];
|
||||
while (file.readLine(line, sizeof(line)) > 0) {
|
||||
printf("%s", line);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
6
tests/auto/corelib/io/qfile/testfile.txt
Normal file
6
tests/auto/corelib/io/qfile/testfile.txt
Normal file
@ -0,0 +1,6 @@
|
||||
----------------------------------------------------------
|
||||
DO NOT CHANGE ANY CONTENT OR ACCESS RIGHTS OF THIS FILE!!!
|
||||
----------------------------------------------------------
|
||||
|
||||
This demo file has only six lines
|
||||
and a size of exactly 245 Bytes.
|
144
tests/auto/corelib/io/qfile/testlog.txt
Normal file
144
tests/auto/corelib/io/qfile/testlog.txt
Normal file
@ -0,0 +1,144 @@
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
||||
2006-09-29 13:50:08.349: -- File log starts_
|
||||
2006-09-29 13:50:08.349: -- File log starts
|
3977
tests/auto/corelib/io/qfile/tst_qfile.cpp
Normal file
3977
tests/auto/corelib/io/qfile/tst_qfile.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1
tests/auto/corelib/io/qfile/two.dots.file
Normal file
1
tests/auto/corelib/io/qfile/two.dots.file
Normal file
@ -0,0 +1 @@
|
||||
foo
|
52
tests/auto/corelib/io/qfileinfo/CMakeLists.txt
Normal file
52
tests/auto/corelib/io/qfileinfo/CMakeLists.txt
Normal file
@ -0,0 +1,52 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qfileinfo Test:
|
||||
#####################################################################
|
||||
|
||||
qt_internal_add_test(tst_qfileinfo
|
||||
SOURCES
|
||||
tst_qfileinfo.cpp
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
)
|
||||
|
||||
# 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)
|
||||
set_source_files_properties(tst_qfileinfo.cpp PROPERTIES LANGUAGE OBJCXX)
|
||||
endif()
|
0
tests/auto/corelib/io/qfileinfo/resources/file1
Normal file
0
tests/auto/corelib/io/qfileinfo/resources/file1
Normal file
2395
tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
Normal file
2395
tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
Normal file
File diff suppressed because it is too large
Load Diff
67
tests/auto/corelib/io/qfileselector/CMakeLists.txt
Normal file
67
tests/auto/corelib/io/qfileselector/CMakeLists.txt
Normal file
@ -0,0 +1,67 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qfileselectors Test:
|
||||
#####################################################################
|
||||
|
||||
# Resources:
|
||||
set(qfileselector_resource_files
|
||||
"extras/+custom1/test"
|
||||
"extras/+custom1/test3"
|
||||
"extras/+custom2/test"
|
||||
"extras/+custom3/+custom2/test"
|
||||
"extras/+custom3/+custom4/test"
|
||||
"extras/+custom3/+custom5/test"
|
||||
"extras/+custom3/test"
|
||||
"extras/+custom5/+custom3/test"
|
||||
"extras/test"
|
||||
"extras/test2"
|
||||
"platforms/+android/test"
|
||||
"platforms/+android/test2"
|
||||
"platforms/+darwin/test"
|
||||
"platforms/+haiku/test"
|
||||
"platforms/+haiku/test2"
|
||||
"platforms/+ios/test"
|
||||
"platforms/+ios/test2"
|
||||
"platforms/+linux/test"
|
||||
"platforms/+linux/test2"
|
||||
"platforms/+macos/test"
|
||||
"platforms/+macos/test2"
|
||||
"platforms/+qnx/test"
|
||||
"platforms/+qnx/test2"
|
||||
"platforms/+unix/+android/test"
|
||||
"platforms/+unix/+darwin/+ios/test"
|
||||
"platforms/+unix/+darwin/+macos/test"
|
||||
"platforms/+unix/+darwin/test"
|
||||
"platforms/+unix/+haiku/test"
|
||||
"platforms/+unix/+linux/test"
|
||||
"platforms/+unix/+qnx/test"
|
||||
"platforms/+unix/test"
|
||||
"platforms/+unix/test3"
|
||||
"platforms/+wince/test"
|
||||
"platforms/+wince/test2"
|
||||
"platforms/+windows/+wince/test"
|
||||
"platforms/+windows/+winnt/test"
|
||||
"platforms/+windows/+winrt/test"
|
||||
"platforms/+windows/test"
|
||||
"platforms/+windows/test3"
|
||||
"platforms/+winnt/test2"
|
||||
"platforms/+winrt/test"
|
||||
"platforms/+winrt/test2"
|
||||
"platforms/test"
|
||||
"platforms/test2"
|
||||
"platforms/test3"
|
||||
"platforms/test4"
|
||||
"platforms/test5"
|
||||
)
|
||||
|
||||
qt_internal_add_test(tst_qfileselectors
|
||||
SOURCES
|
||||
tst_qfileselector.cpp
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
TESTDATA ${qfileselector_resource_files}
|
||||
BUILTIN_TESTDATA
|
||||
)
|
||||
|
0
tests/auto/corelib/io/qfileselector/extras/test
Normal file
0
tests/auto/corelib/io/qfileselector/extras/test
Normal file
0
tests/auto/corelib/io/qfileselector/extras/test2
Normal file
0
tests/auto/corelib/io/qfileselector/extras/test2
Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user