1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include <QtTest/QtTest>
43 #include <qplatformdefs.h>
45 #include <QCoreApplication>
51 #include <private/qabstractfileengine_p.h>
52 #include <private/qfsfileengine_p.h>
56 extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
60 #if !defined(Q_OS_WINCE)
65 # include <qt_windows.h>
67 # include <sys/types.h>
71 # include <sys/mount.h>
72 #elif defined(Q_OS_LINUX)
74 #elif defined(Q_OS_FREEBSD)
75 # include <sys/param.h>
76 # include <sys/mount.h>
77 #elif defined(Q_OS_IRIX)
78 # include <sys/statfs.h>
79 #elif defined(Q_OS_WINCE)
80 # include <qplatformdefs.h>
86 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
87 #include "../../../network-settings.h"
91 #define STDIN_FILENO 0
95 #define STDOUT_FILENO 1
99 #define STDERR_FILENO 2
102 #ifndef QT_OPEN_BINARY
103 #define QT_OPEN_BINARY 0
106 Q_DECLARE_METATYPE(QFile::FileError)
108 class tst_QFile : public QObject
116 void cleanupTestCase();
120 void openUnbuffered();
130 void readLineNullInLine();
133 void readAllBuffer();
135 void readLineStdin();
136 void readLineStdin_lineByLine();
138 void missingEndOfLine();
144 void permissions_data();
146 void permissionsNtfs_data();
147 void permissionsNtfs();
148 void setPermissions();
150 void copyAfterFail();
151 void copyRemovesTemporaryFile() const;
152 void copyShouldntOverwrite();
156 void absolutePathLinkToRelativePath();
157 void readBrokenLink();
158 void readTextFile_data();
160 void readTextFile2();
161 void writeTextFile_data();
162 void writeTextFile();
163 /* void largeFileSupport(); */
164 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
165 void largeUncFileSupport();
174 void seekAfterEndOfFile();
175 void FILEReadWrite();
176 void i18nFileName_data();
178 void longFileName_data();
180 void fileEngineHandler();
181 #ifdef QT_BUILD_INTERNAL
182 void useQFileInAFileHandler();
185 void remove_and_exists();
186 void removeOpenFile();
188 void writeLargeDataBlock_data();
189 void writeLargeDataBlock();
190 void readFromWriteOnlyFile();
191 void writeToReadOnlyFile();
196 void renameWithAtEndSpecialFile() const;
197 void renameFallback();
198 void renameMultiple();
199 void appendAndRead();
200 void miscWithUncPathAsCurrentDir();
201 void standarderror();
203 void nativeHandleLeaks();
210 void mapResource_data();
212 void mapOpenMode_data();
215 void openStandardStreamsFileDescriptors();
216 void openStandardStreamsBufferedStreams();
221 void objectConstructors();
223 void caseSensitivity();
225 void autocloseHandle();
227 void posAfterFailedStat();
229 void openDirectory();
232 void invalidFile_data();
243 bool openFd(QFile &file, QIODevice::OpenMode mode, QFile::FileHandleFlags handleFlags)
245 int fdMode = QT_OPEN_LARGEFILE | QT_OPEN_BINARY;
247 // File will be truncated if in Write mode.
248 if (mode & QIODevice::WriteOnly)
249 fdMode |= QT_OPEN_WRONLY | QT_OPEN_TRUNC;
250 if (mode & QIODevice::ReadOnly)
251 fdMode |= QT_OPEN_RDONLY;
253 fd_ = QT_OPEN(qPrintable(file.fileName()), fdMode);
255 return (-1 != fd_) && file.open(fd_, mode, handleFlags);
258 bool openStream(QFile &file, QIODevice::OpenMode mode, QFile::FileHandleFlags handleFlags)
260 char const *streamMode = "";
262 // File will be truncated if in Write mode.
263 if (mode & QIODevice::WriteOnly)
265 else if (mode & QIODevice::ReadOnly)
268 stream_ = QT_FOPEN(qPrintable(file.fileName()), streamMode);
270 return stream_ && file.open(stream_, mode, handleFlags);
273 bool openFile(QFile &file, QIODevice::OpenMode mode, FileType type = OpenQFile, QFile::FileHandleFlags handleFlags = QFile::DontCloseHandle)
275 if (mode & QIODevice::WriteOnly && !file.exists())
277 // Make sure the file exists
278 QFile createFile(file.fileName());
279 if (!createFile.open(QIODevice::ReadWrite))
283 // Note: openFd and openStream will truncate the file if write mode.
287 return file.open(mode);
290 return openFd(file, mode, handleFlags);
293 return openStream(file, mode, handleFlags);
295 case NumberOfFileTypes:
302 void closeFile(QFile &file)
319 void tst_QFile::init()
325 void tst_QFile::cleanup()
327 // for copyFallback()
328 if (QFile::exists("file-copy-destination.txt")) {
329 QFile::setPermissions("file-copy-destination.txt",
330 QFile::ReadOwner | QFile::WriteOwner);
331 QFile::remove("file-copy-destination.txt");
334 // for renameFallback()
335 QFile::remove("file-rename-destination.txt");
337 // for copyAfterFail()
338 QFile::remove("file-to-be-copied.txt");
339 QFile::remove("existing-file.txt");
340 QFile::remove("copied-file-1.txt");
341 QFile::remove("copied-file-2.txt");
343 // for renameMultiple()
344 QFile::remove("file-to-be-renamed.txt");
345 QFile::remove("existing-file.txt");
346 QFile::remove("file-renamed-once.txt");
347 QFile::remove("file-renamed-twice.txt");
355 void tst_QFile::initTestCase()
357 QString workingDir = QFileInfo(QFINDTESTDATA("stdinprocess")).absolutePath();
358 QVERIFY2(!workingDir.isEmpty(), qPrintable("Could not find working directory!"));
359 QVERIFY2(QDir::setCurrent(workingDir), qPrintable("Could not chdir to " + workingDir));
361 QFile::remove("noreadfile");
363 // create a file and make it read-only
364 QFile file("readonlyfile");
365 file.open(QFile::WriteOnly);
368 file.setPermissions(QFile::ReadOwner);
370 // create another file and make it not readable
371 file.setFileName("noreadfile");
372 file.open(QFile::WriteOnly);
375 file.setPermissions(0);
378 void tst_QFile::cleanupTestCase()
380 // clean up the files we created
381 QFile::remove("readonlyfile");
382 QFile::remove("noreadfile");
383 QFile::remove("myLink.lnk");
384 QFile::remove("appendme.txt");
385 QFile::remove("createme.txt");
386 QFile::remove("file.txt");
387 QFile::remove("genfile.txt");
388 QFile::remove("seekToPos.txt");
389 QFile::remove("setsizeseek.txt");
390 QFile::remove("stdfile.txt");
391 QFile::remove("textfile.txt");
392 QFile::remove("truncate.txt");
393 QFile::remove("winfile.txt");
394 QFile::remove("writeonlyfile");
395 QFile::remove("largeblockfile.txt");
396 QFile::remove("tst_qfile_copy.cpp");
397 QFile::remove("nullinline.txt");
398 QFile::remove("myLink2.lnk");
399 QFile::remove("resources");
400 QFile::remove("qfile_map_testfile");
401 QFile::remove("readAllBuffer.txt");
402 QFile::remove("qt_file.tmp");
403 QFile::remove("File.txt");
406 //------------------------------------------
407 // The 'testfile' is currently just a
408 // testfile. The path of this file, the
409 // attributes and the contents itself
410 // will be changed as far as we have a
411 // proper way to handle files in the
412 // testing environment.
413 //------------------------------------------
415 void tst_QFile::exists()
417 QFile f( QFINDTESTDATA("testfile.txt") );
420 QFile file("nobodyhassuchafile");
422 QVERIFY(!file.exists());
424 QFile file2("nobodyhassuchafile");
425 QVERIFY(file2.open(QIODevice::WriteOnly));
428 QVERIFY(file.exists());
430 QVERIFY(file.open(QIODevice::WriteOnly));
432 QVERIFY(file.exists());
435 QVERIFY(!file.exists());
437 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
438 QFile unc("//" + QtNetworkSettings::winServerName() + "/testshare/readme.txt");
439 QVERIFY(unc.exists());
443 void tst_QFile::open_data()
445 QTest::addColumn<QString>("filename");
446 QTest::addColumn<int>("mode");
447 QTest::addColumn<bool>("ok");
448 QTest::addColumn<QFile::FileError>("status");
451 static const QString denied("Operation not permitted");
453 static const QString denied("Permission denied");
455 QTest::newRow( "exist_readOnly" )
456 << QString(QFINDTESTDATA("testfile.txt")) << int(QIODevice::ReadOnly)
457 << true << QFile::NoError;
459 QTest::newRow( "exist_writeOnly" )
460 << QString("readonlyfile")
461 << int(QIODevice::WriteOnly)
465 QTest::newRow( "exist_append" )
466 << QString("readonlyfile") << int(QIODevice::Append)
467 << false << QFile::OpenError;
469 QTest::newRow( "nonexist_readOnly" )
470 << QString("nonExist.txt") << int(QIODevice::ReadOnly)
471 << false << QFile::OpenError;
473 QTest::newRow("emptyfile")
475 << int(QIODevice::ReadOnly)
479 QTest::newRow("nullfile") << QString() << int(QIODevice::ReadOnly) << false
482 QTest::newRow("two-dots") << QString(QFINDTESTDATA("two.dots.file")) << int(QIODevice::ReadOnly) << true
485 QTest::newRow("readonlyfile") << QString("readonlyfile") << int(QIODevice::WriteOnly)
486 << false << QFile::OpenError;
487 QTest::newRow("noreadfile") << QString("noreadfile") << int(QIODevice::ReadOnly)
488 << false << QFile::OpenError;
489 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
490 //opening devices requires administrative privileges (and elevation).
491 HANDLE hTest = CreateFile(_T("\\\\.\\PhysicalDrive0"), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
492 if (hTest != INVALID_HANDLE_VALUE) {
494 QTest::newRow("//./PhysicalDrive0") << QString("//./PhysicalDrive0") << int(QIODevice::ReadOnly)
495 << true << QFile::NoError;
497 QTest::newRow("//./PhysicalDrive0") << QString("//./PhysicalDrive0") << int(QIODevice::ReadOnly)
498 << false << QFile::OpenError;
500 QTest::newRow("uncFile") << "//" + QtNetworkSettings::winServerName() + "/testshare/test.pri" << int(QIODevice::ReadOnly)
501 << true << QFile::NoError;
505 void tst_QFile::open()
507 QFETCH( QString, filename );
514 #if defined(Q_OS_UNIX)
516 // root and Chuck Norris don't care for file permissions. Skip.
517 QSKIP("Running this test as root doesn't make sense");
520 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
521 QEXPECT_FAIL("noreadfile", "Windows does not currently support non-readable files.", Abort);
523 if (filename.isEmpty())
524 QTest::ignoreMessage(QtWarningMsg, "QFSFileEngine::open: No file name specified");
526 QCOMPARE(f.open( QIODevice::OpenMode(mode) ), ok);
528 QTEST( f.error(), "status" );
531 void tst_QFile::openUnbuffered()
533 QFile file(QFINDTESTDATA("testfile.txt"));
534 QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Unbuffered));
536 QVERIFY(file.seek(1));
537 QCOMPARE(file.pos(), qint64(1));
538 QVERIFY(file.getChar(&c));
539 QCOMPARE(file.pos(), qint64(2));
541 QVERIFY(file.seek(3));
542 QCOMPARE(file.pos(), qint64(3));
543 QVERIFY(file.getChar(&d));
544 QCOMPARE(file.pos(), qint64(4));
545 QVERIFY(file.seek(1));
546 QCOMPARE(file.pos(), qint64(1));
548 QVERIFY(file.getChar(&c2));
549 QCOMPARE(file.pos(), qint64(2));
550 QVERIFY(file.seek(3));
551 QCOMPARE(file.pos(), qint64(3));
553 QVERIFY(file.getChar(&d2));
554 QCOMPARE(file.pos(), qint64(4));
561 void tst_QFile::size_data()
563 QTest::addColumn<QString>("filename");
564 QTest::addColumn<qint64>("size");
566 QTest::newRow( "exist01" ) << QString(QFINDTESTDATA("testfile.txt")) << (qint64)245;
567 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
568 // Only test UNC on Windows./
569 QTest::newRow("unc") << "//" + QString(QtNetworkSettings::winServerName() + "/testshare/test.pri") << (qint64)34;
573 void tst_QFile::size()
575 QFETCH( QString, filename );
576 QFETCH( qint64, size );
579 filename = QFileInfo(filename).absoluteFilePath();
584 QCOMPARE( f.size(), size );
586 QVERIFY( f.open(QIODevice::ReadOnly) );
587 QCOMPARE( f.size(), size );
592 FILE* stream = QT_FOPEN(filename.toLocal8Bit().constData(), "rb");
594 QVERIFY( f.open(stream, QIODevice::ReadOnly) );
595 QCOMPARE( f.size(), size );
601 // Currently low level file I/O is not well supported on Windows CE, so
602 // skip this part of the test.
607 int fd = QT_OPEN(filename.toLocal8Bit().constData(), QT_OPEN_RDONLY);
610 QVERIFY( f.open(fd, QIODevice::ReadOnly) );
611 QCOMPARE( f.size(), size );
619 void tst_QFile::sizeNoExist()
621 QFile file("nonexist01");
622 QVERIFY( !file.exists() );
623 QCOMPARE( file.size(), (qint64)0 );
624 QVERIFY( !file.open(QIODevice::ReadOnly) );
627 void tst_QFile::seek()
629 QFile::remove("newfile.txt");
630 QFile file("newfile.txt");
631 file.open(QIODevice::WriteOnly);
632 QCOMPARE(file.size(), qint64(0));
633 QCOMPARE(file.pos(), qint64(0));
634 QVERIFY(file.seek(10));
635 QCOMPARE(file.pos(), qint64(10));
636 QCOMPARE(file.size(), qint64(0));
638 QFile::remove("newfile.txt");
641 void tst_QFile::setSize()
643 if ( QFile::exists( "createme.txt" ) )
644 QFile::remove( "createme.txt" );
645 QVERIFY( !QFile::exists( "createme.txt" ) );
647 QFile f("createme.txt");
648 QVERIFY(f.open(QIODevice::Truncate | QIODevice::ReadWrite));
656 QCOMPARE(f.size(), (qlonglong)1);
657 bool ok = f.resize(99);
659 QCOMPARE(f.size(), (qlonglong)99);
666 QVERIFY(f.resize(1));
667 QCOMPARE(f.size(), (qlonglong)1);
676 QCOMPARE(f.size(), (qlonglong)1);
677 QVERIFY(f.resize(100));
678 QCOMPARE(f.size(), (qlonglong)100);
679 QVERIFY(f.resize(50));
680 QCOMPARE(f.size(), (qlonglong)50);
683 void tst_QFile::setSizeSeek()
685 QFile::remove("setsizeseek.txt");
686 QFile f("setsizeseek.txt");
687 QVERIFY(f.open(QFile::WriteOnly));
690 QCOMPARE(f.pos(), qint64(4));
692 QCOMPARE(f.pos(), qint64(2));
694 QCOMPARE(f.pos(), qint64(2));
696 QCOMPARE(f.pos(), qint64(0));
698 QCOMPARE(f.pos(), qint64(0));
701 QCOMPARE(f.pos(), qint64(3));
703 QCOMPARE(f.pos(), qint64(2));
706 void tst_QFile::atEnd()
708 QFile f( QFINDTESTDATA("testfile.txt") );
709 QVERIFY(f.open( QIODevice::ReadOnly ));
714 bool end = f.atEnd();
719 void tst_QFile::readLine()
721 QFile f( QFINDTESTDATA("testfile.txt") );
722 QVERIFY(f.open( QIODevice::ReadOnly ));
727 while ( (foo=f.readLine( p, 128 )) > 0 ) {
730 QCOMPARE( p[0], 'T' );
731 QCOMPARE( p[3], 's' );
732 QCOMPARE( p[11], 'i' );
739 void tst_QFile::readLine2()
741 QFile f( QFINDTESTDATA("testfile.txt") );
742 f.open( QIODevice::ReadOnly );
745 QCOMPARE(f.readLine(p, 60), qlonglong(59));
746 QCOMPARE(f.readLine(p, 60), qlonglong(59));
747 memset(p, '@', sizeof(p));
748 QCOMPARE(f.readLine(p, 60), qlonglong(59));
750 QCOMPARE(p[57], '-');
751 QCOMPARE(p[58], '\n');
752 QCOMPARE(p[59], '\0');
753 QCOMPARE(p[60], '@');
756 void tst_QFile::readLineNullInLine()
758 QFile::remove("nullinline.txt");
759 QFile file("nullinline.txt");
760 QVERIFY(file.open(QIODevice::ReadWrite));
761 QVERIFY(file.write("linewith\0null\nanotherline\0withnull\n\0\nnull\0", 42) > 0);
762 QVERIFY(file.flush());
765 QCOMPARE(file.readLine(), QByteArray("linewith\0null\n", 14));
766 QCOMPARE(file.readLine(), QByteArray("anotherline\0withnull\n", 21));
767 QCOMPARE(file.readLine(), QByteArray("\0\n", 2));
768 QCOMPARE(file.readLine(), QByteArray("null\0", 5));
769 QCOMPARE(file.readLine(), QByteArray());
772 void tst_QFile::readAll_data()
774 QTest::addColumn<bool>("textMode");
775 QTest::addColumn<QString>("fileName");
776 QTest::newRow( "TextMode unixfile" ) << true << QFINDTESTDATA("testfile.txt");
777 QTest::newRow( "BinaryMode unixfile" ) << false << QFINDTESTDATA("testfile.txt");
778 QTest::newRow( "TextMode dosfile" ) << true << QFINDTESTDATA("dosfile.txt");
779 QTest::newRow( "BinaryMode dosfile" ) << false << QFINDTESTDATA("dosfile.txt");
780 QTest::newRow( "TextMode bigfile" ) << true << QFINDTESTDATA("tst_qfile.cpp");
781 QTest::newRow( "BinaryMode bigfile" ) << false << QFINDTESTDATA("tst_qfile.cpp");
782 QVERIFY(QFile(QFINDTESTDATA("tst_qfile.cpp")).size() > 64*1024);
785 void tst_QFile::readAll()
787 QFETCH( bool, textMode );
788 QFETCH( QString, fileName );
790 QFile file(fileName);
792 QVERIFY(file.open(QFile::Text | QFile::ReadOnly));
794 QVERIFY(file.open(QFile::ReadOnly));
796 QByteArray a = file.readAll();
798 QVERIFY(file.pos() == 0);
800 QVERIFY(file.bytesAvailable() > 7);
801 QByteArray b = file.read(1);
805 b.append(file.read(5));
806 b.append(file.readAll());
811 void tst_QFile::readAllBuffer()
813 QString fileName = QLatin1String("readAllBuffer.txt");
815 QFile::remove(fileName);
817 QFile writer(fileName);
818 QFile reader(fileName);
820 QByteArray data1("This is arguably a very simple text.");
821 QByteArray data2("This is surely not as simple a test.");
823 QVERIFY( writer.open(QIODevice::ReadWrite | QIODevice::Unbuffered) );
824 QVERIFY( reader.open(QIODevice::ReadOnly) );
826 QCOMPARE( writer.write(data1), qint64(data1.size()) );
827 QVERIFY( writer.seek(0) );
830 result = reader.read(18);
831 QCOMPARE( result.size(), 18 );
833 QCOMPARE( writer.write(data2), qint64(data2.size()) ); // new data, old version buffered in reader
834 QCOMPARE( writer.write(data2), qint64(data2.size()) ); // new data, unbuffered in reader
836 result += reader.readAll();
838 QCOMPARE( result, data1 + data2 );
840 QFile::remove(fileName);
843 void tst_QFile::readAllStdin()
845 #if defined(Q_OS_WINCE)
846 QSKIP("Currently no stdin/out supported for Windows CE");
848 #if defined(QT_NO_PROCESS)
849 QSKIP("Qt was compiled with QT_NO_PROCESS");
851 QByteArray lotsOfData(1024, '@'); // 10 megs
854 process.start("stdinprocess/stdinprocess all");
855 QVERIFY( process.waitForStarted() );
856 for (int i = 0; i < 5; ++i) {
858 process.write(lotsOfData);
859 while (process.bytesToWrite() > 0) {
860 QVERIFY(process.waitForBytesWritten());
864 process.closeWriteChannel();
865 process.waitForFinished();
866 QCOMPARE(process.readAll().size(), lotsOfData.size() * 5);
870 void tst_QFile::readLineStdin()
872 #if defined(Q_OS_WINCE)
873 QSKIP("Currently no stdin/out supported for Windows CE");
875 #if defined(QT_NO_PROCESS)
876 QSKIP("Qt was compiled with QT_NO_PROCESS");
879 QByteArray lotsOfData(1024, '@'); // 10 megs
880 for (int i = 0; i < lotsOfData.size(); ++i) {
882 lotsOfData[i] = '\n';
884 lotsOfData[i] = char('0' + i % 32);
887 for (int i = 0; i < 2; ++i) {
889 process.start((QString("stdinprocess/stdinprocess line %1").arg(i)), QIODevice::Text | QIODevice::ReadWrite);
890 for (int i = 0; i < 5; ++i) {
892 process.write(lotsOfData);
893 while (process.bytesToWrite() > 0) {
894 QVERIFY(process.waitForBytesWritten());
898 process.closeWriteChannel();
899 QVERIFY(process.waitForFinished(5000));
901 QByteArray array = process.readAll();
902 QCOMPARE(array.size(), lotsOfData.size() * 5);
903 for (int i = 0; i < array.size(); ++i) {
905 QCOMPARE(char(array[i]), '\n');
907 QCOMPARE(char(array[i]), char('0' + i % 32));
913 void tst_QFile::readLineStdin_lineByLine()
915 #if defined(Q_OS_WINCE)
916 QSKIP("Currently no stdin/out supported for Windows CE");
918 #if defined(QT_NO_PROCESS)
919 QSKIP("Qt was compiled with QT_NO_PROCESS");
921 for (int i = 0; i < 2; ++i) {
923 process.start(QString("stdinprocess/stdinprocess line %1").arg(i), QIODevice::Text | QIODevice::ReadWrite);
924 QVERIFY(process.waitForStarted());
926 for (int j = 0; j < 3; ++j) {
927 QByteArray line = "line " + QByteArray::number(j) + "\n";
928 QCOMPARE(process.write(line), qint64(line.size()));
929 QVERIFY(process.waitForBytesWritten(2000));
930 if (process.bytesAvailable() == 0)
931 QVERIFY(process.waitForReadyRead(2000));
932 QCOMPARE(process.readAll(), line);
935 process.closeWriteChannel();
936 QVERIFY(process.waitForFinished(5000));
941 void tst_QFile::text()
943 // dosfile.txt is a binary CRLF file
944 QFile file(QFINDTESTDATA("dosfile.txt"));
945 QVERIFY(file.open(QFile::Text | QFile::ReadOnly));
946 QCOMPARE(file.readLine(),
947 QByteArray("/dev/system/root / reiserfs acl,user_xattr 1 1\n"));
948 QCOMPARE(file.readLine(),
949 QByteArray("/dev/sda1 /boot ext3 acl,user_xattr 1 2\n"));
950 file.ungetChar('\n');
952 QCOMPARE(file.readLine().constData(), QByteArray("2\n").constData());
955 void tst_QFile::missingEndOfLine()
957 QFile file(QFINDTESTDATA("noendofline.txt"));
958 QVERIFY(file.open(QFile::ReadOnly));
961 while (!file.atEnd()) {
969 void tst_QFile::readBlock()
971 QFile f( QFINDTESTDATA("testfile.txt") );
972 f.open( QIODevice::ReadOnly );
976 length = f.read( p, 256 );
978 QCOMPARE( length, 245 );
979 QCOMPARE( p[59], 'D' );
980 QCOMPARE( p[178], 'T' );
981 QCOMPARE( p[199], 'l' );
984 void tst_QFile::getch()
986 QFile f( QFINDTESTDATA("testfile.txt") );
987 f.open( QIODevice::ReadOnly );
991 while (f.getChar(&c)) {
992 QCOMPARE(f.pos(), qint64(i + 1));
1001 void tst_QFile::ungetChar()
1003 QFile f(QFINDTESTDATA("testfile.txt"));
1004 QVERIFY(f.open(QIODevice::ReadOnly));
1006 QByteArray array = f.readLine();
1007 QCOMPARE(array.constData(), "----------------------------------------------------------\n");
1010 array = f.readLine();
1011 QCOMPARE(array.constData(), "\n");
1017 array = f.readLine();
1018 QCOMPARE(array.constData(), "--\n");
1020 QFile::remove("genfile.txt");
1021 QFile out("genfile.txt");
1022 QVERIFY(out.open(QIODevice::ReadWrite));
1025 QCOMPARE(out.readAll().constData(), "123");
1029 QCOMPARE(out.readAll().constData(), "124");
1034 QCOMPARE(out.read(buf, sizeof(buf)), qint64(3));
1035 QCOMPARE(buf[0], '1');
1036 QCOMPARE(buf[1], '2');
1037 QCOMPARE(buf[2], '4');
1040 void tst_QFile::invalidFile_data()
1042 QTest::addColumn<QString>("fileName");
1043 #if !defined(Q_OS_WIN)
1044 QTest::newRow( "x11" ) << QString( "qwe//" );
1046 QTest::newRow( "colon1" ) << QString( "fail:invalid" );
1047 QTest::newRow( "colon2" ) << QString( "f:ail:invalid" );
1048 QTest::newRow( "colon3" ) << QString( ":failinvalid" );
1049 QTest::newRow( "forwardslash" ) << QString( "fail/invalid" );
1050 QTest::newRow( "asterisk" ) << QString( "fail*invalid" );
1051 QTest::newRow( "questionmark" ) << QString( "fail?invalid" );
1052 QTest::newRow( "quote" ) << QString( "fail\"invalid" );
1053 QTest::newRow( "lt" ) << QString( "fail<invalid" );
1054 QTest::newRow( "gt" ) << QString( "fail>invalid" );
1055 QTest::newRow( "pipe" ) << QString( "fail|invalid" );
1059 void tst_QFile::invalidFile()
1061 QFETCH( QString, fileName );
1062 QFile f( fileName );
1063 QEXPECT_FAIL("colon1", "QTBUG-27306", Continue);
1064 QVERIFY( !f.open( QIODevice::ReadWrite ) );
1067 void tst_QFile::createFile()
1069 if ( QFile::exists( "createme.txt" ) )
1070 QFile::remove( "createme.txt" );
1071 QVERIFY( !QFile::exists( "createme.txt" ) );
1073 QFile f( "createme.txt" );
1074 QVERIFY( f.open( QIODevice::WriteOnly ) );
1076 QVERIFY( QFile::exists( "createme.txt" ) );
1079 void tst_QFile::append()
1081 const QString name("appendme.txt");
1082 if (QFile::exists(name))
1083 QFile::remove(name);
1084 QVERIFY(!QFile::exists(name));
1087 QVERIFY(f.open(QIODevice::WriteOnly | QIODevice::Truncate));
1091 QVERIFY(f.open(QIODevice::Append));
1092 QVERIFY(f.pos() == 1);
1095 QCOMPARE(int(f.size()), 2);
1098 void tst_QFile::permissions_data()
1100 QTest::addColumn<QString>("file");
1101 QTest::addColumn<uint>("perms");
1102 QTest::addColumn<bool>("expected");
1103 QTest::addColumn<bool>("create");
1105 QTest::newRow("data0") << QCoreApplication::instance()->applicationFilePath() << uint(QFile::ExeUser) << true << false;
1106 QTest::newRow("data1") << QFINDTESTDATA("tst_qfile.cpp") << uint(QFile::ReadUser) << true << false;
1107 QTest::newRow("readonly") << QFINDTESTDATA("readonlyfile") << uint(QFile::WriteUser) << false << false;
1109 QTest::newRow("longfile") << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1110 "longFileNamelongFileNamelongFileNamelongFileName"
1111 "longFileNamelongFileNamelongFileNamelongFileName"
1112 "longFileNamelongFileNamelongFileNamelongFileName"
1113 "longFileNamelongFileNamelongFileNamelongFileName.txt") << uint(QFile::ReadUser) << true << true;
1115 QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << uint(QFile::ReadUser) << true << false;
1116 QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1" << uint(QFile::WriteUser) << false << false;
1117 QTest::newRow("resource3") << ":/tst_qfileinfo/resources/file1.ext1" << uint(QFile::ExeUser) << false << false;
1120 void tst_QFile::permissions()
1122 QFETCH(QString, file);
1123 QFETCH(uint, perms);
1124 QFETCH(bool, expected);
1125 QFETCH(bool, create);
1128 QVERIFY(fc.open(QFile::WriteOnly));
1129 QVERIFY(fc.write("hello\n"));
1134 QFile::Permissions memberResult = f.permissions() & perms;
1135 QFile::Permissions staticResult = QFile::permissions(file) & perms;
1138 QFile::remove(file);
1142 if (qt_ntfs_permission_lookup)
1143 QEXPECT_FAIL("readonly", "QTBUG-25630", Abort);
1145 QCOMPARE((memberResult == QFile::Permissions(perms)), expected);
1146 QCOMPARE((staticResult == QFile::Permissions(perms)), expected);
1149 void tst_QFile::permissionsNtfs_data()
1154 void tst_QFile::permissionsNtfs()
1157 QScopedValueRollback<int> ntfsMode(qt_ntfs_permission_lookup);
1158 qt_ntfs_permission_lookup++;
1161 QSKIP("windows test");
1165 void tst_QFile::setPermissions()
1167 if ( QFile::exists( "createme.txt" ) )
1168 QFile::remove( "createme.txt" );
1169 QVERIFY( !QFile::exists( "createme.txt" ) );
1171 QFile f("createme.txt");
1172 QVERIFY(f.open(QIODevice::WriteOnly | QIODevice::Truncate));
1176 QFile::Permissions perms(QFile::WriteUser | QFile::ReadUser);
1177 QVERIFY(f.setPermissions(perms));
1178 QVERIFY((f.permissions() & perms) == perms);
1182 void tst_QFile::copy()
1184 QFile::setPermissions("tst_qfile_copy.cpp", QFile::WriteUser);
1185 QFile::remove("tst_qfile_copy.cpp");
1186 QFile::remove("test2");
1187 QVERIFY(QFile::copy(QFINDTESTDATA("tst_qfile.cpp"), "tst_qfile_copy.cpp"));
1188 QFile in1(QFINDTESTDATA("tst_qfile.cpp")), in2("tst_qfile_copy.cpp");
1189 QVERIFY(in1.open(QFile::ReadOnly));
1190 QVERIFY(in2.open(QFile::ReadOnly));
1191 QByteArray data1 = in1.readAll(), data2 = in2.readAll();
1192 QCOMPARE(data1, data2);
1193 QFile::remove( "main_copy.cpp" );
1195 QFile::copy(QDir::currentPath(), QDir::currentPath() + QLatin1String("/test2"));
1198 void tst_QFile::copyAfterFail()
1200 QFile file1("file-to-be-copied.txt");
1201 QFile file2("existing-file.txt");
1203 QVERIFY(file1.open(QIODevice::ReadWrite) && "(test-precondition)");
1204 QVERIFY(file2.open(QIODevice::ReadWrite) && "(test-precondition)");
1206 QVERIFY(!QFile::exists("copied-file-1.txt") && "(test-precondition)");
1207 QVERIFY(!QFile::exists("copied-file-2.txt") && "(test-precondition)");
1209 QVERIFY(!file1.copy("existing-file.txt"));
1210 QCOMPARE(file1.error(), QFile::CopyError);
1212 QVERIFY(file1.copy("copied-file-1.txt"));
1213 QVERIFY(!file1.isOpen());
1214 QCOMPARE(file1.error(), QFile::NoError);
1216 QVERIFY(!file1.copy("existing-file.txt"));
1217 QCOMPARE(file1.error(), QFile::CopyError);
1219 QVERIFY(file1.copy("copied-file-2.txt"));
1220 QVERIFY(!file1.isOpen());
1221 QCOMPARE(file1.error(), QFile::NoError);
1223 QVERIFY(QFile::exists("copied-file-1.txt"));
1224 QVERIFY(QFile::exists("copied-file-2.txt"));
1226 QVERIFY(QFile::remove("file-to-be-copied.txt") && "(test-cleanup)");
1227 QVERIFY(QFile::remove("existing-file.txt") && "(test-cleanup)");
1228 QVERIFY(QFile::remove("copied-file-1.txt") && "(test-cleanup)");
1229 QVERIFY(QFile::remove("copied-file-2.txt") && "(test-cleanup)");
1232 void tst_QFile::copyRemovesTemporaryFile() const
1234 const QString newName(QLatin1String("copyRemovesTemporaryFile"));
1235 QVERIFY(QFile::copy(QFINDTESTDATA("forCopying.txt"), newName));
1237 QVERIFY(!QFile::exists(QFINDTESTDATA("qt_temp.XXXXXX")));
1238 QVERIFY(QFile::remove(newName));
1241 void tst_QFile::copyShouldntOverwrite()
1243 // Copy should not overwrite existing files.
1244 QFile::remove("tst_qfile.cpy");
1245 QFile file(QFINDTESTDATA("tst_qfile.cpp"));
1246 QVERIFY(file.copy("tst_qfile.cpy"));
1248 bool ok = QFile::setPermissions("tst_qfile.cpy", QFile::WriteOther);
1250 QVERIFY(!file.copy("tst_qfile.cpy"));
1251 QFile::remove("tst_qfile.cpy");
1254 void tst_QFile::copyFallback()
1256 // Using a resource file to trigger QFile::copy's fallback handling
1257 QFile file(":/copy-fallback.qrc");
1258 QFile::remove("file-copy-destination.txt");
1260 QVERIFY2(file.exists(), "test precondition");
1261 QVERIFY2(!QFile::exists("file-copy-destination.txt"), "test precondition");
1263 // Fallback copy of closed file.
1264 QVERIFY(file.copy("file-copy-destination.txt"));
1265 QVERIFY(QFile::exists("file-copy-destination.txt"));
1266 QVERIFY(!file.isOpen());
1269 // Need to reset permissions on Windows to be able to delete
1270 QVERIFY(QFile::setPermissions("file-copy-destination.txt",
1271 QFile::WriteOther));
1273 // Need to reset permissions on Windows to be able to delete
1274 QVERIFY(QFile::setPermissions("file-copy-destination.txt",
1275 QFile::ReadOwner | QFile::WriteOwner));
1277 QVERIFY(QFile::remove("file-copy-destination.txt"));
1279 // Fallback copy of open file.
1280 QVERIFY(file.open(QIODevice::ReadOnly));
1281 QVERIFY(file.copy("file-copy-destination.txt"));
1282 QVERIFY(QFile::exists("file-copy-destination.txt"));
1283 QVERIFY(!file.isOpen());
1286 QFile::remove("file-copy-destination.txt");
1290 #include <objbase.h>
1294 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1295 static QString getWorkingDirectoryForLink(const QString &linkFileName)
1297 bool neededCoInit = false;
1301 HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
1302 if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized
1303 neededCoInit = true;
1305 hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
1308 if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface.
1310 hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
1311 if (SUCCEEDED(hres)) {
1312 hres = ppf->Load((LPOLESTR)linkFileName.utf16(), STGM_READ);
1313 //The original path of the link is retrieved. If the file/folder
1314 //was moved, the return value still have the old path.
1315 if(SUCCEEDED(hres)) {
1316 wchar_t szGotPath[MAX_PATH];
1317 if (psl->GetWorkingDirectory(szGotPath, MAX_PATH) == NOERROR)
1318 ret = QString::fromWCharArray(szGotPath);
1333 void tst_QFile::link()
1335 QFile::remove("myLink.lnk");
1337 QFileInfo info1(QFINDTESTDATA("tst_qfile.cpp"));
1338 QString referenceTarget = QDir::cleanPath(info1.absoluteFilePath());
1340 QVERIFY(QFile::link(QFINDTESTDATA("tst_qfile.cpp"), "myLink.lnk"));
1342 QFileInfo info2("myLink.lnk");
1343 QVERIFY(info2.isSymLink());
1344 QCOMPARE(info2.symLinkTarget(), referenceTarget);
1346 QFile link("myLink.lnk");
1347 QVERIFY(link.open(QIODevice::ReadOnly));
1348 QCOMPARE(link.symLinkTarget(), referenceTarget);
1351 QCOMPARE(QFile::symLinkTarget("myLink.lnk"), referenceTarget);
1353 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1354 QString wd = getWorkingDirectoryForLink(info2.absoluteFilePath());
1355 QCOMPARE(QDir::fromNativeSeparators(wd), QDir::cleanPath(info1.absolutePath()));
1358 QVERIFY(QFile::remove(info2.absoluteFilePath()));
1361 void tst_QFile::linkToDir()
1363 QFile::remove("myLinkToDir.lnk");
1366 QFileInfo info1("myDir");
1367 QVERIFY(QFile::link("myDir", "myLinkToDir.lnk"));
1368 QFileInfo info2("myLinkToDir.lnk");
1369 #if !(defined Q_OS_HPUX && defined(__ia64))
1370 // absurd HP-UX filesystem bug on gravlaks - checking if a symlink
1371 // resolves or not alters the file system to make the broken symlink
1373 QVERIFY(info2.isSymLink());
1375 QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath());
1376 QVERIFY(QFile::remove(info2.absoluteFilePath()));
1377 QFile::remove("myLinkToDir.lnk");
1381 void tst_QFile::absolutePathLinkToRelativePath()
1383 QFile::remove("myDir/test.txt");
1384 QFile::remove("myDir/myLink.lnk");
1387 QFile("myDir/test.txt").open(QFile::WriteOnly);
1390 QVERIFY(QFile::link("test.txt", "myDir/myLink.lnk"));
1392 QVERIFY(QFile::link("myDir/test.txt", "myDir/myLink.lnk"));
1394 QEXPECT_FAIL("", "Symlinking using relative paths is currently different on Windows and Unix", Continue);
1395 QCOMPARE(QFileInfo(QFile(QFileInfo("myDir/myLink.lnk").absoluteFilePath()).symLinkTarget()).absoluteFilePath(),
1396 QFileInfo("myDir/test.txt").absoluteFilePath());
1398 QFile::remove("myDir/test.txt");
1399 QFile::remove("myDir/myLink.lnk");
1403 void tst_QFile::readBrokenLink()
1405 QFile::remove("myLink2.lnk");
1406 QFileInfo info1("file12");
1407 QVERIFY(QFile::link("file12", "myLink2.lnk"));
1408 QFileInfo info2("myLink2.lnk");
1409 QVERIFY(info2.isSymLink());
1410 QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath());
1411 QVERIFY(QFile::remove(info2.absoluteFilePath()));
1412 QVERIFY(QFile::link("ole/..", "myLink2.lnk"));
1413 QCOMPARE(QFileInfo("myLink2.lnk").symLinkTarget(), QDir::currentPath());
1416 void tst_QFile::readTextFile_data()
1418 QTest::addColumn<QByteArray>("in");
1419 QTest::addColumn<QByteArray>("out");
1421 QTest::newRow("empty") << QByteArray() << QByteArray();
1422 QTest::newRow("a") << QByteArray("a") << QByteArray("a");
1423 QTest::newRow("a\\rb") << QByteArray("a\rb") << QByteArray("ab");
1424 QTest::newRow("\\n") << QByteArray("\n") << QByteArray("\n");
1425 QTest::newRow("\\r\\n") << QByteArray("\r\n") << QByteArray("\n");
1426 QTest::newRow("\\r") << QByteArray("\r") << QByteArray();
1427 QTest::newRow("twolines") << QByteArray("Hello\r\nWorld\r\n") << QByteArray("Hello\nWorld\n");
1428 QTest::newRow("twolines no endline") << QByteArray("Hello\r\nWorld") << QByteArray("Hello\nWorld");
1431 void tst_QFile::readTextFile()
1433 QFETCH(QByteArray, in);
1434 QFETCH(QByteArray, out);
1436 QFile winfile("winfile.txt");
1437 QVERIFY(winfile.open(QFile::WriteOnly | QFile::Truncate));
1441 QVERIFY(winfile.open(QFile::ReadOnly));
1442 QCOMPARE(winfile.readAll(), in);
1445 QVERIFY(winfile.open(QFile::ReadOnly | QFile::Text));
1446 QCOMPARE(winfile.readAll(), out);
1449 void tst_QFile::readTextFile2()
1452 QFile file(QFINDTESTDATA("testlog.txt"));
1453 QVERIFY(file.open(QIODevice::ReadOnly));
1458 QFile file(QFINDTESTDATA("testlog.txt"));
1459 QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
1464 void tst_QFile::writeTextFile_data()
1466 QTest::addColumn<QByteArray>("in");
1468 QTest::newRow("empty") << QByteArray();
1469 QTest::newRow("a") << QByteArray("a");
1470 QTest::newRow("a\\rb") << QByteArray("a\rb");
1471 QTest::newRow("\\n") << QByteArray("\n");
1472 QTest::newRow("\\r\\n") << QByteArray("\r\n");
1473 QTest::newRow("\\r") << QByteArray("\r");
1474 QTest::newRow("twolines crlf") << QByteArray("Hello\r\nWorld\r\n");
1475 QTest::newRow("twolines crlf no endline") << QByteArray("Hello\r\nWorld");
1476 QTest::newRow("twolines lf") << QByteArray("Hello\nWorld\n");
1477 QTest::newRow("twolines lf no endline") << QByteArray("Hello\nWorld");
1478 QTest::newRow("mixed") << QByteArray("this\nis\r\na\nmixed\r\nfile\n");
1481 void tst_QFile::writeTextFile()
1483 QFETCH(QByteArray, in);
1485 QFile file("textfile.txt");
1486 QVERIFY(file.open(QFile::WriteOnly | QFile::Truncate | QFile::Text));
1487 QByteArray out = in;
1489 out.replace('\n', "\r\n");
1491 QCOMPARE(file.write(in), qlonglong(in.size()));
1494 file.open(QFile::ReadOnly);
1495 QCOMPARE(file.readAll(), out);
1498 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1499 void tst_QFile::largeUncFileSupport()
1501 qint64 size = Q_INT64_C(8589934592);
1502 qint64 dataOffset = Q_INT64_C(8589914592);
1503 QByteArray knownData("LargeFile content at offset 8589914592");
1504 QString largeFile("//" + QtNetworkSettings::winServerName() + "/testsharelargefile/file.bin");
1507 // 1) Native file handling.
1508 QFile file(largeFile);
1509 QCOMPARE(file.size(), size);
1510 QVERIFY(file.open(QIODevice::ReadOnly));
1511 QCOMPARE(file.size(), size);
1512 QVERIFY(file.seek(dataOffset));
1513 QCOMPARE(file.read(knownData.size()), knownData);
1516 // 2) stdlib file handling.
1518 FILE *fh = fopen(QFile::encodeName(largeFile).data(), "rb");
1519 QVERIFY(file.open(fh, QIODevice::ReadOnly));
1520 QCOMPARE(file.size(), size);
1521 QVERIFY(file.seek(dataOffset));
1522 QCOMPARE(file.read(knownData.size()), knownData);
1526 // 3) stdio file handling.
1528 FILE *fh = fopen(QFile::encodeName(largeFile).data(), "rb");
1529 int fd = int(_fileno(fh));
1530 QVERIFY(file.open(fd, QIODevice::ReadOnly));
1531 QCOMPARE(file.size(), size);
1532 QVERIFY(file.seek(dataOffset));
1533 QCOMPARE(file.read(knownData.size()), knownData);
1539 void tst_QFile::tailFile()
1541 QSKIP("File change notifications are so far unsupported.");
1543 QFile file("tail.txt");
1544 QVERIFY(file.open(QFile::WriteOnly | QFile::Append));
1546 QFile tailFile("tail.txt");
1547 QVERIFY(tailFile.open(QFile::ReadOnly));
1548 tailFile.seek(file.size());
1550 QSignalSpy readSignalSpy(&tailFile, SIGNAL(readyRead()));
1551 QVERIFY(readSignalSpy.isValid());
1555 QTestEventLoop::instance().enterLoop(5);
1557 QVERIFY(!QTestEventLoop::instance().timeout());
1558 QCOMPARE(readSignalSpy.count(), 1);
1561 void tst_QFile::flush()
1563 QString fileName("stdfile.txt");
1565 QFile::remove(fileName);
1568 QFile file(fileName);
1569 QVERIFY(file.open(QFile::WriteOnly));
1570 QCOMPARE(file.write("abc", 3),qint64(3));
1574 QFile file(fileName);
1575 QVERIFY(file.open(QFile::WriteOnly | QFile::Append));
1576 QCOMPARE(file.pos(), qlonglong(3));
1577 QCOMPARE(file.write("def", 3), qlonglong(3));
1578 QCOMPARE(file.pos(), qlonglong(6));
1582 QFile file("stdfile.txt");
1583 QVERIFY(file.open(QFile::ReadOnly));
1584 QCOMPARE(file.readAll(), QByteArray("abcdef"));
1587 QFile::remove(fileName);
1590 void tst_QFile::bufferedRead()
1592 QFile::remove("stdfile.txt");
1594 QFile file("stdfile.txt");
1595 QVERIFY(file.open(QFile::WriteOnly));
1596 file.write("abcdef");
1599 #if defined(Q_OS_WINCE)
1600 FILE *stdFile = fopen((QCoreApplication::applicationDirPath() + "/stdfile.txt").toLatin1() , "r");
1602 FILE *stdFile = fopen("stdfile.txt", "r");
1606 QCOMPARE(int(fread(&c, 1, 1, stdFile)), 1);
1608 QCOMPARE(int(ftell(stdFile)), 1);
1612 QVERIFY(file.open(stdFile, QFile::ReadOnly));
1613 QCOMPARE(file.pos(), qlonglong(1));
1614 QCOMPARE(file.read(&c, 1), qlonglong(1));
1616 QCOMPARE(file.pos(), qlonglong(2));
1622 void tst_QFile::isSequential()
1625 QSKIP("Unix only test.");
1627 QFile zero("/dev/null");
1628 QVERIFY(zero.open(QFile::ReadOnly));
1629 QVERIFY(zero.isSequential());
1632 void tst_QFile::encodeName()
1634 QCOMPARE(QFile::encodeName(QString::null), QByteArray());
1637 void tst_QFile::truncate()
1639 for (int i = 0; i < 2; ++i) {
1640 QFile file("truncate.txt");
1641 QVERIFY(file.open(QFile::WriteOnly));
1642 file.write(QByteArray(200, '@'));
1645 QVERIFY(file.open((i ? QFile::WriteOnly : QFile::ReadWrite) | QFile::Truncate));
1646 file.write(QByteArray(100, '$'));
1649 QVERIFY(file.open(QFile::ReadOnly));
1650 QCOMPARE(file.readAll(), QByteArray(100, '$'));
1654 void tst_QFile::seekToPos()
1657 QFile file("seekToPos.txt");
1658 QVERIFY(file.open(QFile::WriteOnly));
1659 file.write("a\r\nb\r\nc\r\n");
1663 QFile file("seekToPos.txt");
1664 QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1667 QVERIFY(file.getChar(&c));
1670 QCOMPARE(file.pos(), qint64(3));
1671 file.seek(file.pos());
1672 QCOMPARE(file.pos(), qint64(3));
1675 file.seek(file.pos());
1676 QCOMPARE(file.pos(), qint64(1));
1680 void tst_QFile::seekAfterEndOfFile()
1682 QLatin1String filename("seekAfterEof.dat");
1683 QFile::remove(filename);
1685 QFile file(filename);
1686 QVERIFY(file.open(QFile::WriteOnly));
1688 QCOMPARE(file.size(), qint64(4));
1691 QCOMPARE(file.size(), qint64(12));
1694 QCOMPARE(file.size(), qint64(12));
1697 QCOMPARE(file.size(), qint64(20));
1701 QFile file(filename);
1702 QVERIFY(file.open(QFile::ReadOnly));
1703 QByteArray contents = file.readAll();
1704 QCOMPARE(contents.left(12), QByteArray("abcdefghijkl", 12));
1705 //bytes 12-15 are uninitialised so we don't care what they read as.
1706 QCOMPARE(contents.mid(16), QByteArray("----", 4));
1708 QFile::remove(filename);
1711 void tst_QFile::FILEReadWrite()
1713 // Tests modifying a file. First creates it then reads in 4 bytes and then overwrites these
1714 // 4 bytes with new values. At the end check to see the file contains the new values.
1716 QFile::remove("FILEReadWrite.txt");
1720 QFile f("FILEReadWrite.txt");
1721 QVERIFY(f.open(QFile::WriteOnly));
1751 FILE *fp = fopen(qPrintable(QCoreApplication::applicationDirPath() + "\\FILEReadWrite.txt"), "r+b");
1753 FILE *fp = fopen("FILEReadWrite.txt", "r+b");
1757 QVERIFY(file.open(fp, QFile::ReadWrite));
1758 QDataStream sfile(&file) ;
1760 qint8 var1,var2,var3,var4;
1761 while (!sfile.atEnd())
1763 qint64 base = file.pos();
1765 QCOMPARE(file.pos(), base + 0);
1767 QCOMPARE(file.pos(), base + 1);
1768 file.flush(); // flushing should not change the base
1769 QCOMPARE(file.pos(), base + 1);
1771 QCOMPARE(file.pos(), base + 2);
1773 QCOMPARE(file.pos(), base + 3);
1775 QCOMPARE(file.pos(), base + 4);
1776 file.seek(file.pos() - 4) ; // Move it back 4, for we are going to write new values based on old ones
1777 QCOMPARE(file.pos(), base + 0);
1778 sfile << qint8(var1 + 5);
1779 QCOMPARE(file.pos(), base + 1);
1780 sfile << qint8(var2 + 5);
1781 QCOMPARE(file.pos(), base + 2);
1782 sfile << qint8(var3 + 5);
1783 QCOMPARE(file.pos(), base + 3);
1784 sfile << qint8(var4 + 5);
1785 QCOMPARE(file.pos(), base + 4);
1791 // check modified file
1793 QFile f("FILEReadWrite.txt");
1794 QVERIFY(f.open(QFile::ReadOnly));
1798 QCOMPARE(c, (qint8)5);
1800 QCOMPARE(c, (qint8)6);
1802 QCOMPARE(c, (qint8)7);
1804 QCOMPARE(c, (qint8)8);
1806 QCOMPARE(c, (qint8)9);
1808 QCOMPARE(c, (qint8)10);
1810 QCOMPARE(c, (qint8)11);
1812 QCOMPARE(c, (qint8)12);
1814 QCOMPARE(c, (qint8)13);
1816 QCOMPARE(c, (qint8)14);
1818 QCOMPARE(c, (qint8)15);
1820 QCOMPARE(c, (qint8)16);
1824 QFile::remove("FILEReadWrite.txt");
1829 #include <qglobal.h>
1831 #define FILESIZE 0x10000000f
1832 void tst_QFile::largeFileSupport()
1835 QSKIP("Solaris does not support statfs");
1837 qlonglong sizeNeeded = 2147483647;
1840 qlonglong freespace = qlonglong(0);
1842 _ULARGE_INTEGER free;
1843 if (::GetDiskFreeSpaceEx((wchar_t*)QDir::currentPath().utf16(), &free, 0, 0))
1844 freespace = free.QuadPart;
1845 if (freespace != 0) {
1846 #elif defined(Q_OS_IRIX)
1848 if (statfs(QDir::currentPath().local8Bit(), &info, sizeof(struct statfs), 0) == 0) {
1849 freespace = qlonglong(info.f_bfree * info.f_bsize);
1852 if (statfs(const_cast<char *>(QDir::currentPath().toLocal8Bit().constData()), &info) == 0) {
1853 freespace = qlonglong(info.f_bavail * info.f_bsize);
1855 if (freespace > sizeNeeded) {
1856 QFile bigFile("bigfile");
1857 if (bigFile.open(QFile::ReadWrite)) {
1858 char c[BUFFSIZE] = {'a'};
1859 QVERIFY(bigFile.write(c, BUFFSIZE) == BUFFSIZE);
1860 qlonglong oldPos = bigFile.pos();
1861 QVERIFY(bigFile.resize(sizeNeeded));
1862 QCOMPARE(oldPos, bigFile.pos());
1863 QVERIFY(bigFile.seek(sizeNeeded - BUFFSIZE));
1864 QVERIFY(bigFile.write(c, BUFFSIZE) == BUFFSIZE);
1867 if (bigFile.open(QFile::ReadOnly)) {
1868 QVERIFY(bigFile.read(c, BUFFSIZE) == BUFFSIZE);
1870 for (i=0; i<BUFFSIZE; i++)
1871 QCOMPARE(c[i], 'a');
1872 QVERIFY(bigFile.seek(sizeNeeded - BUFFSIZE));
1873 QVERIFY(bigFile.read(c, BUFFSIZE) == BUFFSIZE);
1874 for (i=0; i<BUFFSIZE; i++)
1875 QCOMPARE(c[i], 'a');
1877 QVERIFY(bigFile.remove());
1879 QVERIFY(bigFile.remove());
1880 QFAIL("Could not reopen file");
1883 QFAIL("Could not open file");
1886 QSKIP("Not enough space to run test");
1889 QFAIL("Could not determin disk space");
1895 void tst_QFile::i18nFileName_data()
1897 QTest::addColumn<QString>("fileName");
1899 QTest::newRow( "01" ) << QString::fromUtf8("xxxxxxx.txt");
1902 void tst_QFile::i18nFileName()
1904 QFETCH(QString, fileName);
1905 if (QFile::exists(fileName)) {
1906 QVERIFY(QFile::remove(fileName));
1909 QFile file(fileName);
1910 QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
1911 QTextStream ts(&file);
1912 ts.setCodec("UTF-8");
1913 ts << fileName << endl;
1916 QFile file(fileName);
1917 QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1918 QTextStream ts(&file);
1919 ts.setCodec("UTF-8");
1920 QString line = ts.readLine();
1921 QCOMPARE(line, fileName);
1923 QVERIFY(QFile::remove(fileName));
1927 void tst_QFile::longFileName_data()
1929 QTest::addColumn<QString>("fileName");
1931 QTest::newRow( "16 chars" ) << QString::fromLatin1("longFileName.txt");
1932 QTest::newRow( "52 chars" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName.txt");
1933 QTest::newRow( "148 chars" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1934 "longFileNamelongFileNamelongFileNamelongFileName"
1935 "longFileNamelongFileNamelongFileNamelongFileName.txt");
1936 QTest::newRow( "244 chars" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1937 "longFileNamelongFileNamelongFileNamelongFileName"
1938 "longFileNamelongFileNamelongFileNamelongFileName"
1939 "longFileNamelongFileNamelongFileNamelongFileName"
1940 "longFileNamelongFileNamelongFileNamelongFileName.txt");
1941 QTest::newRow( "244 chars to absolutepath" ) << QFileInfo(QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1942 "longFileNamelongFileNamelongFileNamelongFileName"
1943 "longFileNamelongFileNamelongFileNamelongFileName"
1944 "longFileNamelongFileNamelongFileNamelongFileName"
1945 "longFileNamelongFileNamelongFileNamelongFileName.txt")).absoluteFilePath();
1946 /* needs to be put on a windows 2000 > test machine
1947 QTest::newRow( "244 chars on UNC" ) << QString::fromLatin1("//arsia/D/troll/tmp/longFileNamelongFileNamelongFileNamelongFileName"
1948 "longFileNamelongFileNamelongFileNamelongFileName"
1949 "longFileNamelongFileNamelongFileNamelongFileName"
1950 "longFileNamelongFileNamelongFileNamelongFileName"
1951 "longFileNamelongFileNamelongFileNamelongFileName.txt");*/
1954 void tst_QFile::longFileName()
1956 QFETCH(QString, fileName);
1957 if (QFile::exists(fileName)) {
1958 QVERIFY(QFile::remove(fileName));
1961 QFile file(fileName);
1962 #if defined(Q_OS_WINCE)
1963 QEXPECT_FAIL("244 chars", "Full pathname must be less than 260 chars", Abort);
1964 QEXPECT_FAIL("244 chars to absolutepath", "Full pathname must be less than 260 chars", Abort);
1966 QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
1967 QTextStream ts(&file);
1968 ts << fileName << endl;
1971 QFile file(fileName);
1972 QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1973 QTextStream ts(&file);
1974 QString line = ts.readLine();
1975 QCOMPARE(line, fileName);
1977 QString newName = fileName + QLatin1String("1");
1979 QVERIFY(QFile::copy(fileName, newName));
1980 QFile file(newName);
1981 QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1982 QTextStream ts(&file);
1983 QString line = ts.readLine();
1984 QCOMPARE(line, fileName);
1987 QVERIFY(QFile::remove(newName));
1989 QVERIFY(QFile::rename(fileName, newName));
1990 QFile file(newName);
1991 QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1992 QTextStream ts(&file);
1993 QString line = ts.readLine();
1994 QCOMPARE(line, fileName);
1996 QVERIFY(QFile::exists(newName));
1997 QVERIFY(QFile::remove(newName));
2000 #ifdef QT_BUILD_INTERNAL
2001 class MyEngine : public QAbstractFileEngine
2004 MyEngine(int n) { number = n; }
2005 virtual ~MyEngine() {}
2007 void setFileName(const QString &) {}
2008 bool open(QIODevice::OpenMode) { return false; }
2009 bool close() { return false; }
2010 bool flush() { return false; }
2011 qint64 size() const { return 123 + number; }
2012 qint64 at() const { return -1; }
2013 bool seek(qint64) { return false; }
2014 bool isSequential() const { return false; }
2015 qint64 read(char *, qint64) { return -1; }
2016 qint64 write(const char *, qint64) { return -1; }
2017 bool remove() { return false; }
2018 bool copy(const QString &) { return false; }
2019 bool rename(const QString &) { return false; }
2020 bool link(const QString &) { return false; }
2021 bool mkdir(const QString &, bool) const { return false; }
2022 bool rmdir(const QString &, bool) const { return false; }
2023 bool setSize(qint64) { return false; }
2024 QStringList entryList(QDir::Filters, const QStringList &) const { return QStringList(); }
2025 bool caseSensitive() const { return false; }
2026 bool isRelativePath() const { return false; }
2027 FileFlags fileFlags(FileFlags) const { return 0; }
2028 bool chmod(uint) { return false; }
2029 QString fileName(FileName) const { return name; }
2030 uint ownerId(FileOwner) const { return 0; }
2031 QString owner(FileOwner) const { return QString(); }
2032 QDateTime fileTime(FileTime) const { return QDateTime(); }
2039 class MyHandler : public QAbstractFileEngineHandler
2042 inline QAbstractFileEngine *create(const QString &) const
2044 return new MyEngine(1);
2048 class MyHandler2 : public QAbstractFileEngineHandler
2051 inline QAbstractFileEngine *create(const QString &) const
2053 return new MyEngine(2);
2058 void tst_QFile::fileEngineHandler()
2060 // A file that does not exist has a size of 0.
2061 QFile::remove("ole.bull");
2062 QFile file("ole.bull");
2063 QCOMPARE(file.size(), qint64(0));
2065 #ifdef QT_BUILD_INTERNAL
2066 // Instantiating our handler will enable the new engine.
2068 file.setFileName("ole.bull");
2069 QCOMPARE(file.size(), qint64(124));
2071 // A new, identical handler should take preference over the last one.
2072 MyHandler2 handler2;
2073 file.setFileName("ole.bull");
2074 QCOMPARE(file.size(), qint64(125));
2078 #ifdef QT_BUILD_INTERNAL
2079 class MyRecursiveHandler : public QAbstractFileEngineHandler
2082 inline QAbstractFileEngine *create(const QString &fileName) const
2084 if (fileName.startsWith(":!")) {
2086 QString realFile = QFINDTESTDATA(fileName.mid(2));
2087 if (dir.exists(realFile))
2088 return new QFSFileEngine(realFile);
2095 #ifdef QT_BUILD_INTERNAL
2096 void tst_QFile::useQFileInAFileHandler()
2098 // This test should not dead-lock
2099 MyRecursiveHandler handler;
2100 QFile file(":!tst_qfile.cpp");
2101 QVERIFY(file.exists());
2105 void tst_QFile::getCharFF()
2107 QFile file("file.txt");
2108 file.open(QFile::ReadWrite);
2109 file.write("\xff\xff\xff");
2114 QVERIFY(file.getChar(&c));
2115 QVERIFY(file.getChar(&c));
2116 QVERIFY(file.getChar(&c));
2119 void tst_QFile::remove_and_exists()
2121 QFile::remove("tull_i_grunn.txt");
2122 QFile f("tull_i_grunn.txt");
2124 QVERIFY(!f.exists());
2126 bool opened = f.open(QIODevice::WriteOnly);
2129 f.write(QString("testing that remove/exists work...").toLatin1());
2132 QVERIFY(f.exists());
2135 QVERIFY(!f.exists());
2138 void tst_QFile::removeOpenFile()
2141 // remove an opened, write-only file
2142 QFile::remove("remove_unclosed.txt");
2143 QFile f("remove_unclosed.txt");
2145 QVERIFY(!f.exists());
2146 bool opened = f.open(QIODevice::WriteOnly);
2148 f.write(QString("testing that remove closes the file first...").toLatin1());
2150 bool removed = f.remove(); // remove should both close and remove the file
2152 QVERIFY(!f.isOpen());
2153 QVERIFY(!f.exists());
2154 QVERIFY(f.error() == QFile::NoError);
2158 // remove an opened, read-only file
2159 QFile::remove("remove_unclosed.txt");
2161 // first, write a file that we can remove
2163 QFile f("remove_unclosed.txt");
2164 QVERIFY(!f.exists());
2165 bool opened = f.open(QIODevice::WriteOnly);
2167 f.write(QString("testing that remove closes the file first...").toLatin1());
2171 QFile f("remove_unclosed.txt");
2172 bool opened = f.open(QIODevice::ReadOnly);
2175 // this used to only fail on FreeBSD (and Mac OS X)
2177 bool removed = f.remove(); // remove should both close and remove the file
2179 QVERIFY(!f.isOpen());
2180 QVERIFY(!f.exists());
2181 QVERIFY(f.error() == QFile::NoError);
2185 void tst_QFile::fullDisk()
2187 QFile file("/dev/full");
2189 QSKIP("/dev/full doesn't exist on this system");
2191 QVERIFY(file.open(QIODevice::WriteOnly));
2192 file.write("foobar", 6);
2194 QVERIFY(!file.flush());
2195 QCOMPARE(file.error(), QFile::ResourceError);
2196 QVERIFY(!file.flush());
2197 QCOMPARE(file.error(), QFile::ResourceError);
2201 QVERIFY(!file.flush());
2202 QCOMPARE(file.error(), QFile::ResourceError);
2203 QCOMPARE(file.write(&c, 1), qint64(1));
2204 QVERIFY(!file.flush());
2205 QCOMPARE(file.error(), QFile::ResourceError);
2208 QVERIFY(!file.isOpen());
2209 QCOMPARE(file.error(), QFile::ResourceError);
2211 file.open(QIODevice::WriteOnly);
2212 QCOMPARE(file.error(), QFile::NoError);
2213 QVERIFY(file.flush()); // Shouldn't inherit write buffer
2215 QCOMPARE(file.error(), QFile::NoError);
2217 // try again without flush:
2218 QVERIFY(file.open(QIODevice::WriteOnly));
2219 file.write("foobar", 6);
2221 QVERIFY(file.error() != QFile::NoError);
2224 void tst_QFile::writeLargeDataBlock_data()
2226 QTest::addColumn<QString>("fileName");
2227 QTest::addColumn<int>("type");
2229 QTest::newRow("localfile-QFile") << "./largeblockfile.txt" << (int)OpenQFile;
2230 QTest::newRow("localfile-Fd") << "./largeblockfile.txt" << (int)OpenFd;
2231 QTest::newRow("localfile-Stream") << "./largeblockfile.txt" << (int)OpenStream;
2233 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
2234 // Some semi-randomness to avoid collisions.
2235 QTest::newRow("unc file")
2236 << QString("//" + QtNetworkSettings::winServerName() + "/TESTSHAREWRITABLE/largefile-%1-%2.txt")
2237 .arg(QHostInfo::localHostName())
2238 .arg(QTime::currentTime().msec()) << (int)OpenQFile;
2242 static QByteArray getLargeDataBlock()
2244 static QByteArray array;
2248 #if defined(Q_OS_WINCE)
2249 int resizeSize = 1024 * 1024; // WinCE does not have much space
2251 int resizeSize = 64 * 1024 * 1024;
2253 array.resize(resizeSize);
2254 for (int i = 0; i < array.size(); ++i)
2255 array[i] = uchar(i);
2261 void tst_QFile::writeLargeDataBlock()
2263 QFETCH(QString, fileName);
2264 QFETCH( int, type );
2266 QByteArray const originalData = getLargeDataBlock();
2269 QFile file(fileName);
2271 QVERIFY2( openFile(file, QIODevice::WriteOnly, (FileType)type),
2272 qPrintable(QString("Couldn't open file for writing: [%1]").arg(fileName)) );
2273 qint64 fileWriteOriginalData = file.write(originalData);
2274 qint64 originalDataSize = (qint64)originalData.size();
2275 #if defined(Q_OS_WIN)
2276 if (fileWriteOriginalData != originalDataSize) {
2277 qWarning() << qPrintable(QString("Error writing a large data block to [%1]: %2")
2279 .arg(file.errorString()));
2280 QEXPECT_FAIL("unc file", "QTBUG-26906 writing", Abort);
2283 QCOMPARE( fileWriteOriginalData, originalDataSize );
2284 QVERIFY( file.flush() );
2289 QByteArray readData;
2292 QFile file(fileName);
2294 QVERIFY2( openFile(file, QIODevice::ReadOnly, (FileType)type),
2295 qPrintable(QString("Couldn't open file for reading: [%1]").arg(fileName)) );
2296 readData = file.readAll();
2298 #if defined(Q_OS_WIN)
2299 if (readData != originalData) {
2300 qWarning() << qPrintable(QString("Error reading a large data block from [%1]: %2")
2302 .arg(file.errorString()));
2303 QEXPECT_FAIL("unc file", "QTBUG-26906 reading", Abort);
2308 QCOMPARE( readData, originalData );
2309 QVERIFY( QFile::remove(fileName) );
2312 void tst_QFile::readFromWriteOnlyFile()
2314 QFile file("writeonlyfile");
2315 QVERIFY(file.open(QFile::WriteOnly));
2317 QTest::ignoreMessage(QtWarningMsg, "QIODevice::read: WriteOnly device");
2318 QCOMPARE(file.read(&c, 1), qint64(-1));
2321 void tst_QFile::writeToReadOnlyFile()
2323 QFile file("readonlyfile");
2324 QVERIFY(file.open(QFile::ReadOnly));
2326 QTest::ignoreMessage(QtWarningMsg, "QIODevice::write: ReadOnly device");
2327 QCOMPARE(file.write(&c, 1), qint64(-1));
2330 void tst_QFile::virtualFile()
2332 // test if QFile works with virtual files
2334 #if defined(Q_OS_LINUX)
2335 fname = "/proc/self/maps";
2336 #elif defined(Q_OS_AIX)
2337 fname = QString("/proc/%1/map").arg(getpid());
2338 #elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
2339 fname = "/proc/curproc/map";
2341 QSKIP("This platform does not have 0-sized virtual files");
2344 // consistency check
2345 QFileInfo fi(fname);
2346 QVERIFY(fi.exists());
2347 QVERIFY(fi.isFile());
2348 QCOMPARE(fi.size(), Q_INT64_C(0));
2352 QVERIFY(f.open(QIODevice::ReadOnly));
2353 QCOMPARE(f.size(), Q_INT64_C(0));
2357 QByteArray data = f.read(16);
2358 QCOMPARE(data.size(), 16);
2359 QCOMPARE(f.pos(), Q_INT64_C(16));
2362 data = f.readLine();
2363 QVERIFY(!data.isEmpty());
2367 QVERIFY(f.pos() != 0);
2368 QVERIFY(!data.isEmpty());
2372 QCOMPARE(f.pos(), Q_INT64_C(1));
2375 void tst_QFile::textFile()
2377 #if defined(Q_OS_WINCE)
2378 FILE *fs = ::fopen((QCoreApplication::applicationDirPath() + "/writeabletextfile").toLatin1() , "wt");
2379 #elif defined(Q_OS_WIN)
2380 FILE *fs = ::fopen("writeabletextfile", "wt");
2382 FILE *fs = ::fopen("writeabletextfile", "w");
2385 QByteArray part1("This\nis\na\nfile\nwith\nnewlines\n");
2386 QByteArray part2("Add\nsome\nmore\nnewlines\n");
2388 QVERIFY(f.open(fs, QIODevice::WriteOnly));
2394 QFile file("writeabletextfile");
2395 QVERIFY(file.open(QIODevice::ReadOnly));
2397 QByteArray data = file.readAll();
2399 QByteArray expected = part1 + part2;
2401 expected.replace("\n", "\015\012");
2403 QCOMPARE(data, expected);
2408 void tst_QFile::rename_data()
2410 QTest::addColumn<QString>("source");
2411 QTest::addColumn<QString>("destination");
2412 QTest::addColumn<bool>("result");
2414 QTest::newRow("a -> b") << QString("a") << QString("b") << false;
2415 QTest::newRow("a -> .") << QString("a") << QString(".") << false;
2416 QTest::newRow("renamefile -> renamefile") << QString("renamefile") << QString("renamefile") << false;
2417 QTest::newRow("renamefile -> noreadfile") << QString("renamefile") << QString("noreadfile") << false;
2418 #if defined(Q_OS_UNIX)
2419 QTest::newRow("renamefile -> /etc/renamefile") << QString("renamefile") << QString("/etc/renamefile") << false;
2421 QTest::newRow("renamefile -> renamedfile") << QString("renamefile") << QString("renamedfile") << true;
2422 QTest::newRow("renamefile -> ..") << QString("renamefile") << QString("..") << false;
2425 void tst_QFile::rename()
2427 QFETCH(QString, source);
2428 QFETCH(QString, destination);
2429 QFETCH(bool, result);
2431 #if defined(Q_OS_UNIX)
2432 if (strcmp(QTest::currentDataTag(), "renamefile -> /etc/renamefile") == 0) {
2433 if (::getuid() == 0)
2434 QSKIP("Running this test as root doesn't make sense");
2438 QFile::remove("renamedfile");
2439 QFile f("renamefile");
2440 f.open(QFile::WriteOnly);
2444 QCOMPARE(file.rename(destination), result);
2447 QCOMPARE(file.error(), QFile::NoError);
2449 QCOMPARE(file.error(), QFile::RenameError);
2451 QFile::remove("renamefile");
2457 Some special files have QFile::atEnd() returning true, even though there is
2458 more data available. True for corner cases, as well as some mounts on OS X.
2460 Here, we reproduce that condition by having a QFile sub-class with this
2461 peculiar atEnd() behavior.
2463 void tst_QFile::renameWithAtEndSpecialFile() const
2465 class PeculiarAtEnd : public QFile
2468 virtual bool atEnd() const
2474 const QString newName(QLatin1String("newName.txt"));
2475 /* Cleanup, so we're a bit more robust. */
2476 QFile::remove(newName);
2478 const QString originalName(QString(QFINDTESTDATA("forRenaming.txt")));
2481 file.setFileName(originalName);
2482 QVERIFY(file.open(QIODevice::ReadOnly));
2484 QVERIFY(file.rename(newName));
2487 /* Guess what, we have to rename it back, otherwise we'll fail on second
2489 QVERIFY(QFile::rename(newName, originalName));
2492 void tst_QFile::renameFallback()
2494 // Using a resource file both to trigger QFile::rename's fallback handling
2495 // and as a *read-only* source whose move should fail.
2496 QFile file(":/rename-fallback.qrc");
2497 QVERIFY(file.exists() && "(test-precondition)");
2498 QFile::remove("file-rename-destination.txt");
2500 QVERIFY(!file.rename("file-rename-destination.txt"));
2501 QVERIFY(!QFile::exists("file-rename-destination.txt"));
2502 QVERIFY(!file.isOpen());
2505 void tst_QFile::renameMultiple()
2507 // create the file if it doesn't exist
2508 QFile file("file-to-be-renamed.txt");
2509 QFile file2("existing-file.txt");
2510 QVERIFY(file.open(QIODevice::ReadWrite) && "(test-precondition)");
2511 QVERIFY(file2.open(QIODevice::ReadWrite) && "(test-precondition)");
2513 // any stale files from previous test failures?
2514 QFile::remove("file-renamed-once.txt");
2515 QFile::remove("file-renamed-twice.txt");
2518 QVERIFY(QFile::exists("existing-file.txt"));
2519 QVERIFY(!file.rename("existing-file.txt"));
2520 QCOMPARE(file.error(), QFile::RenameError);
2521 QCOMPARE(file.fileName(), QString("file-to-be-renamed.txt"));
2523 QVERIFY(file.rename("file-renamed-once.txt"));
2524 QVERIFY(!file.isOpen());
2525 QCOMPARE(file.fileName(), QString("file-renamed-once.txt"));
2527 QVERIFY(QFile::exists("existing-file.txt"));
2528 QVERIFY(!file.rename("existing-file.txt"));
2529 QCOMPARE(file.error(), QFile::RenameError);
2530 QCOMPARE(file.fileName(), QString("file-renamed-once.txt"));
2532 QVERIFY(file.rename("file-renamed-twice.txt"));
2533 QVERIFY(!file.isOpen());
2534 QCOMPARE(file.fileName(), QString("file-renamed-twice.txt"));
2536 QVERIFY(QFile::exists("existing-file.txt"));
2537 QVERIFY(!QFile::exists("file-to-be-renamed.txt"));
2538 QVERIFY(!QFile::exists("file-renamed-once.txt"));
2539 QVERIFY(QFile::exists("file-renamed-twice.txt"));
2543 QVERIFY(!QFile::exists("file-renamed-twice.txt"));
2544 QVERIFY(!QFile::exists("existing-file.txt"));
2547 void tst_QFile::appendAndRead()
2549 QFile writeFile(QLatin1String("appendfile.txt"));
2550 QVERIFY(writeFile.open(QIODevice::WriteOnly | QIODevice::Truncate));
2552 QFile readFile(QLatin1String("appendfile.txt"));
2553 QVERIFY(readFile.open(QIODevice::ReadOnly));
2555 // Write to the end of the file, then read that character back, and so on.
2556 for (int i = 0; i < 100; ++i) {
2558 writeFile.putChar(char(i % 256));
2560 QVERIFY(readFile.getChar(&c));
2561 QCOMPARE(c, char(i % 256));
2562 QCOMPARE(readFile.pos(), writeFile.pos());
2565 // Write blocks and read them back
2566 for (int j = 0; j < 18; ++j) {
2567 writeFile.write(QByteArray(1 << j, '@'));
2569 QCOMPARE(readFile.read(1 << j).size(), 1 << j);
2573 QFile::remove(QLatin1String("appendfile.txt"));
2576 void tst_QFile::miscWithUncPathAsCurrentDir()
2578 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
2579 QString current = QDir::currentPath();
2580 QVERIFY(QDir::setCurrent("//" + QtNetworkSettings::winServerName() + "/testshare"));
2581 QFile file("test.pri");
2582 QVERIFY(file.exists());
2583 QCOMPARE(int(file.size()), 34);
2584 QVERIFY(file.open(QIODevice::ReadOnly));
2585 QVERIFY(QDir::setCurrent(current));
2589 void tst_QFile::standarderror()
2592 bool ok = f.open(stderr, QFile::WriteOnly);
2597 void tst_QFile::handle()
2600 #if !defined(Q_OS_WINCE)
2601 QFile file(QFINDTESTDATA("tst_qfile.cpp"));
2602 QVERIFY(file.open(QIODevice::ReadOnly));
2603 fd = int(file.handle());
2605 QCOMPARE(int(file.handle()), fd);
2607 QT_READ(int(file.handle()), &c, 1);
2610 // test if the QFile and the handle remain in sync
2611 QVERIFY(file.getChar(&c));
2614 // same, but read from QFile first now
2616 QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Unbuffered));
2617 fd = int(file.handle());
2619 QVERIFY(file.getChar(&c));
2622 QCOMPARE(QT_READ(fd, &c, 1), ssize_t(1));
2624 QCOMPARE(QT_READ(fd, &c, 1), 1);
2630 //test round trip of adopted stdio file handle
2632 FILE *fp = fopen(qPrintable(QFINDTESTDATA("tst_qfile.cpp")), "r");
2633 file2.open(fp, QIODevice::ReadOnly);
2634 QCOMPARE(int(file2.handle()), int(fileno(fp)));
2635 QCOMPARE(int(file2.handle()), int(fileno(fp)));
2638 //test round trip of adopted posix file handle
2641 fd = QT_OPEN(qPrintable(QFINDTESTDATA("tst_qfile.cpp")), QT_OPEN_RDONLY);
2642 file3.open(fd, QIODevice::ReadOnly);
2643 QCOMPARE(int(file3.handle()), fd);
2648 void tst_QFile::nativeHandleLeaks()
2653 HANDLE handle1, handle2;
2657 QFile file("qt_file.tmp");
2658 QVERIFY( file.open(QIODevice::ReadWrite) );
2660 fd1 = file.handle();
2661 QVERIFY( -1 != fd1 );
2665 handle1 = ::CreateFileA("qt_file.tmp", GENERIC_READ, 0, NULL,
2666 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2667 QVERIFY( INVALID_HANDLE_VALUE != handle1 );
2668 QVERIFY( ::CloseHandle(handle1) );
2672 QFile file("qt_file.tmp");
2673 QVERIFY( file.open(QIODevice::ReadOnly) );
2675 fd2 = file.handle();
2676 QVERIFY( -1 != fd2 );
2680 handle2 = ::CreateFileA("qt_file.tmp", GENERIC_READ, 0, NULL,
2681 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2682 QVERIFY( INVALID_HANDLE_VALUE != handle2 );
2683 QVERIFY( ::CloseHandle(handle2) );
2686 QCOMPARE( fd2, fd1 );
2689 QCOMPARE( handle2, handle1 );
2693 void tst_QFile::readEof_data()
2695 QTest::addColumn<QString>("filename");
2696 QTest::addColumn<int>("imode");
2698 QTest::newRow("buffered") << QFINDTESTDATA("testfile.txt") << 0;
2699 QTest::newRow("unbuffered") << QFINDTESTDATA("testfile.txt") << int(QIODevice::Unbuffered);
2701 #if defined(Q_OS_UNIX)
2702 QTest::newRow("sequential,buffered") << "/dev/null" << 0;
2703 QTest::newRow("sequential,unbuffered") << "/dev/null" << int(QIODevice::Unbuffered);
2707 void tst_QFile::readEof()
2709 QFETCH(QString, filename);
2711 QIODevice::OpenMode mode = QIODevice::OpenMode(imode);
2714 QFile file(filename);
2715 QVERIFY(file.open(QIODevice::ReadOnly | mode));
2716 bool isSequential = file.isSequential();
2717 if (!isSequential) {
2718 QVERIFY(file.seek(245));
2719 QVERIFY(file.atEnd());
2723 int ret = file.read(buf, sizeof buf);
2725 QVERIFY(file.error() == QFile::NoError);
2726 QVERIFY(file.atEnd());
2728 // Do it again to ensure that we get the same result
2729 ret = file.read(buf, sizeof buf);
2731 QVERIFY(file.error() == QFile::NoError);
2732 QVERIFY(file.atEnd());
2736 QFile file(filename);
2737 QVERIFY(file.open(QIODevice::ReadOnly | mode));
2738 bool isSequential = file.isSequential();
2739 if (!isSequential) {
2740 QVERIFY(file.seek(245));
2741 QVERIFY(file.atEnd());
2744 QByteArray ret = file.read(10);
2745 QVERIFY(ret.isEmpty());
2746 QVERIFY(file.error() == QFile::NoError);
2747 QVERIFY(file.atEnd());
2749 // Do it again to ensure that we get the same result
2750 ret = file.read(10);
2751 QVERIFY(ret.isEmpty());
2752 QVERIFY(file.error() == QFile::NoError);
2753 QVERIFY(file.atEnd());
2757 QFile file(filename);
2758 QVERIFY(file.open(QIODevice::ReadOnly | mode));
2759 bool isSequential = file.isSequential();
2760 if (!isSequential) {
2761 QVERIFY(file.seek(245));
2762 QVERIFY(file.atEnd());
2766 int ret = file.readLine(buf, sizeof buf);
2768 QVERIFY(file.error() == QFile::NoError);
2769 QVERIFY(file.atEnd());
2771 // Do it again to ensure that we get the same result
2772 ret = file.readLine(buf, sizeof buf);
2774 QVERIFY(file.error() == QFile::NoError);
2775 QVERIFY(file.atEnd());
2779 QFile file(filename);
2780 QVERIFY(file.open(QIODevice::ReadOnly | mode));
2781 bool isSequential = file.isSequential();
2782 if (!isSequential) {
2783 QVERIFY(file.seek(245));
2784 QVERIFY(file.atEnd());
2787 QByteArray ret = file.readLine();
2788 QVERIFY(ret.isNull());
2789 QVERIFY(file.error() == QFile::NoError);
2790 QVERIFY(file.atEnd());
2792 // Do it again to ensure that we get the same result
2793 ret = file.readLine();
2794 QVERIFY(ret.isNull());
2795 QVERIFY(file.error() == QFile::NoError);
2796 QVERIFY(file.atEnd());
2800 QFile file(filename);
2801 QVERIFY(file.open(QIODevice::ReadOnly | mode));
2802 bool isSequential = file.isSequential();
2803 if (!isSequential) {
2804 QVERIFY(file.seek(245));
2805 QVERIFY(file.atEnd());
2809 QVERIFY(!file.getChar(&c));
2810 QVERIFY(file.error() == QFile::NoError);
2811 QVERIFY(file.atEnd());
2813 // Do it again to ensure that we get the same result
2814 QVERIFY(!file.getChar(&c));
2815 QVERIFY(file.error() == QFile::NoError);
2816 QVERIFY(file.atEnd());
2820 void tst_QFile::posAfterFailedStat()
2822 // Regression test for a bug introduced in 4.3.0; after a failed stat,
2823 // pos() could no longer be calculated correctly.
2824 QFile::remove("tmp.txt");
2825 QFile file("tmp.txt");
2826 QVERIFY(!file.exists());
2827 QVERIFY(file.open(QIODevice::Append));
2828 QVERIFY(file.exists());
2829 file.write("qt430", 5);
2830 QVERIFY(!file.isSequential());
2831 QCOMPARE(file.pos(), qint64(5));
2835 #define FILESIZE 65536 * 3
2837 void tst_QFile::map_data()
2839 QTest::addColumn<int>("fileSize");
2840 QTest::addColumn<int>("offset");
2841 QTest::addColumn<int>("size");
2842 QTest::addColumn<QFile::FileError>("error");
2844 QTest::newRow("zero") << FILESIZE << 0 << FILESIZE << QFile::NoError;
2845 QTest::newRow("small, but 0") << FILESIZE << 30 << FILESIZE - 30 << QFile::NoError;
2846 QTest::newRow("a page") << FILESIZE << 4096 << FILESIZE - 4096 << QFile::NoError;
2847 QTest::newRow("+page") << FILESIZE << 5000 << FILESIZE - 5000 << QFile::NoError;
2848 QTest::newRow("++page") << FILESIZE << 65576 << FILESIZE - 65576 << QFile::NoError;
2849 QTest::newRow("bad size") << FILESIZE << 0 << -1 << QFile::ResourceError;
2850 QTest::newRow("bad offset") << FILESIZE << -1 << 1 << QFile::UnspecifiedError;
2851 QTest::newRow("zerozero") << FILESIZE << 0 << 0 << QFile::UnspecifiedError;
2854 void tst_QFile::map()
2856 QFETCH(int, fileSize);
2857 QFETCH(int, offset);
2859 QFETCH(QFile::FileError, error);
2861 QString fileName = QDir::currentPath() + '/' + "qfile_map_testfile";
2864 fileName = QFileInfo(fileName).absoluteFilePath();
2867 if (QFile::exists(fileName)) {
2868 QVERIFY(QFile::setPermissions(fileName,
2869 QFile::WriteOwner | QFile::ReadOwner | QFile::WriteUser | QFile::ReadUser));
2870 QFile::remove(fileName);
2872 QFile file(fileName);
2874 // invalid, not open
2875 uchar *memory = file.map(0, size);
2877 QCOMPARE(file.error(), QFile::PermissionsError);
2878 QVERIFY(!file.unmap(memory));
2879 QCOMPARE(file.error(), QFile::PermissionsError);
2882 QVERIFY(file.open(QFile::ReadWrite));
2883 QVERIFY(file.resize(fileSize));
2884 QVERIFY(file.flush());
2886 QVERIFY(file.open(QFile::ReadWrite));
2887 memory = file.map(offset, size);
2888 if (error != QFile::NoError) {
2889 QVERIFY(file.error() != QFile::NoError);
2893 QCOMPARE(file.error(), error);
2896 QVERIFY(file.unmap(memory));
2897 QCOMPARE(file.error(), QFile::NoError);
2899 // Verify changes were saved
2900 memory = file.map(offset, size);
2901 QCOMPARE(file.error(), QFile::NoError);
2903 QVERIFY(memory[0] == 'Q');
2904 QVERIFY(file.unmap(memory));
2905 QCOMPARE(file.error(), QFile::NoError);
2907 // hpux wont let you map multiple times.
2908 #if !defined(Q_OS_HPUX) && !defined(Q_USE_DEPRECATED_MAP_API) && !defined(Q_OS_WINCE)
2909 // exotic test to make sure that multiple maps work
2911 // note: windows ce does not reference count mutliple maps
2912 // it's essentially just the same reference but it
2913 // cause a resource lock on the file which prevents it
2914 // from being removed uchar *memory1 = file.map(0, file.size());
2915 uchar *memory1 = file.map(0, file.size());
2916 QCOMPARE(file.error(), QFile::NoError);
2917 uchar *memory2 = file.map(0, file.size());
2918 QCOMPARE(file.error(), QFile::NoError);
2921 QVERIFY(file.unmap(memory1));
2922 QCOMPARE(file.error(), QFile::NoError);
2923 QVERIFY(file.unmap(memory2));
2924 QCOMPARE(file.error(), QFile::NoError);
2925 memory1 = file.map(0, file.size());
2926 QCOMPARE(file.error(), QFile::NoError);
2928 QVERIFY(file.unmap(memory1));
2929 QCOMPARE(file.error(), QFile::NoError);
2934 #if defined(Q_OS_UNIX)
2935 if (::getuid() != 0)
2936 // root always has permissions
2939 // Change permissions on a file, just to confirm it would fail
2940 QFile::Permissions originalPermissions = file.permissions();
2941 QVERIFY(file.setPermissions(QFile::ReadOther));
2942 QVERIFY(!file.open(QFile::ReadWrite));
2943 memory = file.map(offset, size);
2944 QCOMPARE(file.error(), QFile::PermissionsError);
2946 QVERIFY(file.setPermissions(originalPermissions));
2948 QVERIFY(file.remove());
2951 void tst_QFile::mapResource_data()
2953 QTest::addColumn<int>("offset");
2954 QTest::addColumn<int>("size");
2955 QTest::addColumn<QFile::FileError>("error");
2956 QTest::addColumn<QString>("fileName");
2958 QString validFile = ":/tst_qfileinfo/resources/file1.ext1";
2959 QString invalidFile = ":/tst_qfileinfo/resources/filefoo.ext1";
2961 for (int i = 0; i < 2; ++i) {
2962 QString file = (i == 0) ? validFile : invalidFile;
2963 QTest::newRow("0, 0") << 0 << 0 << QFile::UnspecifiedError << file;
2964 QTest::newRow("0, BIG") << 0 << 4096 << QFile::UnspecifiedError << file;
2965 QTest::newRow("-1, 0") << -1 << 0 << QFile::UnspecifiedError << file;
2966 QTest::newRow("0, -1") << 0 << -1 << QFile::UnspecifiedError << file;
2969 QTest::newRow("0, 1") << 0 << 1 << QFile::NoError << validFile;
2972 void tst_QFile::mapResource()
2974 QFETCH(QString, fileName);
2975 QFETCH(int, offset);
2977 QFETCH(QFile::FileError, error);
2979 QFile file(fileName);
2980 uchar *memory = file.map(offset, size);
2981 QCOMPARE(file.error(), error);
2982 QVERIFY((error == QFile::NoError) ? (memory != 0) : (memory == 0));
2983 if (error == QFile::NoError)
2984 QCOMPARE(QString(memory[0]), QString::number(offset + 1));
2985 QVERIFY(file.unmap(memory));
2988 void tst_QFile::mapOpenMode_data()
2990 QTest::addColumn<int>("openMode");
2992 QTest::newRow("ReadOnly") << int(QIODevice::ReadOnly);
2993 //QTest::newRow("WriteOnly") << int(QIODevice::WriteOnly); // this doesn't make sense
2994 QTest::newRow("ReadWrite") << int(QIODevice::ReadWrite);
2995 QTest::newRow("ReadOnly,Unbuffered") << int(QIODevice::ReadOnly | QIODevice::Unbuffered);
2996 QTest::newRow("ReadWrite,Unbuffered") << int(QIODevice::ReadWrite | QIODevice::Unbuffered);
2999 void tst_QFile::mapOpenMode()
3001 QFETCH(int, openMode);
3002 static const qint64 fileSize = 4096;
3004 QByteArray pattern(fileSize, 'A');
3006 QString fileName = QDir::currentPath() + '/' + "qfile_map_testfile";
3007 if (QFile::exists(fileName)) {
3008 QVERIFY(QFile::setPermissions(fileName,
3009 QFile::WriteOwner | QFile::ReadOwner | QFile::WriteUser | QFile::ReadUser));
3010 QFile::remove(fileName);
3012 QFile file(fileName);
3015 QVERIFY(file.open(QFile::ReadWrite));
3016 QVERIFY(file.write(pattern));
3017 QVERIFY(file.flush());
3020 // open according to our mode
3021 QVERIFY(file.open(QIODevice::OpenMode(openMode)));
3023 uchar *memory = file.map(0, fileSize);
3025 QVERIFY(memcmp(memory, pattern, fileSize) == 0);
3027 if (openMode & QIODevice::WriteOnly) {
3028 // try to write to the file
3032 file.open(QIODevice::OpenMode(openMode));
3035 QVERIFY(file.getChar(&c));
3042 void tst_QFile::openDirectory()
3044 QFile f1(QFINDTESTDATA("resources"));
3045 // it's a directory, it must exist
3046 QVERIFY(f1.exists());
3048 // ...but not be openable
3049 QVERIFY(!f1.open(QIODevice::ReadOnly));
3051 QVERIFY(!f1.open(QIODevice::ReadOnly|QIODevice::Unbuffered));
3053 QVERIFY(!f1.open(QIODevice::ReadWrite));
3055 QVERIFY(!f1.open(QIODevice::WriteOnly));
3057 QVERIFY(!f1.open(QIODevice::WriteOnly|QIODevice::Unbuffered));
3061 static qint64 streamExpectedSize(int fd)
3064 if (QT_FSTAT(fd, &sb) != -1)
3069 static qint64 streamCurrentPosition(int fd)
3071 QT_OFF_T pos = QT_LSEEK(fd, 0, SEEK_CUR);
3077 static qint64 streamCurrentPosition(FILE *f)
3079 QT_OFF_T pos = QT_FTELL(f);
3085 class MessageHandler {
3087 MessageHandler(QtMessageHandler messageHandler = handler)
3090 oldMessageHandler = qInstallMessageHandler(messageHandler);
3095 qInstallMessageHandler(oldMessageHandler);
3098 static bool testPassed()
3103 static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
3105 if (msg == QString::fromLatin1("QIODevice::seek: Cannot call seek on a sequential device"))
3107 // Defer to old message handler.
3108 if (oldMessageHandler)
3109 oldMessageHandler(type, context, msg);
3112 static QtMessageHandler oldMessageHandler;
3116 bool MessageHandler::ok = true;
3117 QtMessageHandler MessageHandler::oldMessageHandler = 0;
3119 void tst_QFile::openStandardStreamsFileDescriptors()
3122 //allthough Windows CE (not mobile!) has functions that allow redirecting
3123 //the standard file descriptors to a file (see SetStdioPathW/GetStdioPathW)
3124 //it does not have functions to simply open them like below .
3125 QSKIP("Opening standard streams on Windows CE via descriptor not implemented");
3128 // Check that QIODevice::seek() isn't called when opening a sequential device (QFile).
3129 MessageHandler msgHandler;
3133 in.open(STDIN_FILENO, QIODevice::ReadOnly);
3134 QCOMPARE( in.pos(), streamCurrentPosition(STDIN_FILENO) );
3135 QCOMPARE( in.size(), streamExpectedSize(STDIN_FILENO) );
3140 QVERIFY(out.open(STDOUT_FILENO, QIODevice::WriteOnly));
3141 QCOMPARE( out.pos(), streamCurrentPosition(STDOUT_FILENO) );
3142 QCOMPARE( out.size(), streamExpectedSize(STDOUT_FILENO) );
3147 err.open(STDERR_FILENO, QIODevice::WriteOnly);
3148 QCOMPARE( err.pos(), streamCurrentPosition(STDERR_FILENO) );
3149 QCOMPARE( err.size(), streamExpectedSize(STDERR_FILENO) );
3152 QVERIFY(msgHandler.testPassed());
3155 void tst_QFile::openStandardStreamsBufferedStreams()
3158 QSKIP("Not tested on Windows CE.");
3160 // Check that QIODevice::seek() isn't called when opening a sequential device (QFile).
3161 MessageHandler msgHandler;
3166 in.open(stdin, QIODevice::ReadOnly);
3167 QCOMPARE( in.pos(), streamCurrentPosition(stdin) );
3168 QCOMPARE( in.size(), streamExpectedSize(QT_FILENO(stdin)) );
3173 out.open(stdout, QIODevice::WriteOnly);
3174 QCOMPARE( out.pos(), streamCurrentPosition(stdout) );
3175 QCOMPARE( out.size(), streamExpectedSize(QT_FILENO(stdout)) );
3180 err.open(stderr, QIODevice::WriteOnly);
3181 QCOMPARE( err.pos(), streamCurrentPosition(stderr) );
3182 QCOMPARE( err.size(), streamExpectedSize(QT_FILENO(stderr)) );
3185 QVERIFY(msgHandler.testPassed());
3188 void tst_QFile::writeNothing()
3190 for (int i = 0; i < NumberOfFileTypes; ++i) {
3191 QFile file("file.txt");
3192 QVERIFY( openFile(file, QIODevice::WriteOnly | QIODevice::Unbuffered, FileType(i)) );
3193 QVERIFY( 0 == file.write((char *)0, 0) );
3194 QCOMPARE( file.error(), QFile::NoError );
3199 void tst_QFile::resize_data()
3201 QTest::addColumn<int>("filetype");
3203 QTest::newRow("native") << int(OpenQFile);
3204 QTest::newRow("fileno") << int(OpenFd);
3205 QTest::newRow("stream") << int(OpenStream);
3208 void tst_QFile::resize()
3210 QFETCH(int, filetype);
3211 QString filename(QLatin1String("file.txt"));
3212 QFile file(filename);
3213 QVERIFY(openFile(file, QIODevice::ReadWrite, FileType(filetype)));
3214 QVERIFY(file.resize(8));
3215 QCOMPARE(file.size(), qint64(8));
3217 QFile::resize(filename, 4);
3218 QCOMPARE(QFileInfo(filename).size(), qint64(4));
3219 QVERIFY(QFile::remove(filename));
3222 void tst_QFile::objectConstructors()
3225 QFile* file1 = new QFile(QFINDTESTDATA("testfile.txt"), &ob);
3226 QFile* file2 = new QFile(&ob);
3227 QVERIFY(file1->exists());
3228 QVERIFY(!file2->exists());
3231 void tst_QFile::caseSensitivity()
3233 #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
3234 const bool caseSensitive = false;
3236 const bool caseSensitive = true;
3238 QByteArray testData("a little test");
3239 QString filename("File.txt");
3242 QVERIFY(f.open(QIODevice::WriteOnly));
3243 QVERIFY(f.write(testData));
3246 QStringList alternates;
3247 QFileInfo fi(filename);
3248 QVERIFY(fi.exists());
3249 alternates << "file.txt" << "File.TXT" << "fIlE.TxT" << fi.absoluteFilePath().toUpper() << fi.absoluteFilePath().toLower();
3250 foreach (QString alt, alternates) {
3252 QCOMPARE(fi2.exists(), !caseSensitive);
3253 QCOMPARE(fi.size() == fi2.size(), !caseSensitive);
3255 QCOMPARE(f2.open(QIODevice::ReadOnly), !caseSensitive);
3257 QCOMPARE(f2.readAll(), testData);
3261 //MSVCRT asserts when any function is called with a closed file handle.
3262 //This replaces the default crashing error handler with one that ignores the error (allowing EBADF to be returned)
3263 class AutoIgnoreInvalidParameter
3266 #if defined(Q_OS_WIN) && defined (Q_CC_MSVC)
3267 static void ignore_invalid_parameter(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t) {}
3268 AutoIgnoreInvalidParameter()
3270 oldHandler = _set_invalid_parameter_handler(ignore_invalid_parameter);
3271 //also disable the abort/retry/ignore popup
3272 oldReportMode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
3274 ~AutoIgnoreInvalidParameter()
3276 //restore previous settings
3277 _set_invalid_parameter_handler(oldHandler);
3278 _CrtSetReportMode(_CRT_ASSERT, oldReportMode);
3280 _invalid_parameter_handler oldHandler;
3285 void tst_QFile::autocloseHandle()
3288 QFile file("readonlyfile");
3289 QVERIFY(openFile(file, QIODevice::ReadOnly, OpenFd, QFile::AutoCloseHandle));
3291 QCOMPARE(file.handle(), fd);
3294 QCOMPARE(file.handle(), -1);
3295 AutoIgnoreInvalidParameter a;
3297 //file is closed, read should fail
3299 QCOMPARE((int)QT_READ(fd, &buf, 1), -1);
3300 QVERIFY(errno = EBADF);
3304 QFile file("readonlyfile");
3305 QVERIFY(openFile(file, QIODevice::ReadOnly, OpenFd, QFile::DontCloseHandle));
3306 QCOMPARE(file.handle(), fd_);
3308 QCOMPARE(file.handle(), -1);
3309 //file is not closed, read should succeed
3311 QCOMPARE((int)QT_READ(fd_, &buf, 1), 1);
3317 QFile file("readonlyfile");
3318 QVERIFY(openFile(file, QIODevice::ReadOnly, OpenStream, QFile::AutoCloseHandle));
3319 int fd = QT_FILENO(stream_);
3320 QCOMPARE(file.handle(), fd);
3323 QCOMPARE(file.handle(), -1);
3324 AutoIgnoreInvalidParameter a;
3326 //file is closed, read should fail
3328 QCOMPARE((int)QT_READ(fd, &buf, 1), -1); //not using fread because the FILE* was freed by fclose
3332 QFile file("readonlyfile");
3333 QVERIFY(openFile(file, QIODevice::ReadOnly, OpenStream, QFile::DontCloseHandle));
3334 QCOMPARE(file.handle(), QT_FILENO(stream_));
3336 QCOMPARE(file.handle(), -1);
3337 //file is not closed, read should succeed
3339 QCOMPARE(int(::fread(&buf, 1, 1, stream_)), 1);
3345 QTEST_MAIN(tst_QFile)
3346 #include "tst_qfile.moc"