/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** 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 either Technology Preview License Agreement or the ** Beta Release License Agreement. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #ifndef Q_OS_WINCE #include #endif #include #ifndef Q_OS_WIN # include # include #endif #ifdef Q_OS_MAC # include #elif defined(Q_OS_LINUX) # include #elif defined(Q_OS_FREEBSD) # include # include #elif defined(Q_OS_IRIX) # include #elif defined(Q_OS_WINCE) # include # include #endif #include #include "../network-settings.h" 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 seek(); void setSize(); void setSizeSeek(); void atEnd(); void readLine(); void readLine2(); void readLineNullInLine(); 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 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 readEof_data(); void readEof(); void map_data(); void map(); void mapResource_data(); void mapResource(); void mapOpenMode_data(); void mapOpenMode(); // --- Task related tests below this line void task167217(); void openDirectory(); public: // disabled this test for the moment... it hangs void invalidFile_data(); void invalidFile(); }; 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. } 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"); } 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"); } //------------------------------------------ // 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 enviroment. //------------------------------------------ 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("filename"); QTest::addColumn("mode"); QTest::addColumn("ok"); QTest::addColumn("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() + "/testsharewritable/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 ); #ifdef 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("filename"); QTest::addColumn("size"); QTest::newRow( "exist01" ) << QString(SRCDIR "testfile.txt") << 245; QTest::newRow( "nonexist01" ) << QString("foo.txt") << 0; #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) // Only test UNC on Windows./ QTest::newRow("unc") << "//" + QString(QtNetworkSettings::winServerName() + "/testsharewritable/test.pri") << 34; #endif } void tst_QFile::size() { QFETCH( QString, filename ); QFile f( filename ); QTEST( (int)f.size(), "size" ); if (f.open(QFile::ReadOnly)) QTEST( (int)f.size(), "size" ); } 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)); 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::readAllStdin() { #if defined(Q_OS_WINCE) 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 QByteArray lotsOfData(1024, '@'); // 10 megs QProcess process; process.start("stdinprocess/stdinprocess all"); 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) 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 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) 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("fileName"); #ifndef Q_WS_WIN 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( "failinvalid" ); 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("file"); QTest::addColumn("perms"); QTest::addColumn("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() { QFETCH(QString, file); QFETCH(uint, perms); QFETCH(bool, expected); QFile f(file); QCOMPARE(((f.permissions() & 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")); bool ok = QFile::setPermissions("tst_qfile.cpy", QFile::WriteOther); 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()); // Need to reset permissions on Windows to be able to delete QVERIFY(QFile::setPermissions("file-copy-destination.txt", QFile::ReadOwner | QFile::WriteOwner)); 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()); QFile::remove("file-copy-destination.txt"); } #ifdef Q_OS_WIN #include #include #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() { QFile::remove("myLink.lnk"); QFileInfo info1("tst_qfile.cpp"); QVERIFY(QFile::link("tst_qfile.cpp", "myLink.lnk")); QFileInfo info2("myLink.lnk"); QVERIFY(info2.isSymLink()); #ifdef Q_OS_WIN // on windows links are always absolute QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath()); #else QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath()); #endif #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) QString wd = getWorkingDirectoryForLink(info2.absoluteFilePath()); QCOMPARE(QDir::fromNativeSeparators(wd), info1.absolutePath()); #endif QVERIFY(QFile::remove(info2.absoluteFilePath())); } void tst_QFile::linkToDir() { 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 #ifdef Q_OS_WIN // on windows links are alway absolute QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath()); #else QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath()); #endif QVERIFY(QFile::remove(info2.absoluteFilePath())); QFile::remove("myLinkToDir.lnk"); dir.rmdir("myDir"); } void tst_QFile::absolutePathLinkToRelativePath() { 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", 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() { QFile::remove("myLink2.lnk"); QFileInfo info1("file12"); QVERIFY(QFile::link("file12", "myLink2.lnk")); QFileInfo info2("myLink2.lnk"); QVERIFY(info2.isSymLink()); #ifdef Q_OS_WIN // on windows links are alway absolute QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath()); #else QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath()); #endif QVERIFY(QFile::remove(info2.absoluteFilePath())); QVERIFY(QFile::link("ole/..", "myLink2.lnk")); QCOMPARE(QFileInfo("myLink2.lnk").symLinkTarget(), QDir::currentPath()); } void tst_QFile::readTextFile_data() { QTest::addColumn("in"); QTest::addColumn("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("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) 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::FILEReadWrite() { // Tests modifing 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 #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(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("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("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) 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); file.write(&c, 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); 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("fileName"); QTest::newRow("localfile") << QString("./largeblockfile.txt"); #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()); #endif } void tst_QFile::writeLargeDataBlock() { QFETCH(QString, fileName); // Generate a 64MB array with well defined contents. QByteArray array; #if defined(Q_OS_WINCE) int resizeSize = 1024 * 1024; // WinCE does 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); // Remove and open the target file QFile file(fileName); file.remove(); if (file.open(QFile::WriteOnly)) { QCOMPARE(file.write(array), qint64(array.size())); file.close(); QVERIFY(file.open(QFile::ReadOnly)); array.clear(); array = file.readAll(); file.remove(); } else { QFAIL(qPrintable(QString("Couldn't open file for writing: [%1]").arg(fileName))); } // Check that we got the right content QCOMPARE(array.size(), resizeSize); for (int i = 0; i < array.size(); ++i) { if (array[i] != char(i)) { QFAIL(qPrintable(QString("Wrong contents! Char at %1 = %2, expected %3") .arg(i).arg(int(uchar(array[i]))).arg(int(uchar(i))))); } } } 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("source"); QTest::addColumn("destination"); QTest::addColumn("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; #ifdef Q_OS_UNIX 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); } 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() + "/testsharewritable")); 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() { #ifndef Q_OS_WINCE QFile file(SRCDIR "tst_qfile.cpp"); QVERIFY(file.open(QIODevice::ReadOnly)); int 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 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); #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::readEof_data() { QTest::addColumn("filename"); QTest::addColumn("imode"); QTest::newRow("buffered") << SRCDIR "testfile.txt" << 0; QTest::newRow("unbuffered") << SRCDIR "testfile.txt" << int(QIODevice::Unbuffered); #ifdef Q_OS_UNIX 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.isNull()); 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.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 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("fileSize"); QTest::addColumn("offset"); QTest::addColumn("size"); QTest::addColumn("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"; 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) // exotic test to make sure that multiple maps work 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(); #ifdef 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("offset"); QTest::addColumn("size"); QTest::addColumn("error"); QTest::addColumn("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("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("resources"); QVERIFY(!f1.open(QIODevice::ReadOnly)); f1.close(); QVERIFY(!f1.open(QIODevice::ReadOnly|QIODevice::Unbuffered)); } QTEST_MAIN(tst_QFile) #include "tst_qfile.moc"