b2cb00b423140920079033d2d8b51b5d2af4c6ba
[profile/ivi/qtbase.git] / tests / auto / corelib / io / qfile / tst_qfile.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtTest/QtTest>
43 #include <qplatformdefs.h>
44
45 #include <QCoreApplication>
46 #include <QDebug>
47 #include <QDir>
48 #include <QFile>
49 #include <QFileInfo>
50
51 #include <private/qabstractfileengine_p.h>
52 #include <private/qfsfileengine_p.h>
53
54 #ifdef Q_OS_WIN
55 QT_BEGIN_NAMESPACE
56 extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
57 QT_END_NAMESPACE
58 #endif
59
60 #if !defined(Q_OS_WINCE)
61 #include <QHostInfo>
62 #endif
63 #include <QProcess>
64 #ifdef Q_OS_WIN
65 # include <qt_windows.h>
66 #else
67 # include <sys/types.h>
68 # include <unistd.h>
69 #endif
70 #ifdef Q_OS_MAC
71 # include <sys/mount.h>
72 #elif defined(Q_OS_LINUX)
73 # include <sys/vfs.h>
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>
81 #endif
82
83 #include <stdio.h>
84 #include <errno.h>
85
86 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
87 #include "../../../network-settings.h"
88 #endif
89
90 #ifndef STDIN_FILENO
91 #define STDIN_FILENO 0
92 #endif
93
94 #ifndef STDOUT_FILENO
95 #define STDOUT_FILENO 1
96 #endif
97
98 #ifndef STDERR_FILENO
99 #define STDERR_FILENO 2
100 #endif
101
102 #ifndef QT_OPEN_BINARY
103 #define QT_OPEN_BINARY 0
104 #endif
105
106 Q_DECLARE_METATYPE(QFile::FileError)
107
108 class tst_QFile : public QObject
109 {
110     Q_OBJECT
111
112 private slots:
113     void init();
114     void cleanup();
115     void initTestCase();
116     void cleanupTestCase();
117     void exists();
118     void open_data();
119     void open();
120     void openUnbuffered();
121     void size_data();
122     void size();
123     void sizeNoExist();
124     void seek();
125     void setSize();
126     void setSizeSeek();
127     void atEnd();
128     void readLine();
129     void readLine2();
130     void readLineNullInLine();
131     void readAll_data();
132     void readAll();
133     void readAllBuffer();
134     void readAllStdin();
135     void readLineStdin();
136     void readLineStdin_lineByLine();
137     void text();
138     void missingEndOfLine();
139     void readBlock();
140     void getch();
141     void ungetChar();
142     void createFile();
143     void append();
144     void permissions_data();
145     void permissions();
146     void permissionsNtfs_data();
147     void permissionsNtfs();
148     void setPermissions();
149     void copy();
150     void copyAfterFail();
151     void copyRemovesTemporaryFile() const;
152     void copyShouldntOverwrite();
153     void copyFallback();
154     void link();
155     void linkToDir();
156     void absolutePathLinkToRelativePath();
157     void readBrokenLink();
158     void readTextFile_data();
159     void readTextFile();
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();
166 #endif
167     void tailFile();
168     void flush();
169     void bufferedRead();
170     void isSequential();
171     void encodeName();
172     void truncate();
173     void seekToPos();
174     void seekAfterEndOfFile();
175     void FILEReadWrite();
176     void i18nFileName_data();
177     void i18nFileName();
178     void longFileName_data();
179     void longFileName();
180     void fileEngineHandler();
181     void useQFileInAFileHandler();
182     void getCharFF();
183     void remove_and_exists();
184     void removeOpenFile();
185     void fullDisk();
186     void writeLargeDataBlock_data();
187     void writeLargeDataBlock();
188     void readFromWriteOnlyFile();
189     void writeToReadOnlyFile();
190     void virtualFile();
191     void textFile();
192     void rename_data();
193     void rename();
194     void renameWithAtEndSpecialFile() const;
195     void renameFallback();
196     void renameMultiple();
197     void appendAndRead();
198     void miscWithUncPathAsCurrentDir();
199     void standarderror();
200     void handle();
201     void nativeHandleLeaks();
202
203     void readEof_data();
204     void readEof();
205
206     void map_data();
207     void map();
208     void mapResource_data();
209     void mapResource();
210     void mapOpenMode_data();
211     void mapOpenMode();
212
213     void openStandardStreamsFileDescriptors();
214     void openStandardStreamsBufferedStreams();
215
216     void resize_data();
217     void resize();
218
219     void objectConstructors();
220
221     void caseSensitivity();
222
223     void autocloseHandle();
224
225     void posAfterFailedStat();
226
227     void openDirectory();
228     void writeNothing();
229
230 public:
231 // disabled this test for the moment... it hangs
232     void invalidFile_data();
233     void invalidFile();
234
235 private:
236     enum FileType {
237         OpenQFile,
238         OpenFd,
239         OpenStream,
240         NumberOfFileTypes
241     };
242
243     bool openFd(QFile &file, QIODevice::OpenMode mode, QFile::FileHandleFlags handleFlags)
244     {
245         int fdMode = QT_OPEN_LARGEFILE | QT_OPEN_BINARY;
246
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;
252
253         fd_ = QT_OPEN(qPrintable(file.fileName()), fdMode);
254
255         return (-1 != fd_) && file.open(fd_, mode, handleFlags);
256     }
257
258     bool openStream(QFile &file, QIODevice::OpenMode mode, QFile::FileHandleFlags handleFlags)
259     {
260         char const *streamMode = "";
261
262         // File will be truncated if in Write mode.
263         if (mode & QIODevice::WriteOnly)
264             streamMode = "wb+";
265         else if (mode & QIODevice::ReadOnly)
266             streamMode = "rb";
267
268         stream_ = QT_FOPEN(qPrintable(file.fileName()), streamMode);
269
270         return stream_ && file.open(stream_, mode, handleFlags);
271     }
272
273     bool openFile(QFile &file, QIODevice::OpenMode mode, FileType type = OpenQFile, QFile::FileHandleFlags handleFlags = QFile::DontCloseHandle)
274     {
275         if (mode & QIODevice::WriteOnly && !file.exists())
276         {
277             // Make sure the file exists
278             QFile createFile(file.fileName());
279             if (!createFile.open(QIODevice::ReadWrite))
280                 return false;
281         }
282
283         // Note: openFd and openStream will truncate the file if write mode.
284         switch (type)
285         {
286             case OpenQFile:
287                 return file.open(mode);
288
289             case OpenFd:
290                 return openFd(file, mode, handleFlags);
291
292             case OpenStream:
293                 return openStream(file, mode, handleFlags);
294
295             case NumberOfFileTypes:
296                 break;
297         }
298
299         return false;
300     }
301
302     void closeFile(QFile &file)
303     {
304         file.close();
305
306         if (-1 != fd_)
307             QT_CLOSE(fd_);
308         if (stream_)
309             ::fclose(stream_);
310
311         fd_ = -1;
312         stream_ = 0;
313     }
314
315     int fd_;
316     FILE *stream_;
317 };
318
319 void tst_QFile::init()
320 {
321     fd_ = -1;
322     stream_ = 0;
323 }
324
325 void tst_QFile::cleanup()
326 {
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");
332     }
333
334     // for renameFallback()
335     QFile::remove("file-rename-destination.txt");
336
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");
342
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");
348
349     if (-1 != fd_)
350         QT_CLOSE(fd_);
351     if (stream_)
352         ::fclose(stream_);
353 }
354
355 void tst_QFile::initTestCase()
356 {
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));
360
361     QFile::remove("noreadfile");
362
363     // create a file and make it read-only
364     QFile file("readonlyfile");
365     file.open(QFile::WriteOnly);
366     file.write("a", 1);
367     file.close();
368     file.setPermissions(QFile::ReadOwner);
369
370     // create another file and make it not readable
371     file.setFileName("noreadfile");
372     file.open(QFile::WriteOnly);
373     file.write("b", 1);
374     file.close();
375     file.setPermissions(0);
376 }
377
378 void tst_QFile::cleanupTestCase()
379 {
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");
404 }
405
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 //------------------------------------------
414
415 void tst_QFile::exists()
416 {
417     QFile f( QFINDTESTDATA("testfile.txt") );
418     QVERIFY(f.exists());
419
420     QFile file("nobodyhassuchafile");
421     file.remove();
422     QVERIFY(!file.exists());
423
424     QFile file2("nobodyhassuchafile");
425     QVERIFY(file2.open(QIODevice::WriteOnly));
426     file2.close();
427
428     QVERIFY(file.exists());
429
430     QVERIFY(file.open(QIODevice::WriteOnly));
431     file.close();
432     QVERIFY(file.exists());
433
434     file.remove();
435     QVERIFY(!file.exists());
436
437 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
438     QFile unc("//" + QtNetworkSettings::winServerName() + "/testshare/readme.txt");
439     QVERIFY(unc.exists());
440 #endif
441 }
442
443 void tst_QFile::open_data()
444 {
445     QTest::addColumn<QString>("filename");
446     QTest::addColumn<int>("mode");
447     QTest::addColumn<bool>("ok");
448     QTest::addColumn<QFile::FileError>("status");
449
450 #ifdef Q_OS_MAC
451     static const QString denied("Operation not permitted");
452 #else
453     static const QString denied("Permission denied");
454 #endif
455     QTest::newRow( "exist_readOnly"  )
456         << QString(QFINDTESTDATA("testfile.txt")) << int(QIODevice::ReadOnly)
457         << true << QFile::NoError;
458
459     QTest::newRow( "exist_writeOnly" )
460         << QString("readonlyfile")
461         << int(QIODevice::WriteOnly)
462         << false
463         << QFile::OpenError;
464
465     QTest::newRow( "exist_append"    )
466         << QString("readonlyfile") << int(QIODevice::Append)
467         << false << QFile::OpenError;
468
469     QTest::newRow( "nonexist_readOnly"  )
470         << QString("nonExist.txt") << int(QIODevice::ReadOnly)
471         << false << QFile::OpenError;
472
473     QTest::newRow("emptyfile")
474         << QString("")
475         << int(QIODevice::ReadOnly)
476         << false
477         << QFile::OpenError;
478
479     QTest::newRow("nullfile") << QString() << int(QIODevice::ReadOnly) << false
480         << QFile::OpenError;
481
482     QTest::newRow("two-dots") << QString(QFINDTESTDATA("two.dots.file")) << int(QIODevice::ReadOnly) << true
483         << QFile::NoError;
484
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) {
493         CloseHandle(hTest);
494         QTest::newRow("//./PhysicalDrive0") << QString("//./PhysicalDrive0") << int(QIODevice::ReadOnly)
495                                             << true << QFile::NoError;
496     } else {
497         QTest::newRow("//./PhysicalDrive0") << QString("//./PhysicalDrive0") << int(QIODevice::ReadOnly)
498                                             << false << QFile::OpenError;
499     }
500     QTest::newRow("uncFile") << "//" + QtNetworkSettings::winServerName() + "/testshare/test.pri" << int(QIODevice::ReadOnly)
501                              << true << QFile::NoError;
502 #endif
503 }
504
505 void tst_QFile::open()
506 {
507     QFETCH( QString, filename );
508     QFETCH( int, mode );
509
510     QFile f( filename );
511
512     QFETCH( bool, ok );
513
514 #if defined(Q_OS_UNIX)
515     if (::getuid() == 0)
516         // root and Chuck Norris don't care for file permissions. Skip.
517         QSKIP("Running this test as root doesn't make sense");
518 #endif
519
520 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
521     QEXPECT_FAIL("noreadfile", "Windows does not currently support non-readable files.", Abort);
522 #endif
523     if (filename.isEmpty())
524         QTest::ignoreMessage(QtWarningMsg, "QFSFileEngine::open: No file name specified");
525
526     QCOMPARE(f.open( QIODevice::OpenMode(mode) ), ok);
527
528     QTEST( f.error(), "status" );
529 }
530
531 void tst_QFile::openUnbuffered()
532 {
533     QFile file(QFINDTESTDATA("testfile.txt"));
534     QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Unbuffered));
535     char c = '\0';
536     QVERIFY(file.seek(1));
537     QCOMPARE(file.pos(), qint64(1));
538     QVERIFY(file.getChar(&c));
539     QCOMPARE(file.pos(), qint64(2));
540     char d = '\0';
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));
547     char c2 = '\0';
548     QVERIFY(file.getChar(&c2));
549     QCOMPARE(file.pos(), qint64(2));
550     QVERIFY(file.seek(3));
551     QCOMPARE(file.pos(), qint64(3));
552     char d2 = '\0';
553     QVERIFY(file.getChar(&d2));
554     QCOMPARE(file.pos(), qint64(4));
555     QCOMPARE(c, c2);
556     QCOMPARE(d, d2);
557     QCOMPARE(c, '-');
558     QCOMPARE(d, '-');
559 }
560
561 void tst_QFile::size_data()
562 {
563     QTest::addColumn<QString>("filename");
564     QTest::addColumn<qint64>("size");
565
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;
570 #endif
571 }
572
573 void tst_QFile::size()
574 {
575     QFETCH( QString, filename );
576     QFETCH( qint64, size );
577
578 #ifdef Q_OS_WINCE
579         filename = QFileInfo(filename).absoluteFilePath();
580 #endif
581
582     {
583         QFile f( filename );
584         QCOMPARE( f.size(), size );
585
586         QVERIFY( f.open(QIODevice::ReadOnly) );
587         QCOMPARE( f.size(), size );
588     }
589
590     {
591         QFile f;
592         FILE* stream = QT_FOPEN(filename.toLocal8Bit().constData(), "rb");
593         QVERIFY( stream );
594         QVERIFY( f.open(stream, QIODevice::ReadOnly) );
595         QCOMPARE( f.size(), size );
596
597         f.close();
598         fclose(stream);
599     }
600
601     // Currently low level file I/O is not well supported on Windows CE, so
602     // skip this part of the test.
603 #ifndef Q_OS_WINCE
604     {
605         QFile f;
606
607         int fd = QT_OPEN(filename.toLocal8Bit().constData(), QT_OPEN_RDONLY);
608
609         QVERIFY( fd != -1 );
610         QVERIFY( f.open(fd, QIODevice::ReadOnly) );
611         QCOMPARE( f.size(), size );
612
613         f.close();
614         QT_CLOSE(fd);
615     }
616 #endif
617 }
618
619 void tst_QFile::sizeNoExist()
620 {
621     QFile file("nonexist01");
622     QVERIFY( !file.exists() );
623     QCOMPARE( file.size(), (qint64)0 );
624     QVERIFY( !file.open(QIODevice::ReadOnly) );
625 }
626
627 void tst_QFile::seek()
628 {
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));
637     file.close();
638     QFile::remove("newfile.txt");
639 }
640
641 void tst_QFile::setSize()
642 {
643     if ( QFile::exists( "createme.txt" ) )
644         QFile::remove( "createme.txt" );
645     QVERIFY( !QFile::exists( "createme.txt" ) );
646
647     QFile f("createme.txt");
648     QVERIFY(f.open(QIODevice::Truncate | QIODevice::ReadWrite));
649     f.putChar('a');
650
651     f.seek(0);
652     char c = '\0';
653     f.getChar(&c);
654     QCOMPARE(c, 'a');
655
656     QCOMPARE(f.size(), (qlonglong)1);
657     bool ok = f.resize(99);
658     QVERIFY(ok);
659     QCOMPARE(f.size(), (qlonglong)99);
660
661     f.seek(0);
662     c = '\0';
663     f.getChar(&c);
664     QCOMPARE(c, 'a');
665
666     QVERIFY(f.resize(1));
667     QCOMPARE(f.size(), (qlonglong)1);
668
669     f.seek(0);
670     c = '\0';
671     f.getChar(&c);
672     QCOMPARE(c, 'a');
673
674     f.close();
675
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);
681 }
682
683 void tst_QFile::setSizeSeek()
684 {
685     QFile::remove("setsizeseek.txt");
686     QFile f("setsizeseek.txt");
687     QVERIFY(f.open(QFile::WriteOnly));
688     f.write("ABCD");
689
690     QCOMPARE(f.pos(), qint64(4));
691     f.resize(2);
692     QCOMPARE(f.pos(), qint64(2));
693     f.resize(4);
694     QCOMPARE(f.pos(), qint64(2));
695     f.resize(0);
696     QCOMPARE(f.pos(), qint64(0));
697     f.resize(4);
698     QCOMPARE(f.pos(), qint64(0));
699
700     f.seek(3);
701     QCOMPARE(f.pos(), qint64(3));
702     f.resize(2);
703     QCOMPARE(f.pos(), qint64(2));
704 }
705
706 void tst_QFile::atEnd()
707 {
708     QFile f( QFINDTESTDATA("testfile.txt") );
709     QVERIFY(f.open( QIODevice::ReadOnly ));
710
711     int size = f.size();
712     f.seek( size );
713
714     bool end = f.atEnd();
715     f.close();
716     QVERIFY(end);
717 }
718
719 void tst_QFile::readLine()
720 {
721     QFile f( QFINDTESTDATA("testfile.txt") );
722     QVERIFY(f.open( QIODevice::ReadOnly ));
723
724     int i = 0;
725     char p[128];
726     int foo;
727     while ( (foo=f.readLine( p, 128 )) > 0 ) {
728         ++i;
729         if ( i == 5 ) {
730             QCOMPARE( p[0], 'T' );
731             QCOMPARE( p[3], 's' );
732             QCOMPARE( p[11], 'i' );
733         }
734     }
735     f.close();
736     QCOMPARE( i, 6 );
737 }
738
739 void tst_QFile::readLine2()
740 {
741     QFile f( QFINDTESTDATA("testfile.txt") );
742     f.open( QIODevice::ReadOnly );
743
744     char p[128];
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));
749
750     QCOMPARE(p[57], '-');
751     QCOMPARE(p[58], '\n');
752     QCOMPARE(p[59], '\0');
753     QCOMPARE(p[60], '@');
754 }
755
756 void tst_QFile::readLineNullInLine()
757 {
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());
763     file.reset();
764
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());
770 }
771
772 void tst_QFile::readAll_data()
773 {
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);
783 }
784
785 void tst_QFile::readAll()
786 {
787     QFETCH( bool, textMode );
788     QFETCH( QString, fileName );
789
790     QFile file(fileName);
791     if (textMode)
792         QVERIFY(file.open(QFile::Text | QFile::ReadOnly));
793     else
794         QVERIFY(file.open(QFile::ReadOnly));
795
796     QByteArray a = file.readAll();
797     file.reset();
798     QVERIFY(file.pos() == 0);
799
800     QVERIFY(file.bytesAvailable() > 7);
801     QByteArray b = file.read(1);
802     char x;
803     file.getChar(&x);
804     b.append(x);
805     b.append(file.read(5));
806     b.append(file.readAll());
807
808     QCOMPARE(a, b);
809 }
810
811 void tst_QFile::readAllBuffer()
812 {
813     QString fileName = QLatin1String("readAllBuffer.txt");
814
815     QFile::remove(fileName);
816
817     QFile writer(fileName);
818     QFile reader(fileName);
819
820     QByteArray data1("This is arguably a very simple text.");
821     QByteArray data2("This is surely not as simple a test.");
822
823     QVERIFY( writer.open(QIODevice::ReadWrite | QIODevice::Unbuffered) );
824     QVERIFY( reader.open(QIODevice::ReadOnly) );
825
826     QCOMPARE( writer.write(data1), qint64(data1.size()) );
827     QVERIFY( writer.seek(0) );
828
829     QByteArray result;
830     result = reader.read(18);
831     QCOMPARE( result.size(), 18 );
832
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
835
836     result += reader.readAll();
837
838     QCOMPARE( result, data1 + data2 );
839
840     QFile::remove(fileName);
841 }
842
843 void tst_QFile::readAllStdin()
844 {
845 #if defined(Q_OS_WINCE)
846     QSKIP("Currently no stdin/out supported for Windows CE");
847 #endif
848 #if defined(QT_NO_PROCESS)
849     QSKIP("Qt was compiled with QT_NO_PROCESS");
850 #else
851     QByteArray lotsOfData(1024, '@'); // 10 megs
852
853     QProcess process;
854     process.start("stdinprocess/stdinprocess all");
855     QVERIFY( process.waitForStarted() );
856     for (int i = 0; i < 5; ++i) {
857         QTest::qWait(1000);
858         process.write(lotsOfData);
859         while (process.bytesToWrite() > 0) {
860             QVERIFY(process.waitForBytesWritten());
861         }
862     }
863
864     process.closeWriteChannel();
865     process.waitForFinished();
866     QCOMPARE(process.readAll().size(), lotsOfData.size() * 5);
867 #endif
868 }
869
870 void tst_QFile::readLineStdin()
871 {
872 #if defined(Q_OS_WINCE)
873     QSKIP("Currently no stdin/out supported for Windows CE");
874 #endif
875 #if defined(QT_NO_PROCESS)
876     QSKIP("Qt was compiled with QT_NO_PROCESS");
877 #else
878
879     QByteArray lotsOfData(1024, '@'); // 10 megs
880     for (int i = 0; i < lotsOfData.size(); ++i) {
881         if ((i % 32) == 31)
882             lotsOfData[i] = '\n';
883         else
884             lotsOfData[i] = char('0' + i % 32);
885     }
886
887     for (int i = 0; i < 2; ++i) {
888         QProcess process;
889         process.start((QString("stdinprocess/stdinprocess line %1").arg(i)), QIODevice::Text | QIODevice::ReadWrite);
890         for (int i = 0; i < 5; ++i) {
891             QTest::qWait(1000);
892             process.write(lotsOfData);
893             while (process.bytesToWrite() > 0) {
894                 QVERIFY(process.waitForBytesWritten());
895             }
896         }
897
898         process.closeWriteChannel();
899         QVERIFY(process.waitForFinished(5000));
900
901         QByteArray array = process.readAll();
902         QCOMPARE(array.size(), lotsOfData.size() * 5);
903         for (int i = 0; i < array.size(); ++i) {
904             if ((i % 32) == 31)
905                 QCOMPARE(char(array[i]), '\n');
906             else
907                 QCOMPARE(char(array[i]), char('0' + i % 32));
908         }
909     }
910 #endif
911 }
912
913 void tst_QFile::readLineStdin_lineByLine()
914 {
915 #if defined(Q_OS_WINCE)
916     QSKIP("Currently no stdin/out supported for Windows CE");
917 #endif
918 #if defined(QT_NO_PROCESS)
919     QSKIP("Qt was compiled with QT_NO_PROCESS");
920 #else
921     for (int i = 0; i < 2; ++i) {
922         QProcess process;
923         process.start(QString("stdinprocess/stdinprocess line %1").arg(i), QIODevice::Text | QIODevice::ReadWrite);
924         QVERIFY(process.waitForStarted());
925
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);
933         }
934
935         process.closeWriteChannel();
936         QVERIFY(process.waitForFinished(5000));
937     }
938 #endif
939 }
940
941 void tst_QFile::text()
942 {
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');
951     file.ungetChar('2');
952     QCOMPARE(file.readLine().constData(), QByteArray("2\n").constData());
953 }
954
955 void tst_QFile::missingEndOfLine()
956 {
957     QFile file(QFINDTESTDATA("noendofline.txt"));
958     QVERIFY(file.open(QFile::ReadOnly));
959
960     int nlines = 0;
961     while (!file.atEnd()) {
962         ++nlines;
963         file.readLine();
964     }
965
966     QCOMPARE(nlines, 3);
967 }
968
969 void tst_QFile::readBlock()
970 {
971     QFile f( QFINDTESTDATA("testfile.txt") );
972     f.open( QIODevice::ReadOnly );
973
974     int length = 0;
975     char p[256];
976     length = f.read( p, 256 );
977     f.close();
978     QCOMPARE( length, 245 );
979     QCOMPARE( p[59], 'D' );
980     QCOMPARE( p[178], 'T' );
981     QCOMPARE( p[199], 'l' );
982 }
983
984 void tst_QFile::getch()
985 {
986     QFile f( QFINDTESTDATA("testfile.txt") );
987     f.open( QIODevice::ReadOnly );
988
989     char c;
990     int i = 0;
991     while (f.getChar(&c)) {
992         QCOMPARE(f.pos(), qint64(i + 1));
993         if ( i == 59 )
994             QCOMPARE( c, 'D' );
995         ++i;
996     }
997     f.close();
998     QCOMPARE( i, 245 );
999 }
1000
1001 void tst_QFile::ungetChar()
1002 {
1003     QFile f(QFINDTESTDATA("testfile.txt"));
1004     QVERIFY(f.open(QIODevice::ReadOnly));
1005
1006     QByteArray array = f.readLine();
1007     QCOMPARE(array.constData(), "----------------------------------------------------------\n");
1008     f.ungetChar('\n');
1009
1010     array = f.readLine();
1011     QCOMPARE(array.constData(), "\n");
1012
1013     f.ungetChar('\n');
1014     f.ungetChar('-');
1015     f.ungetChar('-');
1016
1017     array = f.readLine();
1018     QCOMPARE(array.constData(), "--\n");
1019
1020     QFile::remove("genfile.txt");
1021     QFile out("genfile.txt");
1022     QVERIFY(out.open(QIODevice::ReadWrite));
1023     out.write("123");
1024     out.seek(0);
1025     QCOMPARE(out.readAll().constData(), "123");
1026     out.ungetChar('3');
1027     out.write("4");
1028     out.seek(0);
1029     QCOMPARE(out.readAll().constData(), "124");
1030     out.ungetChar('4');
1031     out.ungetChar('2');
1032     out.ungetChar('1');
1033     char buf[3];
1034     QCOMPARE(out.read(buf, sizeof(buf)), qint64(3));
1035     QCOMPARE(buf[0], '1');
1036     QCOMPARE(buf[1], '2');
1037     QCOMPARE(buf[2], '4');
1038 }
1039
1040 void tst_QFile::invalidFile_data()
1041 {
1042     QTest::addColumn<QString>("fileName");
1043 #if !defined(Q_OS_WIN)
1044     QTest::newRow( "x11" ) << QString( "qwe//" );
1045 #else
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" );
1056 #endif
1057 }
1058
1059 void tst_QFile::invalidFile()
1060 {
1061     QFETCH( QString, fileName );
1062     QFile f( fileName );
1063     QVERIFY( !f.open( QIODevice::ReadWrite ) );
1064 }
1065
1066 void tst_QFile::createFile()
1067 {
1068     if ( QFile::exists( "createme.txt" ) )
1069         QFile::remove( "createme.txt" );
1070     QVERIFY( !QFile::exists( "createme.txt" ) );
1071
1072     QFile f( "createme.txt" );
1073     QVERIFY( f.open( QIODevice::WriteOnly ) );
1074     f.close();
1075     QVERIFY( QFile::exists( "createme.txt" ) );
1076 }
1077
1078 void tst_QFile::append()
1079 {
1080     const QString name("appendme.txt");
1081     if (QFile::exists(name))
1082         QFile::remove(name);
1083     QVERIFY(!QFile::exists(name));
1084
1085     QFile f(name);
1086     QVERIFY(f.open(QIODevice::WriteOnly | QIODevice::Truncate));
1087     f.putChar('a');
1088     f.close();
1089
1090     QVERIFY(f.open(QIODevice::Append));
1091     QVERIFY(f.pos() == 1);
1092     f.putChar('a');
1093     f.close();
1094     QCOMPARE(int(f.size()), 2);
1095 }
1096
1097 void tst_QFile::permissions_data()
1098 {
1099     QTest::addColumn<QString>("file");
1100     QTest::addColumn<uint>("perms");
1101     QTest::addColumn<bool>("expected");
1102     QTest::addColumn<bool>("create");
1103
1104     QTest::newRow("data0") << QCoreApplication::instance()->applicationFilePath() << uint(QFile::ExeUser) << true << false;
1105     QTest::newRow("data1") << QFINDTESTDATA("tst_qfile.cpp") << uint(QFile::ReadUser) << true << false;
1106     QTest::newRow("readonly") << QFINDTESTDATA("readonlyfile") << uint(QFile::WriteUser) << false << false;
1107 #ifndef Q_OS_WINCE
1108     QTest::newRow("longfile") << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1109                                                     "longFileNamelongFileNamelongFileNamelongFileName"
1110                                                     "longFileNamelongFileNamelongFileNamelongFileName"
1111                                                     "longFileNamelongFileNamelongFileNamelongFileName"
1112                                                     "longFileNamelongFileNamelongFileNamelongFileName.txt") << uint(QFile::ReadUser) << true << true;
1113 #endif
1114     QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << uint(QFile::ReadUser) << true << false;
1115     QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1" << uint(QFile::WriteUser) << false << false;
1116     QTest::newRow("resource3") << ":/tst_qfileinfo/resources/file1.ext1" << uint(QFile::ExeUser) << false << false;
1117 }
1118
1119 void tst_QFile::permissions()
1120 {
1121     QFETCH(QString, file);
1122     QFETCH(uint, perms);
1123     QFETCH(bool, expected);
1124     QFETCH(bool, create);
1125     if (create) {
1126         QFile fc(file);
1127         QVERIFY(fc.open(QFile::WriteOnly));
1128         QVERIFY(fc.write("hello\n"));
1129         fc.close();
1130     }
1131
1132     QFile f(file);
1133     QFile::Permissions memberResult = f.permissions() & perms;
1134     QFile::Permissions staticResult = QFile::permissions(file) & perms;
1135
1136     if (create) {
1137         QFile::remove(file);
1138     }
1139
1140 #ifdef Q_OS_WIN
1141     if (qt_ntfs_permission_lookup)
1142         QEXPECT_FAIL("readonly", "QTBUG-25630", Abort);
1143 #endif
1144     QCOMPARE((memberResult == QFile::Permissions(perms)), expected);
1145     QCOMPARE((staticResult == QFile::Permissions(perms)), expected);
1146 }
1147
1148 void tst_QFile::permissionsNtfs_data()
1149 {
1150     permissions_data();
1151 }
1152
1153 void tst_QFile::permissionsNtfs()
1154 {
1155 #ifdef Q_OS_WIN
1156     QScopedValueRollback<int> ntfsMode(qt_ntfs_permission_lookup);
1157     qt_ntfs_permission_lookup++;
1158     permissions();
1159 #else
1160     QSKIP("windows test");
1161 #endif
1162 }
1163
1164 void tst_QFile::setPermissions()
1165 {
1166     if ( QFile::exists( "createme.txt" ) )
1167         QFile::remove( "createme.txt" );
1168     QVERIFY( !QFile::exists( "createme.txt" ) );
1169
1170     QFile f("createme.txt");
1171     QVERIFY(f.open(QIODevice::WriteOnly | QIODevice::Truncate));
1172     f.putChar('a');
1173     f.close();
1174
1175     QFile::Permissions perms(QFile::WriteUser | QFile::ReadUser);
1176     QVERIFY(f.setPermissions(perms));
1177     QVERIFY((f.permissions() & perms) == perms);
1178
1179 }
1180
1181 void tst_QFile::copy()
1182 {
1183     QFile::setPermissions("tst_qfile_copy.cpp", QFile::WriteUser);
1184     QFile::remove("tst_qfile_copy.cpp");
1185     QFile::remove("test2");
1186     QVERIFY(QFile::copy(QFINDTESTDATA("tst_qfile.cpp"), "tst_qfile_copy.cpp"));
1187     QFile in1(QFINDTESTDATA("tst_qfile.cpp")), in2("tst_qfile_copy.cpp");
1188     QVERIFY(in1.open(QFile::ReadOnly));
1189     QVERIFY(in2.open(QFile::ReadOnly));
1190     QByteArray data1 = in1.readAll(), data2 = in2.readAll();
1191     QCOMPARE(data1, data2);
1192     QFile::remove( "main_copy.cpp" );
1193
1194     QFile::copy(QDir::currentPath(), QDir::currentPath() + QLatin1String("/test2"));
1195 }
1196
1197 void tst_QFile::copyAfterFail()
1198 {
1199     QFile file1("file-to-be-copied.txt");
1200     QFile file2("existing-file.txt");
1201
1202     QVERIFY(file1.open(QIODevice::ReadWrite) && "(test-precondition)");
1203     QVERIFY(file2.open(QIODevice::ReadWrite) && "(test-precondition)");
1204     file2.close();
1205     QVERIFY(!QFile::exists("copied-file-1.txt") && "(test-precondition)");
1206     QVERIFY(!QFile::exists("copied-file-2.txt") && "(test-precondition)");
1207
1208     QVERIFY(!file1.copy("existing-file.txt"));
1209     QCOMPARE(file1.error(), QFile::CopyError);
1210
1211     QVERIFY(file1.copy("copied-file-1.txt"));
1212     QVERIFY(!file1.isOpen());
1213     QCOMPARE(file1.error(), QFile::NoError);
1214
1215     QVERIFY(!file1.copy("existing-file.txt"));
1216     QCOMPARE(file1.error(), QFile::CopyError);
1217
1218     QVERIFY(file1.copy("copied-file-2.txt"));
1219     QVERIFY(!file1.isOpen());
1220     QCOMPARE(file1.error(), QFile::NoError);
1221
1222     QVERIFY(QFile::exists("copied-file-1.txt"));
1223     QVERIFY(QFile::exists("copied-file-2.txt"));
1224
1225     QVERIFY(QFile::remove("file-to-be-copied.txt") && "(test-cleanup)");
1226     QVERIFY(QFile::remove("existing-file.txt") && "(test-cleanup)");
1227     QVERIFY(QFile::remove("copied-file-1.txt") && "(test-cleanup)");
1228     QVERIFY(QFile::remove("copied-file-2.txt") && "(test-cleanup)");
1229 }
1230
1231 void tst_QFile::copyRemovesTemporaryFile() const
1232 {
1233     const QString newName(QLatin1String("copyRemovesTemporaryFile"));
1234     QVERIFY(QFile::copy(QFINDTESTDATA("forCopying.txt"), newName));
1235
1236     QVERIFY(!QFile::exists(QFINDTESTDATA("qt_temp.XXXXXX")));
1237     QVERIFY(QFile::remove(newName));
1238 }
1239
1240 void tst_QFile::copyShouldntOverwrite()
1241 {
1242     // Copy should not overwrite existing files.
1243     QFile::remove("tst_qfile.cpy");
1244     QFile file(QFINDTESTDATA("tst_qfile.cpp"));
1245     QVERIFY(file.copy("tst_qfile.cpy"));
1246
1247     bool ok = QFile::setPermissions("tst_qfile.cpy", QFile::WriteOther);
1248     QVERIFY(ok);
1249     QVERIFY(!file.copy("tst_qfile.cpy"));
1250     QFile::remove("tst_qfile.cpy");
1251 }
1252
1253 void tst_QFile::copyFallback()
1254 {
1255     // Using a resource file to trigger QFile::copy's fallback handling
1256     QFile file(":/copy-fallback.qrc");
1257     QFile::remove("file-copy-destination.txt");
1258
1259     QVERIFY2(file.exists(), "test precondition");
1260     QVERIFY2(!QFile::exists("file-copy-destination.txt"), "test precondition");
1261
1262     // Fallback copy of closed file.
1263     QVERIFY(file.copy("file-copy-destination.txt"));
1264     QVERIFY(QFile::exists("file-copy-destination.txt"));
1265     QVERIFY(!file.isOpen());
1266
1267 #ifdef Q_OS_WINCE
1268     // Need to reset permissions on Windows to be able to delete
1269     QVERIFY(QFile::setPermissions("file-copy-destination.txt",
1270             QFile::WriteOther));
1271 #else
1272      // Need to reset permissions on Windows to be able to delete
1273     QVERIFY(QFile::setPermissions("file-copy-destination.txt",
1274            QFile::ReadOwner | QFile::WriteOwner));
1275 #endif
1276     QVERIFY(QFile::remove("file-copy-destination.txt"));
1277
1278     // Fallback copy of open file.
1279     QVERIFY(file.open(QIODevice::ReadOnly));
1280     QVERIFY(file.copy("file-copy-destination.txt"));
1281     QVERIFY(QFile::exists("file-copy-destination.txt"));
1282     QVERIFY(!file.isOpen());
1283
1284     file.close(); 
1285     QFile::remove("file-copy-destination.txt");
1286 }
1287
1288 #ifdef Q_OS_WIN
1289 #include <objbase.h>
1290 #include <shlobj.h>
1291 #endif
1292
1293 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1294 static QString getWorkingDirectoryForLink(const QString &linkFileName)
1295 {
1296     bool neededCoInit = false;
1297     QString ret;
1298
1299     IShellLink *psl;
1300     HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
1301     if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized
1302         neededCoInit = true;
1303         CoInitialize(NULL);
1304         hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
1305     }
1306
1307     if (SUCCEEDED(hres)) {    // Get pointer to the IPersistFile interface.
1308         IPersistFile *ppf;
1309         hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
1310         if (SUCCEEDED(hres))  {
1311             hres = ppf->Load((LPOLESTR)linkFileName.utf16(), STGM_READ);
1312             //The original path of the link is retrieved. If the file/folder
1313             //was moved, the return value still have the old path.
1314             if(SUCCEEDED(hres)) {
1315                 wchar_t szGotPath[MAX_PATH];
1316                 if (psl->GetWorkingDirectory(szGotPath, MAX_PATH) == NOERROR)
1317                     ret = QString::fromWCharArray(szGotPath);
1318             }
1319             ppf->Release();
1320         }
1321         psl->Release();
1322     }
1323
1324     if (neededCoInit) {
1325         CoUninitialize();
1326     }
1327
1328     return ret;
1329 }
1330 #endif
1331
1332 void tst_QFile::link()
1333 {
1334     QFile::remove("myLink.lnk");
1335
1336     QFileInfo info1(QFINDTESTDATA("tst_qfile.cpp"));
1337     QString referenceTarget = QDir::cleanPath(info1.absoluteFilePath());
1338
1339     QVERIFY(QFile::link(QFINDTESTDATA("tst_qfile.cpp"), "myLink.lnk"));
1340
1341     QFileInfo info2("myLink.lnk");
1342     QVERIFY(info2.isSymLink());
1343     QCOMPARE(info2.symLinkTarget(), referenceTarget);
1344
1345     QFile link("myLink.lnk");
1346     QVERIFY(link.open(QIODevice::ReadOnly));
1347     QCOMPARE(link.symLinkTarget(), referenceTarget);
1348     link.close();
1349
1350     QCOMPARE(QFile::symLinkTarget("myLink.lnk"), referenceTarget);
1351
1352 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1353     QString wd = getWorkingDirectoryForLink(info2.absoluteFilePath());
1354     QCOMPARE(QDir::fromNativeSeparators(wd), QDir::cleanPath(info1.absolutePath()));
1355 #endif
1356
1357     QVERIFY(QFile::remove(info2.absoluteFilePath()));
1358 }
1359
1360 void tst_QFile::linkToDir()
1361 {
1362     QFile::remove("myLinkToDir.lnk");
1363     QDir dir;
1364     dir.mkdir("myDir");
1365     QFileInfo info1("myDir");
1366     QVERIFY(QFile::link("myDir", "myLinkToDir.lnk"));
1367     QFileInfo info2("myLinkToDir.lnk");
1368 #if !(defined Q_OS_HPUX && defined(__ia64))
1369     // absurd HP-UX filesystem bug on gravlaks - checking if a symlink
1370     // resolves or not alters the file system to make the broken symlink
1371     // later fail...
1372     QVERIFY(info2.isSymLink());
1373 #endif
1374     QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath());
1375     QVERIFY(QFile::remove(info2.absoluteFilePath()));
1376     QFile::remove("myLinkToDir.lnk");
1377     dir.rmdir("myDir");
1378 }
1379
1380 void tst_QFile::absolutePathLinkToRelativePath()
1381 {
1382     QFile::remove("myDir/test.txt");
1383     QFile::remove("myDir/myLink.lnk");
1384     QDir dir;
1385     dir.mkdir("myDir");
1386     QFile("myDir/test.txt").open(QFile::WriteOnly);
1387
1388 #ifdef Q_OS_WIN
1389     QVERIFY(QFile::link("test.txt", "myDir/myLink.lnk"));
1390 #else
1391     QVERIFY(QFile::link("myDir/test.txt", "myDir/myLink.lnk"));
1392 #endif
1393     QEXPECT_FAIL("", "Symlinking using relative paths is currently different on Windows and Unix", Continue);
1394     QCOMPARE(QFileInfo(QFile(QFileInfo("myDir/myLink.lnk").absoluteFilePath()).symLinkTarget()).absoluteFilePath(),
1395              QFileInfo("myDir/test.txt").absoluteFilePath());
1396
1397     QFile::remove("myDir/test.txt");
1398     QFile::remove("myDir/myLink.lnk");
1399     dir.rmdir("myDir");
1400 }
1401
1402 void tst_QFile::readBrokenLink()
1403 {
1404     QFile::remove("myLink2.lnk");
1405     QFileInfo info1("file12");
1406     QVERIFY(QFile::link("file12", "myLink2.lnk"));
1407     QFileInfo info2("myLink2.lnk");
1408     QVERIFY(info2.isSymLink());
1409     QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath());
1410     QVERIFY(QFile::remove(info2.absoluteFilePath()));
1411     QVERIFY(QFile::link("ole/..", "myLink2.lnk"));
1412     QCOMPARE(QFileInfo("myLink2.lnk").symLinkTarget(), QDir::currentPath());
1413 }
1414
1415 void tst_QFile::readTextFile_data()
1416 {
1417     QTest::addColumn<QByteArray>("in");
1418     QTest::addColumn<QByteArray>("out");
1419
1420     QTest::newRow("empty") << QByteArray() << QByteArray();
1421     QTest::newRow("a") << QByteArray("a") << QByteArray("a");
1422     QTest::newRow("a\\rb") << QByteArray("a\rb") << QByteArray("ab");
1423     QTest::newRow("\\n") << QByteArray("\n") << QByteArray("\n");
1424     QTest::newRow("\\r\\n") << QByteArray("\r\n") << QByteArray("\n");
1425     QTest::newRow("\\r") << QByteArray("\r") << QByteArray();
1426     QTest::newRow("twolines") << QByteArray("Hello\r\nWorld\r\n") << QByteArray("Hello\nWorld\n");
1427     QTest::newRow("twolines no endline") << QByteArray("Hello\r\nWorld") << QByteArray("Hello\nWorld");
1428 }
1429
1430 void tst_QFile::readTextFile()
1431 {
1432     QFETCH(QByteArray, in);
1433     QFETCH(QByteArray, out);
1434
1435     QFile winfile("winfile.txt");
1436     QVERIFY(winfile.open(QFile::WriteOnly | QFile::Truncate));
1437     winfile.write(in);
1438     winfile.close();
1439
1440     QVERIFY(winfile.open(QFile::ReadOnly));
1441     QCOMPARE(winfile.readAll(), in);
1442     winfile.close();
1443
1444     QVERIFY(winfile.open(QFile::ReadOnly | QFile::Text));
1445     QCOMPARE(winfile.readAll(), out);
1446 }
1447
1448 void tst_QFile::readTextFile2()
1449 {
1450     {
1451         QFile file(QFINDTESTDATA("testlog.txt"));
1452         QVERIFY(file.open(QIODevice::ReadOnly));
1453         file.read(4097);
1454     }
1455
1456     {
1457         QFile file(QFINDTESTDATA("testlog.txt"));
1458         QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
1459         file.read(4097);
1460     }
1461 }
1462
1463 void tst_QFile::writeTextFile_data()
1464 {
1465     QTest::addColumn<QByteArray>("in");
1466
1467     QTest::newRow("empty") << QByteArray();
1468     QTest::newRow("a") << QByteArray("a");
1469     QTest::newRow("a\\rb") << QByteArray("a\rb");
1470     QTest::newRow("\\n") << QByteArray("\n");
1471     QTest::newRow("\\r\\n") << QByteArray("\r\n");
1472     QTest::newRow("\\r") << QByteArray("\r");
1473     QTest::newRow("twolines crlf") << QByteArray("Hello\r\nWorld\r\n");
1474     QTest::newRow("twolines crlf no endline") << QByteArray("Hello\r\nWorld");
1475     QTest::newRow("twolines lf") << QByteArray("Hello\nWorld\n");
1476     QTest::newRow("twolines lf no endline") << QByteArray("Hello\nWorld");
1477     QTest::newRow("mixed") << QByteArray("this\nis\r\na\nmixed\r\nfile\n");
1478 }
1479
1480 void tst_QFile::writeTextFile()
1481 {
1482     QFETCH(QByteArray, in);
1483
1484     QFile file("textfile.txt");
1485     QVERIFY(file.open(QFile::WriteOnly | QFile::Truncate | QFile::Text));
1486     QByteArray out = in;
1487 #ifdef Q_OS_WIN
1488     out.replace('\n', "\r\n");
1489 #endif
1490     QCOMPARE(file.write(in), qlonglong(in.size()));
1491     file.close();
1492
1493     file.open(QFile::ReadOnly);
1494     QCOMPARE(file.readAll(), out);
1495 }
1496
1497 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1498 void tst_QFile::largeUncFileSupport()
1499 {
1500     qint64 size = Q_INT64_C(8589934592);
1501     qint64 dataOffset = Q_INT64_C(8589914592);
1502     QByteArray knownData("LargeFile content at offset 8589914592");
1503     QString largeFile("//" + QtNetworkSettings::winServerName() + "/testsharelargefile/file.bin");
1504
1505     {
1506         // 1) Native file handling.
1507         QFile file(largeFile);
1508         QCOMPARE(file.size(), size);
1509         QVERIFY(file.open(QIODevice::ReadOnly));
1510         QCOMPARE(file.size(), size);
1511         QVERIFY(file.seek(dataOffset));
1512         QCOMPARE(file.read(knownData.size()), knownData);
1513     }
1514     {
1515         // 2) stdlib file handling.
1516         QFile file;
1517         FILE *fh = fopen(QFile::encodeName(largeFile).data(), "rb");
1518         QVERIFY(file.open(fh, QIODevice::ReadOnly));
1519         QCOMPARE(file.size(), size);
1520         QVERIFY(file.seek(dataOffset));
1521         QCOMPARE(file.read(knownData.size()), knownData);
1522         fclose(fh);
1523     }
1524     {
1525         // 3) stdio file handling.
1526         QFile file;
1527         FILE *fh = fopen(QFile::encodeName(largeFile).data(), "rb");
1528         int fd = int(_fileno(fh));
1529         QVERIFY(file.open(fd, QIODevice::ReadOnly));
1530         QCOMPARE(file.size(), size);
1531         QVERIFY(file.seek(dataOffset));
1532         QCOMPARE(file.read(knownData.size()), knownData);
1533         fclose(fh);
1534     }
1535 }
1536 #endif
1537
1538 void tst_QFile::tailFile()
1539 {
1540     QSKIP("File change notifications are so far unsupported.");
1541
1542     QFile file("tail.txt");
1543     QVERIFY(file.open(QFile::WriteOnly | QFile::Append));
1544
1545     QFile tailFile("tail.txt");
1546     QVERIFY(tailFile.open(QFile::ReadOnly));
1547     tailFile.seek(file.size());
1548
1549     QSignalSpy readSignalSpy(&tailFile, SIGNAL(readyRead()));
1550     QVERIFY(readSignalSpy.isValid());
1551
1552     file.write("", 1);
1553
1554     QTestEventLoop::instance().enterLoop(5);
1555
1556     QVERIFY(!QTestEventLoop::instance().timeout());
1557     QCOMPARE(readSignalSpy.count(), 1);
1558 }
1559
1560 void tst_QFile::flush()
1561 {
1562     QString fileName("stdfile.txt");
1563
1564     QFile::remove(fileName);
1565
1566     {
1567         QFile file(fileName);
1568         QVERIFY(file.open(QFile::WriteOnly));
1569         QCOMPARE(file.write("abc", 3),qint64(3));
1570     }
1571
1572     {
1573         QFile file(fileName);
1574         QVERIFY(file.open(QFile::WriteOnly | QFile::Append));
1575         QCOMPARE(file.pos(), qlonglong(3));
1576         QCOMPARE(file.write("def", 3), qlonglong(3));
1577         QCOMPARE(file.pos(), qlonglong(6));
1578     }
1579
1580     {
1581         QFile file("stdfile.txt");
1582         QVERIFY(file.open(QFile::ReadOnly));
1583         QCOMPARE(file.readAll(), QByteArray("abcdef"));
1584     }
1585
1586     QFile::remove(fileName);
1587 }
1588
1589 void tst_QFile::bufferedRead()
1590 {
1591     QFile::remove("stdfile.txt");
1592
1593     QFile file("stdfile.txt");
1594     QVERIFY(file.open(QFile::WriteOnly));
1595     file.write("abcdef");
1596     file.close();
1597
1598 #if defined(Q_OS_WINCE)
1599     FILE *stdFile = fopen((QCoreApplication::applicationDirPath() + "/stdfile.txt").toLatin1() , "r");
1600 #else
1601     FILE *stdFile = fopen("stdfile.txt", "r");
1602 #endif
1603     QVERIFY(stdFile);
1604     char c;
1605     QCOMPARE(int(fread(&c, 1, 1, stdFile)), 1);
1606     QCOMPARE(c, 'a');
1607     QCOMPARE(int(ftell(stdFile)), 1);
1608
1609     {
1610         QFile file;
1611         QVERIFY(file.open(stdFile, QFile::ReadOnly));
1612         QCOMPARE(file.pos(), qlonglong(1));
1613         QCOMPARE(file.read(&c, 1), qlonglong(1));
1614         QCOMPARE(c, 'b');
1615         QCOMPARE(file.pos(), qlonglong(2));
1616     }
1617
1618     fclose(stdFile);
1619 }
1620
1621 void tst_QFile::isSequential()
1622 {
1623 #ifndef Q_OS_UNIX
1624     QSKIP("Unix only test.");
1625 #endif
1626     QFile zero("/dev/null");
1627     QVERIFY(zero.open(QFile::ReadOnly));
1628     QVERIFY(zero.isSequential());
1629 }
1630
1631 void tst_QFile::encodeName()
1632 {
1633     QCOMPARE(QFile::encodeName(QString::null), QByteArray());
1634 }
1635
1636 void tst_QFile::truncate()
1637 {
1638     for (int i = 0; i < 2; ++i) {
1639         QFile file("truncate.txt");
1640         QVERIFY(file.open(QFile::WriteOnly));
1641         file.write(QByteArray(200, '@'));
1642         file.close();
1643
1644         QVERIFY(file.open((i ? QFile::WriteOnly : QFile::ReadWrite) | QFile::Truncate));
1645         file.write(QByteArray(100, '$'));
1646         file.close();
1647
1648         QVERIFY(file.open(QFile::ReadOnly));
1649         QCOMPARE(file.readAll(), QByteArray(100, '$'));
1650     }
1651 }
1652
1653 void tst_QFile::seekToPos()
1654 {
1655     {
1656         QFile file("seekToPos.txt");
1657         QVERIFY(file.open(QFile::WriteOnly));
1658         file.write("a\r\nb\r\nc\r\n");
1659         file.flush();
1660     }
1661
1662     QFile file("seekToPos.txt");
1663     QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1664     file.seek(1);
1665     char c;
1666     QVERIFY(file.getChar(&c));
1667     QCOMPARE(c, '\n');
1668
1669     QCOMPARE(file.pos(), qint64(3));
1670     file.seek(file.pos());
1671     QCOMPARE(file.pos(), qint64(3));
1672
1673     file.seek(1);
1674     file.seek(file.pos());
1675     QCOMPARE(file.pos(), qint64(1));
1676
1677 }
1678
1679 void tst_QFile::seekAfterEndOfFile()
1680 {
1681     QLatin1String filename("seekAfterEof.dat");
1682     QFile::remove(filename);
1683     {
1684         QFile file(filename);
1685         QVERIFY(file.open(QFile::WriteOnly));
1686         file.write("abcd");
1687         QCOMPARE(file.size(), qint64(4));
1688         file.seek(8);
1689         file.write("ijkl");
1690         QCOMPARE(file.size(), qint64(12));
1691         file.seek(4);
1692         file.write("efgh");
1693         QCOMPARE(file.size(), qint64(12));
1694         file.seek(16);
1695         file.write("----");
1696         QCOMPARE(file.size(), qint64(20));
1697         file.flush();
1698     }
1699
1700     QFile file(filename);
1701     QVERIFY(file.open(QFile::ReadOnly));
1702     QByteArray contents = file.readAll();
1703     QCOMPARE(contents.left(12), QByteArray("abcdefghijkl", 12));
1704     //bytes 12-15 are uninitialised so we don't care what they read as.
1705     QCOMPARE(contents.mid(16), QByteArray("----", 4));
1706     file.close();
1707     QFile::remove(filename);
1708 }
1709
1710 void tst_QFile::FILEReadWrite()
1711 {
1712     // Tests modifying a file. First creates it then reads in 4 bytes and then overwrites these
1713     // 4 bytes with new values. At the end check to see the file contains the new values.
1714
1715     QFile::remove("FILEReadWrite.txt");
1716
1717     // create test file
1718     {
1719         QFile f("FILEReadWrite.txt");
1720         QVERIFY(f.open(QFile::WriteOnly));
1721         QDataStream ds(&f);
1722         qint8 c = 0;
1723         ds << c;
1724         c = 1;
1725         ds << c;
1726         c = 2;
1727         ds << c;
1728         c = 3;
1729         ds << c;
1730         c = 4;
1731         ds << c;
1732         c = 5;
1733         ds << c;
1734         c = 6;
1735         ds << c;
1736         c = 7;
1737         ds << c;
1738         c = 8;
1739         ds << c;
1740         c = 9;
1741         ds << c;
1742         c = 10;
1743         ds << c;
1744         c = 11;
1745         ds << c;
1746         f.close();
1747     }
1748
1749 #ifdef Q_OS_WINCE
1750     FILE *fp = fopen(qPrintable(QCoreApplication::applicationDirPath() + "\\FILEReadWrite.txt"), "r+b");
1751 #else
1752     FILE *fp = fopen("FILEReadWrite.txt", "r+b");
1753 #endif
1754     QVERIFY(fp);
1755     QFile file;
1756     QVERIFY(file.open(fp, QFile::ReadWrite));
1757     QDataStream sfile(&file) ;
1758
1759     qint8 var1,var2,var3,var4;
1760     while (!sfile.atEnd())
1761     {
1762         qint64 base = file.pos();
1763
1764         QCOMPARE(file.pos(), base + 0);
1765         sfile >> var1;
1766         QCOMPARE(file.pos(), base + 1);
1767         file.flush(); // flushing should not change the base
1768         QCOMPARE(file.pos(), base + 1);
1769         sfile >> var2;
1770         QCOMPARE(file.pos(), base + 2);
1771         sfile >> var3;
1772         QCOMPARE(file.pos(), base + 3);
1773         sfile >> var4;
1774         QCOMPARE(file.pos(), base + 4);
1775         file.seek(file.pos() - 4) ;   // Move it back 4, for we are going to write new values based on old ones
1776         QCOMPARE(file.pos(), base + 0);
1777         sfile << qint8(var1 + 5);
1778         QCOMPARE(file.pos(), base + 1);
1779         sfile << qint8(var2 + 5);
1780         QCOMPARE(file.pos(), base + 2);
1781         sfile << qint8(var3 + 5);
1782         QCOMPARE(file.pos(), base + 3);
1783         sfile << qint8(var4 + 5);
1784         QCOMPARE(file.pos(), base + 4);
1785
1786     }
1787     file.close();
1788     fclose(fp);
1789
1790     // check modified file
1791     {
1792         QFile f("FILEReadWrite.txt");
1793         QVERIFY(f.open(QFile::ReadOnly));
1794         QDataStream ds(&f);
1795         qint8 c = 0;
1796         ds >> c;
1797         QCOMPARE(c, (qint8)5);
1798         ds >> c;
1799         QCOMPARE(c, (qint8)6);
1800         ds >> c;
1801         QCOMPARE(c, (qint8)7);
1802         ds >> c;
1803         QCOMPARE(c, (qint8)8);
1804         ds >> c;
1805         QCOMPARE(c, (qint8)9);
1806         ds >> c;
1807         QCOMPARE(c, (qint8)10);
1808         ds >> c;
1809         QCOMPARE(c, (qint8)11);
1810         ds >> c;
1811         QCOMPARE(c, (qint8)12);
1812         ds >> c;
1813         QCOMPARE(c, (qint8)13);
1814         ds >> c;
1815         QCOMPARE(c, (qint8)14);
1816         ds >> c;
1817         QCOMPARE(c, (qint8)15);
1818         ds >> c;
1819         QCOMPARE(c, (qint8)16);
1820         f.close();
1821     }
1822
1823     QFile::remove("FILEReadWrite.txt");
1824 }
1825
1826
1827 /*
1828 #include <qglobal.h>
1829 #define BUFFSIZE 1
1830 #define FILESIZE   0x10000000f
1831 void tst_QFile::largeFileSupport()
1832 {
1833 #ifdef Q_OS_SOLARIS
1834     QSKIP("Solaris does not support statfs");
1835 #else
1836     qlonglong sizeNeeded = 2147483647;
1837     sizeNeeded *= 2;
1838     sizeNeeded += 1024;
1839     qlonglong freespace = qlonglong(0);
1840 #ifdef Q_OS_WIN
1841     _ULARGE_INTEGER free;
1842     if (::GetDiskFreeSpaceEx((wchar_t*)QDir::currentPath().utf16(), &free, 0, 0))
1843         freespace = free.QuadPart;
1844     if (freespace != 0) {
1845 #elif defined(Q_OS_IRIX)
1846     struct statfs info;
1847     if (statfs(QDir::currentPath().local8Bit(), &info, sizeof(struct statfs), 0) == 0) {
1848         freespace = qlonglong(info.f_bfree * info.f_bsize);
1849 #else
1850     struct statfs info;
1851     if (statfs(const_cast<char *>(QDir::currentPath().toLocal8Bit().constData()), &info) == 0) {
1852         freespace = qlonglong(info.f_bavail * info.f_bsize);
1853 #endif
1854         if (freespace > sizeNeeded) {
1855             QFile bigFile("bigfile");
1856             if (bigFile.open(QFile::ReadWrite)) {
1857                 char c[BUFFSIZE] = {'a'};
1858                 QVERIFY(bigFile.write(c, BUFFSIZE) == BUFFSIZE);
1859                 qlonglong oldPos = bigFile.pos();
1860                 QVERIFY(bigFile.resize(sizeNeeded));
1861                 QCOMPARE(oldPos, bigFile.pos());
1862                 QVERIFY(bigFile.seek(sizeNeeded - BUFFSIZE));
1863                 QVERIFY(bigFile.write(c, BUFFSIZE) == BUFFSIZE);
1864
1865                 bigFile.close();
1866                 if (bigFile.open(QFile::ReadOnly)) {
1867                     QVERIFY(bigFile.read(c, BUFFSIZE) == BUFFSIZE);
1868                     int i = 0;
1869                     for (i=0; i<BUFFSIZE; i++)
1870                         QCOMPARE(c[i], 'a');
1871                     QVERIFY(bigFile.seek(sizeNeeded - BUFFSIZE));
1872                     QVERIFY(bigFile.read(c, BUFFSIZE) == BUFFSIZE);
1873                     for (i=0; i<BUFFSIZE; i++)
1874                         QCOMPARE(c[i], 'a');
1875                     bigFile.close();
1876                     QVERIFY(bigFile.remove());
1877                 } else {
1878                     QVERIFY(bigFile.remove());
1879                     QFAIL("Could not reopen file");
1880                 }
1881             } else {
1882                 QFAIL("Could not open file");
1883             }
1884         } else {
1885             QSKIP("Not enough space to run test");
1886         }
1887     } else {
1888         QFAIL("Could not determin disk space");
1889     }
1890 #endif
1891 }
1892 */
1893
1894 void tst_QFile::i18nFileName_data()
1895 {
1896     QTest::addColumn<QString>("fileName");
1897
1898     QTest::newRow( "01" ) << QString::fromUtf8("xxxxxxx.txt");
1899 }
1900
1901 void tst_QFile::i18nFileName()
1902 {
1903      QFETCH(QString, fileName);
1904      if (QFile::exists(fileName)) {
1905          QVERIFY(QFile::remove(fileName));
1906      }
1907      {
1908         QFile file(fileName);
1909         QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
1910         QTextStream ts(&file);
1911         ts.setCodec("UTF-8");
1912         ts << fileName << endl;
1913      }
1914      {
1915         QFile file(fileName);
1916         QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1917         QTextStream ts(&file);
1918         ts.setCodec("UTF-8");
1919         QString line = ts.readLine();
1920         QCOMPARE(line, fileName);
1921      }
1922      QVERIFY(QFile::remove(fileName));
1923 }
1924
1925
1926 void tst_QFile::longFileName_data()
1927 {
1928     QTest::addColumn<QString>("fileName");
1929
1930     QTest::newRow( "16 chars" ) << QString::fromLatin1("longFileName.txt");
1931     QTest::newRow( "52 chars" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName.txt");
1932     QTest::newRow( "148 chars" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1933                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1934                                                      "longFileNamelongFileNamelongFileNamelongFileName.txt");
1935     QTest::newRow( "244 chars" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1936                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1937                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1938                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1939                                                      "longFileNamelongFileNamelongFileNamelongFileName.txt");
1940     QTest::newRow( "244 chars to absolutepath" ) << QFileInfo(QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1941                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1942                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1943                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1944                                                      "longFileNamelongFileNamelongFileNamelongFileName.txt")).absoluteFilePath();
1945   /* needs to be put on a windows 2000 > test machine
1946   QTest::newRow( "244 chars on UNC" ) <<  QString::fromLatin1("//arsia/D/troll/tmp/longFileNamelongFileNamelongFileNamelongFileName"
1947                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1948                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1949                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1950                                                      "longFileNamelongFileNamelongFileNamelongFileName.txt");*/
1951 }
1952
1953 void tst_QFile::longFileName()
1954 {
1955     QFETCH(QString, fileName);
1956     if (QFile::exists(fileName)) {
1957         QVERIFY(QFile::remove(fileName));
1958     }
1959     {
1960         QFile file(fileName);
1961 #if defined(Q_OS_WINCE)
1962         QEXPECT_FAIL("244 chars", "Full pathname must be less than 260 chars", Abort);
1963         QEXPECT_FAIL("244 chars to absolutepath", "Full pathname must be less than 260 chars", Abort);
1964 #endif
1965         QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
1966         QTextStream ts(&file);
1967         ts << fileName << endl;
1968     }
1969     {
1970         QFile file(fileName);
1971         QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1972         QTextStream ts(&file);
1973         QString line = ts.readLine();
1974         QCOMPARE(line, fileName);
1975     }
1976     QString newName = fileName + QLatin1String("1");
1977     {
1978         QVERIFY(QFile::copy(fileName, newName));
1979         QFile file(newName);
1980         QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1981         QTextStream ts(&file);
1982         QString line = ts.readLine();
1983         QCOMPARE(line, fileName);
1984
1985     }
1986     QVERIFY(QFile::remove(newName));
1987     {
1988         QVERIFY(QFile::rename(fileName, newName));
1989         QFile file(newName);
1990         QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1991         QTextStream ts(&file);
1992         QString line = ts.readLine();
1993         QCOMPARE(line, fileName);
1994     }
1995     QVERIFY(QFile::exists(newName));
1996     QVERIFY(QFile::remove(newName));
1997 }
1998
1999 #ifdef QT_BUILD_INTERNAL
2000 class MyEngine : public QAbstractFileEngine
2001 {
2002 public:
2003     MyEngine(int n) { number = n; }
2004     virtual ~MyEngine() {}
2005
2006     void setFileName(const QString &) {}
2007     bool open(QIODevice::OpenMode) { return false; }
2008     bool close() { return false; }
2009     bool flush() { return false; }
2010     qint64 size() const { return 123 + number; }
2011     qint64 at() const { return -1; }
2012     bool seek(qint64) { return false; }
2013     bool isSequential() const { return false; }
2014     qint64 read(char *, qint64) { return -1; }
2015     qint64 write(const char *, qint64) { return -1; }
2016     bool remove() { return false; }
2017     bool copy(const QString &) { return false; }
2018     bool rename(const QString &) { return false; }
2019     bool link(const QString &) { return false; }
2020     bool mkdir(const QString &, bool) const { return false; }
2021     bool rmdir(const QString &, bool) const { return false; }
2022     bool setSize(qint64) { return false; }
2023     QStringList entryList(QDir::Filters, const QStringList &) const { return QStringList(); }
2024     bool caseSensitive() const { return false; }
2025     bool isRelativePath() const { return false; }
2026     FileFlags fileFlags(FileFlags) const { return 0; }
2027     bool chmod(uint) { return false; }
2028     QString fileName(FileName) const { return name; }
2029     uint ownerId(FileOwner) const { return 0; }
2030     QString owner(FileOwner) const { return QString(); }
2031     QDateTime fileTime(FileTime) const { return QDateTime(); }
2032
2033 private:
2034     int number;
2035     QString name;
2036 };
2037
2038 class MyHandler : public QAbstractFileEngineHandler
2039 {
2040 public:
2041     inline QAbstractFileEngine *create(const QString &) const
2042     {
2043         return new MyEngine(1);
2044     }
2045 };
2046
2047 class MyHandler2 : public QAbstractFileEngineHandler
2048 {
2049 public:
2050     inline QAbstractFileEngine *create(const QString &) const
2051     {
2052         return new MyEngine(2);
2053     }
2054 };
2055 #endif
2056
2057 void tst_QFile::fileEngineHandler()
2058 {
2059     // A file that does not exist has a size of 0.
2060     QFile::remove("ole.bull");
2061     QFile file("ole.bull");
2062     QCOMPARE(file.size(), qint64(0));
2063
2064 #ifdef QT_BUILD_INTERNAL
2065     // Instantiating our handler will enable the new engine.
2066     MyHandler handler;
2067     file.setFileName("ole.bull");
2068     QCOMPARE(file.size(), qint64(124));
2069
2070     // A new, identical handler should take preference over the last one.
2071     MyHandler2 handler2;
2072     file.setFileName("ole.bull");
2073     QCOMPARE(file.size(), qint64(125));
2074 #endif
2075 }
2076
2077 #ifdef QT_BUILD_INTERNAL
2078 class MyRecursiveHandler : public QAbstractFileEngineHandler
2079 {
2080 public:
2081     inline QAbstractFileEngine *create(const QString &fileName) const
2082     {
2083         if (fileName.startsWith(":!")) {
2084             QDir dir;
2085             QString realFile = QFINDTESTDATA(fileName.mid(2));
2086             if (dir.exists(realFile))
2087                 return new QFSFileEngine(realFile);
2088         }
2089         return 0;
2090     }
2091 };
2092 #endif
2093
2094 void tst_QFile::useQFileInAFileHandler()
2095 {
2096 #ifdef QT_BUILD_INTERNAL
2097     // This test should not dead-lock
2098     MyRecursiveHandler handler;
2099     QFile file(":!tst_qfile.cpp");
2100     QVERIFY(file.exists());
2101 #else
2102     QSKIP("This test requires -developer-build.");
2103 #endif
2104 }
2105
2106 void tst_QFile::getCharFF()
2107 {
2108     QFile file("file.txt");
2109     file.open(QFile::ReadWrite);
2110     file.write("\xff\xff\xff");
2111     file.flush();
2112     file.seek(0);
2113
2114     char c;
2115     QVERIFY(file.getChar(&c));
2116     QVERIFY(file.getChar(&c));
2117     QVERIFY(file.getChar(&c));
2118 }
2119
2120 void tst_QFile::remove_and_exists()
2121 {
2122     QFile::remove("tull_i_grunn.txt");
2123     QFile f("tull_i_grunn.txt");
2124
2125     QVERIFY(!f.exists());
2126
2127     bool opened = f.open(QIODevice::WriteOnly);
2128     QVERIFY(opened);
2129
2130     f.write(QString("testing that remove/exists work...").toLatin1());
2131     f.close();
2132
2133     QVERIFY(f.exists());
2134
2135     f.remove();
2136     QVERIFY(!f.exists());
2137 }
2138
2139 void tst_QFile::removeOpenFile()
2140 {
2141     {
2142         // remove an opened, write-only file
2143         QFile::remove("remove_unclosed.txt");
2144         QFile f("remove_unclosed.txt");
2145
2146         QVERIFY(!f.exists());
2147         bool opened = f.open(QIODevice::WriteOnly);
2148         QVERIFY(opened);
2149         f.write(QString("testing that remove closes the file first...").toLatin1());
2150
2151         bool removed = f.remove(); // remove should both close and remove the file
2152         QVERIFY(removed);
2153         QVERIFY(!f.isOpen());
2154         QVERIFY(!f.exists());
2155         QVERIFY(f.error() == QFile::NoError);
2156     }
2157
2158     {
2159         // remove an opened, read-only file
2160         QFile::remove("remove_unclosed.txt");
2161
2162         // first, write a file that we can remove
2163         {
2164             QFile f("remove_unclosed.txt");
2165             QVERIFY(!f.exists());
2166             bool opened = f.open(QIODevice::WriteOnly);
2167             QVERIFY(opened);
2168             f.write(QString("testing that remove closes the file first...").toLatin1());
2169             f.close();
2170         }
2171
2172         QFile f("remove_unclosed.txt");
2173         bool opened = f.open(QIODevice::ReadOnly);
2174         QVERIFY(opened);
2175         f.readAll();
2176         // this used to only fail on FreeBSD (and Mac OS X)
2177         QVERIFY(f.flush());
2178         bool removed = f.remove(); // remove should both close and remove the file
2179         QVERIFY(removed);
2180         QVERIFY(!f.isOpen());
2181         QVERIFY(!f.exists());
2182         QVERIFY(f.error() == QFile::NoError);
2183     }
2184 }
2185
2186 void tst_QFile::fullDisk()
2187 {
2188     QFile file("/dev/full");
2189     if (!file.exists())
2190         QSKIP("/dev/full doesn't exist on this system");
2191
2192     QVERIFY(file.open(QIODevice::WriteOnly));
2193     file.write("foobar", 6);
2194
2195     QVERIFY(!file.flush());
2196     QCOMPARE(file.error(), QFile::ResourceError);
2197     QVERIFY(!file.flush());
2198     QCOMPARE(file.error(), QFile::ResourceError);
2199
2200     char c = 0;
2201     file.write(&c, 0);
2202     QVERIFY(!file.flush());
2203     QCOMPARE(file.error(), QFile::ResourceError);
2204     QCOMPARE(file.write(&c, 1), qint64(1));
2205     QVERIFY(!file.flush());
2206     QCOMPARE(file.error(), QFile::ResourceError);
2207
2208     file.close();
2209     QVERIFY(!file.isOpen());
2210     QCOMPARE(file.error(), QFile::ResourceError);
2211
2212     file.open(QIODevice::WriteOnly);
2213     QCOMPARE(file.error(), QFile::NoError);
2214     QVERIFY(file.flush()); // Shouldn't inherit write buffer
2215     file.close();
2216     QCOMPARE(file.error(), QFile::NoError);
2217
2218     // try again without flush:
2219     QVERIFY(file.open(QIODevice::WriteOnly));
2220     file.write("foobar", 6);
2221     file.close();
2222     QVERIFY(file.error() != QFile::NoError);
2223 }
2224
2225 void tst_QFile::writeLargeDataBlock_data()
2226 {
2227     QTest::addColumn<QString>("fileName");
2228     QTest::addColumn<int>("type");
2229
2230     QTest::newRow("localfile-QFile")  << "./largeblockfile.txt" << (int)OpenQFile;
2231     QTest::newRow("localfile-Fd")     << "./largeblockfile.txt" << (int)OpenFd;
2232     QTest::newRow("localfile-Stream") << "./largeblockfile.txt" << (int)OpenStream;
2233
2234 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
2235     // Some semi-randomness to avoid collisions.
2236     QTest::newRow("unc file")
2237         << QString("//" + QtNetworkSettings::winServerName() + "/TESTSHAREWRITABLE/largefile-%1-%2.txt")
2238         .arg(QHostInfo::localHostName())
2239         .arg(QTime::currentTime().msec()) << (int)OpenQFile;
2240 #endif
2241 }
2242
2243 static QByteArray getLargeDataBlock()
2244 {
2245     static QByteArray array;
2246
2247     if (array.isNull())
2248     {
2249 #if defined(Q_OS_WINCE)
2250         int resizeSize = 1024 * 1024; // WinCE does not have much space
2251 #else
2252         int resizeSize = 64 * 1024 * 1024;
2253 #endif
2254         array.resize(resizeSize);
2255         for (int i = 0; i < array.size(); ++i)
2256             array[i] = uchar(i);
2257     }
2258
2259     return array;
2260 }
2261
2262 void tst_QFile::writeLargeDataBlock()
2263 {
2264     QFETCH(QString, fileName);
2265     QFETCH( int, type );
2266
2267     QByteArray const originalData = getLargeDataBlock();
2268
2269     {
2270         QFile file(fileName);
2271
2272         QVERIFY2( openFile(file, QIODevice::WriteOnly, (FileType)type),
2273             qPrintable(QString("Couldn't open file for writing: [%1]").arg(fileName)) );
2274         qint64 fileWriteOriginalData = file.write(originalData);
2275         qint64 originalDataSize      = (qint64)originalData.size();
2276 #if defined(Q_OS_WIN)
2277         if (fileWriteOriginalData == -1) {
2278             qWarning() << qPrintable(QString("Error writing a large data block to [%1]: %2")
2279                 .arg(fileName)
2280                 .arg(file.errorString()));
2281             QEXPECT_FAIL("unc file", "QTBUG-26906", Abort);
2282         }
2283 #endif
2284         QCOMPARE( fileWriteOriginalData, originalDataSize );
2285         QVERIFY( file.flush() );
2286
2287         closeFile(file);
2288     }
2289
2290     QByteArray readData;
2291
2292     {
2293         QFile file(fileName);
2294
2295         QVERIFY2( openFile(file, QIODevice::ReadOnly, (FileType)type),
2296             qPrintable(QString("Couldn't open file for reading: [%1]").arg(fileName)) );
2297         readData = file.readAll();
2298         closeFile(file);
2299     }
2300
2301     QCOMPARE( readData, originalData );
2302     QVERIFY( QFile::remove(fileName) );
2303 }
2304
2305 void tst_QFile::readFromWriteOnlyFile()
2306 {
2307     QFile file("writeonlyfile");
2308     QVERIFY(file.open(QFile::WriteOnly));
2309     char c;
2310     QTest::ignoreMessage(QtWarningMsg, "QIODevice::read: WriteOnly device");
2311     QCOMPARE(file.read(&c, 1), qint64(-1));
2312 }
2313
2314 void tst_QFile::writeToReadOnlyFile()
2315 {
2316     QFile file("readonlyfile");
2317     QVERIFY(file.open(QFile::ReadOnly));
2318     char c = 0;
2319     QTest::ignoreMessage(QtWarningMsg, "QIODevice::write: ReadOnly device");
2320     QCOMPARE(file.write(&c, 1), qint64(-1));
2321 }
2322
2323 void tst_QFile::virtualFile()
2324 {
2325     // test if QFile works with virtual files
2326     QString fname;
2327 #if defined(Q_OS_LINUX)
2328     fname = "/proc/self/maps";
2329 #elif defined(Q_OS_AIX)
2330     fname = QString("/proc/%1/map").arg(getpid());
2331 #elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
2332     fname = "/proc/curproc/map";
2333 #else
2334     QSKIP("This platform does not have 0-sized virtual files");
2335 #endif
2336
2337     // consistency check
2338     QFileInfo fi(fname);
2339     QVERIFY(fi.exists());
2340     QVERIFY(fi.isFile());
2341     QCOMPARE(fi.size(), Q_INT64_C(0));
2342
2343     // open the file
2344     QFile f(fname);
2345     QVERIFY(f.open(QIODevice::ReadOnly));
2346     QCOMPARE(f.size(), Q_INT64_C(0));
2347     QVERIFY(f.atEnd());
2348
2349     // read data
2350     QByteArray data = f.read(16);
2351     QCOMPARE(data.size(), 16);
2352     QCOMPARE(f.pos(), Q_INT64_C(16));
2353
2354     // line-reading
2355     data = f.readLine();
2356     QVERIFY(!data.isEmpty());
2357
2358     // read all:
2359     data = f.readAll();
2360     QVERIFY(f.pos() != 0);
2361     QVERIFY(!data.isEmpty());
2362
2363     // seeking
2364     QVERIFY(f.seek(1));
2365     QCOMPARE(f.pos(), Q_INT64_C(1));
2366 }
2367
2368 void tst_QFile::textFile()
2369 {
2370 #if defined(Q_OS_WINCE)
2371     FILE *fs = ::fopen((QCoreApplication::applicationDirPath() + "/writeabletextfile").toLatin1() , "wt");
2372 #elif defined(Q_OS_WIN)
2373     FILE *fs = ::fopen("writeabletextfile", "wt");
2374 #else
2375     FILE *fs = ::fopen("writeabletextfile", "w");
2376 #endif
2377     QFile f;
2378     QByteArray part1("This\nis\na\nfile\nwith\nnewlines\n");
2379     QByteArray part2("Add\nsome\nmore\nnewlines\n");
2380
2381     QVERIFY(f.open(fs, QIODevice::WriteOnly));
2382     f.write(part1);
2383     f.write(part2);
2384     f.close();
2385     ::fclose(fs);
2386
2387     QFile file("writeabletextfile");
2388     QVERIFY(file.open(QIODevice::ReadOnly));
2389
2390     QByteArray data = file.readAll();
2391
2392     QByteArray expected = part1 + part2;
2393 #ifdef Q_OS_WIN
2394     expected.replace("\n", "\015\012");
2395 #endif
2396     QCOMPARE(data, expected);
2397     file.close();
2398     file.remove();
2399 }
2400
2401 void tst_QFile::rename_data()
2402 {
2403     QTest::addColumn<QString>("source");
2404     QTest::addColumn<QString>("destination");
2405     QTest::addColumn<bool>("result");
2406
2407     QTest::newRow("a -> b") << QString("a") << QString("b") << false;
2408     QTest::newRow("a -> .") << QString("a") << QString(".") << false;
2409     QTest::newRow("renamefile -> renamefile") << QString("renamefile") << QString("renamefile") << false;
2410     QTest::newRow("renamefile -> noreadfile") << QString("renamefile") << QString("noreadfile") << false;
2411 #if defined(Q_OS_UNIX)
2412     QTest::newRow("renamefile -> /etc/renamefile") << QString("renamefile") << QString("/etc/renamefile") << false;
2413 #endif
2414     QTest::newRow("renamefile -> renamedfile") << QString("renamefile") << QString("renamedfile") << true;
2415     QTest::newRow("renamefile -> ..") << QString("renamefile") << QString("..") << false;
2416 }
2417
2418 void tst_QFile::rename()
2419 {
2420     QFETCH(QString, source);
2421     QFETCH(QString, destination);
2422     QFETCH(bool, result);
2423
2424 #if defined(Q_OS_UNIX)
2425     if (strcmp(QTest::currentDataTag(), "renamefile -> /etc/renamefile") == 0) {
2426         if (::getuid() == 0)
2427             QSKIP("Running this test as root doesn't make sense");
2428     }
2429 #endif
2430
2431     QFile::remove("renamedfile");
2432     QFile f("renamefile");
2433     f.open(QFile::WriteOnly);
2434     f.close();
2435
2436     QFile file(source);
2437     QCOMPARE(file.rename(destination), result);
2438
2439     if (result)
2440         QCOMPARE(file.error(), QFile::NoError);
2441     else
2442         QCOMPARE(file.error(), QFile::RenameError);
2443
2444     QFile::remove("renamefile");
2445 }
2446
2447 /*!
2448  \since 4.5
2449
2450  Some special files have QFile::atEnd() returning true, even though there is
2451  more data available. True for corner cases, as well as some mounts on OS X.
2452
2453  Here, we reproduce that condition by having a QFile sub-class with this
2454  peculiar atEnd() behavior.
2455 */
2456 void tst_QFile::renameWithAtEndSpecialFile() const
2457 {
2458     class PeculiarAtEnd : public QFile
2459     {
2460     public:
2461         virtual bool atEnd() const
2462         {
2463             return true;
2464         }
2465     };
2466
2467     const QString newName(QLatin1String("newName.txt"));
2468     /* Cleanup, so we're a bit more robust. */
2469     QFile::remove(newName);
2470
2471     const QString originalName(QString(QFINDTESTDATA("forRenaming.txt")));
2472
2473     PeculiarAtEnd file;
2474     file.setFileName(originalName);
2475     QVERIFY(file.open(QIODevice::ReadOnly));
2476
2477     QVERIFY(file.rename(newName));
2478
2479     file.close();
2480     /* Guess what, we have to rename it back, otherwise we'll fail on second
2481      * invocation. */
2482     QVERIFY(QFile::rename(newName, originalName));
2483 }
2484
2485 void tst_QFile::renameFallback()
2486 {
2487     // Using a resource file both to trigger QFile::rename's fallback handling
2488     // and as a *read-only* source whose move should fail.
2489     QFile file(":/rename-fallback.qrc");
2490     QVERIFY(file.exists() && "(test-precondition)");
2491     QFile::remove("file-rename-destination.txt");
2492
2493     QVERIFY(!file.rename("file-rename-destination.txt"));
2494     QVERIFY(!QFile::exists("file-rename-destination.txt"));
2495     QVERIFY(!file.isOpen());
2496 }
2497
2498 void tst_QFile::renameMultiple()
2499 {
2500     // create the file if it doesn't exist
2501     QFile file("file-to-be-renamed.txt");
2502     QFile file2("existing-file.txt");
2503     QVERIFY(file.open(QIODevice::ReadWrite) && "(test-precondition)");
2504     QVERIFY(file2.open(QIODevice::ReadWrite) && "(test-precondition)");
2505
2506     // any stale files from previous test failures?
2507     QFile::remove("file-renamed-once.txt");
2508     QFile::remove("file-renamed-twice.txt");
2509
2510     // begin testing
2511     QVERIFY(QFile::exists("existing-file.txt"));
2512     QVERIFY(!file.rename("existing-file.txt"));
2513     QCOMPARE(file.error(), QFile::RenameError);
2514     QCOMPARE(file.fileName(), QString("file-to-be-renamed.txt"));
2515
2516     QVERIFY(file.rename("file-renamed-once.txt"));
2517     QVERIFY(!file.isOpen());
2518     QCOMPARE(file.fileName(), QString("file-renamed-once.txt"));
2519
2520     QVERIFY(QFile::exists("existing-file.txt"));
2521     QVERIFY(!file.rename("existing-file.txt"));
2522     QCOMPARE(file.error(), QFile::RenameError);
2523     QCOMPARE(file.fileName(), QString("file-renamed-once.txt"));
2524
2525     QVERIFY(file.rename("file-renamed-twice.txt"));
2526     QVERIFY(!file.isOpen());
2527     QCOMPARE(file.fileName(), QString("file-renamed-twice.txt"));
2528
2529     QVERIFY(QFile::exists("existing-file.txt"));
2530     QVERIFY(!QFile::exists("file-to-be-renamed.txt"));
2531     QVERIFY(!QFile::exists("file-renamed-once.txt"));
2532     QVERIFY(QFile::exists("file-renamed-twice.txt"));
2533
2534     file.remove();
2535     file2.remove();
2536     QVERIFY(!QFile::exists("file-renamed-twice.txt"));
2537     QVERIFY(!QFile::exists("existing-file.txt"));
2538 }
2539
2540 void tst_QFile::appendAndRead()
2541 {
2542     QFile writeFile(QLatin1String("appendfile.txt"));
2543     QVERIFY(writeFile.open(QIODevice::WriteOnly | QIODevice::Truncate));
2544
2545     QFile readFile(QLatin1String("appendfile.txt"));
2546     QVERIFY(readFile.open(QIODevice::ReadOnly));
2547
2548     // Write to the end of the file, then read that character back, and so on.
2549     for (int i = 0; i < 100; ++i) {
2550         char c = '\0';
2551         writeFile.putChar(char(i % 256));
2552         writeFile.flush();
2553         QVERIFY(readFile.getChar(&c));
2554         QCOMPARE(c, char(i % 256));
2555         QCOMPARE(readFile.pos(), writeFile.pos());
2556     }
2557
2558     // Write blocks and read them back
2559     for (int j = 0; j < 18; ++j) {
2560         writeFile.write(QByteArray(1 << j, '@'));
2561         writeFile.flush();
2562         QCOMPARE(readFile.read(1 << j).size(), 1 << j);
2563     }
2564
2565     readFile.close();
2566     QFile::remove(QLatin1String("appendfile.txt"));
2567 }
2568
2569 void tst_QFile::miscWithUncPathAsCurrentDir()
2570 {
2571 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
2572     QString current = QDir::currentPath();
2573     QVERIFY(QDir::setCurrent("//" + QtNetworkSettings::winServerName() + "/testshare"));
2574     QFile file("test.pri");
2575     QVERIFY(file.exists());
2576     QCOMPARE(int(file.size()), 34);
2577     QVERIFY(file.open(QIODevice::ReadOnly));
2578     QVERIFY(QDir::setCurrent(current));
2579 #endif
2580 }
2581
2582 void tst_QFile::standarderror()
2583 {
2584     QFile f;
2585     bool ok = f.open(stderr, QFile::WriteOnly);
2586     QVERIFY(ok);
2587     f.close();
2588 }
2589
2590 void tst_QFile::handle()
2591 {
2592     int fd;
2593 #if !defined(Q_OS_WINCE)
2594     QFile file(QFINDTESTDATA("tst_qfile.cpp"));
2595     QVERIFY(file.open(QIODevice::ReadOnly));
2596     fd = int(file.handle());
2597     QVERIFY(fd > 2);
2598     QCOMPARE(int(file.handle()), fd);
2599     char c = '\0';
2600     QT_READ(int(file.handle()), &c, 1);
2601     QCOMPARE(c, '/');
2602
2603     // test if the QFile and the handle remain in sync
2604     QVERIFY(file.getChar(&c));
2605     QCOMPARE(c, '*');
2606
2607     // same, but read from QFile first now
2608     file.close();
2609     QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Unbuffered));
2610     fd = int(file.handle());
2611     QVERIFY(fd > 2);
2612     QVERIFY(file.getChar(&c));
2613     QCOMPARE(c, '/');
2614 #ifdef Q_OS_UNIX
2615     QCOMPARE(QT_READ(fd, &c, 1), ssize_t(1));
2616 #else
2617     QCOMPARE(QT_READ(fd, &c, 1), 1);
2618 #endif
2619
2620     QCOMPARE(c, '*');
2621 #endif
2622
2623     //test round trip of adopted stdio file handle
2624     QFile file2;
2625     FILE *fp = fopen(qPrintable(QFINDTESTDATA("tst_qfile.cpp")), "r");
2626     file2.open(fp, QIODevice::ReadOnly);
2627     QCOMPARE(int(file2.handle()), int(fileno(fp)));
2628     QCOMPARE(int(file2.handle()), int(fileno(fp)));
2629     fclose(fp);
2630
2631     //test round trip of adopted posix file handle
2632 #ifdef Q_OS_UNIX
2633     QFile file3;
2634     fd = QT_OPEN(qPrintable(QFINDTESTDATA("tst_qfile.cpp")), QT_OPEN_RDONLY);
2635     file3.open(fd, QIODevice::ReadOnly);
2636     QCOMPARE(int(file3.handle()), fd);
2637     QT_CLOSE(fd);
2638 #endif
2639 }
2640
2641 void tst_QFile::nativeHandleLeaks()
2642 {
2643     int fd1, fd2;
2644
2645 #ifdef Q_OS_WIN
2646     HANDLE handle1, handle2;
2647 #endif
2648
2649     {
2650         QFile file("qt_file.tmp");
2651         QVERIFY( file.open(QIODevice::ReadWrite) );
2652
2653         fd1 = file.handle();
2654         QVERIFY( -1 != fd1 );
2655     }
2656
2657 #ifdef Q_OS_WIN
2658     handle1 = ::CreateFileA("qt_file.tmp", GENERIC_READ, 0, NULL,
2659             OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2660     QVERIFY( INVALID_HANDLE_VALUE != handle1 );
2661     QVERIFY( ::CloseHandle(handle1) );
2662 #endif
2663
2664     {
2665         QFile file("qt_file.tmp");
2666         QVERIFY( file.open(QIODevice::ReadOnly) );
2667
2668         fd2 = file.handle();
2669         QVERIFY( -1 != fd2 );
2670     }
2671
2672 #ifdef Q_OS_WIN
2673     handle2 = ::CreateFileA("qt_file.tmp", GENERIC_READ, 0, NULL,
2674             OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2675     QVERIFY( INVALID_HANDLE_VALUE != handle2 );
2676     QVERIFY( ::CloseHandle(handle2) );
2677 #endif
2678
2679     QCOMPARE( fd2, fd1 );
2680
2681 #ifdef Q_OS_WIN
2682     QCOMPARE( handle2, handle1 );
2683 #endif
2684 }
2685
2686 void tst_QFile::readEof_data()
2687 {
2688     QTest::addColumn<QString>("filename");
2689     QTest::addColumn<int>("imode");
2690
2691     QTest::newRow("buffered") << QFINDTESTDATA("testfile.txt") << 0;
2692     QTest::newRow("unbuffered") << QFINDTESTDATA("testfile.txt") << int(QIODevice::Unbuffered);
2693
2694 #if defined(Q_OS_UNIX)
2695     QTest::newRow("sequential,buffered") << "/dev/null" << 0;
2696     QTest::newRow("sequential,unbuffered") << "/dev/null" << int(QIODevice::Unbuffered);
2697 #endif
2698 }
2699
2700 void tst_QFile::readEof()
2701 {
2702     QFETCH(QString, filename);
2703     QFETCH(int, imode);
2704     QIODevice::OpenMode mode = QIODevice::OpenMode(imode);
2705
2706     {
2707         QFile file(filename);
2708         QVERIFY(file.open(QIODevice::ReadOnly | mode));
2709         bool isSequential = file.isSequential();
2710         if (!isSequential) {
2711             QVERIFY(file.seek(245));
2712             QVERIFY(file.atEnd());
2713         }
2714
2715         char buf[10];
2716         int ret = file.read(buf, sizeof buf);
2717         QCOMPARE(ret, 0);
2718         QVERIFY(file.error() == QFile::NoError);
2719         QVERIFY(file.atEnd());
2720
2721         // Do it again to ensure that we get the same result
2722         ret = file.read(buf, sizeof buf);
2723         QCOMPARE(ret, 0);
2724         QVERIFY(file.error() == QFile::NoError);
2725         QVERIFY(file.atEnd());
2726     }
2727
2728     {
2729         QFile file(filename);
2730         QVERIFY(file.open(QIODevice::ReadOnly | mode));
2731         bool isSequential = file.isSequential();
2732         if (!isSequential) {
2733             QVERIFY(file.seek(245));
2734             QVERIFY(file.atEnd());
2735         }
2736
2737         QByteArray ret = file.read(10);
2738         QVERIFY(ret.isEmpty());
2739         QVERIFY(file.error() == QFile::NoError);
2740         QVERIFY(file.atEnd());
2741
2742         // Do it again to ensure that we get the same result
2743         ret = file.read(10);
2744         QVERIFY(ret.isEmpty());
2745         QVERIFY(file.error() == QFile::NoError);
2746         QVERIFY(file.atEnd());
2747     }
2748
2749     {
2750         QFile file(filename);
2751         QVERIFY(file.open(QIODevice::ReadOnly | mode));
2752         bool isSequential = file.isSequential();
2753         if (!isSequential) {
2754             QVERIFY(file.seek(245));
2755             QVERIFY(file.atEnd());
2756         }
2757
2758         char buf[10];
2759         int ret = file.readLine(buf, sizeof buf);
2760         QCOMPARE(ret, -1);
2761         QVERIFY(file.error() == QFile::NoError);
2762         QVERIFY(file.atEnd());
2763
2764         // Do it again to ensure that we get the same result
2765         ret = file.readLine(buf, sizeof buf);
2766         QCOMPARE(ret, -1);
2767         QVERIFY(file.error() == QFile::NoError);
2768         QVERIFY(file.atEnd());
2769     }
2770
2771     {
2772         QFile file(filename);
2773         QVERIFY(file.open(QIODevice::ReadOnly | mode));
2774         bool isSequential = file.isSequential();
2775         if (!isSequential) {
2776             QVERIFY(file.seek(245));
2777             QVERIFY(file.atEnd());
2778         }
2779
2780         QByteArray ret = file.readLine();
2781         QVERIFY(ret.isNull());
2782         QVERIFY(file.error() == QFile::NoError);
2783         QVERIFY(file.atEnd());
2784
2785         // Do it again to ensure that we get the same result
2786         ret = file.readLine();
2787         QVERIFY(ret.isNull());
2788         QVERIFY(file.error() == QFile::NoError);
2789         QVERIFY(file.atEnd());
2790     }
2791
2792     {
2793         QFile file(filename);
2794         QVERIFY(file.open(QIODevice::ReadOnly | mode));
2795         bool isSequential = file.isSequential();
2796         if (!isSequential) {
2797             QVERIFY(file.seek(245));
2798             QVERIFY(file.atEnd());
2799         }
2800
2801         char c;
2802         QVERIFY(!file.getChar(&c));
2803         QVERIFY(file.error() == QFile::NoError);
2804         QVERIFY(file.atEnd());
2805
2806         // Do it again to ensure that we get the same result
2807         QVERIFY(!file.getChar(&c));
2808         QVERIFY(file.error() == QFile::NoError);
2809         QVERIFY(file.atEnd());
2810     }
2811 }
2812
2813 void tst_QFile::posAfterFailedStat()
2814 {
2815     // Regression test for a bug introduced in 4.3.0; after a failed stat,
2816     // pos() could no longer be calculated correctly.
2817     QFile::remove("tmp.txt");
2818     QFile file("tmp.txt");
2819     QVERIFY(!file.exists());
2820     QVERIFY(file.open(QIODevice::Append));
2821     QVERIFY(file.exists());
2822     file.write("qt430", 5);
2823     QVERIFY(!file.isSequential());
2824     QCOMPARE(file.pos(), qint64(5));
2825     file.remove();
2826 }
2827
2828 #define FILESIZE 65536 * 3
2829
2830 void tst_QFile::map_data()
2831 {
2832     QTest::addColumn<int>("fileSize");
2833     QTest::addColumn<int>("offset");
2834     QTest::addColumn<int>("size");
2835     QTest::addColumn<QFile::FileError>("error");
2836
2837     QTest::newRow("zero")         << FILESIZE << 0     << FILESIZE         << QFile::NoError;
2838     QTest::newRow("small, but 0") << FILESIZE << 30    << FILESIZE - 30    << QFile::NoError;
2839     QTest::newRow("a page")       << FILESIZE << 4096  << FILESIZE - 4096  << QFile::NoError;
2840     QTest::newRow("+page")        << FILESIZE << 5000  << FILESIZE - 5000  << QFile::NoError;
2841     QTest::newRow("++page")       << FILESIZE << 65576 << FILESIZE - 65576 << QFile::NoError;
2842     QTest::newRow("bad size")     << FILESIZE << 0     << -1               << QFile::ResourceError;
2843     QTest::newRow("bad offset")   << FILESIZE << -1    << 1                << QFile::UnspecifiedError;
2844     QTest::newRow("zerozero")     << FILESIZE << 0     << 0                << QFile::UnspecifiedError;
2845 }
2846
2847 void tst_QFile::map()
2848 {
2849     QFETCH(int, fileSize);
2850     QFETCH(int, offset);
2851     QFETCH(int, size);
2852     QFETCH(QFile::FileError, error);
2853
2854     QString fileName = QDir::currentPath() + '/' + "qfile_map_testfile";
2855
2856 #ifdef Q_OS_WINCE
2857      fileName = QFileInfo(fileName).absoluteFilePath();
2858 #endif
2859
2860     if (QFile::exists(fileName)) {
2861         QVERIFY(QFile::setPermissions(fileName,
2862             QFile::WriteOwner | QFile::ReadOwner | QFile::WriteUser | QFile::ReadUser));
2863         QFile::remove(fileName);
2864     }
2865     QFile file(fileName);
2866
2867     // invalid, not open
2868     uchar *memory = file.map(0, size);
2869     QVERIFY(!memory);
2870     QCOMPARE(file.error(), QFile::PermissionsError);
2871     QVERIFY(!file.unmap(memory));
2872     QCOMPARE(file.error(), QFile::PermissionsError);
2873
2874     // make a file
2875     QVERIFY(file.open(QFile::ReadWrite));
2876     QVERIFY(file.resize(fileSize));
2877     QVERIFY(file.flush());
2878     file.close();
2879     QVERIFY(file.open(QFile::ReadWrite));
2880     memory = file.map(offset, size);
2881     if (error != QFile::NoError) {
2882         QVERIFY(file.error() != QFile::NoError);
2883         return;
2884     }
2885
2886     QCOMPARE(file.error(), error);
2887     QVERIFY(memory);
2888     memory[0] = 'Q';
2889     QVERIFY(file.unmap(memory));
2890     QCOMPARE(file.error(), QFile::NoError);
2891
2892     // Verify changes were saved
2893     memory = file.map(offset, size);
2894     QCOMPARE(file.error(), QFile::NoError);
2895     QVERIFY(memory);
2896     QVERIFY(memory[0] == 'Q');
2897     QVERIFY(file.unmap(memory));
2898     QCOMPARE(file.error(), QFile::NoError);
2899
2900     // hpux wont let you map multiple times.
2901 #if !defined(Q_OS_HPUX) && !defined(Q_USE_DEPRECATED_MAP_API) && !defined(Q_OS_WINCE)
2902     // exotic test to make sure that multiple maps work
2903
2904     // note: windows ce does not reference count mutliple maps
2905     // it's essentially just the same reference but it 
2906     // cause a resource lock on the file which prevents it 
2907     // from being removed    uchar *memory1 = file.map(0, file.size());
2908     uchar *memory1 = file.map(0, file.size());
2909     QCOMPARE(file.error(), QFile::NoError);
2910     uchar *memory2 = file.map(0, file.size());
2911     QCOMPARE(file.error(), QFile::NoError);
2912     QVERIFY(memory1);
2913     QVERIFY(memory2);
2914     QVERIFY(file.unmap(memory1));
2915     QCOMPARE(file.error(), QFile::NoError);
2916     QVERIFY(file.unmap(memory2));
2917     QCOMPARE(file.error(), QFile::NoError);
2918     memory1 = file.map(0, file.size());
2919     QCOMPARE(file.error(), QFile::NoError);
2920     QVERIFY(memory1);
2921     QVERIFY(file.unmap(memory1));
2922     QCOMPARE(file.error(), QFile::NoError);
2923 #endif
2924
2925     file.close();
2926
2927 #if defined(Q_OS_UNIX)
2928     if (::getuid() != 0)
2929         // root always has permissions
2930 #endif
2931     {
2932         // Change permissions on a file, just to confirm it would fail
2933         QFile::Permissions originalPermissions = file.permissions();
2934         QVERIFY(file.setPermissions(QFile::ReadOther));
2935         QVERIFY(!file.open(QFile::ReadWrite));
2936         memory = file.map(offset, size);
2937         QCOMPARE(file.error(), QFile::PermissionsError);
2938         QVERIFY(!memory);
2939         QVERIFY(file.setPermissions(originalPermissions));
2940     }
2941     QVERIFY(file.remove());
2942 }
2943
2944 void tst_QFile::mapResource_data()
2945 {
2946     QTest::addColumn<int>("offset");
2947     QTest::addColumn<int>("size");
2948     QTest::addColumn<QFile::FileError>("error");
2949     QTest::addColumn<QString>("fileName");
2950
2951     QString validFile = ":/tst_qfileinfo/resources/file1.ext1";
2952     QString invalidFile = ":/tst_qfileinfo/resources/filefoo.ext1";
2953
2954     for (int i = 0; i < 2; ++i) {
2955         QString file = (i == 0) ? validFile : invalidFile;
2956         QTest::newRow("0, 0") << 0 << 0 << QFile::UnspecifiedError << file;
2957         QTest::newRow("0, BIG") << 0 << 4096 << QFile::UnspecifiedError << file;
2958         QTest::newRow("-1, 0") << -1 << 0 << QFile::UnspecifiedError << file;
2959         QTest::newRow("0, -1") << 0 << -1 << QFile::UnspecifiedError << file;
2960     }
2961
2962     QTest::newRow("0, 1") << 0 << 1 << QFile::NoError << validFile;
2963 }
2964
2965 void tst_QFile::mapResource()
2966 {
2967     QFETCH(QString, fileName);
2968     QFETCH(int, offset);
2969     QFETCH(int, size);
2970     QFETCH(QFile::FileError, error);
2971
2972     QFile file(fileName);
2973     uchar *memory = file.map(offset, size);
2974     QCOMPARE(file.error(), error);
2975     QVERIFY((error == QFile::NoError) ? (memory != 0) : (memory == 0));
2976     if (error == QFile::NoError)
2977         QCOMPARE(QString(memory[0]), QString::number(offset + 1));
2978     QVERIFY(file.unmap(memory));
2979 }
2980
2981 void tst_QFile::mapOpenMode_data()
2982 {
2983     QTest::addColumn<int>("openMode");
2984
2985     QTest::newRow("ReadOnly") << int(QIODevice::ReadOnly);
2986     //QTest::newRow("WriteOnly") << int(QIODevice::WriteOnly); // this doesn't make sense
2987     QTest::newRow("ReadWrite") << int(QIODevice::ReadWrite);
2988     QTest::newRow("ReadOnly,Unbuffered") << int(QIODevice::ReadOnly | QIODevice::Unbuffered);
2989     QTest::newRow("ReadWrite,Unbuffered") << int(QIODevice::ReadWrite | QIODevice::Unbuffered);
2990 }
2991
2992 void tst_QFile::mapOpenMode()
2993 {
2994     QFETCH(int, openMode);
2995     static const qint64 fileSize = 4096;
2996
2997     QByteArray pattern(fileSize, 'A');
2998
2999     QString fileName = QDir::currentPath() + '/' + "qfile_map_testfile";
3000     if (QFile::exists(fileName)) {
3001         QVERIFY(QFile::setPermissions(fileName,
3002             QFile::WriteOwner | QFile::ReadOwner | QFile::WriteUser | QFile::ReadUser));
3003         QFile::remove(fileName);
3004     }
3005     QFile file(fileName);
3006
3007     // make a file
3008     QVERIFY(file.open(QFile::ReadWrite));
3009     QVERIFY(file.write(pattern));
3010     QVERIFY(file.flush());
3011     file.close();
3012
3013     // open according to our mode
3014     QVERIFY(file.open(QIODevice::OpenMode(openMode)));
3015
3016     uchar *memory = file.map(0, fileSize);
3017     QVERIFY(memory);
3018     QVERIFY(memcmp(memory, pattern, fileSize) == 0);
3019
3020     if (openMode & QIODevice::WriteOnly) {
3021         // try to write to the file
3022         *memory = 'a';
3023         file.unmap(memory);
3024         file.close();
3025         file.open(QIODevice::OpenMode(openMode));
3026         file.seek(0);
3027         char c;
3028         QVERIFY(file.getChar(&c));
3029         QCOMPARE(c, 'a');
3030     }
3031
3032     file.close();
3033 }
3034
3035 void tst_QFile::openDirectory()
3036 {
3037     QFile f1(QFINDTESTDATA("resources"));
3038     // it's a directory, it must exist
3039     QVERIFY(f1.exists());
3040
3041     // ...but not be openable
3042     QVERIFY(!f1.open(QIODevice::ReadOnly));
3043     f1.close();
3044     QVERIFY(!f1.open(QIODevice::ReadOnly|QIODevice::Unbuffered));
3045     f1.close();
3046     QVERIFY(!f1.open(QIODevice::ReadWrite));
3047     f1.close();
3048     QVERIFY(!f1.open(QIODevice::WriteOnly));
3049     f1.close();
3050     QVERIFY(!f1.open(QIODevice::WriteOnly|QIODevice::Unbuffered));
3051     f1.close();
3052 }
3053
3054 static qint64 streamExpectedSize(int fd)
3055 {
3056     QT_STATBUF sb;
3057     if (QT_FSTAT(fd, &sb) != -1)
3058         return sb.st_size;
3059     return 0;
3060 }
3061
3062 static qint64 streamCurrentPosition(int fd)
3063 {
3064     QT_OFF_T pos = QT_LSEEK(fd, 0, SEEK_CUR);
3065     if (pos != -1)
3066         return pos;
3067     return 0;
3068 }
3069
3070 static qint64 streamCurrentPosition(FILE *f)
3071 {
3072     QT_OFF_T pos = QT_FTELL(f);
3073     if (pos != -1)
3074         return pos;
3075     return 0;
3076 }
3077
3078 class MessageHandler {
3079 public:
3080     MessageHandler(QtMessageHandler messageHandler = handler)
3081     {
3082         ok = true;
3083         oldMessageHandler = qInstallMessageHandler(messageHandler);
3084     }
3085
3086     ~MessageHandler()
3087     {
3088         qInstallMessageHandler(oldMessageHandler);
3089     }
3090
3091     static bool testPassed()
3092     {
3093         return ok;
3094     }
3095 protected:
3096     static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
3097     {
3098         if (msg == QString::fromLatin1("QIODevice::seek: Cannot call seek on a sequential device"))
3099             ok = false;
3100         // Defer to old message handler.
3101         if (oldMessageHandler)
3102             oldMessageHandler(type, context, msg);
3103     }
3104
3105     static QtMessageHandler oldMessageHandler;
3106     static bool ok;
3107 };
3108
3109 bool MessageHandler::ok = true;
3110 QtMessageHandler MessageHandler::oldMessageHandler = 0;
3111
3112 void tst_QFile::openStandardStreamsFileDescriptors()
3113 {
3114 #ifdef Q_OS_WINCE
3115     //allthough Windows CE (not mobile!) has functions that allow redirecting
3116     //the standard file descriptors to a file (see SetStdioPathW/GetStdioPathW)
3117     //it does not have functions to simply open them like below .
3118     QSKIP("Opening standard streams on Windows CE via descriptor not implemented");
3119 #endif
3120
3121     // Check that QIODevice::seek() isn't called when opening a sequential device (QFile).
3122     MessageHandler msgHandler;
3123
3124     {
3125         QFile in;
3126         in.open(STDIN_FILENO, QIODevice::ReadOnly);
3127         QCOMPARE( in.pos(), streamCurrentPosition(STDIN_FILENO) );
3128         QCOMPARE( in.size(), streamExpectedSize(STDIN_FILENO) );
3129     }
3130
3131     {
3132         QFile out;
3133         QVERIFY(out.open(STDOUT_FILENO, QIODevice::WriteOnly));
3134         QCOMPARE( out.pos(), streamCurrentPosition(STDOUT_FILENO) );
3135         QCOMPARE( out.size(), streamExpectedSize(STDOUT_FILENO) );
3136     }
3137
3138     {
3139         QFile err;
3140         err.open(STDERR_FILENO, QIODevice::WriteOnly);
3141         QCOMPARE( err.pos(), streamCurrentPosition(STDERR_FILENO) );
3142         QCOMPARE( err.size(), streamExpectedSize(STDERR_FILENO) );
3143     }
3144
3145     QVERIFY(msgHandler.testPassed());
3146 }
3147
3148 void tst_QFile::openStandardStreamsBufferedStreams()
3149 {
3150 #ifdef Q_OS_WINCE
3151     QSKIP("Not tested on Windows CE.");
3152 #endif
3153     // Check that QIODevice::seek() isn't called when opening a sequential device (QFile).
3154     MessageHandler msgHandler;
3155
3156     // Using streams
3157     {
3158         QFile in;
3159         in.open(stdin, QIODevice::ReadOnly);
3160         QCOMPARE( in.pos(), streamCurrentPosition(stdin) );
3161         QCOMPARE( in.size(), streamExpectedSize(QT_FILENO(stdin)) );
3162     }
3163
3164     {
3165         QFile out;
3166         out.open(stdout, QIODevice::WriteOnly);
3167         QCOMPARE( out.pos(), streamCurrentPosition(stdout) );
3168         QCOMPARE( out.size(), streamExpectedSize(QT_FILENO(stdout)) );
3169     }
3170
3171     {
3172         QFile err;
3173         err.open(stderr, QIODevice::WriteOnly);
3174         QCOMPARE( err.pos(), streamCurrentPosition(stderr) );
3175         QCOMPARE( err.size(), streamExpectedSize(QT_FILENO(stderr)) );
3176     }
3177
3178     QVERIFY(msgHandler.testPassed());
3179 }
3180
3181 void tst_QFile::writeNothing()
3182 {
3183     for (int i = 0; i < NumberOfFileTypes; ++i) {
3184         QFile file("file.txt");
3185         QVERIFY( openFile(file, QIODevice::WriteOnly | QIODevice::Unbuffered, FileType(i)) );
3186         QVERIFY( 0 == file.write((char *)0, 0) );
3187         QCOMPARE( file.error(), QFile::NoError );
3188         closeFile(file);
3189     }
3190 }
3191
3192 void tst_QFile::resize_data()
3193 {
3194     QTest::addColumn<int>("filetype");
3195
3196     QTest::newRow("native") << int(OpenQFile);
3197     QTest::newRow("fileno") << int(OpenFd);
3198     QTest::newRow("stream") << int(OpenStream);
3199 }
3200
3201 void tst_QFile::resize()
3202 {
3203     QFETCH(int, filetype);
3204     QString filename(QLatin1String("file.txt"));
3205     QFile file(filename);
3206     QVERIFY(openFile(file, QIODevice::ReadWrite, FileType(filetype)));
3207     QVERIFY(file.resize(8));
3208     QCOMPARE(file.size(), qint64(8));
3209     closeFile(file);
3210     QFile::resize(filename, 4);
3211     QCOMPARE(QFileInfo(filename).size(), qint64(4));
3212     QVERIFY(QFile::remove(filename));
3213 }
3214
3215 void tst_QFile::objectConstructors()
3216 {
3217     QObject ob;
3218     QFile* file1 = new QFile(QFINDTESTDATA("testfile.txt"), &ob);
3219     QFile* file2 = new QFile(&ob);
3220     QVERIFY(file1->exists());
3221     QVERIFY(!file2->exists());
3222 }
3223
3224 void tst_QFile::caseSensitivity()
3225 {
3226 #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
3227     const bool caseSensitive = false;
3228 #else
3229     const bool caseSensitive = true;
3230 #endif
3231     QByteArray testData("a little test");
3232     QString filename("File.txt");
3233     {
3234         QFile f(filename);
3235         QVERIFY(f.open(QIODevice::WriteOnly));
3236         QVERIFY(f.write(testData));
3237         f.close();
3238     }
3239     QStringList alternates;
3240     QFileInfo fi(filename);
3241     QVERIFY(fi.exists());
3242     alternates << "file.txt" << "File.TXT" << "fIlE.TxT" << fi.absoluteFilePath().toUpper() << fi.absoluteFilePath().toLower();
3243     foreach (QString alt, alternates) {
3244         QFileInfo fi2(alt);
3245         QCOMPARE(fi2.exists(), !caseSensitive);
3246         QCOMPARE(fi.size() == fi2.size(), !caseSensitive);
3247         QFile f2(alt);
3248         QCOMPARE(f2.open(QIODevice::ReadOnly), !caseSensitive);
3249         if (!caseSensitive)
3250             QCOMPARE(f2.readAll(), testData);
3251     }
3252 }
3253
3254 //MSVCRT asserts when any function is called with a closed file handle.
3255 //This replaces the default crashing error handler with one that ignores the error (allowing EBADF to be returned)
3256 class AutoIgnoreInvalidParameter
3257 {
3258 public:
3259 #if defined(Q_OS_WIN) && defined (Q_CC_MSVC)
3260     static void ignore_invalid_parameter(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t) {}
3261     AutoIgnoreInvalidParameter()
3262     {
3263         oldHandler = _set_invalid_parameter_handler(ignore_invalid_parameter);
3264         //also disable the abort/retry/ignore popup
3265         oldReportMode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
3266     }
3267     ~AutoIgnoreInvalidParameter()
3268     {
3269         //restore previous settings
3270         _set_invalid_parameter_handler(oldHandler);
3271         _CrtSetReportMode(_CRT_ASSERT, oldReportMode);
3272     }
3273     _invalid_parameter_handler oldHandler;
3274     int oldReportMode;
3275 #endif
3276 };
3277
3278 void tst_QFile::autocloseHandle()
3279 {
3280     {
3281         QFile file("readonlyfile");
3282         QVERIFY(openFile(file, QIODevice::ReadOnly, OpenFd, QFile::AutoCloseHandle));
3283         int fd = fd_;
3284         QCOMPARE(file.handle(), fd);
3285         file.close();
3286         fd_ = -1;
3287         QCOMPARE(file.handle(), -1);
3288         AutoIgnoreInvalidParameter a;
3289         Q_UNUSED(a);
3290         //file is closed, read should fail
3291         char buf;
3292         QCOMPARE((int)QT_READ(fd, &buf, 1), -1);
3293         QVERIFY(errno = EBADF);
3294     }
3295
3296     {
3297         QFile file("readonlyfile");
3298         QVERIFY(openFile(file, QIODevice::ReadOnly, OpenFd, QFile::DontCloseHandle));
3299         QCOMPARE(file.handle(), fd_);
3300         file.close();
3301         QCOMPARE(file.handle(), -1);
3302         //file is not closed, read should succeed
3303         char buf;
3304         QCOMPARE((int)QT_READ(fd_, &buf, 1), 1);
3305         QT_CLOSE(fd_);
3306         fd_ = -1;
3307     }
3308
3309     {
3310         QFile file("readonlyfile");
3311         QVERIFY(openFile(file, QIODevice::ReadOnly, OpenStream, QFile::AutoCloseHandle));
3312         int fd = QT_FILENO(stream_);
3313         QCOMPARE(file.handle(), fd);
3314         file.close();
3315         stream_ = 0;
3316         QCOMPARE(file.handle(), -1);
3317         AutoIgnoreInvalidParameter a;
3318         Q_UNUSED(a);
3319         //file is closed, read should fail
3320         char buf;
3321         QCOMPARE((int)QT_READ(fd, &buf, 1), -1); //not using fread because the FILE* was freed by fclose
3322     }
3323
3324     {
3325         QFile file("readonlyfile");
3326         QVERIFY(openFile(file, QIODevice::ReadOnly, OpenStream, QFile::DontCloseHandle));
3327         QCOMPARE(file.handle(), QT_FILENO(stream_));
3328         file.close();
3329         QCOMPARE(file.handle(), -1);
3330         //file is not closed, read should succeed
3331         char buf;
3332         QCOMPARE(int(::fread(&buf, 1, 1, stream_)), 1);
3333         ::fclose(stream_);
3334         stream_ = 0;
3335     }
3336 }
3337
3338 QTEST_MAIN(tst_QFile)
3339 #include "tst_qfile.moc"