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