qt 6.5.1 original

This commit is contained in:
kleuter
2023-10-29 23:33:08 +01:00
parent 71d22ab6b0
commit 85d238dfda
21202 changed files with 5499099 additions and 0 deletions

View 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()

View 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
)

View 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"

View 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}
)

View File

@ -0,0 +1 @@
This is a simple text file.

View 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"

View 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
)

View 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"

View 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
)

View 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"

View 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()

File diff suppressed because it is too large Load Diff

View 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()

View 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>

View 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>

View File

@ -0,0 +1 @@
mostly empty

View File

@ -0,0 +1 @@
mostly empty

View File

@ -0,0 +1 @@
this is just so QDir has something to dive into.

View 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
)

View 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

View 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

File diff suppressed because it is too large Load Diff

View File

View File

@ -0,0 +1 @@
a

View File

@ -0,0 +1 @@
aa

View File

@ -0,0 +1 @@
aaa

View File

View File

@ -0,0 +1 @@
aaaaaa

View File

@ -0,0 +1 @@
aaaa

View File

@ -0,0 +1 @@
aaaaa

View File

View File

@ -0,0 +1 @@
aaaaaaaaa

View File

@ -0,0 +1 @@
aaaaaaaa

View File

@ -0,0 +1 @@
aaaaaaa

View File

View File

View File

View 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
)

View 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"

View 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()

View File

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>copy-fallback.qrc</file>
</qresource>
</RCC>

View 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

View File

@ -0,0 +1 @@
A basic file for copying.

File diff suppressed because one or more lines are too long

View 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

View File

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>rename-fallback.qrc</file>
</qresource>
</RCC>

View File

@ -0,0 +1 @@
12345

View 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
)

View 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;
}

View 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.

View 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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
foo

View 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()

File diff suppressed because it is too large Load Diff

View 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
)

Some files were not shown because too many files have changed in this diff Show More