Test: tst_QFile::writeLargeDataBlock() unstable failure as XFAIL
[profile/ivi/qtbase.git] / tests / auto / corelib / io / qfile / tst_qfile.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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 #ifdef QT_BUILD_INTERNAL
182     void useQFileInAFileHandler();
183 #endif
184     void getCharFF();
185     void remove_and_exists();
186     void removeOpenFile();
187     void fullDisk();
188     void writeLargeDataBlock_data();
189     void writeLargeDataBlock();
190     void readFromWriteOnlyFile();
191     void writeToReadOnlyFile();
192     void virtualFile();
193     void textFile();
194     void rename_data();
195     void rename();
196     void renameWithAtEndSpecialFile() const;
197     void renameFallback();
198     void renameMultiple();
199     void appendAndRead();
200     void miscWithUncPathAsCurrentDir();
201     void standarderror();
202     void handle();
203     void nativeHandleLeaks();
204
205     void readEof_data();
206     void readEof();
207
208     void map_data();
209     void map();
210     void mapResource_data();
211     void mapResource();
212     void mapOpenMode_data();
213     void mapOpenMode();
214
215     void openStandardStreamsFileDescriptors();
216     void openStandardStreamsBufferedStreams();
217
218     void resize_data();
219     void resize();
220
221     void objectConstructors();
222
223     void caseSensitivity();
224
225     void autocloseHandle();
226
227     void posAfterFailedStat();
228
229     void openDirectory();
230     void writeNothing();
231
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     QEXPECT_FAIL("colon1", "QTBUG-27306", Continue);
1064     QVERIFY( !f.open( QIODevice::ReadWrite ) );
1065 }
1066
1067 void tst_QFile::createFile()
1068 {
1069     if ( QFile::exists( "createme.txt" ) )
1070         QFile::remove( "createme.txt" );
1071     QVERIFY( !QFile::exists( "createme.txt" ) );
1072
1073     QFile f( "createme.txt" );
1074     QVERIFY( f.open( QIODevice::WriteOnly ) );
1075     f.close();
1076     QVERIFY( QFile::exists( "createme.txt" ) );
1077 }
1078
1079 void tst_QFile::append()
1080 {
1081     const QString name("appendme.txt");
1082     if (QFile::exists(name))
1083         QFile::remove(name);
1084     QVERIFY(!QFile::exists(name));
1085
1086     QFile f(name);
1087     QVERIFY(f.open(QIODevice::WriteOnly | QIODevice::Truncate));
1088     f.putChar('a');
1089     f.close();
1090
1091     QVERIFY(f.open(QIODevice::Append));
1092     QVERIFY(f.pos() == 1);
1093     f.putChar('a');
1094     f.close();
1095     QCOMPARE(int(f.size()), 2);
1096 }
1097
1098 void tst_QFile::permissions_data()
1099 {
1100     QTest::addColumn<QString>("file");
1101     QTest::addColumn<uint>("perms");
1102     QTest::addColumn<bool>("expected");
1103     QTest::addColumn<bool>("create");
1104
1105     QTest::newRow("data0") << QCoreApplication::instance()->applicationFilePath() << uint(QFile::ExeUser) << true << false;
1106     QTest::newRow("data1") << QFINDTESTDATA("tst_qfile.cpp") << uint(QFile::ReadUser) << true << false;
1107     QTest::newRow("readonly") << QFINDTESTDATA("readonlyfile") << uint(QFile::WriteUser) << false << false;
1108 #ifndef Q_OS_WINCE
1109     QTest::newRow("longfile") << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1110                                                     "longFileNamelongFileNamelongFileNamelongFileName"
1111                                                     "longFileNamelongFileNamelongFileNamelongFileName"
1112                                                     "longFileNamelongFileNamelongFileNamelongFileName"
1113                                                     "longFileNamelongFileNamelongFileNamelongFileName.txt") << uint(QFile::ReadUser) << true << true;
1114 #endif
1115     QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << uint(QFile::ReadUser) << true << false;
1116     QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1" << uint(QFile::WriteUser) << false << false;
1117     QTest::newRow("resource3") << ":/tst_qfileinfo/resources/file1.ext1" << uint(QFile::ExeUser) << false << false;
1118 }
1119
1120 void tst_QFile::permissions()
1121 {
1122     QFETCH(QString, file);
1123     QFETCH(uint, perms);
1124     QFETCH(bool, expected);
1125     QFETCH(bool, create);
1126     if (create) {
1127         QFile fc(file);
1128         QVERIFY(fc.open(QFile::WriteOnly));
1129         QVERIFY(fc.write("hello\n"));
1130         fc.close();
1131     }
1132
1133     QFile f(file);
1134     QFile::Permissions memberResult = f.permissions() & perms;
1135     QFile::Permissions staticResult = QFile::permissions(file) & perms;
1136
1137     if (create) {
1138         QFile::remove(file);
1139     }
1140
1141 #ifdef Q_OS_WIN
1142     if (qt_ntfs_permission_lookup)
1143         QEXPECT_FAIL("readonly", "QTBUG-25630", Abort);
1144 #endif
1145     QCOMPARE((memberResult == QFile::Permissions(perms)), expected);
1146     QCOMPARE((staticResult == QFile::Permissions(perms)), expected);
1147 }
1148
1149 void tst_QFile::permissionsNtfs_data()
1150 {
1151     permissions_data();
1152 }
1153
1154 void tst_QFile::permissionsNtfs()
1155 {
1156 #ifdef Q_OS_WIN
1157     QScopedValueRollback<int> ntfsMode(qt_ntfs_permission_lookup);
1158     qt_ntfs_permission_lookup++;
1159     permissions();
1160 #else
1161     QSKIP("windows test");
1162 #endif
1163 }
1164
1165 void tst_QFile::setPermissions()
1166 {
1167     if ( QFile::exists( "createme.txt" ) )
1168         QFile::remove( "createme.txt" );
1169     QVERIFY( !QFile::exists( "createme.txt" ) );
1170
1171     QFile f("createme.txt");
1172     QVERIFY(f.open(QIODevice::WriteOnly | QIODevice::Truncate));
1173     f.putChar('a');
1174     f.close();
1175
1176     QFile::Permissions perms(QFile::WriteUser | QFile::ReadUser);
1177     QVERIFY(f.setPermissions(perms));
1178     QVERIFY((f.permissions() & perms) == perms);
1179
1180 }
1181
1182 void tst_QFile::copy()
1183 {
1184     QFile::setPermissions("tst_qfile_copy.cpp", QFile::WriteUser);
1185     QFile::remove("tst_qfile_copy.cpp");
1186     QFile::remove("test2");
1187     QVERIFY(QFile::copy(QFINDTESTDATA("tst_qfile.cpp"), "tst_qfile_copy.cpp"));
1188     QFile in1(QFINDTESTDATA("tst_qfile.cpp")), in2("tst_qfile_copy.cpp");
1189     QVERIFY(in1.open(QFile::ReadOnly));
1190     QVERIFY(in2.open(QFile::ReadOnly));
1191     QByteArray data1 = in1.readAll(), data2 = in2.readAll();
1192     QCOMPARE(data1, data2);
1193     QFile::remove( "main_copy.cpp" );
1194
1195     QFile::copy(QDir::currentPath(), QDir::currentPath() + QLatin1String("/test2"));
1196 }
1197
1198 void tst_QFile::copyAfterFail()
1199 {
1200     QFile file1("file-to-be-copied.txt");
1201     QFile file2("existing-file.txt");
1202
1203     QVERIFY(file1.open(QIODevice::ReadWrite) && "(test-precondition)");
1204     QVERIFY(file2.open(QIODevice::ReadWrite) && "(test-precondition)");
1205     file2.close();
1206     QVERIFY(!QFile::exists("copied-file-1.txt") && "(test-precondition)");
1207     QVERIFY(!QFile::exists("copied-file-2.txt") && "(test-precondition)");
1208
1209     QVERIFY(!file1.copy("existing-file.txt"));
1210     QCOMPARE(file1.error(), QFile::CopyError);
1211
1212     QVERIFY(file1.copy("copied-file-1.txt"));
1213     QVERIFY(!file1.isOpen());
1214     QCOMPARE(file1.error(), QFile::NoError);
1215
1216     QVERIFY(!file1.copy("existing-file.txt"));
1217     QCOMPARE(file1.error(), QFile::CopyError);
1218
1219     QVERIFY(file1.copy("copied-file-2.txt"));
1220     QVERIFY(!file1.isOpen());
1221     QCOMPARE(file1.error(), QFile::NoError);
1222
1223     QVERIFY(QFile::exists("copied-file-1.txt"));
1224     QVERIFY(QFile::exists("copied-file-2.txt"));
1225
1226     QVERIFY(QFile::remove("file-to-be-copied.txt") && "(test-cleanup)");
1227     QVERIFY(QFile::remove("existing-file.txt") && "(test-cleanup)");
1228     QVERIFY(QFile::remove("copied-file-1.txt") && "(test-cleanup)");
1229     QVERIFY(QFile::remove("copied-file-2.txt") && "(test-cleanup)");
1230 }
1231
1232 void tst_QFile::copyRemovesTemporaryFile() const
1233 {
1234     const QString newName(QLatin1String("copyRemovesTemporaryFile"));
1235     QVERIFY(QFile::copy(QFINDTESTDATA("forCopying.txt"), newName));
1236
1237     QVERIFY(!QFile::exists(QFINDTESTDATA("qt_temp.XXXXXX")));
1238     QVERIFY(QFile::remove(newName));
1239 }
1240
1241 void tst_QFile::copyShouldntOverwrite()
1242 {
1243     // Copy should not overwrite existing files.
1244     QFile::remove("tst_qfile.cpy");
1245     QFile file(QFINDTESTDATA("tst_qfile.cpp"));
1246     QVERIFY(file.copy("tst_qfile.cpy"));
1247
1248     bool ok = QFile::setPermissions("tst_qfile.cpy", QFile::WriteOther);
1249     QVERIFY(ok);
1250     QVERIFY(!file.copy("tst_qfile.cpy"));
1251     QFile::remove("tst_qfile.cpy");
1252 }
1253
1254 void tst_QFile::copyFallback()
1255 {
1256     // Using a resource file to trigger QFile::copy's fallback handling
1257     QFile file(":/copy-fallback.qrc");
1258     QFile::remove("file-copy-destination.txt");
1259
1260     QVERIFY2(file.exists(), "test precondition");
1261     QVERIFY2(!QFile::exists("file-copy-destination.txt"), "test precondition");
1262
1263     // Fallback copy of closed file.
1264     QVERIFY(file.copy("file-copy-destination.txt"));
1265     QVERIFY(QFile::exists("file-copy-destination.txt"));
1266     QVERIFY(!file.isOpen());
1267
1268 #ifdef Q_OS_WINCE
1269     // Need to reset permissions on Windows to be able to delete
1270     QVERIFY(QFile::setPermissions("file-copy-destination.txt",
1271             QFile::WriteOther));
1272 #else
1273      // Need to reset permissions on Windows to be able to delete
1274     QVERIFY(QFile::setPermissions("file-copy-destination.txt",
1275            QFile::ReadOwner | QFile::WriteOwner));
1276 #endif
1277     QVERIFY(QFile::remove("file-copy-destination.txt"));
1278
1279     // Fallback copy of open file.
1280     QVERIFY(file.open(QIODevice::ReadOnly));
1281     QVERIFY(file.copy("file-copy-destination.txt"));
1282     QVERIFY(QFile::exists("file-copy-destination.txt"));
1283     QVERIFY(!file.isOpen());
1284
1285     file.close(); 
1286     QFile::remove("file-copy-destination.txt");
1287 }
1288
1289 #ifdef Q_OS_WIN
1290 #include <objbase.h>
1291 #include <shlobj.h>
1292 #endif
1293
1294 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1295 static QString getWorkingDirectoryForLink(const QString &linkFileName)
1296 {
1297     bool neededCoInit = false;
1298     QString ret;
1299
1300     IShellLink *psl;
1301     HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
1302     if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized
1303         neededCoInit = true;
1304         CoInitialize(NULL);
1305         hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
1306     }
1307
1308     if (SUCCEEDED(hres)) {    // Get pointer to the IPersistFile interface.
1309         IPersistFile *ppf;
1310         hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
1311         if (SUCCEEDED(hres))  {
1312             hres = ppf->Load((LPOLESTR)linkFileName.utf16(), STGM_READ);
1313             //The original path of the link is retrieved. If the file/folder
1314             //was moved, the return value still have the old path.
1315             if(SUCCEEDED(hres)) {
1316                 wchar_t szGotPath[MAX_PATH];
1317                 if (psl->GetWorkingDirectory(szGotPath, MAX_PATH) == NOERROR)
1318                     ret = QString::fromWCharArray(szGotPath);
1319             }
1320             ppf->Release();
1321         }
1322         psl->Release();
1323     }
1324
1325     if (neededCoInit) {
1326         CoUninitialize();
1327     }
1328
1329     return ret;
1330 }
1331 #endif
1332
1333 void tst_QFile::link()
1334 {
1335     QFile::remove("myLink.lnk");
1336
1337     QFileInfo info1(QFINDTESTDATA("tst_qfile.cpp"));
1338     QString referenceTarget = QDir::cleanPath(info1.absoluteFilePath());
1339
1340     QVERIFY(QFile::link(QFINDTESTDATA("tst_qfile.cpp"), "myLink.lnk"));
1341
1342     QFileInfo info2("myLink.lnk");
1343     QVERIFY(info2.isSymLink());
1344     QCOMPARE(info2.symLinkTarget(), referenceTarget);
1345
1346     QFile link("myLink.lnk");
1347     QVERIFY(link.open(QIODevice::ReadOnly));
1348     QCOMPARE(link.symLinkTarget(), referenceTarget);
1349     link.close();
1350
1351     QCOMPARE(QFile::symLinkTarget("myLink.lnk"), referenceTarget);
1352
1353 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1354     QString wd = getWorkingDirectoryForLink(info2.absoluteFilePath());
1355     QCOMPARE(QDir::fromNativeSeparators(wd), QDir::cleanPath(info1.absolutePath()));
1356 #endif
1357
1358     QVERIFY(QFile::remove(info2.absoluteFilePath()));
1359 }
1360
1361 void tst_QFile::linkToDir()
1362 {
1363     QFile::remove("myLinkToDir.lnk");
1364     QDir dir;
1365     dir.mkdir("myDir");
1366     QFileInfo info1("myDir");
1367     QVERIFY(QFile::link("myDir", "myLinkToDir.lnk"));
1368     QFileInfo info2("myLinkToDir.lnk");
1369 #if !(defined Q_OS_HPUX && defined(__ia64))
1370     // absurd HP-UX filesystem bug on gravlaks - checking if a symlink
1371     // resolves or not alters the file system to make the broken symlink
1372     // later fail...
1373     QVERIFY(info2.isSymLink());
1374 #endif
1375     QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath());
1376     QVERIFY(QFile::remove(info2.absoluteFilePath()));
1377     QFile::remove("myLinkToDir.lnk");
1378     dir.rmdir("myDir");
1379 }
1380
1381 void tst_QFile::absolutePathLinkToRelativePath()
1382 {
1383     QFile::remove("myDir/test.txt");
1384     QFile::remove("myDir/myLink.lnk");
1385     QDir dir;
1386     dir.mkdir("myDir");
1387     QFile("myDir/test.txt").open(QFile::WriteOnly);
1388
1389 #ifdef Q_OS_WIN
1390     QVERIFY(QFile::link("test.txt", "myDir/myLink.lnk"));
1391 #else
1392     QVERIFY(QFile::link("myDir/test.txt", "myDir/myLink.lnk"));
1393 #endif
1394     QEXPECT_FAIL("", "Symlinking using relative paths is currently different on Windows and Unix", Continue);
1395     QCOMPARE(QFileInfo(QFile(QFileInfo("myDir/myLink.lnk").absoluteFilePath()).symLinkTarget()).absoluteFilePath(),
1396              QFileInfo("myDir/test.txt").absoluteFilePath());
1397
1398     QFile::remove("myDir/test.txt");
1399     QFile::remove("myDir/myLink.lnk");
1400     dir.rmdir("myDir");
1401 }
1402
1403 void tst_QFile::readBrokenLink()
1404 {
1405     QFile::remove("myLink2.lnk");
1406     QFileInfo info1("file12");
1407     QVERIFY(QFile::link("file12", "myLink2.lnk"));
1408     QFileInfo info2("myLink2.lnk");
1409     QVERIFY(info2.isSymLink());
1410     QCOMPARE(info2.symLinkTarget(), info1.absoluteFilePath());
1411     QVERIFY(QFile::remove(info2.absoluteFilePath()));
1412     QVERIFY(QFile::link("ole/..", "myLink2.lnk"));
1413     QCOMPARE(QFileInfo("myLink2.lnk").symLinkTarget(), QDir::currentPath());
1414 }
1415
1416 void tst_QFile::readTextFile_data()
1417 {
1418     QTest::addColumn<QByteArray>("in");
1419     QTest::addColumn<QByteArray>("out");
1420
1421     QTest::newRow("empty") << QByteArray() << QByteArray();
1422     QTest::newRow("a") << QByteArray("a") << QByteArray("a");
1423     QTest::newRow("a\\rb") << QByteArray("a\rb") << QByteArray("ab");
1424     QTest::newRow("\\n") << QByteArray("\n") << QByteArray("\n");
1425     QTest::newRow("\\r\\n") << QByteArray("\r\n") << QByteArray("\n");
1426     QTest::newRow("\\r") << QByteArray("\r") << QByteArray();
1427     QTest::newRow("twolines") << QByteArray("Hello\r\nWorld\r\n") << QByteArray("Hello\nWorld\n");
1428     QTest::newRow("twolines no endline") << QByteArray("Hello\r\nWorld") << QByteArray("Hello\nWorld");
1429 }
1430
1431 void tst_QFile::readTextFile()
1432 {
1433     QFETCH(QByteArray, in);
1434     QFETCH(QByteArray, out);
1435
1436     QFile winfile("winfile.txt");
1437     QVERIFY(winfile.open(QFile::WriteOnly | QFile::Truncate));
1438     winfile.write(in);
1439     winfile.close();
1440
1441     QVERIFY(winfile.open(QFile::ReadOnly));
1442     QCOMPARE(winfile.readAll(), in);
1443     winfile.close();
1444
1445     QVERIFY(winfile.open(QFile::ReadOnly | QFile::Text));
1446     QCOMPARE(winfile.readAll(), out);
1447 }
1448
1449 void tst_QFile::readTextFile2()
1450 {
1451     {
1452         QFile file(QFINDTESTDATA("testlog.txt"));
1453         QVERIFY(file.open(QIODevice::ReadOnly));
1454         file.read(4097);
1455     }
1456
1457     {
1458         QFile file(QFINDTESTDATA("testlog.txt"));
1459         QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
1460         file.read(4097);
1461     }
1462 }
1463
1464 void tst_QFile::writeTextFile_data()
1465 {
1466     QTest::addColumn<QByteArray>("in");
1467
1468     QTest::newRow("empty") << QByteArray();
1469     QTest::newRow("a") << QByteArray("a");
1470     QTest::newRow("a\\rb") << QByteArray("a\rb");
1471     QTest::newRow("\\n") << QByteArray("\n");
1472     QTest::newRow("\\r\\n") << QByteArray("\r\n");
1473     QTest::newRow("\\r") << QByteArray("\r");
1474     QTest::newRow("twolines crlf") << QByteArray("Hello\r\nWorld\r\n");
1475     QTest::newRow("twolines crlf no endline") << QByteArray("Hello\r\nWorld");
1476     QTest::newRow("twolines lf") << QByteArray("Hello\nWorld\n");
1477     QTest::newRow("twolines lf no endline") << QByteArray("Hello\nWorld");
1478     QTest::newRow("mixed") << QByteArray("this\nis\r\na\nmixed\r\nfile\n");
1479 }
1480
1481 void tst_QFile::writeTextFile()
1482 {
1483     QFETCH(QByteArray, in);
1484
1485     QFile file("textfile.txt");
1486     QVERIFY(file.open(QFile::WriteOnly | QFile::Truncate | QFile::Text));
1487     QByteArray out = in;
1488 #ifdef Q_OS_WIN
1489     out.replace('\n', "\r\n");
1490 #endif
1491     QCOMPARE(file.write(in), qlonglong(in.size()));
1492     file.close();
1493
1494     file.open(QFile::ReadOnly);
1495     QCOMPARE(file.readAll(), out);
1496 }
1497
1498 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1499 void tst_QFile::largeUncFileSupport()
1500 {
1501     qint64 size = Q_INT64_C(8589934592);
1502     qint64 dataOffset = Q_INT64_C(8589914592);
1503     QByteArray knownData("LargeFile content at offset 8589914592");
1504     QString largeFile("//" + QtNetworkSettings::winServerName() + "/testsharelargefile/file.bin");
1505
1506     {
1507         // 1) Native file handling.
1508         QFile file(largeFile);
1509         QCOMPARE(file.size(), size);
1510         QVERIFY(file.open(QIODevice::ReadOnly));
1511         QCOMPARE(file.size(), size);
1512         QVERIFY(file.seek(dataOffset));
1513         QCOMPARE(file.read(knownData.size()), knownData);
1514     }
1515     {
1516         // 2) stdlib file handling.
1517         QFile file;
1518         FILE *fh = fopen(QFile::encodeName(largeFile).data(), "rb");
1519         QVERIFY(file.open(fh, QIODevice::ReadOnly));
1520         QCOMPARE(file.size(), size);
1521         QVERIFY(file.seek(dataOffset));
1522         QCOMPARE(file.read(knownData.size()), knownData);
1523         fclose(fh);
1524     }
1525     {
1526         // 3) stdio file handling.
1527         QFile file;
1528         FILE *fh = fopen(QFile::encodeName(largeFile).data(), "rb");
1529         int fd = int(_fileno(fh));
1530         QVERIFY(file.open(fd, QIODevice::ReadOnly));
1531         QCOMPARE(file.size(), size);
1532         QVERIFY(file.seek(dataOffset));
1533         QCOMPARE(file.read(knownData.size()), knownData);
1534         fclose(fh);
1535     }
1536 }
1537 #endif
1538
1539 void tst_QFile::tailFile()
1540 {
1541     QSKIP("File change notifications are so far unsupported.");
1542
1543     QFile file("tail.txt");
1544     QVERIFY(file.open(QFile::WriteOnly | QFile::Append));
1545
1546     QFile tailFile("tail.txt");
1547     QVERIFY(tailFile.open(QFile::ReadOnly));
1548     tailFile.seek(file.size());
1549
1550     QSignalSpy readSignalSpy(&tailFile, SIGNAL(readyRead()));
1551     QVERIFY(readSignalSpy.isValid());
1552
1553     file.write("", 1);
1554
1555     QTestEventLoop::instance().enterLoop(5);
1556
1557     QVERIFY(!QTestEventLoop::instance().timeout());
1558     QCOMPARE(readSignalSpy.count(), 1);
1559 }
1560
1561 void tst_QFile::flush()
1562 {
1563     QString fileName("stdfile.txt");
1564
1565     QFile::remove(fileName);
1566
1567     {
1568         QFile file(fileName);
1569         QVERIFY(file.open(QFile::WriteOnly));
1570         QCOMPARE(file.write("abc", 3),qint64(3));
1571     }
1572
1573     {
1574         QFile file(fileName);
1575         QVERIFY(file.open(QFile::WriteOnly | QFile::Append));
1576         QCOMPARE(file.pos(), qlonglong(3));
1577         QCOMPARE(file.write("def", 3), qlonglong(3));
1578         QCOMPARE(file.pos(), qlonglong(6));
1579     }
1580
1581     {
1582         QFile file("stdfile.txt");
1583         QVERIFY(file.open(QFile::ReadOnly));
1584         QCOMPARE(file.readAll(), QByteArray("abcdef"));
1585     }
1586
1587     QFile::remove(fileName);
1588 }
1589
1590 void tst_QFile::bufferedRead()
1591 {
1592     QFile::remove("stdfile.txt");
1593
1594     QFile file("stdfile.txt");
1595     QVERIFY(file.open(QFile::WriteOnly));
1596     file.write("abcdef");
1597     file.close();
1598
1599 #if defined(Q_OS_WINCE)
1600     FILE *stdFile = fopen((QCoreApplication::applicationDirPath() + "/stdfile.txt").toLatin1() , "r");
1601 #else
1602     FILE *stdFile = fopen("stdfile.txt", "r");
1603 #endif
1604     QVERIFY(stdFile);
1605     char c;
1606     QCOMPARE(int(fread(&c, 1, 1, stdFile)), 1);
1607     QCOMPARE(c, 'a');
1608     QCOMPARE(int(ftell(stdFile)), 1);
1609
1610     {
1611         QFile file;
1612         QVERIFY(file.open(stdFile, QFile::ReadOnly));
1613         QCOMPARE(file.pos(), qlonglong(1));
1614         QCOMPARE(file.read(&c, 1), qlonglong(1));
1615         QCOMPARE(c, 'b');
1616         QCOMPARE(file.pos(), qlonglong(2));
1617     }
1618
1619     fclose(stdFile);
1620 }
1621
1622 void tst_QFile::isSequential()
1623 {
1624 #ifndef Q_OS_UNIX
1625     QSKIP("Unix only test.");
1626 #endif
1627     QFile zero("/dev/null");
1628     QVERIFY(zero.open(QFile::ReadOnly));
1629     QVERIFY(zero.isSequential());
1630 }
1631
1632 void tst_QFile::encodeName()
1633 {
1634     QCOMPARE(QFile::encodeName(QString::null), QByteArray());
1635 }
1636
1637 void tst_QFile::truncate()
1638 {
1639     for (int i = 0; i < 2; ++i) {
1640         QFile file("truncate.txt");
1641         QVERIFY(file.open(QFile::WriteOnly));
1642         file.write(QByteArray(200, '@'));
1643         file.close();
1644
1645         QVERIFY(file.open((i ? QFile::WriteOnly : QFile::ReadWrite) | QFile::Truncate));
1646         file.write(QByteArray(100, '$'));
1647         file.close();
1648
1649         QVERIFY(file.open(QFile::ReadOnly));
1650         QCOMPARE(file.readAll(), QByteArray(100, '$'));
1651     }
1652 }
1653
1654 void tst_QFile::seekToPos()
1655 {
1656     {
1657         QFile file("seekToPos.txt");
1658         QVERIFY(file.open(QFile::WriteOnly));
1659         file.write("a\r\nb\r\nc\r\n");
1660         file.flush();
1661     }
1662
1663     QFile file("seekToPos.txt");
1664     QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1665     file.seek(1);
1666     char c;
1667     QVERIFY(file.getChar(&c));
1668     QCOMPARE(c, '\n');
1669
1670     QCOMPARE(file.pos(), qint64(3));
1671     file.seek(file.pos());
1672     QCOMPARE(file.pos(), qint64(3));
1673
1674     file.seek(1);
1675     file.seek(file.pos());
1676     QCOMPARE(file.pos(), qint64(1));
1677
1678 }
1679
1680 void tst_QFile::seekAfterEndOfFile()
1681 {
1682     QLatin1String filename("seekAfterEof.dat");
1683     QFile::remove(filename);
1684     {
1685         QFile file(filename);
1686         QVERIFY(file.open(QFile::WriteOnly));
1687         file.write("abcd");
1688         QCOMPARE(file.size(), qint64(4));
1689         file.seek(8);
1690         file.write("ijkl");
1691         QCOMPARE(file.size(), qint64(12));
1692         file.seek(4);
1693         file.write("efgh");
1694         QCOMPARE(file.size(), qint64(12));
1695         file.seek(16);
1696         file.write("----");
1697         QCOMPARE(file.size(), qint64(20));
1698         file.flush();
1699     }
1700
1701     QFile file(filename);
1702     QVERIFY(file.open(QFile::ReadOnly));
1703     QByteArray contents = file.readAll();
1704     QCOMPARE(contents.left(12), QByteArray("abcdefghijkl", 12));
1705     //bytes 12-15 are uninitialised so we don't care what they read as.
1706     QCOMPARE(contents.mid(16), QByteArray("----", 4));
1707     file.close();
1708     QFile::remove(filename);
1709 }
1710
1711 void tst_QFile::FILEReadWrite()
1712 {
1713     // Tests modifying a file. First creates it then reads in 4 bytes and then overwrites these
1714     // 4 bytes with new values. At the end check to see the file contains the new values.
1715
1716     QFile::remove("FILEReadWrite.txt");
1717
1718     // create test file
1719     {
1720         QFile f("FILEReadWrite.txt");
1721         QVERIFY(f.open(QFile::WriteOnly));
1722         QDataStream ds(&f);
1723         qint8 c = 0;
1724         ds << c;
1725         c = 1;
1726         ds << c;
1727         c = 2;
1728         ds << c;
1729         c = 3;
1730         ds << c;
1731         c = 4;
1732         ds << c;
1733         c = 5;
1734         ds << c;
1735         c = 6;
1736         ds << c;
1737         c = 7;
1738         ds << c;
1739         c = 8;
1740         ds << c;
1741         c = 9;
1742         ds << c;
1743         c = 10;
1744         ds << c;
1745         c = 11;
1746         ds << c;
1747         f.close();
1748     }
1749
1750 #ifdef Q_OS_WINCE
1751     FILE *fp = fopen(qPrintable(QCoreApplication::applicationDirPath() + "\\FILEReadWrite.txt"), "r+b");
1752 #else
1753     FILE *fp = fopen("FILEReadWrite.txt", "r+b");
1754 #endif
1755     QVERIFY(fp);
1756     QFile file;
1757     QVERIFY(file.open(fp, QFile::ReadWrite));
1758     QDataStream sfile(&file) ;
1759
1760     qint8 var1,var2,var3,var4;
1761     while (!sfile.atEnd())
1762     {
1763         qint64 base = file.pos();
1764
1765         QCOMPARE(file.pos(), base + 0);
1766         sfile >> var1;
1767         QCOMPARE(file.pos(), base + 1);
1768         file.flush(); // flushing should not change the base
1769         QCOMPARE(file.pos(), base + 1);
1770         sfile >> var2;
1771         QCOMPARE(file.pos(), base + 2);
1772         sfile >> var3;
1773         QCOMPARE(file.pos(), base + 3);
1774         sfile >> var4;
1775         QCOMPARE(file.pos(), base + 4);
1776         file.seek(file.pos() - 4) ;   // Move it back 4, for we are going to write new values based on old ones
1777         QCOMPARE(file.pos(), base + 0);
1778         sfile << qint8(var1 + 5);
1779         QCOMPARE(file.pos(), base + 1);
1780         sfile << qint8(var2 + 5);
1781         QCOMPARE(file.pos(), base + 2);
1782         sfile << qint8(var3 + 5);
1783         QCOMPARE(file.pos(), base + 3);
1784         sfile << qint8(var4 + 5);
1785         QCOMPARE(file.pos(), base + 4);
1786
1787     }
1788     file.close();
1789     fclose(fp);
1790
1791     // check modified file
1792     {
1793         QFile f("FILEReadWrite.txt");
1794         QVERIFY(f.open(QFile::ReadOnly));
1795         QDataStream ds(&f);
1796         qint8 c = 0;
1797         ds >> c;
1798         QCOMPARE(c, (qint8)5);
1799         ds >> c;
1800         QCOMPARE(c, (qint8)6);
1801         ds >> c;
1802         QCOMPARE(c, (qint8)7);
1803         ds >> c;
1804         QCOMPARE(c, (qint8)8);
1805         ds >> c;
1806         QCOMPARE(c, (qint8)9);
1807         ds >> c;
1808         QCOMPARE(c, (qint8)10);
1809         ds >> c;
1810         QCOMPARE(c, (qint8)11);
1811         ds >> c;
1812         QCOMPARE(c, (qint8)12);
1813         ds >> c;
1814         QCOMPARE(c, (qint8)13);
1815         ds >> c;
1816         QCOMPARE(c, (qint8)14);
1817         ds >> c;
1818         QCOMPARE(c, (qint8)15);
1819         ds >> c;
1820         QCOMPARE(c, (qint8)16);
1821         f.close();
1822     }
1823
1824     QFile::remove("FILEReadWrite.txt");
1825 }
1826
1827
1828 /*
1829 #include <qglobal.h>
1830 #define BUFFSIZE 1
1831 #define FILESIZE   0x10000000f
1832 void tst_QFile::largeFileSupport()
1833 {
1834 #ifdef Q_OS_SOLARIS
1835     QSKIP("Solaris does not support statfs");
1836 #else
1837     qlonglong sizeNeeded = 2147483647;
1838     sizeNeeded *= 2;
1839     sizeNeeded += 1024;
1840     qlonglong freespace = qlonglong(0);
1841 #ifdef Q_OS_WIN
1842     _ULARGE_INTEGER free;
1843     if (::GetDiskFreeSpaceEx((wchar_t*)QDir::currentPath().utf16(), &free, 0, 0))
1844         freespace = free.QuadPart;
1845     if (freespace != 0) {
1846 #elif defined(Q_OS_IRIX)
1847     struct statfs info;
1848     if (statfs(QDir::currentPath().local8Bit(), &info, sizeof(struct statfs), 0) == 0) {
1849         freespace = qlonglong(info.f_bfree * info.f_bsize);
1850 #else
1851     struct statfs info;
1852     if (statfs(const_cast<char *>(QDir::currentPath().toLocal8Bit().constData()), &info) == 0) {
1853         freespace = qlonglong(info.f_bavail * info.f_bsize);
1854 #endif
1855         if (freespace > sizeNeeded) {
1856             QFile bigFile("bigfile");
1857             if (bigFile.open(QFile::ReadWrite)) {
1858                 char c[BUFFSIZE] = {'a'};
1859                 QVERIFY(bigFile.write(c, BUFFSIZE) == BUFFSIZE);
1860                 qlonglong oldPos = bigFile.pos();
1861                 QVERIFY(bigFile.resize(sizeNeeded));
1862                 QCOMPARE(oldPos, bigFile.pos());
1863                 QVERIFY(bigFile.seek(sizeNeeded - BUFFSIZE));
1864                 QVERIFY(bigFile.write(c, BUFFSIZE) == BUFFSIZE);
1865
1866                 bigFile.close();
1867                 if (bigFile.open(QFile::ReadOnly)) {
1868                     QVERIFY(bigFile.read(c, BUFFSIZE) == BUFFSIZE);
1869                     int i = 0;
1870                     for (i=0; i<BUFFSIZE; i++)
1871                         QCOMPARE(c[i], 'a');
1872                     QVERIFY(bigFile.seek(sizeNeeded - BUFFSIZE));
1873                     QVERIFY(bigFile.read(c, BUFFSIZE) == BUFFSIZE);
1874                     for (i=0; i<BUFFSIZE; i++)
1875                         QCOMPARE(c[i], 'a');
1876                     bigFile.close();
1877                     QVERIFY(bigFile.remove());
1878                 } else {
1879                     QVERIFY(bigFile.remove());
1880                     QFAIL("Could not reopen file");
1881                 }
1882             } else {
1883                 QFAIL("Could not open file");
1884             }
1885         } else {
1886             QSKIP("Not enough space to run test");
1887         }
1888     } else {
1889         QFAIL("Could not determin disk space");
1890     }
1891 #endif
1892 }
1893 */
1894
1895 void tst_QFile::i18nFileName_data()
1896 {
1897     QTest::addColumn<QString>("fileName");
1898
1899     QTest::newRow( "01" ) << QString::fromUtf8("xxxxxxx.txt");
1900 }
1901
1902 void tst_QFile::i18nFileName()
1903 {
1904      QFETCH(QString, fileName);
1905      if (QFile::exists(fileName)) {
1906          QVERIFY(QFile::remove(fileName));
1907      }
1908      {
1909         QFile file(fileName);
1910         QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
1911         QTextStream ts(&file);
1912         ts.setCodec("UTF-8");
1913         ts << fileName << endl;
1914      }
1915      {
1916         QFile file(fileName);
1917         QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1918         QTextStream ts(&file);
1919         ts.setCodec("UTF-8");
1920         QString line = ts.readLine();
1921         QCOMPARE(line, fileName);
1922      }
1923      QVERIFY(QFile::remove(fileName));
1924 }
1925
1926
1927 void tst_QFile::longFileName_data()
1928 {
1929     QTest::addColumn<QString>("fileName");
1930
1931     QTest::newRow( "16 chars" ) << QString::fromLatin1("longFileName.txt");
1932     QTest::newRow( "52 chars" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName.txt");
1933     QTest::newRow( "148 chars" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1934                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1935                                                      "longFileNamelongFileNamelongFileNamelongFileName.txt");
1936     QTest::newRow( "244 chars" ) << QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1937                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1938                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1939                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1940                                                      "longFileNamelongFileNamelongFileNamelongFileName.txt");
1941     QTest::newRow( "244 chars to absolutepath" ) << QFileInfo(QString::fromLatin1("longFileNamelongFileNamelongFileNamelongFileName"
1942                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1943                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1944                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1945                                                      "longFileNamelongFileNamelongFileNamelongFileName.txt")).absoluteFilePath();
1946   /* needs to be put on a windows 2000 > test machine
1947   QTest::newRow( "244 chars on UNC" ) <<  QString::fromLatin1("//arsia/D/troll/tmp/longFileNamelongFileNamelongFileNamelongFileName"
1948                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1949                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1950                                                      "longFileNamelongFileNamelongFileNamelongFileName"
1951                                                      "longFileNamelongFileNamelongFileNamelongFileName.txt");*/
1952 }
1953
1954 void tst_QFile::longFileName()
1955 {
1956     QFETCH(QString, fileName);
1957     if (QFile::exists(fileName)) {
1958         QVERIFY(QFile::remove(fileName));
1959     }
1960     {
1961         QFile file(fileName);
1962 #if defined(Q_OS_WINCE)
1963         QEXPECT_FAIL("244 chars", "Full pathname must be less than 260 chars", Abort);
1964         QEXPECT_FAIL("244 chars to absolutepath", "Full pathname must be less than 260 chars", Abort);
1965 #endif
1966         QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
1967         QTextStream ts(&file);
1968         ts << fileName << endl;
1969     }
1970     {
1971         QFile file(fileName);
1972         QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1973         QTextStream ts(&file);
1974         QString line = ts.readLine();
1975         QCOMPARE(line, fileName);
1976     }
1977     QString newName = fileName + QLatin1String("1");
1978     {
1979         QVERIFY(QFile::copy(fileName, newName));
1980         QFile file(newName);
1981         QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1982         QTextStream ts(&file);
1983         QString line = ts.readLine();
1984         QCOMPARE(line, fileName);
1985
1986     }
1987     QVERIFY(QFile::remove(newName));
1988     {
1989         QVERIFY(QFile::rename(fileName, newName));
1990         QFile file(newName);
1991         QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
1992         QTextStream ts(&file);
1993         QString line = ts.readLine();
1994         QCOMPARE(line, fileName);
1995     }
1996     QVERIFY(QFile::exists(newName));
1997     QVERIFY(QFile::remove(newName));
1998 }
1999
2000 #ifdef QT_BUILD_INTERNAL
2001 class MyEngine : public QAbstractFileEngine
2002 {
2003 public:
2004     MyEngine(int n) { number = n; }
2005     virtual ~MyEngine() {}
2006
2007     void setFileName(const QString &) {}
2008     bool open(QIODevice::OpenMode) { return false; }
2009     bool close() { return false; }
2010     bool flush() { return false; }
2011     qint64 size() const { return 123 + number; }
2012     qint64 at() const { return -1; }
2013     bool seek(qint64) { return false; }
2014     bool isSequential() const { return false; }
2015     qint64 read(char *, qint64) { return -1; }
2016     qint64 write(const char *, qint64) { return -1; }
2017     bool remove() { return false; }
2018     bool copy(const QString &) { return false; }
2019     bool rename(const QString &) { return false; }
2020     bool link(const QString &) { return false; }
2021     bool mkdir(const QString &, bool) const { return false; }
2022     bool rmdir(const QString &, bool) const { return false; }
2023     bool setSize(qint64) { return false; }
2024     QStringList entryList(QDir::Filters, const QStringList &) const { return QStringList(); }
2025     bool caseSensitive() const { return false; }
2026     bool isRelativePath() const { return false; }
2027     FileFlags fileFlags(FileFlags) const { return 0; }
2028     bool chmod(uint) { return false; }
2029     QString fileName(FileName) const { return name; }
2030     uint ownerId(FileOwner) const { return 0; }
2031     QString owner(FileOwner) const { return QString(); }
2032     QDateTime fileTime(FileTime) const { return QDateTime(); }
2033
2034 private:
2035     int number;
2036     QString name;
2037 };
2038
2039 class MyHandler : public QAbstractFileEngineHandler
2040 {
2041 public:
2042     inline QAbstractFileEngine *create(const QString &) const
2043     {
2044         return new MyEngine(1);
2045     }
2046 };
2047
2048 class MyHandler2 : public QAbstractFileEngineHandler
2049 {
2050 public:
2051     inline QAbstractFileEngine *create(const QString &) const
2052     {
2053         return new MyEngine(2);
2054     }
2055 };
2056 #endif
2057
2058 void tst_QFile::fileEngineHandler()
2059 {
2060     // A file that does not exist has a size of 0.
2061     QFile::remove("ole.bull");
2062     QFile file("ole.bull");
2063     QCOMPARE(file.size(), qint64(0));
2064
2065 #ifdef QT_BUILD_INTERNAL
2066     // Instantiating our handler will enable the new engine.
2067     MyHandler handler;
2068     file.setFileName("ole.bull");
2069     QCOMPARE(file.size(), qint64(124));
2070
2071     // A new, identical handler should take preference over the last one.
2072     MyHandler2 handler2;
2073     file.setFileName("ole.bull");
2074     QCOMPARE(file.size(), qint64(125));
2075 #endif
2076 }
2077
2078 #ifdef QT_BUILD_INTERNAL
2079 class MyRecursiveHandler : public QAbstractFileEngineHandler
2080 {
2081 public:
2082     inline QAbstractFileEngine *create(const QString &fileName) const
2083     {
2084         if (fileName.startsWith(":!")) {
2085             QDir dir;
2086             QString realFile = QFINDTESTDATA(fileName.mid(2));
2087             if (dir.exists(realFile))
2088                 return new QFSFileEngine(realFile);
2089         }
2090         return 0;
2091     }
2092 };
2093 #endif
2094
2095 #ifdef QT_BUILD_INTERNAL
2096 void tst_QFile::useQFileInAFileHandler()
2097 {
2098     // This test should not dead-lock
2099     MyRecursiveHandler handler;
2100     QFile file(":!tst_qfile.cpp");
2101     QVERIFY(file.exists());
2102 }
2103 #endif
2104
2105 void tst_QFile::getCharFF()
2106 {
2107     QFile file("file.txt");
2108     file.open(QFile::ReadWrite);
2109     file.write("\xff\xff\xff");
2110     file.flush();
2111     file.seek(0);
2112
2113     char c;
2114     QVERIFY(file.getChar(&c));
2115     QVERIFY(file.getChar(&c));
2116     QVERIFY(file.getChar(&c));
2117 }
2118
2119 void tst_QFile::remove_and_exists()
2120 {
2121     QFile::remove("tull_i_grunn.txt");
2122     QFile f("tull_i_grunn.txt");
2123
2124     QVERIFY(!f.exists());
2125
2126     bool opened = f.open(QIODevice::WriteOnly);
2127     QVERIFY(opened);
2128
2129     f.write(QString("testing that remove/exists work...").toLatin1());
2130     f.close();
2131
2132     QVERIFY(f.exists());
2133
2134     f.remove();
2135     QVERIFY(!f.exists());
2136 }
2137
2138 void tst_QFile::removeOpenFile()
2139 {
2140     {
2141         // remove an opened, write-only file
2142         QFile::remove("remove_unclosed.txt");
2143         QFile f("remove_unclosed.txt");
2144
2145         QVERIFY(!f.exists());
2146         bool opened = f.open(QIODevice::WriteOnly);
2147         QVERIFY(opened);
2148         f.write(QString("testing that remove closes the file first...").toLatin1());
2149
2150         bool removed = f.remove(); // remove should both close and remove the file
2151         QVERIFY(removed);
2152         QVERIFY(!f.isOpen());
2153         QVERIFY(!f.exists());
2154         QVERIFY(f.error() == QFile::NoError);
2155     }
2156
2157     {
2158         // remove an opened, read-only file
2159         QFile::remove("remove_unclosed.txt");
2160
2161         // first, write a file that we can remove
2162         {
2163             QFile f("remove_unclosed.txt");
2164             QVERIFY(!f.exists());
2165             bool opened = f.open(QIODevice::WriteOnly);
2166             QVERIFY(opened);
2167             f.write(QString("testing that remove closes the file first...").toLatin1());
2168             f.close();
2169         }
2170
2171         QFile f("remove_unclosed.txt");
2172         bool opened = f.open(QIODevice::ReadOnly);
2173         QVERIFY(opened);
2174         f.readAll();
2175         // this used to only fail on FreeBSD (and Mac OS X)
2176         QVERIFY(f.flush());
2177         bool removed = f.remove(); // remove should both close and remove the file
2178         QVERIFY(removed);
2179         QVERIFY(!f.isOpen());
2180         QVERIFY(!f.exists());
2181         QVERIFY(f.error() == QFile::NoError);
2182     }
2183 }
2184
2185 void tst_QFile::fullDisk()
2186 {
2187     QFile file("/dev/full");
2188     if (!file.exists())
2189         QSKIP("/dev/full doesn't exist on this system");
2190
2191     QVERIFY(file.open(QIODevice::WriteOnly));
2192     file.write("foobar", 6);
2193
2194     QVERIFY(!file.flush());
2195     QCOMPARE(file.error(), QFile::ResourceError);
2196     QVERIFY(!file.flush());
2197     QCOMPARE(file.error(), QFile::ResourceError);
2198
2199     char c = 0;
2200     file.write(&c, 0);
2201     QVERIFY(!file.flush());
2202     QCOMPARE(file.error(), QFile::ResourceError);
2203     QCOMPARE(file.write(&c, 1), qint64(1));
2204     QVERIFY(!file.flush());
2205     QCOMPARE(file.error(), QFile::ResourceError);
2206
2207     file.close();
2208     QVERIFY(!file.isOpen());
2209     QCOMPARE(file.error(), QFile::ResourceError);
2210
2211     file.open(QIODevice::WriteOnly);
2212     QCOMPARE(file.error(), QFile::NoError);
2213     QVERIFY(file.flush()); // Shouldn't inherit write buffer
2214     file.close();
2215     QCOMPARE(file.error(), QFile::NoError);
2216
2217     // try again without flush:
2218     QVERIFY(file.open(QIODevice::WriteOnly));
2219     file.write("foobar", 6);
2220     file.close();
2221     QVERIFY(file.error() != QFile::NoError);
2222 }
2223
2224 void tst_QFile::writeLargeDataBlock_data()
2225 {
2226     QTest::addColumn<QString>("fileName");
2227     QTest::addColumn<int>("type");
2228
2229     QTest::newRow("localfile-QFile")  << "./largeblockfile.txt" << (int)OpenQFile;
2230     QTest::newRow("localfile-Fd")     << "./largeblockfile.txt" << (int)OpenFd;
2231     QTest::newRow("localfile-Stream") << "./largeblockfile.txt" << (int)OpenStream;
2232
2233 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
2234     // Some semi-randomness to avoid collisions.
2235     QTest::newRow("unc file")
2236         << QString("//" + QtNetworkSettings::winServerName() + "/TESTSHAREWRITABLE/largefile-%1-%2.txt")
2237         .arg(QHostInfo::localHostName())
2238         .arg(QTime::currentTime().msec()) << (int)OpenQFile;
2239 #endif
2240 }
2241
2242 static QByteArray getLargeDataBlock()
2243 {
2244     static QByteArray array;
2245
2246     if (array.isNull())
2247     {
2248 #if defined(Q_OS_WINCE)
2249         int resizeSize = 1024 * 1024; // WinCE does not have much space
2250 #else
2251         int resizeSize = 64 * 1024 * 1024;
2252 #endif
2253         array.resize(resizeSize);
2254         for (int i = 0; i < array.size(); ++i)
2255             array[i] = uchar(i);
2256     }
2257
2258     return array;
2259 }
2260
2261 void tst_QFile::writeLargeDataBlock()
2262 {
2263     QFETCH(QString, fileName);
2264     QFETCH( int, type );
2265
2266     QByteArray const originalData = getLargeDataBlock();
2267
2268     {
2269         QFile file(fileName);
2270
2271         QVERIFY2( openFile(file, QIODevice::WriteOnly, (FileType)type),
2272             qPrintable(QString("Couldn't open file for writing: [%1]").arg(fileName)) );
2273         qint64 fileWriteOriginalData = file.write(originalData);
2274         qint64 originalDataSize      = (qint64)originalData.size();
2275 #if defined(Q_OS_WIN)
2276         if (fileWriteOriginalData != originalDataSize) {
2277             qWarning() << qPrintable(QString("Error writing a large data block to [%1]: %2")
2278                 .arg(fileName)
2279                 .arg(file.errorString()));
2280             QEXPECT_FAIL("unc file", "QTBUG-26906 writing", Abort);
2281         }
2282 #endif
2283         QCOMPARE( fileWriteOriginalData, originalDataSize );
2284         QVERIFY( file.flush() );
2285
2286         closeFile(file);
2287     }
2288
2289     QByteArray readData;
2290
2291     {
2292         QFile file(fileName);
2293
2294         QVERIFY2( openFile(file, QIODevice::ReadOnly, (FileType)type),
2295             qPrintable(QString("Couldn't open file for reading: [%1]").arg(fileName)) );
2296         readData = file.readAll();
2297
2298 #if defined(Q_OS_WIN)
2299         if (readData != originalData) {
2300             qWarning() << qPrintable(QString("Error reading a large data block from [%1]: %2")
2301                 .arg(fileName)
2302                 .arg(file.errorString()));
2303             QEXPECT_FAIL("unc file", "QTBUG-26906 reading", Abort);
2304         }
2305 #endif
2306         closeFile(file);
2307     }
2308     QCOMPARE( readData, originalData );
2309     QVERIFY( QFile::remove(fileName) );
2310 }
2311
2312 void tst_QFile::readFromWriteOnlyFile()
2313 {
2314     QFile file("writeonlyfile");
2315     QVERIFY(file.open(QFile::WriteOnly));
2316     char c;
2317     QTest::ignoreMessage(QtWarningMsg, "QIODevice::read: WriteOnly device");
2318     QCOMPARE(file.read(&c, 1), qint64(-1));
2319 }
2320
2321 void tst_QFile::writeToReadOnlyFile()
2322 {
2323     QFile file("readonlyfile");
2324     QVERIFY(file.open(QFile::ReadOnly));
2325     char c = 0;
2326     QTest::ignoreMessage(QtWarningMsg, "QIODevice::write: ReadOnly device");
2327     QCOMPARE(file.write(&c, 1), qint64(-1));
2328 }
2329
2330 void tst_QFile::virtualFile()
2331 {
2332     // test if QFile works with virtual files
2333     QString fname;
2334 #if defined(Q_OS_LINUX)
2335     fname = "/proc/self/maps";
2336 #elif defined(Q_OS_AIX)
2337     fname = QString("/proc/%1/map").arg(getpid());
2338 #elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)
2339     fname = "/proc/curproc/map";
2340 #else
2341     QSKIP("This platform does not have 0-sized virtual files");
2342 #endif
2343
2344     // consistency check
2345     QFileInfo fi(fname);
2346     QVERIFY(fi.exists());
2347     QVERIFY(fi.isFile());
2348     QCOMPARE(fi.size(), Q_INT64_C(0));
2349
2350     // open the file
2351     QFile f(fname);
2352     QVERIFY(f.open(QIODevice::ReadOnly));
2353     QCOMPARE(f.size(), Q_INT64_C(0));
2354     QVERIFY(f.atEnd());
2355
2356     // read data
2357     QByteArray data = f.read(16);
2358     QCOMPARE(data.size(), 16);
2359     QCOMPARE(f.pos(), Q_INT64_C(16));
2360
2361     // line-reading
2362     data = f.readLine();
2363     QVERIFY(!data.isEmpty());
2364
2365     // read all:
2366     data = f.readAll();
2367     QVERIFY(f.pos() != 0);
2368     QVERIFY(!data.isEmpty());
2369
2370     // seeking
2371     QVERIFY(f.seek(1));
2372     QCOMPARE(f.pos(), Q_INT64_C(1));
2373 }
2374
2375 void tst_QFile::textFile()
2376 {
2377 #if defined(Q_OS_WINCE)
2378     FILE *fs = ::fopen((QCoreApplication::applicationDirPath() + "/writeabletextfile").toLatin1() , "wt");
2379 #elif defined(Q_OS_WIN)
2380     FILE *fs = ::fopen("writeabletextfile", "wt");
2381 #else
2382     FILE *fs = ::fopen("writeabletextfile", "w");
2383 #endif
2384     QFile f;
2385     QByteArray part1("This\nis\na\nfile\nwith\nnewlines\n");
2386     QByteArray part2("Add\nsome\nmore\nnewlines\n");
2387
2388     QVERIFY(f.open(fs, QIODevice::WriteOnly));
2389     f.write(part1);
2390     f.write(part2);
2391     f.close();
2392     ::fclose(fs);
2393
2394     QFile file("writeabletextfile");
2395     QVERIFY(file.open(QIODevice::ReadOnly));
2396
2397     QByteArray data = file.readAll();
2398
2399     QByteArray expected = part1 + part2;
2400 #ifdef Q_OS_WIN
2401     expected.replace("\n", "\015\012");
2402 #endif
2403     QCOMPARE(data, expected);
2404     file.close();
2405     file.remove();
2406 }
2407
2408 void tst_QFile::rename_data()
2409 {
2410     QTest::addColumn<QString>("source");
2411     QTest::addColumn<QString>("destination");
2412     QTest::addColumn<bool>("result");
2413
2414     QTest::newRow("a -> b") << QString("a") << QString("b") << false;
2415     QTest::newRow("a -> .") << QString("a") << QString(".") << false;
2416     QTest::newRow("renamefile -> renamefile") << QString("renamefile") << QString("renamefile") << false;
2417     QTest::newRow("renamefile -> noreadfile") << QString("renamefile") << QString("noreadfile") << false;
2418 #if defined(Q_OS_UNIX)
2419     QTest::newRow("renamefile -> /etc/renamefile") << QString("renamefile") << QString("/etc/renamefile") << false;
2420 #endif
2421     QTest::newRow("renamefile -> renamedfile") << QString("renamefile") << QString("renamedfile") << true;
2422     QTest::newRow("renamefile -> ..") << QString("renamefile") << QString("..") << false;
2423 }
2424
2425 void tst_QFile::rename()
2426 {
2427     QFETCH(QString, source);
2428     QFETCH(QString, destination);
2429     QFETCH(bool, result);
2430
2431 #if defined(Q_OS_UNIX)
2432     if (strcmp(QTest::currentDataTag(), "renamefile -> /etc/renamefile") == 0) {
2433         if (::getuid() == 0)
2434             QSKIP("Running this test as root doesn't make sense");
2435     }
2436 #endif
2437
2438     QFile::remove("renamedfile");
2439     QFile f("renamefile");
2440     f.open(QFile::WriteOnly);
2441     f.close();
2442
2443     QFile file(source);
2444     QCOMPARE(file.rename(destination), result);
2445
2446     if (result)
2447         QCOMPARE(file.error(), QFile::NoError);
2448     else
2449         QCOMPARE(file.error(), QFile::RenameError);
2450
2451     QFile::remove("renamefile");
2452 }
2453
2454 /*!
2455  \since 4.5
2456
2457  Some special files have QFile::atEnd() returning true, even though there is
2458  more data available. True for corner cases, as well as some mounts on OS X.
2459
2460  Here, we reproduce that condition by having a QFile sub-class with this
2461  peculiar atEnd() behavior.
2462 */
2463 void tst_QFile::renameWithAtEndSpecialFile() const
2464 {
2465     class PeculiarAtEnd : public QFile
2466     {
2467     public:
2468         virtual bool atEnd() const
2469         {
2470             return true;
2471         }
2472     };
2473
2474     const QString newName(QLatin1String("newName.txt"));
2475     /* Cleanup, so we're a bit more robust. */
2476     QFile::remove(newName);
2477
2478     const QString originalName(QString(QFINDTESTDATA("forRenaming.txt")));
2479
2480     PeculiarAtEnd file;
2481     file.setFileName(originalName);
2482     QVERIFY(file.open(QIODevice::ReadOnly));
2483
2484     QVERIFY(file.rename(newName));
2485
2486     file.close();
2487     /* Guess what, we have to rename it back, otherwise we'll fail on second
2488      * invocation. */
2489     QVERIFY(QFile::rename(newName, originalName));
2490 }
2491
2492 void tst_QFile::renameFallback()
2493 {
2494     // Using a resource file both to trigger QFile::rename's fallback handling
2495     // and as a *read-only* source whose move should fail.
2496     QFile file(":/rename-fallback.qrc");
2497     QVERIFY(file.exists() && "(test-precondition)");
2498     QFile::remove("file-rename-destination.txt");
2499
2500     QVERIFY(!file.rename("file-rename-destination.txt"));
2501     QVERIFY(!QFile::exists("file-rename-destination.txt"));
2502     QVERIFY(!file.isOpen());
2503 }
2504
2505 void tst_QFile::renameMultiple()
2506 {
2507     // create the file if it doesn't exist
2508     QFile file("file-to-be-renamed.txt");
2509     QFile file2("existing-file.txt");
2510     QVERIFY(file.open(QIODevice::ReadWrite) && "(test-precondition)");
2511     QVERIFY(file2.open(QIODevice::ReadWrite) && "(test-precondition)");
2512
2513     // any stale files from previous test failures?
2514     QFile::remove("file-renamed-once.txt");
2515     QFile::remove("file-renamed-twice.txt");
2516
2517     // begin testing
2518     QVERIFY(QFile::exists("existing-file.txt"));
2519     QVERIFY(!file.rename("existing-file.txt"));
2520     QCOMPARE(file.error(), QFile::RenameError);
2521     QCOMPARE(file.fileName(), QString("file-to-be-renamed.txt"));
2522
2523     QVERIFY(file.rename("file-renamed-once.txt"));
2524     QVERIFY(!file.isOpen());
2525     QCOMPARE(file.fileName(), QString("file-renamed-once.txt"));
2526
2527     QVERIFY(QFile::exists("existing-file.txt"));
2528     QVERIFY(!file.rename("existing-file.txt"));
2529     QCOMPARE(file.error(), QFile::RenameError);
2530     QCOMPARE(file.fileName(), QString("file-renamed-once.txt"));
2531
2532     QVERIFY(file.rename("file-renamed-twice.txt"));
2533     QVERIFY(!file.isOpen());
2534     QCOMPARE(file.fileName(), QString("file-renamed-twice.txt"));
2535
2536     QVERIFY(QFile::exists("existing-file.txt"));
2537     QVERIFY(!QFile::exists("file-to-be-renamed.txt"));
2538     QVERIFY(!QFile::exists("file-renamed-once.txt"));
2539     QVERIFY(QFile::exists("file-renamed-twice.txt"));
2540
2541     file.remove();
2542     file2.remove();
2543     QVERIFY(!QFile::exists("file-renamed-twice.txt"));
2544     QVERIFY(!QFile::exists("existing-file.txt"));
2545 }
2546
2547 void tst_QFile::appendAndRead()
2548 {
2549     QFile writeFile(QLatin1String("appendfile.txt"));
2550     QVERIFY(writeFile.open(QIODevice::WriteOnly | QIODevice::Truncate));
2551
2552     QFile readFile(QLatin1String("appendfile.txt"));
2553     QVERIFY(readFile.open(QIODevice::ReadOnly));
2554
2555     // Write to the end of the file, then read that character back, and so on.
2556     for (int i = 0; i < 100; ++i) {
2557         char c = '\0';
2558         writeFile.putChar(char(i % 256));
2559         writeFile.flush();
2560         QVERIFY(readFile.getChar(&c));
2561         QCOMPARE(c, char(i % 256));
2562         QCOMPARE(readFile.pos(), writeFile.pos());
2563     }
2564
2565     // Write blocks and read them back
2566     for (int j = 0; j < 18; ++j) {
2567         writeFile.write(QByteArray(1 << j, '@'));
2568         writeFile.flush();
2569         QCOMPARE(readFile.read(1 << j).size(), 1 << j);
2570     }
2571
2572     readFile.close();
2573     QFile::remove(QLatin1String("appendfile.txt"));
2574 }
2575
2576 void tst_QFile::miscWithUncPathAsCurrentDir()
2577 {
2578 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
2579     QString current = QDir::currentPath();
2580     QVERIFY(QDir::setCurrent("//" + QtNetworkSettings::winServerName() + "/testshare"));
2581     QFile file("test.pri");
2582     QVERIFY(file.exists());
2583     QCOMPARE(int(file.size()), 34);
2584     QVERIFY(file.open(QIODevice::ReadOnly));
2585     QVERIFY(QDir::setCurrent(current));
2586 #endif
2587 }
2588
2589 void tst_QFile::standarderror()
2590 {
2591     QFile f;
2592     bool ok = f.open(stderr, QFile::WriteOnly);
2593     QVERIFY(ok);
2594     f.close();
2595 }
2596
2597 void tst_QFile::handle()
2598 {
2599     int fd;
2600 #if !defined(Q_OS_WINCE)
2601     QFile file(QFINDTESTDATA("tst_qfile.cpp"));
2602     QVERIFY(file.open(QIODevice::ReadOnly));
2603     fd = int(file.handle());
2604     QVERIFY(fd > 2);
2605     QCOMPARE(int(file.handle()), fd);
2606     char c = '\0';
2607     QT_READ(int(file.handle()), &c, 1);
2608     QCOMPARE(c, '/');
2609
2610     // test if the QFile and the handle remain in sync
2611     QVERIFY(file.getChar(&c));
2612     QCOMPARE(c, '*');
2613
2614     // same, but read from QFile first now
2615     file.close();
2616     QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Unbuffered));
2617     fd = int(file.handle());
2618     QVERIFY(fd > 2);
2619     QVERIFY(file.getChar(&c));
2620     QCOMPARE(c, '/');
2621 #ifdef Q_OS_UNIX
2622     QCOMPARE(QT_READ(fd, &c, 1), ssize_t(1));
2623 #else
2624     QCOMPARE(QT_READ(fd, &c, 1), 1);
2625 #endif
2626
2627     QCOMPARE(c, '*');
2628 #endif
2629
2630     //test round trip of adopted stdio file handle
2631     QFile file2;
2632     FILE *fp = fopen(qPrintable(QFINDTESTDATA("tst_qfile.cpp")), "r");
2633     file2.open(fp, QIODevice::ReadOnly);
2634     QCOMPARE(int(file2.handle()), int(fileno(fp)));
2635     QCOMPARE(int(file2.handle()), int(fileno(fp)));
2636     fclose(fp);
2637
2638     //test round trip of adopted posix file handle
2639 #ifdef Q_OS_UNIX
2640     QFile file3;
2641     fd = QT_OPEN(qPrintable(QFINDTESTDATA("tst_qfile.cpp")), QT_OPEN_RDONLY);
2642     file3.open(fd, QIODevice::ReadOnly);
2643     QCOMPARE(int(file3.handle()), fd);
2644     QT_CLOSE(fd);
2645 #endif
2646 }
2647
2648 void tst_QFile::nativeHandleLeaks()
2649 {
2650     int fd1, fd2;
2651
2652 #ifdef Q_OS_WIN
2653     HANDLE handle1, handle2;
2654 #endif
2655
2656     {
2657         QFile file("qt_file.tmp");
2658         QVERIFY( file.open(QIODevice::ReadWrite) );
2659
2660         fd1 = file.handle();
2661         QVERIFY( -1 != fd1 );
2662     }
2663
2664 #ifdef Q_OS_WIN
2665     handle1 = ::CreateFileA("qt_file.tmp", GENERIC_READ, 0, NULL,
2666             OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2667     QVERIFY( INVALID_HANDLE_VALUE != handle1 );
2668     QVERIFY( ::CloseHandle(handle1) );
2669 #endif
2670
2671     {
2672         QFile file("qt_file.tmp");
2673         QVERIFY( file.open(QIODevice::ReadOnly) );
2674
2675         fd2 = file.handle();
2676         QVERIFY( -1 != fd2 );
2677     }
2678
2679 #ifdef Q_OS_WIN
2680     handle2 = ::CreateFileA("qt_file.tmp", GENERIC_READ, 0, NULL,
2681             OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2682     QVERIFY( INVALID_HANDLE_VALUE != handle2 );
2683     QVERIFY( ::CloseHandle(handle2) );
2684 #endif
2685
2686     QCOMPARE( fd2, fd1 );
2687
2688 #ifdef Q_OS_WIN
2689     QCOMPARE( handle2, handle1 );
2690 #endif
2691 }
2692
2693 void tst_QFile::readEof_data()
2694 {
2695     QTest::addColumn<QString>("filename");
2696     QTest::addColumn<int>("imode");
2697
2698     QTest::newRow("buffered") << QFINDTESTDATA("testfile.txt") << 0;
2699     QTest::newRow("unbuffered") << QFINDTESTDATA("testfile.txt") << int(QIODevice::Unbuffered);
2700
2701 #if defined(Q_OS_UNIX)
2702     QTest::newRow("sequential,buffered") << "/dev/null" << 0;
2703     QTest::newRow("sequential,unbuffered") << "/dev/null" << int(QIODevice::Unbuffered);
2704 #endif
2705 }
2706
2707 void tst_QFile::readEof()
2708 {
2709     QFETCH(QString, filename);
2710     QFETCH(int, imode);
2711     QIODevice::OpenMode mode = QIODevice::OpenMode(imode);
2712
2713     {
2714         QFile file(filename);
2715         QVERIFY(file.open(QIODevice::ReadOnly | mode));
2716         bool isSequential = file.isSequential();
2717         if (!isSequential) {
2718             QVERIFY(file.seek(245));
2719             QVERIFY(file.atEnd());
2720         }
2721
2722         char buf[10];
2723         int ret = file.read(buf, sizeof buf);
2724         QCOMPARE(ret, 0);
2725         QVERIFY(file.error() == QFile::NoError);
2726         QVERIFY(file.atEnd());
2727
2728         // Do it again to ensure that we get the same result
2729         ret = file.read(buf, sizeof buf);
2730         QCOMPARE(ret, 0);
2731         QVERIFY(file.error() == QFile::NoError);
2732         QVERIFY(file.atEnd());
2733     }
2734
2735     {
2736         QFile file(filename);
2737         QVERIFY(file.open(QIODevice::ReadOnly | mode));
2738         bool isSequential = file.isSequential();
2739         if (!isSequential) {
2740             QVERIFY(file.seek(245));
2741             QVERIFY(file.atEnd());
2742         }
2743
2744         QByteArray ret = file.read(10);
2745         QVERIFY(ret.isEmpty());
2746         QVERIFY(file.error() == QFile::NoError);
2747         QVERIFY(file.atEnd());
2748
2749         // Do it again to ensure that we get the same result
2750         ret = file.read(10);
2751         QVERIFY(ret.isEmpty());
2752         QVERIFY(file.error() == QFile::NoError);
2753         QVERIFY(file.atEnd());
2754     }
2755
2756     {
2757         QFile file(filename);
2758         QVERIFY(file.open(QIODevice::ReadOnly | mode));
2759         bool isSequential = file.isSequential();
2760         if (!isSequential) {
2761             QVERIFY(file.seek(245));
2762             QVERIFY(file.atEnd());
2763         }
2764
2765         char buf[10];
2766         int ret = file.readLine(buf, sizeof buf);
2767         QCOMPARE(ret, -1);
2768         QVERIFY(file.error() == QFile::NoError);
2769         QVERIFY(file.atEnd());
2770
2771         // Do it again to ensure that we get the same result
2772         ret = file.readLine(buf, sizeof buf);
2773         QCOMPARE(ret, -1);
2774         QVERIFY(file.error() == QFile::NoError);
2775         QVERIFY(file.atEnd());
2776     }
2777
2778     {
2779         QFile file(filename);
2780         QVERIFY(file.open(QIODevice::ReadOnly | mode));
2781         bool isSequential = file.isSequential();
2782         if (!isSequential) {
2783             QVERIFY(file.seek(245));
2784             QVERIFY(file.atEnd());
2785         }
2786
2787         QByteArray ret = file.readLine();
2788         QVERIFY(ret.isNull());
2789         QVERIFY(file.error() == QFile::NoError);
2790         QVERIFY(file.atEnd());
2791
2792         // Do it again to ensure that we get the same result
2793         ret = file.readLine();
2794         QVERIFY(ret.isNull());
2795         QVERIFY(file.error() == QFile::NoError);
2796         QVERIFY(file.atEnd());
2797     }
2798
2799     {
2800         QFile file(filename);
2801         QVERIFY(file.open(QIODevice::ReadOnly | mode));
2802         bool isSequential = file.isSequential();
2803         if (!isSequential) {
2804             QVERIFY(file.seek(245));
2805             QVERIFY(file.atEnd());
2806         }
2807
2808         char c;
2809         QVERIFY(!file.getChar(&c));
2810         QVERIFY(file.error() == QFile::NoError);
2811         QVERIFY(file.atEnd());
2812
2813         // Do it again to ensure that we get the same result
2814         QVERIFY(!file.getChar(&c));
2815         QVERIFY(file.error() == QFile::NoError);
2816         QVERIFY(file.atEnd());
2817     }
2818 }
2819
2820 void tst_QFile::posAfterFailedStat()
2821 {
2822     // Regression test for a bug introduced in 4.3.0; after a failed stat,
2823     // pos() could no longer be calculated correctly.
2824     QFile::remove("tmp.txt");
2825     QFile file("tmp.txt");
2826     QVERIFY(!file.exists());
2827     QVERIFY(file.open(QIODevice::Append));
2828     QVERIFY(file.exists());
2829     file.write("qt430", 5);
2830     QVERIFY(!file.isSequential());
2831     QCOMPARE(file.pos(), qint64(5));
2832     file.remove();
2833 }
2834
2835 #define FILESIZE 65536 * 3
2836
2837 void tst_QFile::map_data()
2838 {
2839     QTest::addColumn<int>("fileSize");
2840     QTest::addColumn<int>("offset");
2841     QTest::addColumn<int>("size");
2842     QTest::addColumn<QFile::FileError>("error");
2843
2844     QTest::newRow("zero")         << FILESIZE << 0     << FILESIZE         << QFile::NoError;
2845     QTest::newRow("small, but 0") << FILESIZE << 30    << FILESIZE - 30    << QFile::NoError;
2846     QTest::newRow("a page")       << FILESIZE << 4096  << FILESIZE - 4096  << QFile::NoError;
2847     QTest::newRow("+page")        << FILESIZE << 5000  << FILESIZE - 5000  << QFile::NoError;
2848     QTest::newRow("++page")       << FILESIZE << 65576 << FILESIZE - 65576 << QFile::NoError;
2849     QTest::newRow("bad size")     << FILESIZE << 0     << -1               << QFile::ResourceError;
2850     QTest::newRow("bad offset")   << FILESIZE << -1    << 1                << QFile::UnspecifiedError;
2851     QTest::newRow("zerozero")     << FILESIZE << 0     << 0                << QFile::UnspecifiedError;
2852 }
2853
2854 void tst_QFile::map()
2855 {
2856     QFETCH(int, fileSize);
2857     QFETCH(int, offset);
2858     QFETCH(int, size);
2859     QFETCH(QFile::FileError, error);
2860
2861     QString fileName = QDir::currentPath() + '/' + "qfile_map_testfile";
2862
2863 #ifdef Q_OS_WINCE
2864      fileName = QFileInfo(fileName).absoluteFilePath();
2865 #endif
2866
2867     if (QFile::exists(fileName)) {
2868         QVERIFY(QFile::setPermissions(fileName,
2869             QFile::WriteOwner | QFile::ReadOwner | QFile::WriteUser | QFile::ReadUser));
2870         QFile::remove(fileName);
2871     }
2872     QFile file(fileName);
2873
2874     // invalid, not open
2875     uchar *memory = file.map(0, size);
2876     QVERIFY(!memory);
2877     QCOMPARE(file.error(), QFile::PermissionsError);
2878     QVERIFY(!file.unmap(memory));
2879     QCOMPARE(file.error(), QFile::PermissionsError);
2880
2881     // make a file
2882     QVERIFY(file.open(QFile::ReadWrite));
2883     QVERIFY(file.resize(fileSize));
2884     QVERIFY(file.flush());
2885     file.close();
2886     QVERIFY(file.open(QFile::ReadWrite));
2887     memory = file.map(offset, size);
2888     if (error != QFile::NoError) {
2889         QVERIFY(file.error() != QFile::NoError);
2890         return;
2891     }
2892
2893     QCOMPARE(file.error(), error);
2894     QVERIFY(memory);
2895     memory[0] = 'Q';
2896     QVERIFY(file.unmap(memory));
2897     QCOMPARE(file.error(), QFile::NoError);
2898
2899     // Verify changes were saved
2900     memory = file.map(offset, size);
2901     QCOMPARE(file.error(), QFile::NoError);
2902     QVERIFY(memory);
2903     QVERIFY(memory[0] == 'Q');
2904     QVERIFY(file.unmap(memory));
2905     QCOMPARE(file.error(), QFile::NoError);
2906
2907     // hpux wont let you map multiple times.
2908 #if !defined(Q_OS_HPUX) && !defined(Q_USE_DEPRECATED_MAP_API) && !defined(Q_OS_WINCE)
2909     // exotic test to make sure that multiple maps work
2910
2911     // note: windows ce does not reference count mutliple maps
2912     // it's essentially just the same reference but it 
2913     // cause a resource lock on the file which prevents it 
2914     // from being removed    uchar *memory1 = file.map(0, file.size());
2915     uchar *memory1 = file.map(0, file.size());
2916     QCOMPARE(file.error(), QFile::NoError);
2917     uchar *memory2 = file.map(0, file.size());
2918     QCOMPARE(file.error(), QFile::NoError);
2919     QVERIFY(memory1);
2920     QVERIFY(memory2);
2921     QVERIFY(file.unmap(memory1));
2922     QCOMPARE(file.error(), QFile::NoError);
2923     QVERIFY(file.unmap(memory2));
2924     QCOMPARE(file.error(), QFile::NoError);
2925     memory1 = file.map(0, file.size());
2926     QCOMPARE(file.error(), QFile::NoError);
2927     QVERIFY(memory1);
2928     QVERIFY(file.unmap(memory1));
2929     QCOMPARE(file.error(), QFile::NoError);
2930 #endif
2931
2932     file.close();
2933
2934 #if defined(Q_OS_UNIX)
2935     if (::getuid() != 0)
2936         // root always has permissions
2937 #endif
2938     {
2939         // Change permissions on a file, just to confirm it would fail
2940         QFile::Permissions originalPermissions = file.permissions();
2941         QVERIFY(file.setPermissions(QFile::ReadOther));
2942         QVERIFY(!file.open(QFile::ReadWrite));
2943         memory = file.map(offset, size);
2944         QCOMPARE(file.error(), QFile::PermissionsError);
2945         QVERIFY(!memory);
2946         QVERIFY(file.setPermissions(originalPermissions));
2947     }
2948     QVERIFY(file.remove());
2949 }
2950
2951 void tst_QFile::mapResource_data()
2952 {
2953     QTest::addColumn<int>("offset");
2954     QTest::addColumn<int>("size");
2955     QTest::addColumn<QFile::FileError>("error");
2956     QTest::addColumn<QString>("fileName");
2957
2958     QString validFile = ":/tst_qfileinfo/resources/file1.ext1";
2959     QString invalidFile = ":/tst_qfileinfo/resources/filefoo.ext1";
2960
2961     for (int i = 0; i < 2; ++i) {
2962         QString file = (i == 0) ? validFile : invalidFile;
2963         QTest::newRow("0, 0") << 0 << 0 << QFile::UnspecifiedError << file;
2964         QTest::newRow("0, BIG") << 0 << 4096 << QFile::UnspecifiedError << file;
2965         QTest::newRow("-1, 0") << -1 << 0 << QFile::UnspecifiedError << file;
2966         QTest::newRow("0, -1") << 0 << -1 << QFile::UnspecifiedError << file;
2967     }
2968
2969     QTest::newRow("0, 1") << 0 << 1 << QFile::NoError << validFile;
2970 }
2971
2972 void tst_QFile::mapResource()
2973 {
2974     QFETCH(QString, fileName);
2975     QFETCH(int, offset);
2976     QFETCH(int, size);
2977     QFETCH(QFile::FileError, error);
2978
2979     QFile file(fileName);
2980     uchar *memory = file.map(offset, size);
2981     QCOMPARE(file.error(), error);
2982     QVERIFY((error == QFile::NoError) ? (memory != 0) : (memory == 0));
2983     if (error == QFile::NoError)
2984         QCOMPARE(QString(memory[0]), QString::number(offset + 1));
2985     QVERIFY(file.unmap(memory));
2986 }
2987
2988 void tst_QFile::mapOpenMode_data()
2989 {
2990     QTest::addColumn<int>("openMode");
2991
2992     QTest::newRow("ReadOnly") << int(QIODevice::ReadOnly);
2993     //QTest::newRow("WriteOnly") << int(QIODevice::WriteOnly); // this doesn't make sense
2994     QTest::newRow("ReadWrite") << int(QIODevice::ReadWrite);
2995     QTest::newRow("ReadOnly,Unbuffered") << int(QIODevice::ReadOnly | QIODevice::Unbuffered);
2996     QTest::newRow("ReadWrite,Unbuffered") << int(QIODevice::ReadWrite | QIODevice::Unbuffered);
2997 }
2998
2999 void tst_QFile::mapOpenMode()
3000 {
3001     QFETCH(int, openMode);
3002     static const qint64 fileSize = 4096;
3003
3004     QByteArray pattern(fileSize, 'A');
3005
3006     QString fileName = QDir::currentPath() + '/' + "qfile_map_testfile";
3007     if (QFile::exists(fileName)) {
3008         QVERIFY(QFile::setPermissions(fileName,
3009             QFile::WriteOwner | QFile::ReadOwner | QFile::WriteUser | QFile::ReadUser));
3010         QFile::remove(fileName);
3011     }
3012     QFile file(fileName);
3013
3014     // make a file
3015     QVERIFY(file.open(QFile::ReadWrite));
3016     QVERIFY(file.write(pattern));
3017     QVERIFY(file.flush());
3018     file.close();
3019
3020     // open according to our mode
3021     QVERIFY(file.open(QIODevice::OpenMode(openMode)));
3022
3023     uchar *memory = file.map(0, fileSize);
3024     QVERIFY(memory);
3025     QVERIFY(memcmp(memory, pattern, fileSize) == 0);
3026
3027     if (openMode & QIODevice::WriteOnly) {
3028         // try to write to the file
3029         *memory = 'a';
3030         file.unmap(memory);
3031         file.close();
3032         file.open(QIODevice::OpenMode(openMode));
3033         file.seek(0);
3034         char c;
3035         QVERIFY(file.getChar(&c));
3036         QCOMPARE(c, 'a');
3037     }
3038
3039     file.close();
3040 }
3041
3042 void tst_QFile::openDirectory()
3043 {
3044     QFile f1(QFINDTESTDATA("resources"));
3045     // it's a directory, it must exist
3046     QVERIFY(f1.exists());
3047
3048     // ...but not be openable
3049     QVERIFY(!f1.open(QIODevice::ReadOnly));
3050     f1.close();
3051     QVERIFY(!f1.open(QIODevice::ReadOnly|QIODevice::Unbuffered));
3052     f1.close();
3053     QVERIFY(!f1.open(QIODevice::ReadWrite));
3054     f1.close();
3055     QVERIFY(!f1.open(QIODevice::WriteOnly));
3056     f1.close();
3057     QVERIFY(!f1.open(QIODevice::WriteOnly|QIODevice::Unbuffered));
3058     f1.close();
3059 }
3060
3061 static qint64 streamExpectedSize(int fd)
3062 {
3063     QT_STATBUF sb;
3064     if (QT_FSTAT(fd, &sb) != -1)
3065         return sb.st_size;
3066     return 0;
3067 }
3068
3069 static qint64 streamCurrentPosition(int fd)
3070 {
3071     QT_OFF_T pos = QT_LSEEK(fd, 0, SEEK_CUR);
3072     if (pos != -1)
3073         return pos;
3074     return 0;
3075 }
3076
3077 static qint64 streamCurrentPosition(FILE *f)
3078 {
3079     QT_OFF_T pos = QT_FTELL(f);
3080     if (pos != -1)
3081         return pos;
3082     return 0;
3083 }
3084
3085 class MessageHandler {
3086 public:
3087     MessageHandler(QtMessageHandler messageHandler = handler)
3088     {
3089         ok = true;
3090         oldMessageHandler = qInstallMessageHandler(messageHandler);
3091     }
3092
3093     ~MessageHandler()
3094     {
3095         qInstallMessageHandler(oldMessageHandler);
3096     }
3097
3098     static bool testPassed()
3099     {
3100         return ok;
3101     }
3102 protected:
3103     static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
3104     {
3105         if (msg == QString::fromLatin1("QIODevice::seek: Cannot call seek on a sequential device"))
3106             ok = false;
3107         // Defer to old message handler.
3108         if (oldMessageHandler)
3109             oldMessageHandler(type, context, msg);
3110     }
3111
3112     static QtMessageHandler oldMessageHandler;
3113     static bool ok;
3114 };
3115
3116 bool MessageHandler::ok = true;
3117 QtMessageHandler MessageHandler::oldMessageHandler = 0;
3118
3119 void tst_QFile::openStandardStreamsFileDescriptors()
3120 {
3121 #ifdef Q_OS_WINCE
3122     //allthough Windows CE (not mobile!) has functions that allow redirecting
3123     //the standard file descriptors to a file (see SetStdioPathW/GetStdioPathW)
3124     //it does not have functions to simply open them like below .
3125     QSKIP("Opening standard streams on Windows CE via descriptor not implemented");
3126 #endif
3127
3128     // Check that QIODevice::seek() isn't called when opening a sequential device (QFile).
3129     MessageHandler msgHandler;
3130
3131     {
3132         QFile in;
3133         in.open(STDIN_FILENO, QIODevice::ReadOnly);
3134         QCOMPARE( in.pos(), streamCurrentPosition(STDIN_FILENO) );
3135         QCOMPARE( in.size(), streamExpectedSize(STDIN_FILENO) );
3136     }
3137
3138     {
3139         QFile out;
3140         QVERIFY(out.open(STDOUT_FILENO, QIODevice::WriteOnly));
3141         QCOMPARE( out.pos(), streamCurrentPosition(STDOUT_FILENO) );
3142         QCOMPARE( out.size(), streamExpectedSize(STDOUT_FILENO) );
3143     }
3144
3145     {
3146         QFile err;
3147         err.open(STDERR_FILENO, QIODevice::WriteOnly);
3148         QCOMPARE( err.pos(), streamCurrentPosition(STDERR_FILENO) );
3149         QCOMPARE( err.size(), streamExpectedSize(STDERR_FILENO) );
3150     }
3151
3152     QVERIFY(msgHandler.testPassed());
3153 }
3154
3155 void tst_QFile::openStandardStreamsBufferedStreams()
3156 {
3157 #ifdef Q_OS_WINCE
3158     QSKIP("Not tested on Windows CE.");
3159 #endif
3160     // Check that QIODevice::seek() isn't called when opening a sequential device (QFile).
3161     MessageHandler msgHandler;
3162
3163     // Using streams
3164     {
3165         QFile in;
3166         in.open(stdin, QIODevice::ReadOnly);
3167         QCOMPARE( in.pos(), streamCurrentPosition(stdin) );
3168         QCOMPARE( in.size(), streamExpectedSize(QT_FILENO(stdin)) );
3169     }
3170
3171     {
3172         QFile out;
3173         out.open(stdout, QIODevice::WriteOnly);
3174         QCOMPARE( out.pos(), streamCurrentPosition(stdout) );
3175         QCOMPARE( out.size(), streamExpectedSize(QT_FILENO(stdout)) );
3176     }
3177
3178     {
3179         QFile err;
3180         err.open(stderr, QIODevice::WriteOnly);
3181         QCOMPARE( err.pos(), streamCurrentPosition(stderr) );
3182         QCOMPARE( err.size(), streamExpectedSize(QT_FILENO(stderr)) );
3183     }
3184
3185     QVERIFY(msgHandler.testPassed());
3186 }
3187
3188 void tst_QFile::writeNothing()
3189 {
3190     for (int i = 0; i < NumberOfFileTypes; ++i) {
3191         QFile file("file.txt");
3192         QVERIFY( openFile(file, QIODevice::WriteOnly | QIODevice::Unbuffered, FileType(i)) );
3193         QVERIFY( 0 == file.write((char *)0, 0) );
3194         QCOMPARE( file.error(), QFile::NoError );
3195         closeFile(file);
3196     }
3197 }
3198
3199 void tst_QFile::resize_data()
3200 {
3201     QTest::addColumn<int>("filetype");
3202
3203     QTest::newRow("native") << int(OpenQFile);
3204     QTest::newRow("fileno") << int(OpenFd);
3205     QTest::newRow("stream") << int(OpenStream);
3206 }
3207
3208 void tst_QFile::resize()
3209 {
3210     QFETCH(int, filetype);
3211     QString filename(QLatin1String("file.txt"));
3212     QFile file(filename);
3213     QVERIFY(openFile(file, QIODevice::ReadWrite, FileType(filetype)));
3214     QVERIFY(file.resize(8));
3215     QCOMPARE(file.size(), qint64(8));
3216     closeFile(file);
3217     QFile::resize(filename, 4);
3218     QCOMPARE(QFileInfo(filename).size(), qint64(4));
3219     QVERIFY(QFile::remove(filename));
3220 }
3221
3222 void tst_QFile::objectConstructors()
3223 {
3224     QObject ob;
3225     QFile* file1 = new QFile(QFINDTESTDATA("testfile.txt"), &ob);
3226     QFile* file2 = new QFile(&ob);
3227     QVERIFY(file1->exists());
3228     QVERIFY(!file2->exists());
3229 }
3230
3231 void tst_QFile::caseSensitivity()
3232 {
3233 #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
3234     const bool caseSensitive = false;
3235 #else
3236     const bool caseSensitive = true;
3237 #endif
3238     QByteArray testData("a little test");
3239     QString filename("File.txt");
3240     {
3241         QFile f(filename);
3242         QVERIFY(f.open(QIODevice::WriteOnly));
3243         QVERIFY(f.write(testData));
3244         f.close();
3245     }
3246     QStringList alternates;
3247     QFileInfo fi(filename);
3248     QVERIFY(fi.exists());
3249     alternates << "file.txt" << "File.TXT" << "fIlE.TxT" << fi.absoluteFilePath().toUpper() << fi.absoluteFilePath().toLower();
3250     foreach (QString alt, alternates) {
3251         QFileInfo fi2(alt);
3252         QCOMPARE(fi2.exists(), !caseSensitive);
3253         QCOMPARE(fi.size() == fi2.size(), !caseSensitive);
3254         QFile f2(alt);
3255         QCOMPARE(f2.open(QIODevice::ReadOnly), !caseSensitive);
3256         if (!caseSensitive)
3257             QCOMPARE(f2.readAll(), testData);
3258     }
3259 }
3260
3261 //MSVCRT asserts when any function is called with a closed file handle.
3262 //This replaces the default crashing error handler with one that ignores the error (allowing EBADF to be returned)
3263 class AutoIgnoreInvalidParameter
3264 {
3265 public:
3266 #if defined(Q_OS_WIN) && defined (Q_CC_MSVC)
3267     static void ignore_invalid_parameter(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t) {}
3268     AutoIgnoreInvalidParameter()
3269     {
3270         oldHandler = _set_invalid_parameter_handler(ignore_invalid_parameter);
3271         //also disable the abort/retry/ignore popup
3272         oldReportMode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
3273     }
3274     ~AutoIgnoreInvalidParameter()
3275     {
3276         //restore previous settings
3277         _set_invalid_parameter_handler(oldHandler);
3278         _CrtSetReportMode(_CRT_ASSERT, oldReportMode);
3279     }
3280     _invalid_parameter_handler oldHandler;
3281     int oldReportMode;
3282 #endif
3283 };
3284
3285 void tst_QFile::autocloseHandle()
3286 {
3287     {
3288         QFile file("readonlyfile");
3289         QVERIFY(openFile(file, QIODevice::ReadOnly, OpenFd, QFile::AutoCloseHandle));
3290         int fd = fd_;
3291         QCOMPARE(file.handle(), fd);
3292         file.close();
3293         fd_ = -1;
3294         QCOMPARE(file.handle(), -1);
3295         AutoIgnoreInvalidParameter a;
3296         Q_UNUSED(a);
3297         //file is closed, read should fail
3298         char buf;
3299         QCOMPARE((int)QT_READ(fd, &buf, 1), -1);
3300         QVERIFY(errno = EBADF);
3301     }
3302
3303     {
3304         QFile file("readonlyfile");
3305         QVERIFY(openFile(file, QIODevice::ReadOnly, OpenFd, QFile::DontCloseHandle));
3306         QCOMPARE(file.handle(), fd_);
3307         file.close();
3308         QCOMPARE(file.handle(), -1);
3309         //file is not closed, read should succeed
3310         char buf;
3311         QCOMPARE((int)QT_READ(fd_, &buf, 1), 1);
3312         QT_CLOSE(fd_);
3313         fd_ = -1;
3314     }
3315
3316     {
3317         QFile file("readonlyfile");
3318         QVERIFY(openFile(file, QIODevice::ReadOnly, OpenStream, QFile::AutoCloseHandle));
3319         int fd = QT_FILENO(stream_);
3320         QCOMPARE(file.handle(), fd);
3321         file.close();
3322         stream_ = 0;
3323         QCOMPARE(file.handle(), -1);
3324         AutoIgnoreInvalidParameter a;
3325         Q_UNUSED(a);
3326         //file is closed, read should fail
3327         char buf;
3328         QCOMPARE((int)QT_READ(fd, &buf, 1), -1); //not using fread because the FILE* was freed by fclose
3329     }
3330
3331     {
3332         QFile file("readonlyfile");
3333         QVERIFY(openFile(file, QIODevice::ReadOnly, OpenStream, QFile::DontCloseHandle));
3334         QCOMPARE(file.handle(), QT_FILENO(stream_));
3335         file.close();
3336         QCOMPARE(file.handle(), -1);
3337         //file is not closed, read should succeed
3338         char buf;
3339         QCOMPARE(int(::fread(&buf, 1, 1, stream_)), 1);
3340         ::fclose(stream_);
3341         stream_ = 0;
3342     }
3343 }
3344
3345 QTEST_MAIN(tst_QFile)
3346 #include "tst_qfile.moc"