38be0d1383
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
3405 lines
97 KiB
C++
3405 lines
97 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
|
** All rights reserved.
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
**
|
|
** This file is part of the test suite of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
** No Commercial Usage
|
|
** This file contains pre-release code and may not be distributed.
|
|
** You may use this file in accordance with the terms and conditions
|
|
** contained in the Technology Preview License Agreement accompanying
|
|
** this package.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 2.1 as published by the Free Software
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
** packaging of this file. Please review the following information to
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
** If you have questions regarding the use of this file, please contact
|
|
** Nokia at qt-info@nokia.com.
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
|
|
#include <QtTest/QtTest>
|
|
#include <qplatformdefs.h>
|
|
|
|
#include <QAbstractFileEngine>
|
|
#include <QFSFileEngine>
|
|
#include <QCoreApplication>
|
|
#include <QDebug>
|
|
#include <QDir>
|
|
#include <QFile>
|
|
#include <QFileInfo>
|
|
#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
|
|
#include <QHostInfo>
|
|
#endif
|
|
#include <QProcess>
|
|
#ifndef Q_OS_WIN
|
|
# include <sys/types.h>
|
|
# include <unistd.h>
|
|
#endif
|
|
#ifdef Q_OS_MAC
|
|
# include <sys/mount.h>
|
|
#elif defined(Q_OS_LINUX)
|
|
# include <sys/vfs.h>
|
|
#elif defined(Q_OS_FREEBSD)
|
|
# include <sys/param.h>
|
|
# include <sys/mount.h>
|
|
#elif defined(Q_OS_IRIX)
|
|
# include <sys/statfs.h>
|
|
#elif defined(Q_OS_WINCE)
|
|
# include <qplatformdefs.h>
|
|
# include <private/qfsfileengine_p.h>
|
|
#elif defined(Q_OS_SYMBIAN)
|
|
# include <f32file.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include "../network-settings.h"
|
|
|
|
#if defined(Q_OS_SYMBIAN)
|
|
# define SRCDIR ""
|
|
#endif
|
|
|
|
#ifndef STDIN_FILENO
|
|
#define STDIN_FILENO 0
|
|
#endif
|
|
|
|
#ifndef STDOUT_FILENO
|
|
#define STDOUT_FILENO 1
|
|
#endif
|
|
|
|
#ifndef STDERR_FILENO
|
|
#define STDERR_FILENO 2
|
|
#endif
|
|
|
|
#ifndef QT_OPEN_BINARY
|
|
#define QT_OPEN_BINARY 0
|
|
#endif
|
|
|
|
Q_DECLARE_METATYPE(QFile::FileError)
|
|
|
|
//TESTED_CLASS=
|
|
//TESTED_FILES=
|
|
|
|
class tst_QFile : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
tst_QFile();
|
|
virtual ~tst_QFile();
|
|
|
|
|
|
public slots:
|
|
void init();
|
|
void cleanup();
|
|
private slots:
|
|
void initTestCase();
|
|
void cleanupTestCase();
|
|
void exists();
|
|
void open_data();
|
|
void open();
|
|
void openUnbuffered();
|
|
void size_data();
|
|
void size();
|
|
void sizeNoExist();
|
|
void seek();
|
|
void setSize();
|
|
void setSizeSeek();
|
|
void atEnd();
|
|
void readLine();
|
|
void readLine2();
|
|
void readLineNullInLine();
|
|
void readAll_data();
|
|
void readAll();
|
|
void readAllBuffer();
|
|
void readAllStdin();
|
|
void readLineStdin();
|
|
void readLineStdin_lineByLine();
|
|
void text();
|
|
void missingEndOfLine();
|
|
void readBlock();
|
|
void getch();
|
|
void ungetChar();
|
|
void createFile();
|
|
void append();
|
|
void permissions_data();
|
|
void permissions();
|
|
void setPermissions();
|
|
void copy();
|
|
void copyAfterFail();
|
|
void copyRemovesTemporaryFile() const;
|
|
void copyShouldntOverwrite();
|
|
void copyFallback();
|
|
void link();
|
|
void linkToDir();
|
|
void absolutePathLinkToRelativePath();
|
|
void readBrokenLink();
|
|
void readTextFile_data();
|
|
void readTextFile();
|
|
void readTextFile2();
|
|
void writeTextFile_data();
|
|
void writeTextFile();
|
|
/* void largeFileSupport(); */
|
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
|
|
void largeUncFileSupport();
|
|
#endif
|
|
void tailFile();
|
|
void flush();
|
|
void bufferedRead();
|
|
void isSequential();
|
|
void encodeName();
|
|
void truncate();
|
|
void seekToPos();
|
|
void seekAfterEndOfFile();
|
|
void FILEReadWrite();
|
|
void i18nFileName_data();
|
|
void i18nFileName();
|
|
void longFileName_data();
|
|
void longFileName();
|
|
void fileEngineHandler();
|
|
void useQFileInAFileHandler();
|
|
void getCharFF();
|
|
void remove_and_exists();
|
|
void removeOpenFile();
|
|
void fullDisk();
|
|
void writeLargeDataBlock_data();
|
|
void writeLargeDataBlock();
|
|
void readFromWriteOnlyFile();
|
|
void writeToReadOnlyFile();
|
|
void virtualFile();
|
|
void textFile();
|
|
void rename_data();
|
|
void rename();
|
|
void renameWithAtEndSpecialFile() const;
|
|
void renameFallback();
|
|
void renameMultiple();
|
|
void appendAndRead();
|
|
void miscWithUncPathAsCurrentDir();
|
|
void standarderror();
|
|
void handle();
|
|
void nativeHandleLeaks();
|
|
|
|
void readEof_data();
|
|
void readEof();
|
|
|
|
void map_data();
|
|
void map();
|
|
void mapResource_data();
|
|
void mapResource();
|
|
void mapOpenMode_data();
|
|
void mapOpenMode();
|
|
|
|
void openStandardStreams();
|
|
|
|
void resize_data();
|
|
void resize();
|
|
|
|
void objectConstructors();
|
|
#ifdef Q_OS_SYMBIAN
|
|
void platformSecurity_data();
|
|
void platformSecurity();
|
|
#endif
|
|
void caseSensitivity();
|
|
|
|
void autocloseHandle();
|
|
|
|
// --- Task related tests below this line
|
|
void task167217();
|
|
|
|
void openDirectory();
|
|
void writeNothing();
|
|
|
|
public:
|
|
// disabled this test for the moment... it hangs
|
|
void invalidFile_data();
|
|
void invalidFile();
|
|
|
|
private:
|
|
enum FileType {
|
|
OpenQFile,
|
|
OpenFd,
|
|
OpenStream,
|
|
#ifdef Q_OS_SYMBIAN
|
|
OpenRFile,
|
|
#endif
|
|
NumberOfFileTypes
|
|
};
|
|
|
|
void openStandardStreamsFileDescriptors();
|
|
void openStandardStreamsBufferedStreams();
|
|
|
|
bool openFd(QFile &file, QIODevice::OpenMode mode, QFile::FileHandleFlags handleFlags)
|
|
{
|
|
int fdMode = QT_OPEN_LARGEFILE | QT_OPEN_BINARY;
|
|
|
|
// File will be truncated if in Write mode.
|
|
if (mode & QIODevice::WriteOnly)
|
|
fdMode |= QT_OPEN_WRONLY | QT_OPEN_TRUNC;
|
|
if (mode & QIODevice::ReadOnly)
|
|
fdMode |= QT_OPEN_RDONLY;
|
|
|
|
fd_ = QT_OPEN(qPrintable(file.fileName()), fdMode);
|
|
|
|
return (-1 != fd_) && file.open(fd_, mode, handleFlags);
|
|
}
|
|
|
|
bool openStream(QFile &file, QIODevice::OpenMode mode, QFile::FileHandleFlags handleFlags)
|
|
{
|
|
char const *streamMode = "";
|
|
|
|
// File will be truncated if in Write mode.
|
|
if (mode & QIODevice::WriteOnly)
|
|
streamMode = "wb+";
|
|
else if (mode & QIODevice::ReadOnly)
|
|
streamMode = "rb";
|
|
|
|
stream_ = QT_FOPEN(qPrintable(file.fileName()), streamMode);
|
|
|
|
return stream_ && file.open(stream_, mode, handleFlags);
|
|
}
|
|
|
|
#ifdef Q_OS_SYMBIAN
|
|
bool openRFile(QFile &file, QIODevice::OpenMode mode, QFile::FileHandleFlags handleFlags)
|
|
{
|
|
//connect file server first time
|
|
if (!rfs_.Handle() && rfs_.Connect() != KErrNone)
|
|
return false;
|
|
//symbian does not like ./ in filenames, so open by absolute path
|
|
QString fileName(QDir::toNativeSeparators(QFileInfo(file).absoluteFilePath()));
|
|
TPtrC fn(fileName.utf16(), fileName.length());
|
|
TInt smode = 0;
|
|
if (mode & QIODevice::WriteOnly)
|
|
smode |= EFileWrite;
|
|
if (mode & QIODevice::ReadOnly)
|
|
smode |= EFileRead;
|
|
TInt r;
|
|
if ((mode & QIODevice::Truncate) || (!(mode & QIODevice::ReadOnly) && !(mode & QIODevice::Append))) {
|
|
r = rfile_.Replace(rfs_, fn, smode);
|
|
} else {
|
|
r = rfile_.Open(rfs_, fn, smode);
|
|
if (r == KErrNotFound && (mode & QIODevice::WriteOnly)) {
|
|
r = rfile_.Create(rfs_, fn, smode);
|
|
}
|
|
}
|
|
return (r == KErrNone) && file.open(rfile_, mode, handleFlags);
|
|
}
|
|
#endif
|
|
|
|
bool openFile(QFile &file, QIODevice::OpenMode mode, FileType type = OpenQFile, QFile::FileHandleFlags handleFlags = QFile::DontCloseHandle)
|
|
{
|
|
if (mode & QIODevice::WriteOnly && !file.exists())
|
|
{
|
|
// Make sure the file exists
|
|
QFile createFile(file.fileName());
|
|
if (!createFile.open(QIODevice::ReadWrite))
|
|
return false;
|
|
}
|
|
|
|
// Note: openFd and openStream will truncate the file if write mode.
|
|
switch (type)
|
|
{
|
|
case OpenQFile:
|
|
return file.open(mode);
|
|
|
|
case OpenFd:
|
|
return openFd(file, mode, handleFlags);
|
|
|
|
case OpenStream:
|
|
return openStream(file, mode, handleFlags);
|
|
#ifdef Q_OS_SYMBIAN
|
|
case OpenRFile:
|
|
return openRFile(file, mode, handleFlags);
|
|
#endif
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void closeFile(QFile &file)
|
|
{
|
|
file.close();
|
|
|
|
if (-1 != fd_)
|
|
QT_CLOSE(fd_);
|
|
if (stream_)
|
|
::fclose(stream_);
|
|
#ifdef Q_OS_SYMBIAN
|
|
if (rfile_.SubSessionHandle())
|
|
rfile_.Close();
|
|
#endif
|
|
|
|
fd_ = -1;
|
|
stream_ = 0;
|
|
}
|
|
|
|
int fd_;
|
|
FILE *stream_;
|
|
#ifdef Q_OS_SYMBIAN
|
|
RFs rfs_;
|
|
RFile rfile_;
|
|
#endif
|
|
};
|
|
|
|
tst_QFile::tst_QFile()
|
|
{
|
|
}
|
|
|
|
tst_QFile::~tst_QFile()
|
|
{
|
|
|
|
}
|
|
|
|
void tst_QFile::init()
|
|
{
|
|
// TODO: Add initialization code here.
|
|
// This will be executed immediately before each test is run.
|
|
fd_ = -1;
|
|
stream_ = 0;
|
|
}
|
|
|
|
void tst_QFile::cleanup()
|
|
{
|
|
// TODO: Add cleanup code here.
|
|
// This will be executed immediately after each test is run.
|
|
|
|
// for copyFallback()
|
|
if (QFile::exists("file-copy-destination.txt")) {
|
|
QFile::setPermissions("file-copy-destination.txt",
|
|
QFile::ReadOwner | QFile::WriteOwner);
|
|
QFile::remove("file-copy-destination.txt");
|
|
}
|
|
|
|
// for renameFallback()
|
|
QFile::remove("file-rename-destination.txt");
|
|
|
|
// for copyAfterFail()
|
|
QFile::remove("file-to-be-copied.txt");
|
|
QFile::remove("existing-file.txt");
|
|
QFile::remove("copied-file-1.txt");
|
|
QFile::remove("copied-file-2.txt");
|
|
|
|
// for renameMultiple()
|
|
QFile::remove("file-to-be-renamed.txt");
|
|
QFile::remove("existing-file.txt");
|
|
QFile::remove("file-renamed-once.txt");
|
|
QFile::remove("file-renamed-twice.txt");
|
|
|
|
if (-1 != fd_)
|
|
QT_CLOSE(fd_);
|
|
if (stream_)
|
|
::fclose(stream_);
|
|
}
|
|
|
|
void tst_QFile::initTestCase()
|
|
{
|
|
QFile::remove("noreadfile");
|
|
|
|
// create a file and make it read-only
|
|
QFile file("readonlyfile");
|
|
file.open(QFile::WriteOnly);
|
|
file.write("a", 1);
|
|
file.close();
|
|
file.setPermissions(QFile::ReadOwner);
|
|
|
|
// create another file and make it not readable
|
|
file.setFileName("noreadfile");
|
|
file.open(QFile::WriteOnly);
|
|
file.write("b", 1);
|
|
file.close();
|
|
file.setPermissions(0);
|
|
}
|
|
|
|
void tst_QFile::cleanupTestCase()
|
|
{
|
|
// clean up the files we created
|
|
QFile::remove("readonlyfile");
|
|
QFile::remove("noreadfile");
|
|
QFile::remove("myLink.lnk");
|
|
QFile::remove("appendme.txt");
|
|
QFile::remove("createme.txt");
|
|
QFile::remove("file.txt");
|
|
QFile::remove("genfile.txt");
|
|
QFile::remove("seekToPos.txt");
|
|
QFile::remove("setsizeseek.txt");
|
|
QFile::remove("stdfile.txt");
|
|
QFile::remove("textfile.txt");
|
|
QFile::remove("truncate.txt");
|
|
QFile::remove("winfile.txt");
|
|
QFile::remove("writeonlyfile");
|
|
QFile::remove("largeblockfile.txt");
|
|
QFile::remove("tst_qfile_copy.cpp");
|
|
QFile::remove("nullinline.txt");
|
|
QFile::remove("myLink2.lnk");
|
|
QFile::remove("resources");
|
|
QFile::remove("qfile_map_testfile");
|
|
QFile::remove("readAllBuffer.txt");
|
|
QFile::remove("qt_file.tmp");
|
|
QFile::remove("File.txt");
|
|
}
|
|
|
|
//------------------------------------------
|
|
// The 'testfile' is currently just a
|
|
// testfile. The path of this file, the
|
|
// attributes and the contents itself
|
|
// will be changed as far as we have a
|
|
// proper way to handle files in the
|
|
// testing environment.
|
|
//------------------------------------------
|
|
|
|
void tst_QFile::exists()
|
|
{
|
|
QFile f( SRCDIR "testfile.txt" );
|
|
QCOMPARE( f.exists(), (bool)TRUE );
|
|
|
|
QFile file("nobodyhassuchafile");
|
|
file.remove();
|
|
QVERIFY(!file.exists());
|
|
|
|
QFile file2("nobodyhassuchafile");
|
|
QVERIFY(file2.open(QIODevice::WriteOnly));
|
|
file2.close();
|
|
|
|
QVERIFY(file.exists());
|
|
|
|
QVERIFY(file.open(QIODevice::WriteOnly));
|
|
file.close();
|
|
QVERIFY(file.exists());
|
|
|
|
file.remove();
|
|
QVERIFY(!file.exists());
|
|
|
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
|
|
QFile unc("//" + QtNetworkSettings::winServerName() + "/testshare/readme.txt");
|
|
QVERIFY(unc.exists());
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::open_data()
|
|
{
|
|
QTest::addColumn<QString>("filename");
|
|
QTest::addColumn<int>("mode");
|
|
QTest::addColumn<bool>("ok");
|
|
QTest::addColumn<QFile::FileError>("status");
|
|
|
|
#ifdef Q_OS_MAC
|
|
static const QString denied("Operation not permitted");
|
|
#else
|
|
static const QString denied("Permission denied");
|
|
#endif
|
|
QTest::newRow( "exist_readOnly" )
|
|
<< QString(SRCDIR "testfile.txt") << int(QIODevice::ReadOnly)
|
|
<< (bool)TRUE << QFile::NoError;
|
|
|
|
QTest::newRow( "exist_writeOnly" )
|
|
<< QString("readonlyfile")
|
|
<< int(QIODevice::WriteOnly)
|
|
<< (bool)FALSE
|
|
<< QFile::OpenError;
|
|
|
|
QTest::newRow( "exist_append" )
|
|
<< QString("readonlyfile") << int(QIODevice::Append)
|
|
<< (bool)FALSE << QFile::OpenError;
|
|
|
|
QTest::newRow( "nonexist_readOnly" )
|
|
<< QString("nonExist.txt") << int(QIODevice::ReadOnly)
|
|
<< (bool)FALSE << QFile::OpenError;
|
|
|
|
QTest::newRow("emptyfile")
|
|
<< QString("")
|
|
<< int(QIODevice::ReadOnly)
|
|
<< (bool)FALSE
|
|
<< QFile::OpenError;
|
|
|
|
QTest::newRow("nullfile") << QString() << int(QIODevice::ReadOnly) << (bool)FALSE
|
|
<< QFile::OpenError;
|
|
|
|
QTest::newRow("two-dots") << QString(SRCDIR "two.dots.file") << int(QIODevice::ReadOnly) << (bool)TRUE
|
|
<< QFile::NoError;
|
|
|
|
QTest::newRow("readonlyfile") << QString("readonlyfile") << int(QIODevice::WriteOnly)
|
|
<< (bool)FALSE << QFile::OpenError;
|
|
QTest::newRow("noreadfile") << QString("noreadfile") << int(QIODevice::ReadOnly)
|
|
<< (bool)FALSE << QFile::OpenError;
|
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
|
|
QTest::newRow("//./PhysicalDrive0") << QString("//./PhysicalDrive0") << int(QIODevice::ReadOnly)
|
|
<< (bool)TRUE << QFile::NoError;
|
|
QTest::newRow("uncFile") << "//" + QtNetworkSettings::winServerName() + "/testshare/test.pri" << int(QIODevice::ReadOnly)
|
|
<< true << QFile::NoError;
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::open()
|
|
{
|
|
QFETCH( QString, filename );
|
|
QFETCH( int, mode );
|
|
|
|
QFile f( filename );
|
|
|
|
QFETCH( bool, ok );
|
|
|
|
#if defined(Q_OS_SYMBIAN)
|
|
if (qstrcmp(QTest::currentDataTag(), "noreadfile") == 0)
|
|
QSKIP("Symbian does not support non-readable files", SkipSingle);
|
|
#elif defined(Q_OS_UNIX)
|
|
if (::getuid() == 0)
|
|
// root and Chuck Norris don't care for file permissions. Skip.
|
|
QSKIP("Running this test as root doesn't make sense", SkipAll);
|
|
#endif
|
|
|
|
#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
|
|
QEXPECT_FAIL("noreadfile", "Windows does not currently support non-readable files.", Abort);
|
|
#endif
|
|
if (filename.isEmpty())
|
|
QTest::ignoreMessage(QtWarningMsg, "QFSFileEngine::open: No file name specified");
|
|
|
|
QCOMPARE(f.open( QIODevice::OpenMode(mode) ), ok);
|
|
|
|
QTEST( f.error(), "status" );
|
|
}
|
|
|
|
void tst_QFile::openUnbuffered()
|
|
{
|
|
QFile file(SRCDIR "testfile.txt");
|
|
QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Unbuffered));
|
|
char c = '\0';
|
|
QVERIFY(file.seek(1));
|
|
QCOMPARE(file.pos(), qint64(1));
|
|
QVERIFY(file.getChar(&c));
|
|
QCOMPARE(file.pos(), qint64(2));
|
|
char d = '\0';
|
|
QVERIFY(file.seek(3));
|
|
QCOMPARE(file.pos(), qint64(3));
|
|
QVERIFY(file.getChar(&d));
|
|
QCOMPARE(file.pos(), qint64(4));
|
|
QVERIFY(file.seek(1));
|
|
QCOMPARE(file.pos(), qint64(1));
|
|
char c2 = '\0';
|
|
QVERIFY(file.getChar(&c2));
|
|
QCOMPARE(file.pos(), qint64(2));
|
|
QVERIFY(file.seek(3));
|
|
QCOMPARE(file.pos(), qint64(3));
|
|
char d2 = '\0';
|
|
QVERIFY(file.getChar(&d2));
|
|
QCOMPARE(file.pos(), qint64(4));
|
|
QCOMPARE(c, c2);
|
|
QCOMPARE(d, d2);
|
|
QCOMPARE(c, '-');
|
|
QCOMPARE(d, '-');
|
|
}
|
|
|
|
void tst_QFile::size_data()
|
|
{
|
|
QTest::addColumn<QString>("filename");
|
|
QTest::addColumn<qint64>("size");
|
|
|
|
QTest::newRow( "exist01" ) << QString(SRCDIR "testfile.txt") << (qint64)245;
|
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
|
|
// Only test UNC on Windows./
|
|
QTest::newRow("unc") << "//" + QString(QtNetworkSettings::winServerName() + "/testshare/test.pri") << (qint64)34;
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::size()
|
|
{
|
|
QFETCH( QString, filename );
|
|
QFETCH( qint64, size );
|
|
|
|
#ifdef Q_WS_WINCE
|
|
filename = QFileInfo(filename).absoluteFilePath();
|
|
#endif
|
|
|
|
{
|
|
QFile f( filename );
|
|
QCOMPARE( f.size(), size );
|
|
|
|
QVERIFY( f.open(QIODevice::ReadOnly) );
|
|
QCOMPARE( f.size(), size );
|
|
}
|
|
|
|
{
|
|
QFile f;
|
|
FILE* stream = QT_FOPEN(filename.toLocal8Bit().constData(), "rb");
|
|
QVERIFY( stream );
|
|
QVERIFY( f.open(stream, QIODevice::ReadOnly) );
|
|
QCOMPARE( f.size(), size );
|
|
|
|
f.close();
|
|
fclose(stream);
|
|
}
|
|
|
|
{
|
|
#ifdef Q_WS_WINCE
|
|
QSKIP("Currently low level file I/O not well supported on Windows CE", SkipSingle);
|
|
#endif
|
|
QFile f;
|
|
|
|
int fd = QT_OPEN(filename.toLocal8Bit().constData(), QT_OPEN_RDONLY);
|
|
|
|
QVERIFY( fd != -1 );
|
|
QVERIFY( f.open(fd, QIODevice::ReadOnly) );
|
|
QCOMPARE( f.size(), size );
|
|
|
|
f.close();
|
|
QT_CLOSE(fd);
|
|
}
|
|
}
|
|
|
|
void tst_QFile::sizeNoExist()
|
|
{
|
|
QFile file("nonexist01");
|
|
QVERIFY( !file.exists() );
|
|
QCOMPARE( file.size(), (qint64)0 );
|
|
QVERIFY( !file.open(QIODevice::ReadOnly) );
|
|
}
|
|
|
|
void tst_QFile::seek()
|
|
{
|
|
QFile::remove("newfile.txt");
|
|
QFile file("newfile.txt");
|
|
file.open(QIODevice::WriteOnly);
|
|
QCOMPARE(file.size(), qint64(0));
|
|
QCOMPARE(file.pos(), qint64(0));
|
|
QVERIFY(file.seek(10));
|
|
QCOMPARE(file.pos(), qint64(10));
|
|
QCOMPARE(file.size(), qint64(0));
|
|
file.close();
|
|
QFile::remove("newfile.txt");
|
|
}
|
|
|
|
void tst_QFile::setSize()
|
|
{
|
|
DEPENDS_ON( "size" );
|
|
|
|
if ( QFile::exists( "createme.txt" ) )
|
|
QFile::remove( "createme.txt" );
|
|
QVERIFY( !QFile::exists( "createme.txt" ) );
|
|
|
|
QFile f("createme.txt");
|
|
QVERIFY(f.open(QIODevice::Truncate | QIODevice::ReadWrite));
|
|
f.putChar('a');
|
|
|
|
f.seek(0);
|
|
char c = '\0';
|
|
f.getChar(&c);
|
|
QCOMPARE(c, 'a');
|
|
|
|
QCOMPARE(f.size(), (qlonglong)1);
|
|
bool ok = f.resize(99);
|
|
QVERIFY(ok);
|
|
QCOMPARE(f.size(), (qlonglong)99);
|
|
|
|
f.seek(0);
|
|
c = '\0';
|
|
f.getChar(&c);
|
|
QCOMPARE(c, 'a');
|
|
|
|
QVERIFY(f.resize(1));
|
|
QCOMPARE(f.size(), (qlonglong)1);
|
|
|
|
f.seek(0);
|
|
c = '\0';
|
|
f.getChar(&c);
|
|
QCOMPARE(c, 'a');
|
|
|
|
f.close();
|
|
|
|
QCOMPARE(f.size(), (qlonglong)1);
|
|
QVERIFY(f.resize(100));
|
|
QCOMPARE(f.size(), (qlonglong)100);
|
|
QVERIFY(f.resize(50));
|
|
QCOMPARE(f.size(), (qlonglong)50);
|
|
}
|
|
|
|
void tst_QFile::setSizeSeek()
|
|
{
|
|
QFile::remove("setsizeseek.txt");
|
|
QFile f("setsizeseek.txt");
|
|
QVERIFY(f.open(QFile::WriteOnly));
|
|
f.write("ABCD");
|
|
|
|
QCOMPARE(f.pos(), qint64(4));
|
|
f.resize(2);
|
|
QCOMPARE(f.pos(), qint64(2));
|
|
f.resize(4);
|
|
QCOMPARE(f.pos(), qint64(2));
|
|
f.resize(0);
|
|
QCOMPARE(f.pos(), qint64(0));
|
|
f.resize(4);
|
|
QCOMPARE(f.pos(), qint64(0));
|
|
|
|
f.seek(3);
|
|
QCOMPARE(f.pos(), qint64(3));
|
|
f.resize(2);
|
|
QCOMPARE(f.pos(), qint64(2));
|
|
}
|
|
|
|
void tst_QFile::atEnd()
|
|
{
|
|
QFile f( SRCDIR "testfile.txt" );
|
|
QVERIFY(f.open( QIODevice::ReadOnly ));
|
|
|
|
int size = f.size();
|
|
f.seek( size );
|
|
|
|
bool end = f.atEnd();
|
|
f.close();
|
|
QCOMPARE( end, (bool)TRUE );
|
|
}
|
|
|
|
void tst_QFile::readLine()
|
|
{
|
|
QFile f( SRCDIR "testfile.txt" );
|
|
QVERIFY(f.open( QIODevice::ReadOnly ));
|
|
|
|
int i = 0;
|
|
char p[128];
|
|
int foo;
|
|
while ( (foo=f.readLine( p, 128 )) > 0 ) {
|
|
++i;
|
|
if ( i == 5 ) {
|
|
QCOMPARE( p[0], 'T' );
|
|
QCOMPARE( p[3], 's' );
|
|
QCOMPARE( p[11], 'i' );
|
|
}
|
|
}
|
|
f.close();
|
|
QCOMPARE( i, 6 );
|
|
}
|
|
|
|
void tst_QFile::readLine2()
|
|
{
|
|
QFile f( SRCDIR "testfile.txt" );
|
|
f.open( QIODevice::ReadOnly );
|
|
|
|
char p[128];
|
|
QCOMPARE(f.readLine(p, 60), qlonglong(59));
|
|
QCOMPARE(f.readLine(p, 60), qlonglong(59));
|
|
memset(p, '@', sizeof(p));
|
|
QCOMPARE(f.readLine(p, 60), qlonglong(59));
|
|
|
|
QCOMPARE(p[57], '-');
|
|
QCOMPARE(p[58], '\n');
|
|
QCOMPARE(p[59], '\0');
|
|
QCOMPARE(p[60], '@');
|
|
}
|
|
|
|
void tst_QFile::readLineNullInLine()
|
|
{
|
|
QFile::remove("nullinline.txt");
|
|
QFile file("nullinline.txt");
|
|
QVERIFY(file.open(QIODevice::ReadWrite));
|
|
QVERIFY(file.write("linewith\0null\nanotherline\0withnull\n\0\nnull\0", 42) > 0);
|
|
QVERIFY(file.flush());
|
|
file.reset();
|
|
|
|
QCOMPARE(file.readLine(), QByteArray("linewith\0null\n", 14));
|
|
QCOMPARE(file.readLine(), QByteArray("anotherline\0withnull\n", 21));
|
|
QCOMPARE(file.readLine(), QByteArray("\0\n", 2));
|
|
QCOMPARE(file.readLine(), QByteArray("null\0", 5));
|
|
QCOMPARE(file.readLine(), QByteArray());
|
|
}
|
|
|
|
void tst_QFile::readAll_data()
|
|
{
|
|
QTest::addColumn<bool>("textMode");
|
|
QTest::addColumn<QString>("fileName");
|
|
QTest::newRow( "TextMode unixfile" ) << true << SRCDIR "testfile.txt";
|
|
QTest::newRow( "BinaryMode unixfile" ) << false << SRCDIR "testfile.txt";
|
|
QTest::newRow( "TextMode dosfile" ) << true << SRCDIR "dosfile.txt";
|
|
QTest::newRow( "BinaryMode dosfile" ) << false << SRCDIR "dosfile.txt";
|
|
QTest::newRow( "TextMode bigfile" ) << true << SRCDIR "tst_qfile.cpp";
|
|
QTest::newRow( "BinaryMode bigfile" ) << false << SRCDIR "tst_qfile.cpp";
|
|
QVERIFY(QFile(SRCDIR "tst_qfile.cpp").size() > 64*1024);
|
|
}
|
|
|
|
void tst_QFile::readAll()
|
|
{
|
|
QFETCH( bool, textMode );
|
|
QFETCH( QString, fileName );
|
|
|
|
QFile file(fileName);
|
|
if (textMode)
|
|
QVERIFY(file.open(QFile::Text | QFile::ReadOnly));
|
|
else
|
|
QVERIFY(file.open(QFile::ReadOnly));
|
|
|
|
QByteArray a = file.readAll();
|
|
file.reset();
|
|
QVERIFY(file.pos() == 0);
|
|
|
|
QVERIFY(file.bytesAvailable() > 7);
|
|
QByteArray b = file.read(1);
|
|
char x;
|
|
file.getChar(&x);
|
|
b.append(x);
|
|
b.append(file.read(5));
|
|
b.append(file.readAll());
|
|
|
|
QCOMPARE(a, b);
|
|
}
|
|
|
|
void tst_QFile::readAllBuffer()
|
|
{
|
|
QString fileName = QLatin1String("readAllBuffer.txt");
|
|
|
|
QFile::remove(fileName);
|
|
|
|
QFile writer(fileName);
|
|
QFile reader(fileName);
|
|
|
|
QByteArray data1("This is arguably a very simple text.");
|
|
QByteArray data2("This is surely not as simple a test.");
|
|
|
|
QVERIFY( writer.open(QIODevice::ReadWrite | QIODevice::Unbuffered) );
|
|
QVERIFY( reader.open(QIODevice::ReadOnly) );
|
|
|
|
QCOMPARE( writer.write(data1), qint64(data1.size()) );
|
|
QVERIFY( writer.seek(0) );
|
|
|
|
QByteArray result;
|
|
result = reader.read(18);
|
|
QCOMPARE( result.size(), 18 );
|
|
|
|
QCOMPARE( writer.write(data2), qint64(data2.size()) ); // new data, old version buffered in reader
|
|
QCOMPARE( writer.write(data2), qint64(data2.size()) ); // new data, unbuffered in reader
|
|
|
|
result += reader.readAll();
|
|
|
|
QCOMPARE( result, data1 + data2 );
|
|
|
|
QFile::remove(fileName);
|
|
}
|
|
|
|
void tst_QFile::readAllStdin()
|
|
{
|
|
#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
|
|
QSKIP("Currently no stdin/out supported for Windows CE or Symbian", SkipAll);
|
|
#endif
|
|
#if defined(QT_NO_PROCESS)
|
|
QSKIP("Qt was compiled with QT_NO_PROCESS", SkipAll);
|
|
#else
|
|
QByteArray lotsOfData(1024, '@'); // 10 megs
|
|
|
|
QProcess process;
|
|
process.start("stdinprocess/stdinprocess all");
|
|
QVERIFY( process.waitForStarted() );
|
|
for (int i = 0; i < 5; ++i) {
|
|
QTest::qWait(1000);
|
|
process.write(lotsOfData);
|
|
while (process.bytesToWrite() > 0) {
|
|
QVERIFY(process.waitForBytesWritten());
|
|
}
|
|
}
|
|
|
|
process.closeWriteChannel();
|
|
process.waitForFinished();
|
|
QCOMPARE(process.readAll().size(), lotsOfData.size() * 5);
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::readLineStdin()
|
|
{
|
|
#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
|
|
QSKIP("Currently no stdin/out supported for Windows CE or Symbian", SkipAll);
|
|
#endif
|
|
#if defined(QT_NO_PROCESS)
|
|
QSKIP("Qt was compiled with QT_NO_PROCESS", SkipAll);
|
|
#else
|
|
|
|
QByteArray lotsOfData(1024, '@'); // 10 megs
|
|
for (int i = 0; i < lotsOfData.size(); ++i) {
|
|
if ((i % 32) == 31)
|
|
lotsOfData[i] = '\n';
|
|
else
|
|
lotsOfData[i] = char('0' + i % 32);
|
|
}
|
|
|
|
for (int i = 0; i < 2; ++i) {
|
|
QProcess process;
|
|
process.start(QString("stdinprocess/stdinprocess line %1").arg(i), QIODevice::Text | QIODevice::ReadWrite);
|
|
for (int i = 0; i < 5; ++i) {
|
|
QTest::qWait(1000);
|
|
process.write(lotsOfData);
|
|
while (process.bytesToWrite() > 0) {
|
|
QVERIFY(process.waitForBytesWritten());
|
|
}
|
|
}
|
|
|
|
process.closeWriteChannel();
|
|
QVERIFY(process.waitForFinished(5000));
|
|
|
|
QByteArray array = process.readAll();
|
|
QCOMPARE(array.size(), lotsOfData.size() * 5);
|
|
for (int i = 0; i < array.size(); ++i) {
|
|
if ((i % 32) == 31)
|
|
QCOMPARE(char(array[i]), '\n');
|
|
else
|
|
QCOMPARE(char(array[i]), char('0' + i % 32));
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::readLineStdin_lineByLine()
|
|
{
|
|
#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
|
|
QSKIP("Currently no stdin/out supported for Windows CE", SkipAll);
|
|
#endif
|
|
#if defined(QT_NO_PROCESS)
|
|
QSKIP("Qt was compiled with QT_NO_PROCESS", SkipAll);
|
|
#else
|
|
for (int i = 0; i < 2; ++i) {
|
|
QProcess process;
|
|
process.start(QString("stdinprocess/stdinprocess line %1").arg(i), QIODevice::Text | QIODevice::ReadWrite);
|
|
QVERIFY(process.waitForStarted());
|
|
|
|
for (int j = 0; j < 3; ++j) {
|
|
QByteArray line = "line " + QByteArray::number(j) + "\n";
|
|
QCOMPARE(process.write(line), qint64(line.size()));
|
|
QVERIFY(process.waitForBytesWritten(2000));
|
|
if (process.bytesAvailable() == 0)
|
|
QVERIFY(process.waitForReadyRead(2000));
|
|
QCOMPARE(process.readAll(), line);
|
|
}
|
|
|
|
process.closeWriteChannel();
|
|
QVERIFY(process.waitForFinished(5000));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::text()
|
|
{
|
|
// dosfile.txt is a binary CRLF file
|
|
QFile file(SRCDIR "dosfile.txt");
|
|
QVERIFY(file.open(QFile::Text | QFile::ReadOnly));
|
|
QCOMPARE(file.readLine(),
|
|
QByteArray("/dev/system/root / reiserfs acl,user_xattr 1 1\n"));
|
|
QCOMPARE(file.readLine(),
|
|
QByteArray("/dev/sda1 /boot ext3 acl,user_xattr 1 2\n"));
|
|
file.ungetChar('\n');
|
|
file.ungetChar('2');
|
|
QCOMPARE(file.readLine().constData(), QByteArray("2\n").constData());
|
|
}
|
|
|
|
void tst_QFile::missingEndOfLine()
|
|
{
|
|
QFile file(SRCDIR "noendofline.txt");
|
|
QVERIFY(file.open(QFile::ReadOnly));
|
|
|
|
int nlines = 0;
|
|
while (!file.atEnd()) {
|
|
++nlines;
|
|
file.readLine();
|
|
}
|
|
|
|
QCOMPARE(nlines, 3);
|
|
}
|
|
|
|
void tst_QFile::readBlock()
|
|
{
|
|
QFile f( SRCDIR "testfile.txt" );
|
|
f.open( QIODevice::ReadOnly );
|
|
|
|
int length = 0;
|
|
char p[256];
|
|
length = f.read( p, 256 );
|
|
f.close();
|
|
QCOMPARE( length, 245 );
|
|
QCOMPARE( p[59], 'D' );
|
|
QCOMPARE( p[178], 'T' );
|
|
QCOMPARE( p[199], 'l' );
|
|
}
|
|
|
|
void tst_QFile::getch()
|
|
{
|
|
QFile f( SRCDIR "testfile.txt" );
|
|
f.open( QIODevice::ReadOnly );
|
|
|
|
char c;
|
|
int i = 0;
|
|
while (f.getChar(&c)) {
|
|
QCOMPARE(f.pos(), qint64(i + 1));
|
|
if ( i == 59 )
|
|
QCOMPARE( c, 'D' );
|
|
++i;
|
|
}
|
|
f.close();
|
|
QCOMPARE( i, 245 );
|
|
}
|
|
|
|
void tst_QFile::ungetChar()
|
|
{
|
|
QFile f(SRCDIR "testfile.txt");
|
|
QVERIFY(f.open(QIODevice::ReadOnly));
|
|
|
|
QByteArray array = f.readLine();
|
|
QCOMPARE(array.constData(), "----------------------------------------------------------\n");
|
|
f.ungetChar('\n');
|
|
|
|
array = f.readLine();
|
|
QCOMPARE(array.constData(), "\n");
|
|
|
|
f.ungetChar('\n');
|
|
f.ungetChar('-');
|
|
f.ungetChar('-');
|
|
|
|
array = f.readLine();
|
|
QCOMPARE(array.constData(), "--\n");
|
|
|
|
QFile::remove("genfile.txt");
|
|
QFile out("genfile.txt");
|
|
QVERIFY(out.open(QIODevice::ReadWrite));
|
|
out.write("123");
|
|
out.seek(0);
|
|
QCOMPARE(out.readAll().constData(), "123");
|
|
out.ungetChar('3');
|
|
out.write("4");
|
|
out.seek(0);
|
|
QCOMPARE(out.readAll().constData(), "124");
|
|
out.ungetChar('4');
|
|
out.ungetChar('2');
|
|
out.ungetChar('1');
|
|
char buf[3];
|
|
QCOMPARE(out.read(buf, sizeof(buf)), qint64(3));
|
|
QCOMPARE(buf[0], '1');
|
|
QCOMPARE(buf[1], '2');
|
|
QCOMPARE(buf[2], '4');
|
|
}
|
|
|
|
void tst_QFile::invalidFile_data()
|
|
{
|
|
QTest::addColumn<QString>("fileName");
|
|
#if !defined(Q_WS_WIN) && !defined(Q_OS_SYMBIAN)
|
|
QTest::newRow( "x11" ) << QString( "qwe//" );
|
|
#else
|
|
QTest::newRow( "colon1" ) << QString( "fail:invalid" );
|
|
QTest::newRow( "colon2" ) << QString( "f:ail:invalid" );
|
|
QTest::newRow( "colon3" ) << QString( ":failinvalid" );
|
|
QTest::newRow( "forwardslash" ) << QString( "fail/invalid" );
|
|
QTest::newRow( "asterisk" ) << QString( "fail*invalid" );
|
|
QTest::newRow( "questionmark" ) << QString( "fail?invalid" );
|
|
QTest::newRow( "quote" ) << QString( "fail\"invalid" );
|
|
QTest::newRow( "lt" ) << QString( "fail<invalid" );
|
|
QTest::newRow( "gt" ) << QString( "fail>invalid" );
|
|
QTest::newRow( "pipe" ) << QString( "fail|invalid" );
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::invalidFile()
|
|
{
|
|
QFETCH( QString, fileName );
|
|
QFile f( fileName );
|
|
QVERIFY( !f.open( QIODevice::ReadWrite ) );
|
|
}
|
|
|
|
void tst_QFile::createFile()
|
|
{
|
|
if ( QFile::exists( "createme.txt" ) )
|
|
QFile::remove( "createme.txt" );
|
|
QVERIFY( !QFile::exists( "createme.txt" ) );
|
|
|
|
QFile f( "createme.txt" );
|
|
QVERIFY( f.open( QIODevice::WriteOnly ) );
|
|
f.close();
|
|
QVERIFY( QFile::exists( "createme.txt" ) );
|
|
}
|
|
|
|
void tst_QFile::append()
|
|
{
|
|
const QString name("appendme.txt");
|
|
if (QFile::exists(name))
|
|
QFile::remove(name);
|
|
QVERIFY(!QFile::exists(name));
|
|
|
|
QFile f(name);
|
|
QVERIFY(f.open(QIODevice::WriteOnly | QIODevice::Truncate));
|
|
f.putChar('a');
|
|
f.close();
|
|
|
|
QVERIFY(f.open(QIODevice::Append));
|
|
QVERIFY(f.pos() == 1);
|
|
f.putChar('a');
|
|
f.close();
|
|
QCOMPARE(int(f.size()), 2);
|
|
}
|
|
|
|
void tst_QFile::permissions_data()
|
|
{
|
|
QTest::addColumn<QString>("file");
|
|
QTest::addColumn<uint>("perms");
|
|
QTest::addColumn<bool>("expected");
|
|
|
|
QTest::newRow("data0") << QCoreApplication::instance()->applicationFilePath() << uint(QFile::ExeUser) << true;
|
|
QTest::newRow("data1") << SRCDIR "tst_qfile.cpp" << uint(QFile::ReadUser) << true;
|
|
// QTest::newRow("data2") << "tst_qfile.cpp" << int(QFile::WriteUser) << false;
|
|
QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << uint(QFile::ReadUser) << true;
|
|
QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1" << uint(QFile::WriteUser) << false;
|
|
QTest::newRow("resource3") << ":/tst_qfileinfo/resources/file1.ext1" << uint(QFile::ExeUser) << false;
|
|
}
|
|
|
|
void tst_QFile::permissions()
|
|
{
|
|
#if defined(Q_OS_SYMBIAN)
|
|
if (qstrcmp(QTest::currentDataTag(), "data0") == 0)
|
|
QSKIP("Symbian does not have execution permissions", SkipSingle);
|
|
#endif
|
|
QFETCH(QString, file);
|
|
QFETCH(uint, perms);
|
|
QFETCH(bool, expected);
|
|
QFile f(file);
|
|
QCOMPARE(((f.permissions() & perms) == QFile::Permissions(perms)), expected);
|
|
QCOMPARE(((QFile::permissions(file) & perms) == QFile::Permissions(perms)), expected);
|
|
}
|
|
|
|
void tst_QFile::setPermissions()
|
|
{
|
|
DEPENDS_ON( "permissions" ); //if that doesn't work...
|
|
|
|
if ( QFile::exists( "createme.txt" ) )
|
|
QFile::remove( "createme.txt" );
|
|
QVERIFY( !QFile::exists( "createme.txt" ) );
|
|
|
|
QFile f("createme.txt");
|
|
QVERIFY(f.open(QIODevice::WriteOnly | QIODevice::Truncate));
|
|
f.putChar('a');
|
|
f.close();
|
|
|
|
QFile::Permissions perms(QFile::WriteUser | QFile::ReadUser);
|
|
QVERIFY(f.setPermissions(perms));
|
|
QVERIFY((f.permissions() & perms) == perms);
|
|
|
|
}
|
|
|
|
void tst_QFile::copy()
|
|
{
|
|
QFile::setPermissions("tst_qfile_copy.cpp", QFile::WriteUser);
|
|
QFile::remove("tst_qfile_copy.cpp");
|
|
QFile::remove("test2");
|
|
QVERIFY(QFile::copy(SRCDIR "tst_qfile.cpp", "tst_qfile_copy.cpp"));
|
|
QFile in1(SRCDIR "tst_qfile.cpp"), in2("tst_qfile_copy.cpp");
|
|
QVERIFY(in1.open(QFile::ReadOnly));
|
|
QVERIFY(in2.open(QFile::ReadOnly));
|
|
QByteArray data1 = in1.readAll(), data2 = in2.readAll();
|
|
QCOMPARE(data1, data2);
|
|
QFile::remove( "main_copy.cpp" );
|
|
|
|
QFile::copy(QDir::currentPath(), QDir::currentPath() + QLatin1String("/test2"));
|
|
}
|
|
|
|
void tst_QFile::copyAfterFail()
|
|
{
|
|
QFile file1("file-to-be-copied.txt");
|
|
QFile file2("existing-file.txt");
|
|
|
|
QVERIFY(file1.open(QIODevice::ReadWrite) && "(test-precondition)");
|
|
QVERIFY(file2.open(QIODevice::ReadWrite) && "(test-precondition)");
|
|
file2.close();
|
|
QVERIFY(!QFile::exists("copied-file-1.txt") && "(test-precondition)");
|
|
QVERIFY(!QFile::exists("copied-file-2.txt") && "(test-precondition)");
|
|
|
|
QVERIFY(!file1.copy("existing-file.txt"));
|
|
QCOMPARE(file1.error(), QFile::CopyError);
|
|
|
|
QVERIFY(file1.copy("copied-file-1.txt"));
|
|
QVERIFY(!file1.isOpen());
|
|
QCOMPARE(file1.error(), QFile::NoError);
|
|
|
|
QVERIFY(!file1.copy("existing-file.txt"));
|
|
QCOMPARE(file1.error(), QFile::CopyError);
|
|
|
|
QVERIFY(file1.copy("copied-file-2.txt"));
|
|
QVERIFY(!file1.isOpen());
|
|
QCOMPARE(file1.error(), QFile::NoError);
|
|
|
|
QVERIFY(QFile::exists("copied-file-1.txt"));
|
|
QVERIFY(QFile::exists("copied-file-2.txt"));
|
|
|
|
QVERIFY(QFile::remove("file-to-be-copied.txt") && "(test-cleanup)");
|
|
QVERIFY(QFile::remove("existing-file.txt") && "(test-cleanup)");
|
|
QVERIFY(QFile::remove("copied-file-1.txt") && "(test-cleanup)");
|
|
QVERIFY(QFile::remove("copied-file-2.txt") && "(test-cleanup)");
|
|
}
|
|
|
|
void tst_QFile::copyRemovesTemporaryFile() const
|
|
{
|
|
const QString newName(QLatin1String("copyRemovesTemporaryFile"));
|
|
QVERIFY(QFile::copy(SRCDIR "forCopying.txt", newName));
|
|
|
|
QVERIFY(!QFile::exists(QLatin1String( SRCDIR "qt_temp.XXXXXX")));
|
|
QVERIFY(QFile::remove(newName));
|
|
}
|
|
|
|
void tst_QFile::copyShouldntOverwrite()
|
|
{
|
|
// Copy should not overwrite existing files.
|
|
QFile::remove("tst_qfile.cpy");
|
|
QFile file(SRCDIR "tst_qfile.cpp");
|
|
QVERIFY(file.copy("tst_qfile.cpy"));
|
|
#if defined(Q_OS_SYMBIAN)
|
|
bool ok = QFile::setPermissions("tst_qfile.cpy", QFile::WriteUser);
|
|
#else
|
|
bool ok = QFile::setPermissions("tst_qfile.cpy", QFile::WriteOther);
|
|
#endif
|
|
QVERIFY(ok);
|
|
QVERIFY(!file.copy("tst_qfile.cpy"));
|
|
QFile::remove("tst_qfile.cpy");
|
|
}
|
|
|
|
void tst_QFile::copyFallback()
|
|
{
|
|
// Using a resource file to trigger QFile::copy's fallback handling
|
|
QFile file(":/copy-fallback.qrc");
|
|
QFile::remove("file-copy-destination.txt");
|
|
|
|
QVERIFY2(file.exists(), "test precondition");
|
|
QVERIFY2(!QFile::exists("file-copy-destination.txt"), "test precondition");
|
|
|
|
// Fallback copy of closed file.
|
|
QVERIFY(file.copy("file-copy-destination.txt"));
|
|
QVERIFY(QFile::exists("file-copy-destination.txt"));
|
|
QVERIFY(!file.isOpen());
|
|
|
|
#ifdef Q_WS_WINCE
|
|
// Need to reset permissions on Windows to be able to delete
|
|
QVERIFY(QFile::setPermissions("file-copy-destination.txt",
|
|
QFile::WriteOther));
|
|
#else
|
|
// Need to reset permissions on Windows to be able to delete
|
|
QVERIFY(QFile::setPermissions("file-copy-destination.txt",
|
|
QFile::ReadOwner | QFile::WriteOwner));
|
|
#endif
|
|
QVERIFY(QFile::remove("file-copy-destination.txt"));
|
|
|
|
// Fallback copy of open file.
|
|
QVERIFY(file.open(QIODevice::ReadOnly));
|
|
QVERIFY(file.copy("file-copy-destination.txt"));
|
|
QVERIFY(QFile::exists("file-copy-destination.txt"));
|
|
QVERIFY(!file.isOpen());
|
|
|
|
file.close();
|
|
QFile::remove("file-copy-destination.txt");
|
|
}
|
|
|
|
#ifdef Q_OS_WIN
|
|
#include <objbase.h>
|
|
#include <shlobj.h>
|
|
#endif
|
|
|
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
|
|
static QString getWorkingDirectoryForLink(const QString &linkFileName)
|
|
{
|
|
bool neededCoInit = false;
|
|
QString ret;
|
|
|
|
IShellLink *psl;
|
|
HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
|
|
if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized
|
|
neededCoInit = true;
|
|
CoInitialize(NULL);
|
|
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
|
|
}
|
|
|
|
if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface.
|
|
IPersistFile *ppf;
|
|
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
|
|
if (SUCCEEDED(hres)) {
|
|
hres = ppf->Load((LPOLESTR)linkFileName.utf16(), STGM_READ);
|
|
//The original path of the link is retrieved. If the file/folder
|
|
//was moved, the return value still have the old path.
|
|
if(SUCCEEDED(hres)) {
|
|
wchar_t szGotPath[MAX_PATH];
|
|
if (psl->GetWorkingDirectory(szGotPath, MAX_PATH) == NOERROR)
|
|
ret = QString::fromWCharArray(szGotPath);
|
|
}
|
|
ppf->Release();
|
|
}
|
|
psl->Release();
|
|
}
|
|
|
|
if (neededCoInit) {
|
|
CoUninitialize();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
void tst_QFile::link()
|
|
{
|
|
#if defined(Q_OS_SYMBIAN)
|
|
QSKIP("Symbian does not support links", SkipAll);
|
|
#endif
|
|
QFile::remove("myLink.lnk");
|
|
|
|
QFileInfo info1(SRCDIR "tst_qfile.cpp");
|
|
QString referenceTarget = QDir::cleanPath(info1.absoluteFilePath());
|
|
|
|
QVERIFY(QFile::link(SRCDIR "tst_qfile.cpp", "myLink.lnk"));
|
|
|
|
QFileInfo info2("myLink.lnk");
|
|
QVERIFY(info2.isSymLink());
|
|
QCOMPARE(info2.symLinkTarget(), referenceTarget);
|
|
|
|
QFile link("myLink.lnk");
|
|
QVERIFY(link.open(QIODevice::ReadOnly));
|
|
QCOMPARE(link.symLinkTarget(), referenceTarget);
|
|
link.close();
|
|
|
|
QCOMPARE(QFile::symLinkTarget("myLink.lnk"), referenceTarget);
|
|
|
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
|
|
QString wd = getWorkingDirectoryForLink(info2.absoluteFilePath());
|
|
QCOMPARE(QDir::fromNativeSeparators(wd), QDir::cleanPath(info1.absolutePath()));
|
|
#endif
|
|
|
|
QVERIFY(QFile::remove(info2.absoluteFilePath()));
|
|
}
|
|
|
|
void tst_QFile::linkToDir()
|
|
{
|
|
#if defined(Q_OS_SYMBIAN)
|
|
QSKIP("Symbian does not support linking to directories", SkipAll);
|
|
#endif
|
|
QFile::remove("myLinkToDir.lnk");
|
|
QDir dir;
|
|
dir.mkdir("myDir");
|
|
QFileInfo info1("myDir");
|
|
QVERIFY(QFile::link("myDir", "myLinkToDir.lnk"));
|
|
QFileInfo info2("myLinkToDir.lnk");
|
|
#if !(defined Q_OS_HPUX && defined(__ia64))
|
|
// absurd HP-UX filesystem bug on gravlaks - checking if a symlink
|
|
// resolves or not alters the file system to make the broken symlink
|
|
// later fail...
|
|
QVERIFY(info2.isSymLink());
|
|
#endif
|
|
QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath());
|
|
QVERIFY(QFile::remove(info2.absoluteFilePath()));
|
|
QFile::remove("myLinkToDir.lnk");
|
|
dir.rmdir("myDir");
|
|
}
|
|
|
|
void tst_QFile::absolutePathLinkToRelativePath()
|
|
{
|
|
#if defined(Q_OS_SYMBIAN)
|
|
QSKIP("Symbian does not support links", SkipAll);
|
|
#endif
|
|
QFile::remove("myDir/test.txt");
|
|
QFile::remove("myDir/myLink.lnk");
|
|
QDir dir;
|
|
dir.mkdir("myDir");
|
|
QFile("myDir/test.txt").open(QFile::WriteOnly);
|
|
|
|
#ifdef Q_OS_WIN
|
|
QVERIFY(QFile::link("test.txt", "myDir/myLink.lnk"));
|
|
#else
|
|
QVERIFY(QFile::link("myDir/test.txt", "myDir/myLink.lnk"));
|
|
#endif
|
|
QEXPECT_FAIL("", "Symlinking using relative paths is currently different on Windows and Unix/Symbian", Continue);
|
|
QCOMPARE(QFileInfo(QFile(QFileInfo("myDir/myLink.lnk").absoluteFilePath()).symLinkTarget()).absoluteFilePath(),
|
|
QFileInfo("myDir/test.txt").absoluteFilePath());
|
|
|
|
QFile::remove("myDir/test.txt");
|
|
QFile::remove("myDir/myLink.lnk");
|
|
dir.rmdir("myDir");
|
|
}
|
|
|
|
void tst_QFile::readBrokenLink()
|
|
{
|
|
#if defined(Q_OS_SYMBIAN)
|
|
QSKIP("Symbian does not support links", SkipAll);
|
|
#endif
|
|
QFile::remove("myLink2.lnk");
|
|
QFileInfo info1("file12");
|
|
#if defined(Q_OS_SYMBIAN)
|
|
// In Symbian can't link to nonexisting file directly, so create the file temporarily
|
|
QFile tempFile("file12");
|
|
tempFile.open(QIODevice::WriteOnly);
|
|
tempFile.link("myLink2.lnk");
|
|
tempFile.remove();
|
|
#else
|
|
QVERIFY(QFile::link("file12", "myLink2.lnk"));
|
|
#endif
|
|
QFileInfo info2("myLink2.lnk");
|
|
QVERIFY(info2.isSymLink());
|
|
QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath());
|
|
QVERIFY(QFile::remove(info2.absoluteFilePath()));
|
|
|
|
#if !defined(Q_OS_SYMBIAN)
|
|
QVERIFY(QFile::link("ole/..", "myLink2.lnk"));
|
|
QCOMPARE(QFileInfo("myLink2.lnk").symLinkTarget(), QDir::currentPath());
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::readTextFile_data()
|
|
{
|
|
QTest::addColumn<QByteArray>("in");
|
|
QTest::addColumn<QByteArray>("out");
|
|
|
|
QTest::newRow("empty") << QByteArray() << QByteArray();
|
|
QTest::newRow("a") << QByteArray("a") << QByteArray("a");
|
|
QTest::newRow("a\\rb") << QByteArray("a\rb") << QByteArray("ab");
|
|
QTest::newRow("\\n") << QByteArray("\n") << QByteArray("\n");
|
|
QTest::newRow("\\r\\n") << QByteArray("\r\n") << QByteArray("\n");
|
|
QTest::newRow("\\r") << QByteArray("\r") << QByteArray();
|
|
QTest::newRow("twolines") << QByteArray("Hello\r\nWorld\r\n") << QByteArray("Hello\nWorld\n");
|
|
QTest::newRow("twolines no endline") << QByteArray("Hello\r\nWorld") << QByteArray("Hello\nWorld");
|
|
}
|
|
|
|
void tst_QFile::readTextFile()
|
|
{
|
|
QFETCH(QByteArray, in);
|
|
QFETCH(QByteArray, out);
|
|
|
|
QFile winfile("winfile.txt");
|
|
QVERIFY(winfile.open(QFile::WriteOnly | QFile::Truncate));
|
|
winfile.write(in);
|
|
winfile.close();
|
|
|
|
QVERIFY(winfile.open(QFile::ReadOnly));
|
|
QCOMPARE(winfile.readAll(), in);
|
|
winfile.close();
|
|
|
|
QVERIFY(winfile.open(QFile::ReadOnly | QFile::Text));
|
|
QCOMPARE(winfile.readAll(), out);
|
|
}
|
|
|
|
void tst_QFile::readTextFile2()
|
|
{
|
|
{
|
|
QFile file(SRCDIR "testlog.txt");
|
|
QVERIFY(file.open(QIODevice::ReadOnly));
|
|
file.read(4097);
|
|
}
|
|
|
|
{
|
|
QFile file(SRCDIR "testlog.txt");
|
|
QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
|
|
file.read(4097);
|
|
}
|
|
}
|
|
|
|
void tst_QFile::writeTextFile_data()
|
|
{
|
|
QTest::addColumn<QByteArray>("in");
|
|
|
|
QTest::newRow("empty") << QByteArray();
|
|
QTest::newRow("a") << QByteArray("a");
|
|
QTest::newRow("a\\rb") << QByteArray("a\rb");
|
|
QTest::newRow("\\n") << QByteArray("\n");
|
|
QTest::newRow("\\r\\n") << QByteArray("\r\n");
|
|
QTest::newRow("\\r") << QByteArray("\r");
|
|
QTest::newRow("twolines crlf") << QByteArray("Hello\r\nWorld\r\n");
|
|
QTest::newRow("twolines crlf no endline") << QByteArray("Hello\r\nWorld");
|
|
QTest::newRow("twolines lf") << QByteArray("Hello\nWorld\n");
|
|
QTest::newRow("twolines lf no endline") << QByteArray("Hello\nWorld");
|
|
QTest::newRow("mixed") << QByteArray("this\nis\r\na\nmixed\r\nfile\n");
|
|
}
|
|
|
|
void tst_QFile::writeTextFile()
|
|
{
|
|
QFETCH(QByteArray, in);
|
|
|
|
QFile file("textfile.txt");
|
|
QVERIFY(file.open(QFile::WriteOnly | QFile::Truncate | QFile::Text));
|
|
QByteArray out = in;
|
|
#ifdef Q_OS_WIN
|
|
out.replace('\n', "\r\n");
|
|
#endif
|
|
QCOMPARE(file.write(in), qlonglong(in.size()));
|
|
file.close();
|
|
|
|
file.open(QFile::ReadOnly);
|
|
QCOMPARE(file.readAll(), out);
|
|
}
|
|
|
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
|
|
void tst_QFile::largeUncFileSupport()
|
|
{
|
|
qint64 size = Q_INT64_C(8589934592);
|
|
qint64 dataOffset = Q_INT64_C(8589914592);
|
|
QByteArray knownData("LargeFile content at offset 8589914592");
|
|
QString largeFile("//" + QtNetworkSettings::winServerName() + "/testsharelargefile/file.bin");
|
|
|
|
{
|
|
// 1) Native file handling.
|
|
QFile file(largeFile);
|
|
QCOMPARE(file.size(), size);
|
|
QVERIFY(file.open(QIODevice::ReadOnly));
|
|
QCOMPARE(file.size(), size);
|
|
QVERIFY(file.seek(dataOffset));
|
|
QCOMPARE(file.read(knownData.size()), knownData);
|
|
}
|
|
{
|
|
// 2) stdlib file handling.
|
|
#if _MSC_VER <= 1310
|
|
QSKIP("platform SDK for MSVC 2003 does not support large files", SkipAll);
|
|
#endif
|
|
QFile file;
|
|
FILE *fh = fopen(QFile::encodeName(largeFile).data(), "rb");
|
|
QVERIFY(file.open(fh, QIODevice::ReadOnly));
|
|
QCOMPARE(file.size(), size);
|
|
QVERIFY(file.seek(dataOffset));
|
|
QCOMPARE(file.read(knownData.size()), knownData);
|
|
fclose(fh);
|
|
}
|
|
{
|
|
// 3) stdio file handling.
|
|
QFile file;
|
|
FILE *fh = fopen(QFile::encodeName(largeFile).data(), "rb");
|
|
int fd = int(_fileno(fh));
|
|
QVERIFY(file.open(fd, QIODevice::ReadOnly));
|
|
QCOMPARE(file.size(), size);
|
|
QVERIFY(file.seek(dataOffset));
|
|
QCOMPARE(file.read(knownData.size()), knownData);
|
|
fclose(fh);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void tst_QFile::tailFile()
|
|
{
|
|
QSKIP("File change notifications are so far unsupported.", SkipAll);
|
|
|
|
QFile file("tail.txt");
|
|
QVERIFY(file.open(QFile::WriteOnly | QFile::Append));
|
|
|
|
QFile tailFile("tail.txt");
|
|
QVERIFY(tailFile.open(QFile::ReadOnly));
|
|
tailFile.seek(file.size());
|
|
|
|
QSignalSpy readSignal(&tailFile, SIGNAL(readyRead()));
|
|
|
|
file.write("", 1);
|
|
|
|
QTestEventLoop::instance().enterLoop(5);
|
|
|
|
QVERIFY(!QTestEventLoop::instance().timeout());
|
|
QCOMPARE(readSignal.count(), 1);
|
|
}
|
|
|
|
void tst_QFile::flush()
|
|
{
|
|
QString fileName("stdfile.txt");
|
|
|
|
QFile::remove(fileName);
|
|
|
|
{
|
|
QFile file(fileName);
|
|
QVERIFY(file.open(QFile::WriteOnly));
|
|
QCOMPARE(file.write("abc", 3),qint64(3));
|
|
}
|
|
|
|
{
|
|
QFile file(fileName);
|
|
QVERIFY(file.open(QFile::WriteOnly | QFile::Append));
|
|
QCOMPARE(file.pos(), qlonglong(3));
|
|
QCOMPARE(file.write("def", 3), qlonglong(3));
|
|
QCOMPARE(file.pos(), qlonglong(6));
|
|
}
|
|
|
|
{
|
|
QFile file("stdfile.txt");
|
|
QVERIFY(file.open(QFile::ReadOnly));
|
|
QCOMPARE(file.readAll(), QByteArray("abcdef"));
|
|
}
|
|
|
|
QFile::remove(fileName);
|
|
}
|
|
|
|
void tst_QFile::bufferedRead()
|
|
{
|
|
QFile::remove("stdfile.txt");
|
|
|
|
QFile file("stdfile.txt");
|
|
QVERIFY(file.open(QFile::WriteOnly));
|
|
file.write("abcdef");
|
|
file.close();
|
|
|
|
#if defined(Q_OS_WINCE)
|
|
FILE *stdFile = fopen((QCoreApplication::applicationDirPath() + "/stdfile.txt").toAscii() , "r");
|
|
#else
|
|
FILE *stdFile = fopen("stdfile.txt", "r");
|
|
#endif
|
|
QVERIFY(stdFile);
|
|
char c;
|
|
QCOMPARE(int(fread(&c, 1, 1, stdFile)), 1);
|
|
QCOMPARE(c, 'a');
|
|
QCOMPARE(int(ftell(stdFile)), 1);
|
|
|
|
{
|
|
QFile file;
|
|
QVERIFY(file.open(stdFile, QFile::ReadOnly));
|
|
QCOMPARE(file.pos(), qlonglong(1));
|
|
QCOMPARE(file.read(&c, 1), qlonglong(1));
|
|
QCOMPARE(c, 'b');
|
|
QCOMPARE(file.pos(), qlonglong(2));
|
|
}
|
|
|
|
fclose(stdFile);
|
|
}
|
|
|
|
void tst_QFile::isSequential()
|
|
{
|
|
#if defined (Q_OS_WIN) || defined(Q_OS_SYMBIAN)
|
|
QSKIP("Unix only test.", SkipAll);
|
|
#endif
|
|
|
|
QFile zero("/dev/null");
|
|
QVERIFY(zero.open(QFile::ReadOnly));
|
|
QVERIFY(zero.isSequential());
|
|
}
|
|
|
|
void tst_QFile::encodeName()
|
|
{
|
|
QCOMPARE(QFile::encodeName(QString::null), QByteArray());
|
|
}
|
|
|
|
void tst_QFile::truncate()
|
|
{
|
|
for (int i = 0; i < 2; ++i) {
|
|
QFile file("truncate.txt");
|
|
QVERIFY(file.open(QFile::WriteOnly));
|
|
file.write(QByteArray(200, '@'));
|
|
file.close();
|
|
|
|
QVERIFY(file.open((i ? QFile::WriteOnly : QFile::ReadWrite) | QFile::Truncate));
|
|
file.write(QByteArray(100, '$'));
|
|
file.close();
|
|
|
|
QVERIFY(file.open(QFile::ReadOnly));
|
|
QCOMPARE(file.readAll(), QByteArray(100, '$'));
|
|
}
|
|
}
|
|
|
|
void tst_QFile::seekToPos()
|
|
{
|
|
{
|
|
QFile file("seekToPos.txt");
|
|
QVERIFY(file.open(QFile::WriteOnly));
|
|
file.write("a\r\nb\r\nc\r\n");
|
|
file.flush();
|
|
}
|
|
|
|
QFile file("seekToPos.txt");
|
|
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
|
|
file.seek(1);
|
|
char c;
|
|
QVERIFY(file.getChar(&c));
|
|
QCOMPARE(c, '\n');
|
|
|
|
QCOMPARE(file.pos(), qint64(3));
|
|
file.seek(file.pos());
|
|
QCOMPARE(file.pos(), qint64(3));
|
|
|
|
file.seek(1);
|
|
file.seek(file.pos());
|
|
QCOMPARE(file.pos(), qint64(1));
|
|
|
|
}
|
|
|
|
void tst_QFile::seekAfterEndOfFile()
|
|
{
|
|
QLatin1String filename("seekAfterEof.dat");
|
|
QFile::remove(filename);
|
|
{
|
|
QFile file(filename);
|
|
QVERIFY(file.open(QFile::WriteOnly));
|
|
file.write("abcd");
|
|
QCOMPARE(file.size(), qint64(4));
|
|
file.seek(8);
|
|
file.write("ijkl");
|
|
QCOMPARE(file.size(), qint64(12));
|
|
file.seek(4);
|
|
file.write("efgh");
|
|
QCOMPARE(file.size(), qint64(12));
|
|
file.seek(16);
|
|
file.write("----");
|
|
QCOMPARE(file.size(), qint64(20));
|
|
file.flush();
|
|
}
|
|
|
|
QFile file(filename);
|
|
QVERIFY(file.open(QFile::ReadOnly));
|
|
QByteArray contents = file.readAll();
|
|
QCOMPARE(contents.left(12), QByteArray("abcdefghijkl", 12));
|
|
//bytes 12-15 are uninitialised so we don't care what they read as.
|
|
QCOMPARE(contents.mid(16), QByteArray("----", 4));
|
|
file.close();
|
|
QFile::remove(filename);
|
|
}
|
|
|
|
void tst_QFile::FILEReadWrite()
|
|
{
|
|
// Tests modifying a file. First creates it then reads in 4 bytes and then overwrites these
|
|
// 4 bytes with new values. At the end check to see the file contains the new values.
|
|
|
|
QFile::remove("FILEReadWrite.txt");
|
|
|
|
// create test file
|
|
{
|
|
QFile f("FILEReadWrite.txt");
|
|
QVERIFY(f.open(QFile::WriteOnly));
|
|
QDataStream ds(&f);
|
|
qint8 c = 0;
|
|
ds << c;
|
|
c = 1;
|
|
ds << c;
|
|
c = 2;
|
|
ds << c;
|
|
c = 3;
|
|
ds << c;
|
|
c = 4;
|
|
ds << c;
|
|
c = 5;
|
|
ds << c;
|
|
c = 6;
|
|
ds << c;
|
|
c = 7;
|
|
ds << c;
|
|
c = 8;
|
|
ds << c;
|
|
c = 9;
|
|
ds << c;
|
|
c = 10;
|
|
ds << c;
|
|
c = 11;
|
|
ds << c;
|
|
f.close();
|
|
}
|
|
|
|
#ifdef Q_OS_WINCE
|
|
FILE *fp = fopen(qPrintable(QCoreApplication::applicationDirPath() + "\\FILEReadWrite.txt"), "r+b");
|
|
#else
|
|
FILE *fp = fopen("FILEReadWrite.txt", "r+b");
|
|
#endif
|
|
QVERIFY(fp);
|
|
QFile file;
|
|
QVERIFY(file.open(fp, QFile::ReadWrite));
|
|
QDataStream sfile(&file) ;
|
|
|
|
qint8 var1,var2,var3,var4;
|
|
while (!sfile.atEnd())
|
|
{
|
|
qint64 base = file.pos();
|
|
|
|
QCOMPARE(file.pos(), base + 0);
|
|
sfile >> var1;
|
|
QCOMPARE(file.pos(), base + 1);
|
|
file.flush(); // flushing should not change the base
|
|
QCOMPARE(file.pos(), base + 1);
|
|
sfile >> var2;
|
|
QCOMPARE(file.pos(), base + 2);
|
|
sfile >> var3;
|
|
QCOMPARE(file.pos(), base + 3);
|
|
sfile >> var4;
|
|
QCOMPARE(file.pos(), base + 4);
|
|
file.seek(file.pos() - 4) ; // Move it back 4, for we are going to write new values based on old ones
|
|
QCOMPARE(file.pos(), base + 0);
|
|
sfile << qint8(var1 + 5);
|
|
QCOMPARE(file.pos(), base + 1);
|
|
sfile << qint8(var2 + 5);
|
|
QCOMPARE(file.pos(), base + 2);
|
|
sfile << qint8(var3 + 5);
|
|
QCOMPARE(file.pos(), base + 3);
|
|
sfile << qint8(var4 + 5);
|
|
QCOMPARE(file.pos(), base + 4);
|
|
|
|
}
|
|
file.close();
|
|
fclose(fp);
|
|
|
|
// check modified file
|
|
{
|
|
QFile f("FILEReadWrite.txt");
|
|
QVERIFY(f.open(QFile::ReadOnly));
|
|
QDataStream ds(&f);
|
|
qint8 c = 0;
|
|
ds >> c;
|
|
QCOMPARE(c, (qint8)5);
|
|
ds >> c;
|
|
QCOMPARE(c, (qint8)6);
|
|
ds >> c;
|
|
QCOMPARE(c, (qint8)7);
|
|
ds >> c;
|
|
QCOMPARE(c, (qint8)8);
|
|
ds >> c;
|
|
QCOMPARE(c, (qint8)9);
|
|
ds >> c;
|
|
QCOMPARE(c, (qint8)10);
|
|
ds >> c;
|
|
QCOMPARE(c, (qint8)11);
|
|
ds >> c;
|
|
QCOMPARE(c, (qint8)12);
|
|
ds >> c;
|
|
QCOMPARE(c, (qint8)13);
|
|
ds >> c;
|
|
QCOMPARE(c, (qint8)14);
|
|
ds >> c;
|
|
QCOMPARE(c, (qint8)15);
|
|
ds >> c;
|
|
QCOMPARE(c, (qint8)16);
|
|
f.close();
|
|
}
|
|
|
|
QFile::remove("FILEReadWrite.txt");
|
|
}
|
|
|
|
|
|
/*
|
|
#include <qglobal.h>
|
|
#define BUFFSIZE 1
|
|
#define FILESIZE 0x10000000f
|
|
void tst_QFile::largeFileSupport()
|
|
{
|
|
#ifdef Q_OS_SOLARIS
|
|
QSKIP("Solaris does not support statfs", SkipAll);
|
|
#else
|
|
qlonglong sizeNeeded = 2147483647;
|
|
sizeNeeded *= 2;
|
|
sizeNeeded += 1024;
|
|
qlonglong freespace = qlonglong(0);
|
|
#ifdef Q_WS_WIN
|
|
_ULARGE_INTEGER free;
|
|
if (::GetDiskFreeSpaceEx((wchar_t*)QDir::currentPath().utf16(), &free, 0, 0))
|
|
freespace = free.QuadPart;
|
|
if (freespace != 0) {
|
|
#elif defined(Q_OS_IRIX)
|
|
struct statfs info;
|
|
if (statfs(QDir::currentPath().local8Bit(), &info, sizeof(struct statfs), 0) == 0) {
|
|
freespace = qlonglong(info.f_bfree * info.f_bsize);
|
|
#else
|
|
struct statfs info;
|
|
if (statfs(const_cast<char *>(QDir::currentPath().toLocal8Bit().constData()), &info) == 0) {
|
|
freespace = qlonglong(info.f_bavail * info.f_bsize);
|
|
#endif
|
|
if (freespace > sizeNeeded) {
|
|
QFile bigFile("bigfile");
|
|
if (bigFile.open(QFile::ReadWrite)) {
|
|
char c[BUFFSIZE] = {'a'};
|
|
QVERIFY(bigFile.write(c, BUFFSIZE) == BUFFSIZE);
|
|
qlonglong oldPos = bigFile.pos();
|
|
QVERIFY(bigFile.resize(sizeNeeded));
|
|
QCOMPARE(oldPos, bigFile.pos());
|
|
QVERIFY(bigFile.seek(sizeNeeded - BUFFSIZE));
|
|
QVERIFY(bigFile.write(c, BUFFSIZE) == BUFFSIZE);
|
|
|
|
bigFile.close();
|
|
if (bigFile.open(QFile::ReadOnly)) {
|
|
QVERIFY(bigFile.read(c, BUFFSIZE) == BUFFSIZE);
|
|
int i = 0;
|
|
for (i=0; i<BUFFSIZE; i++)
|
|
QCOMPARE(c[i], 'a');
|
|
QVERIFY(bigFile.seek(sizeNeeded - BUFFSIZE));
|
|
QVERIFY(bigFile.read(c, BUFFSIZE) == BUFFSIZE);
|
|
for (i=0; i<BUFFSIZE; i++)
|
|
QCOMPARE(c[i], 'a');
|
|
bigFile.close();
|
|
QVERIFY(bigFile.remove());
|
|
} else {
|
|
QVERIFY(bigFile.remove());
|
|
QFAIL("Could not reopen file");
|
|
}
|
|
} else {
|
|
QFAIL("Could not open file");
|
|
}
|
|
} else {
|
|
QSKIP("Not enough space to run test", SkipSingle);
|
|
}
|
|
} else {
|
|
QFAIL("Could not determin disk space");
|
|
}
|
|
#endif
|
|
}
|
|
*/
|
|
|
|
void tst_QFile::i18nFileName_data()
|
|
{
|
|
QTest::addColumn<QString>("fileName");
|
|
|
|
QTest::newRow( "01" ) << QString::fromUtf8("xxxxxxx.txt");
|
|
}
|
|
|
|
void tst_QFile::i18nFileName()
|
|
{
|
|
QFETCH(QString, fileName);
|
|
if (QFile::exists(fileName)) {
|
|
QVERIFY(QFile::remove(fileName));
|
|
}
|
|
{
|
|
QFile file(fileName);
|
|
QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
|
|
QTextStream ts(&file);
|
|
ts.setCodec("UTF-8");
|
|
ts << fileName << endl;
|
|
}
|
|
{
|
|
QFile file(fileName);
|
|
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
|
|
QTextStream ts(&file);
|
|
ts.setCodec("UTF-8");
|
|
QString line = ts.readLine();
|
|
QCOMPARE(line, fileName);
|
|
}
|
|
QVERIFY(QFile::remove(fileName));
|
|
}
|
|
|
|
|
|
void tst_QFile::longFileName_data()
|
|
{
|
|
QTest::addColumn<QString>("fileName");
|
|
|
|
QTest::newRow( "16 chars" ) << QString::fromLatin1("longFileName.txt");
|
|
QTest::newRow( "52 chars" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName.txt");
|
|
QTest::newRow( "148 chars" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName.txt");
|
|
QTest::newRow( "244 chars" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName.txt");
|
|
QTest::newRow( "244 chars to absolutepath" ) << QFileInfo(QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName.txt")).absoluteFilePath();
|
|
/* needs to be put on a windows 2000 > test machine
|
|
QTest::newRow( "244 chars on UNC" ) << QString::fromLatin1("//arsia/D/troll/tmp/longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName"
|
|
"longFileNamelongFileNamelongFileNamelongFileName.txt");*/
|
|
}
|
|
|
|
void tst_QFile::longFileName()
|
|
{
|
|
QFETCH(QString, fileName);
|
|
if (QFile::exists(fileName)) {
|
|
QVERIFY(QFile::remove(fileName));
|
|
}
|
|
{
|
|
QFile file(fileName);
|
|
#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
|
|
QEXPECT_FAIL("244 chars", "Full pathname must be less than 260 chars", Abort);
|
|
QEXPECT_FAIL("244 chars to absolutepath", "Full pathname must be less than 260 chars", Abort);
|
|
#endif
|
|
QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
|
|
QTextStream ts(&file);
|
|
ts << fileName << endl;
|
|
}
|
|
{
|
|
QFile file(fileName);
|
|
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
|
|
QTextStream ts(&file);
|
|
QString line = ts.readLine();
|
|
QCOMPARE(line, fileName);
|
|
}
|
|
QString newName = fileName + QLatin1String("1");
|
|
{
|
|
QVERIFY(QFile::copy(fileName, newName));
|
|
QFile file(newName);
|
|
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
|
|
QTextStream ts(&file);
|
|
QString line = ts.readLine();
|
|
QCOMPARE(line, fileName);
|
|
|
|
}
|
|
QVERIFY(QFile::remove(newName));
|
|
{
|
|
QVERIFY(QFile::rename(fileName, newName));
|
|
QFile file(newName);
|
|
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
|
|
QTextStream ts(&file);
|
|
QString line = ts.readLine();
|
|
QCOMPARE(line, fileName);
|
|
}
|
|
QVERIFY(QFile::exists(newName));
|
|
QVERIFY(QFile::remove(newName));
|
|
}
|
|
|
|
class MyEngine : public QAbstractFileEngine
|
|
{
|
|
public:
|
|
MyEngine(int n) { number = n; }
|
|
virtual ~MyEngine() {}
|
|
|
|
void setFileName(const QString &) {}
|
|
bool open(int ) { return false; }
|
|
bool close() { return false; }
|
|
bool flush() { return false; }
|
|
qint64 size() const { return 123 + number; }
|
|
qint64 at() const { return -1; }
|
|
bool seek(qint64) { return false; }
|
|
bool isSequential() const { return false; }
|
|
qint64 read(char *, qint64) { return -1; }
|
|
qint64 write(const char *, qint64) { return -1; }
|
|
bool remove() { return false; }
|
|
bool copy(const QString &) { return false; }
|
|
bool rename(const QString &) { return false; }
|
|
bool link(const QString &) { return false; }
|
|
bool mkdir(const QString &, bool) const { return false; }
|
|
bool rmdir(const QString &, bool) const { return false; }
|
|
bool setSize(qint64) { return false; }
|
|
QStringList entryList(QDir::Filters, const QStringList &) const { return QStringList(); }
|
|
bool caseSensitive() const { return false; }
|
|
bool isRelativePath() const { return false; }
|
|
FileFlags fileFlags(FileFlags) const { return 0; }
|
|
bool chmod(uint) { return false; }
|
|
QString fileName(FileName) const { return name; }
|
|
uint ownerId(FileOwner) const { return 0; }
|
|
QString owner(FileOwner) const { return QString(); }
|
|
QDateTime fileTime(FileTime) const { return QDateTime(); }
|
|
|
|
private:
|
|
int number;
|
|
QString name;
|
|
};
|
|
|
|
class MyHandler : public QAbstractFileEngineHandler
|
|
{
|
|
public:
|
|
inline QAbstractFileEngine *create(const QString &) const
|
|
{
|
|
return new MyEngine(1);
|
|
}
|
|
};
|
|
|
|
class MyHandler2 : public QAbstractFileEngineHandler
|
|
{
|
|
public:
|
|
inline QAbstractFileEngine *create(const QString &) const
|
|
{
|
|
return new MyEngine(2);
|
|
}
|
|
};
|
|
|
|
void tst_QFile::fileEngineHandler()
|
|
{
|
|
// A file that does not exist has a size of 0.
|
|
QFile::remove("ole.bull");
|
|
QFile file("ole.bull");
|
|
QCOMPARE(file.size(), qint64(0));
|
|
|
|
// Instantiating our handler will enable the new engine.
|
|
MyHandler handler;
|
|
file.setFileName("ole.bull");
|
|
QCOMPARE(file.size(), qint64(124));
|
|
|
|
// A new, identical handler should take preference over the last one.
|
|
MyHandler2 handler2;
|
|
file.setFileName("ole.bull");
|
|
QCOMPARE(file.size(), qint64(125));
|
|
|
|
}
|
|
|
|
class MyRecursiveHandler : public QAbstractFileEngineHandler
|
|
{
|
|
public:
|
|
inline QAbstractFileEngine *create(const QString &fileName) const
|
|
{
|
|
if (fileName.startsWith(":!")) {
|
|
QDir dir;
|
|
QString realFile = SRCDIR + fileName.mid(2);
|
|
if (dir.exists(realFile))
|
|
return new QFSFileEngine(realFile);
|
|
}
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
void tst_QFile::useQFileInAFileHandler()
|
|
{
|
|
// This test should not dead-lock
|
|
MyRecursiveHandler handler;
|
|
QFile file(":!tst_qfile.cpp");
|
|
QVERIFY(file.exists());
|
|
}
|
|
|
|
void tst_QFile::getCharFF()
|
|
{
|
|
QFile file("file.txt");
|
|
file.open(QFile::ReadWrite);
|
|
file.write("\xff\xff\xff");
|
|
file.flush();
|
|
file.seek(0);
|
|
|
|
char c;
|
|
QVERIFY(file.getChar(&c));
|
|
QVERIFY(file.getChar(&c));
|
|
QVERIFY(file.getChar(&c));
|
|
}
|
|
|
|
void tst_QFile::remove_and_exists()
|
|
{
|
|
QFile::remove("tull_i_grunn.txt");
|
|
QFile f("tull_i_grunn.txt");
|
|
|
|
QVERIFY(!f.exists());
|
|
|
|
bool opened = f.open(QIODevice::WriteOnly);
|
|
QVERIFY(opened);
|
|
|
|
f.write(QString("testing that remove/exists work...").toLatin1());
|
|
f.close();
|
|
|
|
QVERIFY(f.exists());
|
|
|
|
f.remove();
|
|
QVERIFY(!f.exists());
|
|
}
|
|
|
|
void tst_QFile::removeOpenFile()
|
|
{
|
|
{
|
|
// remove an opened, write-only file
|
|
QFile::remove("remove_unclosed.txt");
|
|
QFile f("remove_unclosed.txt");
|
|
|
|
QVERIFY(!f.exists());
|
|
bool opened = f.open(QIODevice::WriteOnly);
|
|
QVERIFY(opened);
|
|
f.write(QString("testing that remove closes the file first...").toLatin1());
|
|
|
|
bool removed = f.remove(); // remove should both close and remove the file
|
|
QVERIFY(removed);
|
|
QVERIFY(!f.isOpen());
|
|
QVERIFY(!f.exists());
|
|
QVERIFY(f.error() == QFile::NoError);
|
|
}
|
|
|
|
{
|
|
// remove an opened, read-only file
|
|
QFile::remove("remove_unclosed.txt");
|
|
|
|
// first, write a file that we can remove
|
|
{
|
|
QFile f("remove_unclosed.txt");
|
|
QVERIFY(!f.exists());
|
|
bool opened = f.open(QIODevice::WriteOnly);
|
|
QVERIFY(opened);
|
|
f.write(QString("testing that remove closes the file first...").toLatin1());
|
|
f.close();
|
|
}
|
|
|
|
QFile f("remove_unclosed.txt");
|
|
bool opened = f.open(QIODevice::ReadOnly);
|
|
QVERIFY(opened);
|
|
f.readAll();
|
|
// this used to only fail on FreeBSD (and Mac OS X)
|
|
QVERIFY(f.flush());
|
|
bool removed = f.remove(); // remove should both close and remove the file
|
|
QVERIFY(removed);
|
|
QVERIFY(!f.isOpen());
|
|
QVERIFY(!f.exists());
|
|
QVERIFY(f.error() == QFile::NoError);
|
|
}
|
|
}
|
|
|
|
void tst_QFile::fullDisk()
|
|
{
|
|
QFile file("/dev/full");
|
|
if (!file.exists())
|
|
QSKIP("/dev/full doesn't exist on this system", SkipAll);
|
|
|
|
QVERIFY(file.open(QIODevice::WriteOnly));
|
|
file.write("foobar", 6);
|
|
|
|
QVERIFY(!file.flush());
|
|
QCOMPARE(file.error(), QFile::ResourceError);
|
|
QVERIFY(!file.flush());
|
|
QCOMPARE(file.error(), QFile::ResourceError);
|
|
|
|
char c = 0;
|
|
file.write(&c, 0);
|
|
QVERIFY(!file.flush());
|
|
QCOMPARE(file.error(), QFile::ResourceError);
|
|
QCOMPARE(file.write(&c, 1), qint64(1));
|
|
QVERIFY(!file.flush());
|
|
QCOMPARE(file.error(), QFile::ResourceError);
|
|
|
|
file.close();
|
|
QVERIFY(!file.isOpen());
|
|
QCOMPARE(file.error(), QFile::ResourceError);
|
|
|
|
file.open(QIODevice::WriteOnly);
|
|
QCOMPARE(file.error(), QFile::NoError);
|
|
QVERIFY(file.flush()); // Shouldn't inherit write buffer
|
|
file.close();
|
|
QCOMPARE(file.error(), QFile::NoError);
|
|
|
|
// try again without flush:
|
|
QVERIFY(file.open(QIODevice::WriteOnly));
|
|
file.write("foobar", 6);
|
|
file.close();
|
|
QVERIFY(file.error() != QFile::NoError);
|
|
}
|
|
|
|
void tst_QFile::writeLargeDataBlock_data()
|
|
{
|
|
QTest::addColumn<QString>("fileName");
|
|
QTest::addColumn<int>("type");
|
|
|
|
QTest::newRow("localfile-QFile") << "./largeblockfile.txt" << (int)OpenQFile;
|
|
QTest::newRow("localfile-Fd") << "./largeblockfile.txt" << (int)OpenFd;
|
|
QTest::newRow("localfile-Stream") << "./largeblockfile.txt" << (int)OpenStream;
|
|
#ifdef Q_OS_SYMBIAN
|
|
QTest::newRow("localfile-RFile") << "./largeblockfile.txt" << (int)OpenRFile;
|
|
#endif
|
|
|
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
|
|
// Some semi-randomness to avoid collisions.
|
|
QTest::newRow("unc file")
|
|
<< QString("//" + QtNetworkSettings::winServerName() + "/TESTSHAREWRITABLE/largefile-%1-%2.txt")
|
|
.arg(QHostInfo::localHostName())
|
|
.arg(QTime::currentTime().msec()) << (int)OpenQFile;
|
|
#endif
|
|
}
|
|
|
|
static QByteArray getLargeDataBlock()
|
|
{
|
|
static QByteArray array;
|
|
|
|
if (array.isNull())
|
|
{
|
|
#if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
|
|
int resizeSize = 1024 * 1024; // WinCE and Symbian do not have much space
|
|
#else
|
|
int resizeSize = 64 * 1024 * 1024;
|
|
#endif
|
|
array.resize(resizeSize);
|
|
for (int i = 0; i < array.size(); ++i)
|
|
array[i] = uchar(i);
|
|
}
|
|
|
|
return array;
|
|
}
|
|
|
|
void tst_QFile::writeLargeDataBlock()
|
|
{
|
|
QFETCH(QString, fileName);
|
|
QFETCH( int, type );
|
|
|
|
QByteArray const originalData = getLargeDataBlock();
|
|
|
|
{
|
|
QFile file(fileName);
|
|
|
|
QVERIFY2( openFile(file, QIODevice::WriteOnly, (FileType)type),
|
|
qPrintable(QString("Couldn't open file for writing: [%1]").arg(fileName)) );
|
|
QCOMPARE( file.write(originalData), (qint64)originalData.size() );
|
|
QVERIFY( file.flush() );
|
|
|
|
closeFile(file);
|
|
}
|
|
|
|
QByteArray readData;
|
|
|
|
{
|
|
QFile file(fileName);
|
|
|
|
QVERIFY2( openFile(file, QIODevice::ReadOnly, (FileType)type),
|
|
qPrintable(QString("Couldn't open file for reading: [%1]").arg(fileName)) );
|
|
readData = file.readAll();
|
|
closeFile(file);
|
|
}
|
|
|
|
QCOMPARE( readData, originalData );
|
|
QVERIFY( QFile::remove(fileName) );
|
|
}
|
|
|
|
void tst_QFile::readFromWriteOnlyFile()
|
|
{
|
|
QFile file("writeonlyfile");
|
|
QVERIFY(file.open(QFile::WriteOnly));
|
|
char c;
|
|
QTest::ignoreMessage(QtWarningMsg, "QIODevice::read: WriteOnly device");
|
|
QCOMPARE(file.read(&c, 1), qint64(-1));
|
|
}
|
|
|
|
void tst_QFile::writeToReadOnlyFile()
|
|
{
|
|
QFile file("readonlyfile");
|
|
QVERIFY(file.open(QFile::ReadOnly));
|
|
char c = 0;
|
|
QTest::ignoreMessage(QtWarningMsg, "QIODevice::write: ReadOnly device");
|
|
QCOMPARE(file.write(&c, 1), qint64(-1));
|
|
}
|
|
|
|
void tst_QFile::virtualFile()
|
|
{
|
|
// test if QFile works with virtual files
|
|
QString fname;
|
|
#if defined(Q_OS_LINUX)
|
|
fname = "/proc/self/maps";
|
|
#elif defined(Q_OS_AIX)
|
|
fname = QString("/proc/%1/map").arg(getpid());
|
|
#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
|
|
fname = "/proc/curproc/map";
|
|
#else
|
|
QSKIP("This platform does not have 0-sized virtual files", SkipAll);
|
|
#endif
|
|
|
|
// consistency check
|
|
QFileInfo fi(fname);
|
|
QVERIFY(fi.exists());
|
|
QVERIFY(fi.isFile());
|
|
QCOMPARE(fi.size(), Q_INT64_C(0));
|
|
|
|
// open the file
|
|
QFile f(fname);
|
|
QVERIFY(f.open(QIODevice::ReadOnly));
|
|
QCOMPARE(f.size(), Q_INT64_C(0));
|
|
QVERIFY(f.atEnd());
|
|
|
|
// read data
|
|
QByteArray data = f.read(16);
|
|
QCOMPARE(data.size(), 16);
|
|
QCOMPARE(f.pos(), Q_INT64_C(16));
|
|
|
|
// line-reading
|
|
data = f.readLine();
|
|
QVERIFY(!data.isEmpty());
|
|
|
|
// read all:
|
|
data = f.readAll();
|
|
QVERIFY(f.pos() != 0);
|
|
QVERIFY(!data.isEmpty());
|
|
|
|
// seeking
|
|
QVERIFY(f.seek(1));
|
|
QCOMPARE(f.pos(), Q_INT64_C(1));
|
|
}
|
|
|
|
void tst_QFile::textFile()
|
|
{
|
|
#if defined(Q_OS_WINCE)
|
|
FILE *fs = ::fopen((QCoreApplication::applicationDirPath() + "/writeabletextfile").toAscii() , "wt");
|
|
#elif defined(Q_OS_WIN)
|
|
FILE *fs = ::fopen("writeabletextfile", "wt");
|
|
#else
|
|
FILE *fs = ::fopen("writeabletextfile", "w");
|
|
#endif
|
|
QFile f;
|
|
QByteArray part1("This\nis\na\nfile\nwith\nnewlines\n");
|
|
QByteArray part2("Add\nsome\nmore\nnewlines\n");
|
|
|
|
QVERIFY(f.open(fs, QIODevice::WriteOnly));
|
|
f.write(part1);
|
|
f.write(part2);
|
|
f.close();
|
|
::fclose(fs);
|
|
|
|
QFile file("writeabletextfile");
|
|
QVERIFY(file.open(QIODevice::ReadOnly));
|
|
|
|
QByteArray data = file.readAll();
|
|
|
|
QByteArray expected = part1 + part2;
|
|
#ifdef Q_OS_WIN
|
|
expected.replace("\n", "\015\012");
|
|
#endif
|
|
QCOMPARE(data, expected);
|
|
file.close();
|
|
file.remove();
|
|
}
|
|
|
|
void tst_QFile::rename_data()
|
|
{
|
|
QTest::addColumn<QString>("source");
|
|
QTest::addColumn<QString>("destination");
|
|
QTest::addColumn<bool>("result");
|
|
|
|
QTest::newRow("a -> b") << QString("a") << QString("b") << false;
|
|
QTest::newRow("a -> .") << QString("a") << QString(".") << false;
|
|
QTest::newRow("renamefile -> renamefile") << QString("renamefile") << QString("renamefile") << false;
|
|
QTest::newRow("renamefile -> Makefile") << QString("renamefile") << QString("Makefile") << false;
|
|
#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
|
|
QTest::newRow("renamefile -> /etc/renamefile") << QString("renamefile") << QString("/etc/renamefile") << false;
|
|
#endif
|
|
QTest::newRow("renamefile -> renamedfile") << QString("renamefile") << QString("renamedfile") << true;
|
|
QTest::newRow("renamefile -> ..") << QString("renamefile") << QString("..") << false;
|
|
}
|
|
|
|
void tst_QFile::rename()
|
|
{
|
|
QFETCH(QString, source);
|
|
QFETCH(QString, destination);
|
|
QFETCH(bool, result);
|
|
|
|
QFile::remove("renamedfile");
|
|
QFile f("renamefile");
|
|
f.open(QFile::WriteOnly);
|
|
f.close();
|
|
|
|
QFile file(source);
|
|
QCOMPARE(file.rename(destination), result);
|
|
|
|
if (result)
|
|
QCOMPARE(file.error(), QFile::NoError);
|
|
else
|
|
QCOMPARE(file.error(), QFile::RenameError);
|
|
|
|
QFile::remove("renamefile");
|
|
}
|
|
|
|
/*!
|
|
\since 4.5
|
|
|
|
Some special files have QFile::atEnd() returning true, even though there is
|
|
more data available. True for corner cases, as well as some mounts on OS X.
|
|
|
|
Here, we reproduce that condition by having a QFile sub-class with this
|
|
peculiar atEnd() behavior.
|
|
|
|
See task 231583.
|
|
*/
|
|
void tst_QFile::renameWithAtEndSpecialFile() const
|
|
{
|
|
class PeculiarAtEnd : public QFile
|
|
{
|
|
public:
|
|
virtual bool atEnd() const
|
|
{
|
|
return true;
|
|
}
|
|
};
|
|
|
|
const QString newName(QLatin1String("newName.txt"));
|
|
/* Cleanup, so we're a bit more robust. */
|
|
QFile::remove(newName);
|
|
|
|
const QString originalName(QString(SRCDIR "forRenaming.txt"));
|
|
|
|
PeculiarAtEnd file;
|
|
file.setFileName(originalName);
|
|
QVERIFY(file.open(QIODevice::ReadOnly));
|
|
|
|
QVERIFY(file.rename(newName));
|
|
|
|
file.close();
|
|
/* Guess what, we have to rename it back, otherwise we'll fail on second
|
|
* invocation. */
|
|
QVERIFY(QFile::rename(newName, originalName));
|
|
}
|
|
|
|
void tst_QFile::renameFallback()
|
|
{
|
|
// Using a resource file both to trigger QFile::rename's fallback handling
|
|
// and as a *read-only* source whose move should fail.
|
|
QFile file(":/rename-fallback.qrc");
|
|
QVERIFY(file.exists() && "(test-precondition)");
|
|
QFile::remove("file-rename-destination.txt");
|
|
|
|
QVERIFY(!file.rename("file-rename-destination.txt"));
|
|
QVERIFY(!QFile::exists("file-rename-destination.txt"));
|
|
QVERIFY(!file.isOpen());
|
|
}
|
|
|
|
void tst_QFile::renameMultiple()
|
|
{
|
|
// create the file if it doesn't exist
|
|
QFile file("file-to-be-renamed.txt");
|
|
QFile file2("existing-file.txt");
|
|
QVERIFY(file.open(QIODevice::ReadWrite) && "(test-precondition)");
|
|
QVERIFY(file2.open(QIODevice::ReadWrite) && "(test-precondition)");
|
|
|
|
// any stale files from previous test failures?
|
|
QFile::remove("file-renamed-once.txt");
|
|
QFile::remove("file-renamed-twice.txt");
|
|
|
|
// begin testing
|
|
QVERIFY(QFile::exists("existing-file.txt"));
|
|
QVERIFY(!file.rename("existing-file.txt"));
|
|
QCOMPARE(file.error(), QFile::RenameError);
|
|
QCOMPARE(file.fileName(), QString("file-to-be-renamed.txt"));
|
|
|
|
QVERIFY(file.rename("file-renamed-once.txt"));
|
|
QVERIFY(!file.isOpen());
|
|
QCOMPARE(file.fileName(), QString("file-renamed-once.txt"));
|
|
|
|
QVERIFY(QFile::exists("existing-file.txt"));
|
|
QVERIFY(!file.rename("existing-file.txt"));
|
|
QCOMPARE(file.error(), QFile::RenameError);
|
|
QCOMPARE(file.fileName(), QString("file-renamed-once.txt"));
|
|
|
|
QVERIFY(file.rename("file-renamed-twice.txt"));
|
|
QVERIFY(!file.isOpen());
|
|
QCOMPARE(file.fileName(), QString("file-renamed-twice.txt"));
|
|
|
|
QVERIFY(QFile::exists("existing-file.txt"));
|
|
QVERIFY(!QFile::exists("file-to-be-renamed.txt"));
|
|
QVERIFY(!QFile::exists("file-renamed-once.txt"));
|
|
QVERIFY(QFile::exists("file-renamed-twice.txt"));
|
|
|
|
file.remove();
|
|
file2.remove();
|
|
QVERIFY(!QFile::exists("file-renamed-twice.txt"));
|
|
QVERIFY(!QFile::exists("existing-file.txt"));
|
|
}
|
|
|
|
void tst_QFile::appendAndRead()
|
|
{
|
|
QFile writeFile(QLatin1String("appendfile.txt"));
|
|
QVERIFY(writeFile.open(QIODevice::WriteOnly | QIODevice::Truncate));
|
|
|
|
QFile readFile(QLatin1String("appendfile.txt"));
|
|
QVERIFY(readFile.open(QIODevice::ReadOnly));
|
|
|
|
// Write to the end of the file, then read that character back, and so on.
|
|
for (int i = 0; i < 100; ++i) {
|
|
char c = '\0';
|
|
writeFile.putChar(char(i % 256));
|
|
writeFile.flush();
|
|
QVERIFY(readFile.getChar(&c));
|
|
QCOMPARE(c, char(i % 256));
|
|
QCOMPARE(readFile.pos(), writeFile.pos());
|
|
}
|
|
|
|
// Write blocks and read them back
|
|
for (int j = 0; j < 18; ++j) {
|
|
writeFile.write(QByteArray(1 << j, '@'));
|
|
writeFile.flush();
|
|
QCOMPARE(readFile.read(1 << j).size(), 1 << j);
|
|
}
|
|
|
|
readFile.close();
|
|
QFile::remove(QLatin1String("appendfile.txt"));
|
|
}
|
|
|
|
void tst_QFile::miscWithUncPathAsCurrentDir()
|
|
{
|
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
|
|
QString current = QDir::currentPath();
|
|
QVERIFY(QDir::setCurrent("//" + QtNetworkSettings::winServerName() + "/testshare"));
|
|
QFile file("test.pri");
|
|
QVERIFY(file.exists());
|
|
QCOMPARE(int(file.size()), 34);
|
|
QVERIFY(file.open(QIODevice::ReadOnly));
|
|
QVERIFY(QDir::setCurrent(current));
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::standarderror()
|
|
{
|
|
QFile f;
|
|
bool ok = f.open(stderr, QFile::WriteOnly);
|
|
QVERIFY(ok);
|
|
f.close();
|
|
}
|
|
|
|
void tst_QFile::handle()
|
|
{
|
|
int fd;
|
|
#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)
|
|
QFile file(SRCDIR "tst_qfile.cpp");
|
|
QVERIFY(file.open(QIODevice::ReadOnly));
|
|
fd = int(file.handle());
|
|
QVERIFY(fd > 2);
|
|
QCOMPARE(int(file.handle()), fd);
|
|
char c = '\0';
|
|
QT_READ(int(file.handle()), &c, 1);
|
|
QCOMPARE(c, '/');
|
|
|
|
// test if the QFile and the handle remain in sync
|
|
QVERIFY(file.getChar(&c));
|
|
QCOMPARE(c, '*');
|
|
|
|
// same, but read from QFile first now
|
|
file.close();
|
|
QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Unbuffered));
|
|
fd = int(file.handle());
|
|
QVERIFY(fd > 2);
|
|
QVERIFY(file.getChar(&c));
|
|
QCOMPARE(c, '/');
|
|
#ifdef Q_OS_UNIX
|
|
QCOMPARE(QT_READ(fd, &c, 1), ssize_t(1));
|
|
#else
|
|
QCOMPARE(QT_READ(fd, &c, 1), 1);
|
|
#endif
|
|
|
|
QCOMPARE(c, '*');
|
|
#endif
|
|
|
|
//test round trip of adopted stdio file handle
|
|
QFile file2;
|
|
FILE *fp = fopen(SRCDIR "tst_qfile.cpp", "r");
|
|
file2.open(fp, QIODevice::ReadOnly);
|
|
QCOMPARE(int(file2.handle()), int(fileno(fp)));
|
|
QCOMPARE(int(file2.handle()), int(fileno(fp)));
|
|
fclose(fp);
|
|
|
|
//test round trip of adopted posix file handle
|
|
#ifdef Q_OS_UNIX
|
|
QFile file3;
|
|
fd = QT_OPEN(SRCDIR "tst_qfile.cpp", QT_OPEN_RDONLY);
|
|
file3.open(fd, QIODevice::ReadOnly);
|
|
QCOMPARE(int(file3.handle()), fd);
|
|
QT_CLOSE(fd);
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::nativeHandleLeaks()
|
|
{
|
|
#ifdef Q_OS_SYMBIAN
|
|
QSKIP("test assumptions invalid for symbian", SkipAll);
|
|
#else
|
|
int fd1, fd2;
|
|
|
|
#ifdef Q_OS_WIN
|
|
HANDLE handle1, handle2;
|
|
#endif
|
|
|
|
{
|
|
QFile file("qt_file.tmp");
|
|
QVERIFY( file.open(QIODevice::ReadWrite) );
|
|
|
|
fd1 = file.handle();
|
|
QVERIFY( -1 != fd1 );
|
|
}
|
|
|
|
#ifdef Q_OS_WIN
|
|
handle1 = ::CreateFileA("qt_file.tmp", GENERIC_READ, 0, NULL,
|
|
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
QVERIFY( INVALID_HANDLE_VALUE != handle1 );
|
|
QVERIFY( ::CloseHandle(handle1) );
|
|
#endif
|
|
|
|
{
|
|
QFile file("qt_file.tmp");
|
|
QVERIFY( file.open(QIODevice::ReadOnly) );
|
|
|
|
fd2 = file.handle();
|
|
QVERIFY( -1 != fd2 );
|
|
}
|
|
|
|
#ifdef Q_OS_WIN
|
|
handle2 = ::CreateFileA("qt_file.tmp", GENERIC_READ, 0, NULL,
|
|
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
QVERIFY( INVALID_HANDLE_VALUE != handle2 );
|
|
QVERIFY( ::CloseHandle(handle2) );
|
|
#endif
|
|
|
|
QCOMPARE( fd2, fd1 );
|
|
|
|
#ifdef Q_OS_WIN
|
|
QCOMPARE( handle2, handle1 );
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::readEof_data()
|
|
{
|
|
QTest::addColumn<QString>("filename");
|
|
QTest::addColumn<int>("imode");
|
|
|
|
QTest::newRow("buffered") << SRCDIR "testfile.txt" << 0;
|
|
QTest::newRow("unbuffered") << SRCDIR "testfile.txt" << int(QIODevice::Unbuffered);
|
|
|
|
#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
|
|
QTest::newRow("sequential,buffered") << "/dev/null" << 0;
|
|
QTest::newRow("sequential,unbuffered") << "/dev/null" << int(QIODevice::Unbuffered);
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::readEof()
|
|
{
|
|
QFETCH(QString, filename);
|
|
QFETCH(int, imode);
|
|
QIODevice::OpenMode mode = QIODevice::OpenMode(imode);
|
|
|
|
{
|
|
QFile file(filename);
|
|
QVERIFY(file.open(QIODevice::ReadOnly | mode));
|
|
bool isSequential = file.isSequential();
|
|
if (!isSequential) {
|
|
QVERIFY(file.seek(245));
|
|
QVERIFY(file.atEnd());
|
|
}
|
|
|
|
char buf[10];
|
|
int ret = file.read(buf, sizeof buf);
|
|
QCOMPARE(ret, 0);
|
|
QVERIFY(file.error() == QFile::NoError);
|
|
QVERIFY(file.atEnd());
|
|
|
|
// Do it again to ensure that we get the same result
|
|
ret = file.read(buf, sizeof buf);
|
|
QCOMPARE(ret, 0);
|
|
QVERIFY(file.error() == QFile::NoError);
|
|
QVERIFY(file.atEnd());
|
|
}
|
|
|
|
{
|
|
QFile file(filename);
|
|
QVERIFY(file.open(QIODevice::ReadOnly | mode));
|
|
bool isSequential = file.isSequential();
|
|
if (!isSequential) {
|
|
QVERIFY(file.seek(245));
|
|
QVERIFY(file.atEnd());
|
|
}
|
|
|
|
QByteArray ret = file.read(10);
|
|
QVERIFY(ret.isEmpty());
|
|
QVERIFY(file.error() == QFile::NoError);
|
|
QVERIFY(file.atEnd());
|
|
|
|
// Do it again to ensure that we get the same result
|
|
ret = file.read(10);
|
|
QVERIFY(ret.isEmpty());
|
|
QVERIFY(file.error() == QFile::NoError);
|
|
QVERIFY(file.atEnd());
|
|
}
|
|
|
|
{
|
|
QFile file(filename);
|
|
QVERIFY(file.open(QIODevice::ReadOnly | mode));
|
|
bool isSequential = file.isSequential();
|
|
if (!isSequential) {
|
|
QVERIFY(file.seek(245));
|
|
QVERIFY(file.atEnd());
|
|
}
|
|
|
|
char buf[10];
|
|
int ret = file.readLine(buf, sizeof buf);
|
|
QCOMPARE(ret, -1);
|
|
QVERIFY(file.error() == QFile::NoError);
|
|
QVERIFY(file.atEnd());
|
|
|
|
// Do it again to ensure that we get the same result
|
|
ret = file.readLine(buf, sizeof buf);
|
|
QCOMPARE(ret, -1);
|
|
QVERIFY(file.error() == QFile::NoError);
|
|
QVERIFY(file.atEnd());
|
|
}
|
|
|
|
{
|
|
QFile file(filename);
|
|
QVERIFY(file.open(QIODevice::ReadOnly | mode));
|
|
bool isSequential = file.isSequential();
|
|
if (!isSequential) {
|
|
QVERIFY(file.seek(245));
|
|
QVERIFY(file.atEnd());
|
|
}
|
|
|
|
QByteArray ret = file.readLine();
|
|
QVERIFY(ret.isNull());
|
|
QVERIFY(file.error() == QFile::NoError);
|
|
QVERIFY(file.atEnd());
|
|
|
|
// Do it again to ensure that we get the same result
|
|
ret = file.readLine();
|
|
QVERIFY(ret.isNull());
|
|
QVERIFY(file.error() == QFile::NoError);
|
|
QVERIFY(file.atEnd());
|
|
}
|
|
|
|
{
|
|
QFile file(filename);
|
|
QVERIFY(file.open(QIODevice::ReadOnly | mode));
|
|
bool isSequential = file.isSequential();
|
|
if (!isSequential) {
|
|
QVERIFY(file.seek(245));
|
|
QVERIFY(file.atEnd());
|
|
}
|
|
|
|
char c;
|
|
QVERIFY(!file.getChar(&c));
|
|
QVERIFY(file.error() == QFile::NoError);
|
|
QVERIFY(file.atEnd());
|
|
|
|
// Do it again to ensure that we get the same result
|
|
QVERIFY(!file.getChar(&c));
|
|
QVERIFY(file.error() == QFile::NoError);
|
|
QVERIFY(file.atEnd());
|
|
}
|
|
}
|
|
|
|
void tst_QFile::task167217()
|
|
{
|
|
// Regression introduced in 4.3.0; after a failed stat, pos() could no
|
|
// longer be calculated correctly.
|
|
QFile::remove("tmp.txt");
|
|
QFile file("tmp.txt");
|
|
QVERIFY(!file.exists());
|
|
QVERIFY(file.open(QIODevice::Append));
|
|
QVERIFY(file.exists());
|
|
file.write("qt430", 5);
|
|
QVERIFY(!file.isSequential());
|
|
QCOMPARE(file.pos(), qint64(5));
|
|
file.remove();
|
|
}
|
|
|
|
#define FILESIZE 65536 * 3
|
|
|
|
void tst_QFile::map_data()
|
|
{
|
|
QTest::addColumn<int>("fileSize");
|
|
QTest::addColumn<int>("offset");
|
|
QTest::addColumn<int>("size");
|
|
QTest::addColumn<QFile::FileError>("error");
|
|
|
|
QTest::newRow("zero") << FILESIZE << 0 << FILESIZE << QFile::NoError;
|
|
QTest::newRow("small, but 0") << FILESIZE << 30 << FILESIZE - 30 << QFile::NoError;
|
|
QTest::newRow("a page") << FILESIZE << 4096 << FILESIZE - 4096 << QFile::NoError;
|
|
QTest::newRow("+page") << FILESIZE << 5000 << FILESIZE - 5000 << QFile::NoError;
|
|
QTest::newRow("++page") << FILESIZE << 65576 << FILESIZE - 65576 << QFile::NoError;
|
|
QTest::newRow("bad size") << FILESIZE << 0 << -1 << QFile::ResourceError;
|
|
QTest::newRow("bad offset") << FILESIZE << -1 << 1 << QFile::UnspecifiedError;
|
|
QTest::newRow("zerozero") << FILESIZE << 0 << 0 << QFile::UnspecifiedError;
|
|
}
|
|
|
|
void tst_QFile::map()
|
|
{
|
|
QFETCH(int, fileSize);
|
|
QFETCH(int, offset);
|
|
QFETCH(int, size);
|
|
QFETCH(QFile::FileError, error);
|
|
|
|
QString fileName = QDir::currentPath() + '/' + "qfile_map_testfile";
|
|
|
|
#ifdef Q_WS_WINCE
|
|
fileName = QFileInfo(fileName).absoluteFilePath();
|
|
#endif
|
|
|
|
if (QFile::exists(fileName)) {
|
|
QVERIFY(QFile::setPermissions(fileName,
|
|
QFile::WriteOwner | QFile::ReadOwner | QFile::WriteUser | QFile::ReadUser));
|
|
QFile::remove(fileName);
|
|
}
|
|
QFile file(fileName);
|
|
|
|
// invalid, not open
|
|
uchar *memory = file.map(0, size);
|
|
QVERIFY(!memory);
|
|
QCOMPARE(file.error(), QFile::PermissionsError);
|
|
QVERIFY(!file.unmap(memory));
|
|
QCOMPARE(file.error(), QFile::PermissionsError);
|
|
|
|
// make a file
|
|
QVERIFY(file.open(QFile::ReadWrite));
|
|
QVERIFY(file.resize(fileSize));
|
|
QVERIFY(file.flush());
|
|
file.close();
|
|
QVERIFY(file.open(QFile::ReadWrite));
|
|
memory = file.map(offset, size);
|
|
if (error != QFile::NoError) {
|
|
|
|
QVERIFY(file.error() != QFile::NoError);
|
|
return;
|
|
}
|
|
|
|
QCOMPARE(file.error(), error);
|
|
QVERIFY(memory);
|
|
memory[0] = 'Q';
|
|
QVERIFY(file.unmap(memory));
|
|
QCOMPARE(file.error(), QFile::NoError);
|
|
|
|
// Verify changes were saved
|
|
memory = file.map(offset, size);
|
|
QCOMPARE(file.error(), QFile::NoError);
|
|
QVERIFY(memory);
|
|
QVERIFY(memory[0] == 'Q');
|
|
QVERIFY(file.unmap(memory));
|
|
QCOMPARE(file.error(), QFile::NoError);
|
|
|
|
// hpux wont let you map multiple times.
|
|
#if !defined(Q_OS_HPUX) && !defined(Q_USE_DEPRECATED_MAP_API) && !defined(Q_OS_WINCE)
|
|
// exotic test to make sure that multiple maps work
|
|
|
|
// note: windows ce does not reference count mutliple maps
|
|
// it's essentially just the same reference but it
|
|
// cause a resource lock on the file which prevents it
|
|
// from being removed uchar *memory1 = file.map(0, file.size());
|
|
uchar *memory1 = file.map(0, file.size());
|
|
QCOMPARE(file.error(), QFile::NoError);
|
|
uchar *memory2 = file.map(0, file.size());
|
|
QCOMPARE(file.error(), QFile::NoError);
|
|
QVERIFY(memory1);
|
|
QVERIFY(memory2);
|
|
QVERIFY(file.unmap(memory1));
|
|
QCOMPARE(file.error(), QFile::NoError);
|
|
QVERIFY(file.unmap(memory2));
|
|
QCOMPARE(file.error(), QFile::NoError);
|
|
memory1 = file.map(0, file.size());
|
|
QCOMPARE(file.error(), QFile::NoError);
|
|
QVERIFY(memory1);
|
|
QVERIFY(file.unmap(memory1));
|
|
QCOMPARE(file.error(), QFile::NoError);
|
|
#endif
|
|
|
|
file.close();
|
|
|
|
#if defined(Q_OS_SYMBIAN)
|
|
if (false) // No permissions for user makes no sense in Symbian
|
|
#elif defined(Q_OS_UNIX)
|
|
if (::getuid() != 0)
|
|
// root always has permissions
|
|
#endif
|
|
{
|
|
// Change permissions on a file, just to confirm it would fail
|
|
QFile::Permissions originalPermissions = file.permissions();
|
|
QVERIFY(file.setPermissions(QFile::ReadOther));
|
|
QVERIFY(!file.open(QFile::ReadWrite));
|
|
memory = file.map(offset, size);
|
|
QCOMPARE(file.error(), QFile::PermissionsError);
|
|
QVERIFY(!memory);
|
|
QVERIFY(file.setPermissions(originalPermissions));
|
|
}
|
|
QVERIFY(file.remove());
|
|
}
|
|
|
|
void tst_QFile::mapResource_data()
|
|
{
|
|
QTest::addColumn<int>("offset");
|
|
QTest::addColumn<int>("size");
|
|
QTest::addColumn<QFile::FileError>("error");
|
|
QTest::addColumn<QString>("fileName");
|
|
|
|
QString validFile = ":/tst_qfileinfo/resources/file1.ext1";
|
|
QString invalidFile = ":/tst_qfileinfo/resources/filefoo.ext1";
|
|
|
|
for (int i = 0; i < 2; ++i) {
|
|
QString file = (i == 0) ? validFile : invalidFile;
|
|
QTest::newRow("0, 0") << 0 << 0 << QFile::UnspecifiedError << file;
|
|
QTest::newRow("0, BIG") << 0 << 4096 << QFile::UnspecifiedError << file;
|
|
QTest::newRow("-1, 0") << -1 << 0 << QFile::UnspecifiedError << file;
|
|
QTest::newRow("0, -1") << 0 << -1 << QFile::UnspecifiedError << file;
|
|
}
|
|
|
|
QTest::newRow("0, 1") << 0 << 1 << QFile::NoError << validFile;
|
|
}
|
|
|
|
void tst_QFile::mapResource()
|
|
{
|
|
QFETCH(QString, fileName);
|
|
QFETCH(int, offset);
|
|
QFETCH(int, size);
|
|
QFETCH(QFile::FileError, error);
|
|
|
|
QFile file(fileName);
|
|
uchar *memory = file.map(offset, size);
|
|
QCOMPARE(file.error(), error);
|
|
QVERIFY((error == QFile::NoError) ? (memory != 0) : (memory == 0));
|
|
if (error == QFile::NoError)
|
|
QCOMPARE(QString(memory[0]), QString::number(offset + 1));
|
|
QVERIFY(file.unmap(memory));
|
|
}
|
|
|
|
void tst_QFile::mapOpenMode_data()
|
|
{
|
|
QTest::addColumn<int>("openMode");
|
|
|
|
QTest::newRow("ReadOnly") << int(QIODevice::ReadOnly);
|
|
//QTest::newRow("WriteOnly") << int(QIODevice::WriteOnly); // this doesn't make sense
|
|
QTest::newRow("ReadWrite") << int(QIODevice::ReadWrite);
|
|
QTest::newRow("ReadOnly,Unbuffered") << int(QIODevice::ReadOnly | QIODevice::Unbuffered);
|
|
QTest::newRow("ReadWrite,Unbuffered") << int(QIODevice::ReadWrite | QIODevice::Unbuffered);
|
|
}
|
|
|
|
void tst_QFile::mapOpenMode()
|
|
{
|
|
QFETCH(int, openMode);
|
|
static const qint64 fileSize = 4096;
|
|
|
|
QByteArray pattern(fileSize, 'A');
|
|
|
|
QString fileName = QDir::currentPath() + '/' + "qfile_map_testfile";
|
|
if (QFile::exists(fileName)) {
|
|
QVERIFY(QFile::setPermissions(fileName,
|
|
QFile::WriteOwner | QFile::ReadOwner | QFile::WriteUser | QFile::ReadUser));
|
|
QFile::remove(fileName);
|
|
}
|
|
QFile file(fileName);
|
|
|
|
// make a file
|
|
QVERIFY(file.open(QFile::ReadWrite));
|
|
QVERIFY(file.write(pattern));
|
|
QVERIFY(file.flush());
|
|
file.close();
|
|
|
|
// open according to our mode
|
|
QVERIFY(file.open(QIODevice::OpenMode(openMode)));
|
|
|
|
uchar *memory = file.map(0, fileSize);
|
|
QVERIFY(memory);
|
|
QVERIFY(memcmp(memory, pattern, fileSize) == 0);
|
|
|
|
if (openMode & QIODevice::WriteOnly) {
|
|
// try to write to the file
|
|
*memory = 'a';
|
|
file.unmap(memory);
|
|
file.close();
|
|
file.open(QIODevice::OpenMode(openMode));
|
|
file.seek(0);
|
|
char c;
|
|
QVERIFY(file.getChar(&c));
|
|
QCOMPARE(c, 'a');
|
|
}
|
|
|
|
file.close();
|
|
}
|
|
|
|
void tst_QFile::openDirectory()
|
|
{
|
|
QFile f1(SRCDIR "resources");
|
|
// it's a directory, it must exist
|
|
QVERIFY(f1.exists());
|
|
|
|
// ...but not be openable
|
|
QVERIFY(!f1.open(QIODevice::ReadOnly));
|
|
f1.close();
|
|
QVERIFY(!f1.open(QIODevice::ReadOnly|QIODevice::Unbuffered));
|
|
f1.close();
|
|
QVERIFY(!f1.open(QIODevice::ReadWrite));
|
|
f1.close();
|
|
QVERIFY(!f1.open(QIODevice::WriteOnly));
|
|
f1.close();
|
|
QVERIFY(!f1.open(QIODevice::WriteOnly|QIODevice::Unbuffered));
|
|
f1.close();
|
|
}
|
|
|
|
void tst_QFile::openStandardStreamsFileDescriptors()
|
|
{
|
|
#ifdef Q_WS_WINCE
|
|
//allthough Windows CE (not mobile!) has functions that allow redirecting
|
|
//the standard file descriptors to a file (see SetStdioPathW/GetStdioPathW)
|
|
//it does not have functions to simply open them like below .
|
|
QSKIP("Opening standard streams on Windows CE via descriptor not implemented", SkipAll);
|
|
#endif
|
|
// Using file descriptors
|
|
{
|
|
QFile in;
|
|
in.open(STDIN_FILENO, QIODevice::ReadOnly);
|
|
QCOMPARE( in.pos(), (qint64)0 );
|
|
QCOMPARE( in.size(), (qint64)0 );
|
|
QVERIFY( in.isSequential() );
|
|
}
|
|
|
|
{
|
|
QFile out;
|
|
out.open(STDOUT_FILENO, QIODevice::WriteOnly);
|
|
QCOMPARE( out.pos(), (qint64)0 );
|
|
QCOMPARE( out.size(), (qint64)0 );
|
|
QVERIFY( out.isSequential() );
|
|
}
|
|
|
|
{
|
|
QFile err;
|
|
err.open(STDERR_FILENO, QIODevice::WriteOnly);
|
|
QCOMPARE( err.pos(), (qint64)0 );
|
|
QCOMPARE( err.size(), (qint64)0 );
|
|
QVERIFY( err.isSequential() );
|
|
}
|
|
}
|
|
|
|
void tst_QFile::openStandardStreamsBufferedStreams()
|
|
{
|
|
#if defined (Q_OS_WIN) || defined(Q_OS_SYMBIAN)
|
|
QSKIP("Unix only test.", SkipAll);
|
|
#endif
|
|
// Using streams
|
|
{
|
|
QFile in;
|
|
in.open(stdin, QIODevice::ReadOnly);
|
|
QCOMPARE( in.pos(), (qint64)0 );
|
|
QCOMPARE( in.size(), (qint64)0 );
|
|
QVERIFY( in.isSequential() );
|
|
}
|
|
|
|
{
|
|
QFile out;
|
|
out.open(stdout, QIODevice::WriteOnly);
|
|
QCOMPARE( out.pos(), (qint64)0 );
|
|
QCOMPARE( out.size(), (qint64)0 );
|
|
QVERIFY( out.isSequential() );
|
|
}
|
|
|
|
{
|
|
QFile err;
|
|
err.open(stderr, QIODevice::WriteOnly);
|
|
QCOMPARE( err.pos(), (qint64)0 );
|
|
QCOMPARE( err.size(), (qint64)0 );
|
|
QVERIFY( err.isSequential() );
|
|
}
|
|
}
|
|
|
|
void tst_QFile::openStandardStreams()
|
|
{
|
|
openStandardStreamsFileDescriptors();
|
|
openStandardStreamsBufferedStreams();
|
|
}
|
|
|
|
void tst_QFile::writeNothing()
|
|
{
|
|
for (int i = 0; i < NumberOfFileTypes; ++i) {
|
|
QFile file("file.txt");
|
|
QVERIFY( openFile(file, QIODevice::WriteOnly | QIODevice::Unbuffered, FileType(i)) );
|
|
QVERIFY( 0 == file.write((char *)0, 0) );
|
|
QCOMPARE( file.error(), QFile::NoError );
|
|
closeFile(file);
|
|
}
|
|
}
|
|
|
|
void tst_QFile::resize_data()
|
|
{
|
|
QTest::addColumn<int>("filetype");
|
|
|
|
QTest::newRow("native") << int(OpenQFile);
|
|
QTest::newRow("fileno") << int(OpenFd);
|
|
QTest::newRow("stream") << int(OpenStream);
|
|
#ifdef Q_OS_SYMBIAN
|
|
QTest::newRow("rfile") << int(OpenRFile);
|
|
#endif
|
|
}
|
|
|
|
void tst_QFile::resize()
|
|
{
|
|
QFETCH(int, filetype);
|
|
QString filename(QLatin1String("file.txt"));
|
|
QFile file(filename);
|
|
QVERIFY(openFile(file, QIODevice::ReadWrite, FileType(filetype)));
|
|
QVERIFY(file.resize(8));
|
|
QCOMPARE(file.size(), qint64(8));
|
|
closeFile(file);
|
|
QFile::resize(filename, 4);
|
|
QCOMPARE(QFileInfo(filename).size(), qint64(4));
|
|
QVERIFY(QFile::remove(filename));
|
|
}
|
|
|
|
void tst_QFile::objectConstructors()
|
|
{
|
|
QObject ob;
|
|
QFile* file1 = new QFile(SRCDIR "testfile.txt", &ob);
|
|
QFile* file2 = new QFile(&ob);
|
|
QVERIFY(file1->exists());
|
|
QVERIFY(!file2->exists());
|
|
}
|
|
|
|
#ifdef Q_OS_SYMBIAN
|
|
void tst_QFile::platformSecurity_data()
|
|
{
|
|
QTest::addColumn<QString>("file");
|
|
QTest::addColumn<bool>("readable");
|
|
QTest::addColumn<bool>("writable");
|
|
|
|
QString selfname = QCoreApplication::applicationFilePath();
|
|
QString ownprivate = QCoreApplication::applicationDirPath();
|
|
QString owndrive = selfname.left(2);
|
|
bool amiprivileged = RProcess().HasCapability(ECapabilityAllFiles);
|
|
QTest::newRow("resource") << owndrive + "/resource/apps/tst_qfile.rsc" << true << amiprivileged;
|
|
QTest::newRow("sys") << selfname << amiprivileged << false;
|
|
QTest::newRow("own private") << ownprivate + "/testfile.txt" << true << true;
|
|
QTest::newRow("other private") << owndrive + "/private/10003a3f/import/apps/tst_qfile_reg.rsc" << amiprivileged << amiprivileged;
|
|
}
|
|
|
|
void tst_QFile::platformSecurity()
|
|
{
|
|
QFETCH(QString,file);
|
|
QFETCH(bool,readable);
|
|
QFETCH(bool,writable);
|
|
|
|
{
|
|
QFile f(file);
|
|
QCOMPARE(f.open(QIODevice::ReadOnly), readable);
|
|
}
|
|
|
|
{
|
|
QFile f(file);
|
|
QCOMPARE(f.open(QIODevice::ReadOnly | QIODevice::Unbuffered), readable);
|
|
}
|
|
|
|
//append mode used to avoid truncating the files.
|
|
{
|
|
QFile f(file);
|
|
QCOMPARE(f.open(QIODevice::WriteOnly | QIODevice::Append), writable);
|
|
}
|
|
|
|
{
|
|
QFile f(file);
|
|
QCOMPARE(f.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Unbuffered), writable);
|
|
}
|
|
|
|
{
|
|
QFile f(file);
|
|
QCOMPARE(f.open(QIODevice::ReadWrite), writable);
|
|
}
|
|
|
|
{
|
|
QFile f(file);
|
|
QCOMPARE(f.open(QIODevice::ReadWrite | QIODevice::Unbuffered), writable);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void tst_QFile::caseSensitivity()
|
|
{
|
|
#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
|
const bool caseSensitive = false;
|
|
#else
|
|
const bool caseSensitive = true;
|
|
#endif
|
|
QByteArray testData("a little test");
|
|
QString filename("File.txt");
|
|
{
|
|
QFile f(filename);
|
|
QVERIFY(f.open(QIODevice::WriteOnly));
|
|
QVERIFY(f.write(testData));
|
|
f.close();
|
|
}
|
|
QStringList alternates;
|
|
QFileInfo fi(filename);
|
|
QVERIFY(fi.exists());
|
|
alternates << "file.txt" << "File.TXT" << "fIlE.TxT" << fi.absoluteFilePath().toUpper() << fi.absoluteFilePath().toLower();
|
|
foreach (QString alt, alternates) {
|
|
QFileInfo fi2(alt);
|
|
QCOMPARE(fi2.exists(), !caseSensitive);
|
|
QCOMPARE(fi.size() == fi2.size(), !caseSensitive);
|
|
QFile f2(alt);
|
|
QCOMPARE(f2.open(QIODevice::ReadOnly), !caseSensitive);
|
|
if (!caseSensitive)
|
|
QCOMPARE(f2.readAll(), testData);
|
|
}
|
|
}
|
|
|
|
//MSVCRT asserts when any function is called with a closed file handle.
|
|
//This replaces the default crashing error handler with one that ignores the error (allowing EBADF to be returned)
|
|
class AutoIgnoreInvalidParameter
|
|
{
|
|
public:
|
|
#if defined(Q_OS_WIN) && defined (Q_CC_MSVC)
|
|
static void ignore_invalid_parameter(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t) {}
|
|
AutoIgnoreInvalidParameter()
|
|
{
|
|
oldHandler = _set_invalid_parameter_handler(ignore_invalid_parameter);
|
|
//also disable the abort/retry/ignore popup
|
|
oldReportMode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
|
|
}
|
|
~AutoIgnoreInvalidParameter()
|
|
{
|
|
//restore previous settings
|
|
_set_invalid_parameter_handler(oldHandler);
|
|
_CrtSetReportMode(_CRT_ASSERT, oldReportMode);
|
|
}
|
|
_invalid_parameter_handler oldHandler;
|
|
int oldReportMode;
|
|
#endif
|
|
};
|
|
|
|
void tst_QFile::autocloseHandle()
|
|
{
|
|
#ifdef Q_OS_SYMBIAN
|
|
// these tests are a bit different, because using a closed file handle results in a panic rather than error
|
|
{
|
|
QFile file("readonlyfile");
|
|
QFile file2("readonlyfile");
|
|
QVERIFY(openFile(file, QIODevice::ReadOnly, OpenRFile, QFile::AutoCloseHandle));
|
|
// file is opened with mandatory lock, so opening again should fail
|
|
QVERIFY(!file2.open(QIODevice::ReadOnly));
|
|
|
|
file.close();
|
|
// opening again should now succeed (because handle is closed)
|
|
QVERIFY(file2.open(QIODevice::ReadOnly));
|
|
}
|
|
|
|
{
|
|
QFile file("readonlyfile");
|
|
QFile file2("readonlyfile");
|
|
QVERIFY(openFile(file, QIODevice::ReadOnly, OpenRFile, QFile::DontCloseHandle));
|
|
// file is opened with mandatory lock, so opening again should fail
|
|
QVERIFY(!file2.open(QIODevice::ReadOnly));
|
|
|
|
file.close();
|
|
// opening again should still fail (because handle is not auto closed)
|
|
QVERIFY(!file2.open(QIODevice::ReadOnly));
|
|
|
|
rfile_.Close();
|
|
// now it should succeed
|
|
QVERIFY(file2.open(QIODevice::ReadOnly));
|
|
}
|
|
#endif
|
|
|
|
{
|
|
QFile file("readonlyfile");
|
|
QVERIFY(openFile(file, QIODevice::ReadOnly, OpenFd, QFile::AutoCloseHandle));
|
|
int fd = fd_;
|
|
QCOMPARE(file.handle(), fd);
|
|
file.close();
|
|
fd_ = -1;
|
|
QCOMPARE(file.handle(), -1);
|
|
AutoIgnoreInvalidParameter a;
|
|
Q_UNUSED(a);
|
|
//file is closed, read should fail
|
|
char buf;
|
|
QCOMPARE((int)QT_READ(fd, &buf, 1), -1);
|
|
QVERIFY(errno = EBADF);
|
|
}
|
|
|
|
{
|
|
QFile file("readonlyfile");
|
|
QVERIFY(openFile(file, QIODevice::ReadOnly, OpenFd, QFile::DontCloseHandle));
|
|
QCOMPARE(file.handle(), fd_);
|
|
file.close();
|
|
QCOMPARE(file.handle(), -1);
|
|
//file is not closed, read should succeed
|
|
char buf;
|
|
QCOMPARE((int)QT_READ(fd_, &buf, 1), 1);
|
|
::close(fd_);
|
|
fd_ = -1;
|
|
}
|
|
|
|
{
|
|
QFile file("readonlyfile");
|
|
QVERIFY(openFile(file, QIODevice::ReadOnly, OpenStream, QFile::AutoCloseHandle));
|
|
int fd = fileno(stream_);
|
|
QCOMPARE(file.handle(), fd);
|
|
file.close();
|
|
stream_ = 0;
|
|
QCOMPARE(file.handle(), -1);
|
|
AutoIgnoreInvalidParameter a;
|
|
Q_UNUSED(a);
|
|
//file is closed, read should fail
|
|
char buf;
|
|
QCOMPARE((int)QT_READ(fd, &buf, 1), -1); //not using fread because the FILE* was freed by fclose
|
|
}
|
|
|
|
{
|
|
QFile file("readonlyfile");
|
|
QVERIFY(openFile(file, QIODevice::ReadOnly, OpenStream, QFile::DontCloseHandle));
|
|
QCOMPARE(file.handle(), fileno(stream_));
|
|
file.close();
|
|
QCOMPARE(file.handle(), -1);
|
|
//file is not closed, read should succeed
|
|
char buf;
|
|
QCOMPARE(int(::fread(&buf, 1, 1, stream_)), 1);
|
|
::fclose(stream_);
|
|
stream_ = 0;
|
|
}
|
|
}
|
|
|
|
QTEST_MAIN(tst_QFile)
|
|
#include "tst_qfile.moc"
|