| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
| 4 | ** Copyright (C) 2017 Intel Corporation. | 
| 5 | ** Contact: https://www.qt.io/licensing/ | 
| 6 | ** | 
| 7 | ** This file is part of the test suite of the Qt Toolkit. | 
| 8 | ** | 
| 9 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | 
| 10 | ** Commercial License Usage | 
| 11 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 12 | ** accordance with the commercial license agreement provided with the | 
| 13 | ** Software or, alternatively, in accordance with the terms contained in | 
| 14 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 15 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 16 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 17 | ** | 
| 18 | ** GNU General Public License Usage | 
| 19 | ** Alternatively, this file may be used under the terms of the GNU | 
| 20 | ** General Public License version 3 as published by the Free Software | 
| 21 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
| 22 | ** included in the packaging of this file. Please review the following | 
| 23 | ** information to ensure the GNU General Public License requirements will | 
| 24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
| 25 | ** | 
| 26 | ** $QT_END_LICENSE$ | 
| 27 | ** | 
| 28 | ****************************************************************************/ | 
| 29 |  | 
| 30 | #include <QtTest/QtTest> | 
| 31 | #include <qcoreapplication.h> | 
| 32 | #include <qstring.h> | 
| 33 | #include <qtemporarydir.h> | 
| 34 | #include <qtemporaryfile.h> | 
| 35 | #include <qfile.h> | 
| 36 | #include <qdatetime.h> | 
| 37 | #include <qdir.h> | 
| 38 | #include <qset.h> | 
| 39 | #include <qtextcodec.h> | 
| 40 |  | 
| 41 | #include <QtTest/private/qtesthelpers_p.h> | 
| 42 |  | 
| 43 | #if defined(Q_OS_WIN) | 
| 44 | # include <windows.h> | 
| 45 | #endif | 
| 46 | #if defined(Q_OS_UNIX) | 
| 47 | # include <sys/types.h> | 
| 48 | # include <sys/stat.h> | 
| 49 | # include <errno.h> | 
| 50 | # include <fcntl.h>             // open(2) | 
| 51 | # include <unistd.h>            // close(2) | 
| 52 | #endif | 
| 53 |  | 
| 54 | class tst_QTemporaryFile : public QObject | 
| 55 | { | 
| 56 |     Q_OBJECT | 
| 57 | public slots: | 
| 58 |     void initTestCase(); | 
| 59 |     void cleanupTestCase(); | 
| 60 |  | 
| 61 | private slots: | 
| 62 |     void construction(); | 
| 63 |     void fileTemplate(); | 
| 64 |     void fileTemplate_data(); | 
| 65 |     void getSetCheck(); | 
| 66 |     void fileName(); | 
| 67 |     void fileNameIsEmpty(); | 
| 68 |     void autoRemove(); | 
| 69 |     void nonWritableCurrentDir(); | 
| 70 |     void io(); | 
| 71 |     void openCloseOpenClose(); | 
| 72 |     void removeAndReOpen(); | 
| 73 |     void removeUnnamed(); | 
| 74 |     void size(); | 
| 75 |     void resize(); | 
| 76 |     void openOnRootDrives(); | 
| 77 |     void stressTest(); | 
| 78 |     void rename(); | 
| 79 |     void renameFdLeak(); | 
| 80 |     void reOpenThroughQFile(); | 
| 81 |     void keepOpenMode(); | 
| 82 |     void resetTemplateAfterError(); | 
| 83 |     void setTemplateAfterOpen(); | 
| 84 |     void autoRemoveAfterFailedRename(); | 
| 85 |     void createNativeFile_data(); | 
| 86 |     void createNativeFile(); | 
| 87 |     void QTBUG_4796_data(); | 
| 88 |     void QTBUG_4796(); | 
| 89 |     void guaranteeUnique(); | 
| 90 | private: | 
| 91 |     QTemporaryDir m_temporaryDir; | 
| 92 |     QString m_previousCurrent; | 
| 93 | }; | 
| 94 |  | 
| 95 | void tst_QTemporaryFile::initTestCase() | 
| 96 | { | 
| 97 |     QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString())); | 
| 98 |     m_previousCurrent = QDir::currentPath(); | 
| 99 |     QVERIFY(QDir::setCurrent(m_temporaryDir.path())); | 
| 100 |  | 
| 101 |     // For QTBUG_4796 | 
| 102 |     QVERIFY(QDir("test-XXXXXX" ).exists() || QDir().mkdir("test-XXXXXX" )); | 
| 103 |     QCoreApplication::setApplicationName("tst_qtemporaryfile" ); | 
| 104 |  | 
| 105 | #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) | 
| 106 |     QString sourceDir(":/android_testdata/" ); | 
| 107 |     QDirIterator it(sourceDir, QDirIterator::Subdirectories); | 
| 108 |     while (it.hasNext()) { | 
| 109 |         it.next(); | 
| 110 |  | 
| 111 |         QFileInfo sourceFileInfo = it.fileInfo(); | 
| 112 |         if (!sourceFileInfo.isDir()) { | 
| 113 |             QFileInfo destinationFileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1Char('/') + sourceFileInfo.filePath().mid(sourceDir.length())); | 
| 114 |  | 
| 115 |             if (!destinationFileInfo.exists()) { | 
| 116 |                 QVERIFY(QDir().mkpath(destinationFileInfo.path())); | 
| 117 |                 QVERIFY(QFile::copy(sourceFileInfo.filePath(), destinationFileInfo.filePath())); | 
| 118 |             } | 
| 119 |         } | 
| 120 |     } | 
| 121 | #endif | 
| 122 | } | 
| 123 |  | 
| 124 | void tst_QTemporaryFile::cleanupTestCase() | 
| 125 | { | 
| 126 |     QDir::setCurrent(m_previousCurrent); | 
| 127 | } | 
| 128 |  | 
| 129 | void tst_QTemporaryFile::construction() | 
| 130 | { | 
| 131 |     QTemporaryFile file(0); | 
| 132 |     QString tmp = QDir::tempPath(); | 
| 133 |     QCOMPARE(file.fileTemplate().left(tmp.size()), tmp); | 
| 134 |     QCOMPARE(file.fileTemplate().at(tmp.size()), QChar('/')); | 
| 135 | } | 
| 136 |  | 
| 137 | // Testing get/set functions | 
| 138 | void tst_QTemporaryFile::getSetCheck() | 
| 139 | { | 
| 140 |     QTemporaryFile obj1; | 
| 141 |     // bool QTemporaryFile::autoRemove() | 
| 142 |     // void QTemporaryFile::setAutoRemove(bool) | 
| 143 |     obj1.setAutoRemove(false); | 
| 144 |     QCOMPARE(false, obj1.autoRemove()); | 
| 145 |     obj1.setAutoRemove(true); | 
| 146 |     QCOMPARE(true, obj1.autoRemove()); | 
| 147 | } | 
| 148 |  | 
| 149 | static QString hanTestText() | 
| 150 | { | 
| 151 |     QString text; | 
| 152 |     text += QChar(0x65B0); | 
| 153 |     text += QChar(0x5E10); | 
| 154 |     text += QChar(0x6237); | 
| 155 |     return text; | 
| 156 | } | 
| 157 |  | 
| 158 | static QString umlautTestText() | 
| 159 | { | 
| 160 |     QString text; | 
| 161 |     text += QChar(0xc4); | 
| 162 |     text += QChar(0xe4); | 
| 163 |     text += QChar(0xd6); | 
| 164 |     text += QChar(0xf6); | 
| 165 |     text += QChar(0xdc); | 
| 166 |     text += QChar(0xfc); | 
| 167 |     text += QChar(0xdf); | 
| 168 |     return text; | 
| 169 | } | 
| 170 |  | 
| 171 | void tst_QTemporaryFile::fileTemplate_data() | 
| 172 | { | 
| 173 |     QTest::addColumn<QString>(name: "constructorTemplate" ); | 
| 174 |     QTest::addColumn<QString>(name: "prefix" ); | 
| 175 |     QTest::addColumn<QString>(name: "suffix" ); | 
| 176 |     QTest::addColumn<QString>(name: "fileTemplate" ); | 
| 177 |  | 
| 178 |     QTest::newRow(dataTag: "constructor default" ) << ""  << "."  << ""  << "" ; | 
| 179 |     QTest::newRow(dataTag: "constructor with xxx sufix" ) << "qt_XXXXXXxxx"  << "qt_"  << "xxx"  << "" ; | 
| 180 |     QTest::newRow(dataTag: "constructor with xXx sufix" ) << "qt_XXXXXXxXx"  << "qt_"  << "xXx"  << "" ; | 
| 181 |     QTest::newRow(dataTag: "constructor with no sufix" ) << "qt_XXXXXX"  << "qt_"  << ""  << "" ; | 
| 182 |     QTest::newRow(dataTag: "constructor with >6 X's and xxx suffix" ) << "qt_XXXXXXXXXXxxx"  << "qt_"  << "xxx"  << "" ; | 
| 183 |     QTest::newRow(dataTag: "constructor with >6 X's, no suffix" ) << "qt_XXXXXXXXXX"  << "qt_"  << ""  << "" ; | 
| 184 |  | 
| 185 |     QTest::newRow(dataTag: "constructor with XXXX suffix" ) << "qt_XXXXXX_XXXX"  << "qt_"  << "_XXXX"  << "" ; | 
| 186 |     QTest::newRow(dataTag: "constructor with XXXXX suffix" ) << "qt_XXXXXX_XXXXX"  << "qt_"  << "_XXXXX"  << "" ; | 
| 187 |     QTest::newRow(dataTag: "constructor with XXXX prefix" ) << "qt_XXXX"  << "qt_XXXX."  << ""  << "" ; | 
| 188 |     QTest::newRow(dataTag: "constructor with XXXXX prefix" ) << "qt_XXXXX"  << "qt_XXXXX."  << ""  << "" ; | 
| 189 |     QTest::newRow(dataTag: "constructor with XXXX  prefix and suffix" ) << "qt_XXXX_XXXXXX_XXXX"  << "qt_XXXX_"  << "_XXXX"  << "" ; | 
| 190 |     QTest::newRow(dataTag: "constructor with XXXXX prefix and suffix" ) << "qt_XXXXX_XXXXXX_XXXXX"  << "qt_XXXXX_"  << "_XXXXX"  << "" ; | 
| 191 |  | 
| 192 |     QTest::newRow(dataTag: "set template, no suffix" ) << ""  << "foo"  << ""  << "foo" ; | 
| 193 |     QTest::newRow(dataTag: "set template, with lowercase XXXXXX" ) << ""  << "qt_"  << "xxxxxx"  << "qt_XXXXXXxxxxxx" ; | 
| 194 |     QTest::newRow(dataTag: "set template, with xxx" ) << ""  << "qt_"  << ".xxx"  << "qt_XXXXXX.xxx" ; | 
| 195 |     QTest::newRow(dataTag: "set template, with >6 X's" ) << ""  << "qt_"  << ".xxx"  << "qt_XXXXXXXXXXXXXX.xxx" ; | 
| 196 |     QTest::newRow(dataTag: "set template, with >6 X's, no suffix" ) << ""  << "qt_"  << ""  << "qt_XXXXXXXXXXXXXX" ; | 
| 197 |     if (QTestPrivate::canHandleUnicodeFileNames()) { | 
| 198 |         // Test Umlauts (contained in Latin1) | 
| 199 |         QString prefix = "qt_"  + umlautTestText(); | 
| 200 |         QTest::newRow(dataTag: "Umlauts" ) << (prefix + "XXXXXX" ) << prefix << QString() << QString(); | 
| 201 |         // Test Chinese | 
| 202 |         prefix = "qt_"  + hanTestText(); | 
| 203 |         QTest::newRow(dataTag: "Chinese characters" ) << (prefix + "XXXXXX" ) << prefix << QString() << QString(); | 
| 204 |     } | 
| 205 | } | 
| 206 |  | 
| 207 | void tst_QTemporaryFile::fileTemplate() | 
| 208 | { | 
| 209 |     QFETCH(QString, constructorTemplate); | 
| 210 |     QFETCH(QString, prefix); | 
| 211 |     QFETCH(QString, suffix); | 
| 212 |     QFETCH(QString, fileTemplate); | 
| 213 |  | 
| 214 |     QTemporaryFile file(constructorTemplate); | 
| 215 |     if (!fileTemplate.isEmpty()) | 
| 216 |         file.setFileTemplate(fileTemplate); | 
| 217 |  | 
| 218 |     QVERIFY2(file.open(), qPrintable(file.errorString())); | 
| 219 |  | 
| 220 |     QString fileName = QFileInfo(file).fileName(); | 
| 221 |     if (prefix.length()) | 
| 222 |         QCOMPARE(fileName.left(prefix.length()), prefix); | 
| 223 |  | 
| 224 |     if (suffix.length()) | 
| 225 |         QCOMPARE(fileName.right(suffix.length()), suffix); | 
| 226 | } | 
| 227 |  | 
| 228 |  | 
| 229 | /* | 
| 230 |     This tests whether the temporary file really gets placed in QDir::tempPath | 
| 231 | */ | 
| 232 | void tst_QTemporaryFile::fileName() | 
| 233 | { | 
| 234 |     // Get QDir::tempPath and make an absolute path. | 
| 235 |     QString tempPath = QDir::tempPath(); | 
| 236 |     QString absoluteTempPath = QDir(tempPath).absolutePath(); | 
| 237 |     QTemporaryFile file; | 
| 238 |     file.setAutoRemove(true); | 
| 239 |     file.open(); | 
| 240 |     QString fileName = file.fileName(); | 
| 241 |     QVERIFY2(fileName.contains("/tst_qtemporaryfile." ), qPrintable(fileName)); | 
| 242 |     QVERIFY(QFile::exists(fileName)); | 
| 243 |     // Get path to the temp file, without the file name. | 
| 244 |     QString absoluteFilePath = QFileInfo(fileName).absolutePath(); | 
| 245 | #if defined(Q_OS_WIN) | 
| 246 |     absoluteFilePath = absoluteFilePath.toLower(); | 
| 247 |     absoluteTempPath = absoluteTempPath.toLower(); | 
| 248 | #endif | 
| 249 |     QCOMPARE(absoluteFilePath, absoluteTempPath); | 
| 250 | } | 
| 251 |  | 
| 252 | void tst_QTemporaryFile::fileNameIsEmpty() | 
| 253 | { | 
| 254 |     QString filename; | 
| 255 |     { | 
| 256 |         QTemporaryFile file; | 
| 257 |         QVERIFY(file.fileName().isEmpty()); | 
| 258 |  | 
| 259 |         QVERIFY(file.open()); | 
| 260 |         QVERIFY(!file.fileName().isEmpty()); | 
| 261 |  | 
| 262 |         filename = file.fileName(); | 
| 263 |         QVERIFY(QFile::exists(filename)); | 
| 264 |  | 
| 265 |         file.close(); | 
| 266 |         QVERIFY(!file.isOpen()); | 
| 267 |         QVERIFY(QFile::exists(filename)); | 
| 268 |         QVERIFY(!file.fileName().isEmpty()); | 
| 269 |     } | 
| 270 |     QVERIFY(!QFile::exists(filename)); | 
| 271 | } | 
| 272 |  | 
| 273 | void tst_QTemporaryFile::autoRemove() | 
| 274 | { | 
| 275 |     // Test auto remove | 
| 276 |     QString fileName; | 
| 277 |     { | 
| 278 |         QTemporaryFile file("tempXXXXXX" ); | 
| 279 |         file.setAutoRemove(true); | 
| 280 |         QVERIFY(file.open()); | 
| 281 |         fileName = file.fileName(); | 
| 282 |         file.close(); | 
| 283 |     } | 
| 284 |     QVERIFY(!fileName.isEmpty()); | 
| 285 |     QVERIFY(!QFile::exists(fileName)); | 
| 286 |  | 
| 287 |     // same, but gets the file name after closing | 
| 288 |     { | 
| 289 |         QTemporaryFile file("tempXXXXXX" ); | 
| 290 |         file.setAutoRemove(true); | 
| 291 |         QVERIFY(file.open()); | 
| 292 |         file.close(); | 
| 293 |         fileName = file.fileName(); | 
| 294 |     } | 
| 295 |     QVERIFY(!fileName.isEmpty()); | 
| 296 |     QVERIFY(!QFile::exists(fileName)); | 
| 297 |  | 
| 298 |     // Test if disabling auto remove works. | 
| 299 |     { | 
| 300 |         QTemporaryFile file("tempXXXXXX" ); | 
| 301 |         file.setAutoRemove(false); | 
| 302 |         QVERIFY(file.open()); | 
| 303 |         fileName = file.fileName(); | 
| 304 |         file.close(); | 
| 305 |     } | 
| 306 |     QVERIFY(!fileName.isEmpty()); | 
| 307 |     QVERIFY(QFile::exists(fileName)); | 
| 308 |     QVERIFY(QFile::remove(fileName)); | 
| 309 |  | 
| 310 |     // same, but gets the file name after closing | 
| 311 |     { | 
| 312 |         QTemporaryFile file("tempXXXXXX" ); | 
| 313 |         file.setAutoRemove(false); | 
| 314 |         QVERIFY(file.open()); | 
| 315 |         file.close(); | 
| 316 |         fileName = file.fileName(); | 
| 317 |     } | 
| 318 |     QVERIFY(!fileName.isEmpty()); | 
| 319 |     QVERIFY(QFile::exists(fileName)); | 
| 320 |     QVERIFY(QFile::remove(fileName)); | 
| 321 |  | 
| 322 |     // Do not explicitly call setAutoRemove (tests if it really is the default as documented) | 
| 323 |     { | 
| 324 |         QTemporaryFile file("tempXXXXXX" ); | 
| 325 |         QVERIFY(file.open()); | 
| 326 |         fileName = file.fileName(); | 
| 327 |         // QTBUG-39976, file mappings should be cleared as well. | 
| 328 |         QVERIFY(file.write("test" )); | 
| 329 |         QVERIFY(file.flush()); | 
| 330 |         uchar *mapped = file.map(offset: 0, size: file.size()); | 
| 331 |         QVERIFY(mapped); | 
| 332 |         file.close(); | 
| 333 |     } | 
| 334 |     QVERIFY(!QFile::exists(fileName)); | 
| 335 | } | 
| 336 |  | 
| 337 | struct ChdirOnReturn | 
| 338 | { | 
| 339 |     ChdirOnReturn(const QString& d) : dir(d) {} | 
| 340 |     ~ChdirOnReturn() { | 
| 341 |         QDir::setCurrent(dir); | 
| 342 |     } | 
| 343 |     QString dir; | 
| 344 | }; | 
| 345 |  | 
| 346 | void tst_QTemporaryFile::nonWritableCurrentDir() | 
| 347 | { | 
| 348 | #ifdef Q_OS_UNIX | 
| 349 |     if (::geteuid() == 0) | 
| 350 |         QSKIP("not valid running this test as root" ); | 
| 351 |  | 
| 352 |     ChdirOnReturn cor(QDir::currentPath()); | 
| 353 |  | 
| 354 | #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) | 
| 355 |     QDir::setCurrent("/data" ); | 
| 356 | #else | 
| 357 |     QDir::setCurrent("/home" ); | 
| 358 | #endif | 
| 359 |  | 
| 360 |     // QTemporaryFile("tempXXXXXX") is probably a bad idea in any app | 
| 361 |     // where the current dir could anything... | 
| 362 |     QTemporaryFile file("tempXXXXXX" ); | 
| 363 |     file.setAutoRemove(true); | 
| 364 |     QVERIFY(!file.open()); | 
| 365 |     QVERIFY(file.fileName().isEmpty()); | 
| 366 | #endif | 
| 367 | } | 
| 368 |  | 
| 369 | void tst_QTemporaryFile::io() | 
| 370 | { | 
| 371 |     QByteArray data("OLE\nOLE\nOLE" ); | 
| 372 |     QTemporaryFile file; | 
| 373 |     QDateTime before = QDateTime::currentDateTimeUtc().addMSecs(msecs: -250); | 
| 374 |  | 
| 375 |     // discard msec component (round down) - not all FSs and OSs support them | 
| 376 |     before.setSecsSinceEpoch(before.toSecsSinceEpoch()); | 
| 377 |  | 
| 378 |     QVERIFY(file.open()); | 
| 379 |     QVERIFY(file.symLinkTarget().isEmpty()); // it's not a link! | 
| 380 |     QFile::Permissions perm = file.permissions(); | 
| 381 |     QVERIFY(perm & QFile::ReadOwner); | 
| 382 |     QVERIFY(file.setPermissions(perm)); | 
| 383 |  | 
| 384 |     QCOMPARE(int(file.size()), 0); | 
| 385 |     QVERIFY(file.resize(data.size())); | 
| 386 |     QCOMPARE(int(file.size()), data.size()); | 
| 387 |     QCOMPARE((int)file.write(data), data.size()); | 
| 388 |     QCOMPARE(int(file.size()), data.size()); | 
| 389 |  | 
| 390 |     QDateTime mtime = file.fileTime(time: QFile::FileModificationTime).toUTC(); | 
| 391 |     QDateTime btime = file.fileTime(time: QFile::FileBirthTime).toUTC(); | 
| 392 |     QDateTime ctime = file.fileTime(time: QFile::FileMetadataChangeTime).toUTC(); | 
| 393 |     QDateTime atime = file.fileTime(time: QFile::FileAccessTime).toUTC(); | 
| 394 |  | 
| 395 |     QDateTime after = QDateTime::currentDateTimeUtc().toUTC().addMSecs(msecs: 250); | 
| 396 |     // round msecs up | 
| 397 |     after.setSecsSinceEpoch(after.toSecsSinceEpoch() + 1); | 
| 398 |  | 
| 399 |     // mtime must be valid, the rest could fail | 
| 400 |     QVERIFY(mtime <= after && mtime >= before); | 
| 401 |     QVERIFY(!btime.isValid() || (btime <= after && btime >= before)); | 
| 402 |     QVERIFY(!ctime.isValid() || (ctime <= after && ctime >= before)); | 
| 403 |     QVERIFY(!btime.isValid() || (btime <= after && btime >= before)); | 
| 404 |  | 
| 405 |     QVERIFY(file.setFileTime(before.addSecs(-10), QFile::FileModificationTime)); | 
| 406 |     mtime = file.fileTime(time: QFile::FileModificationTime).toUTC(); | 
| 407 |     QCOMPARE(mtime, before.addSecs(-10)); | 
| 408 |  | 
| 409 |     file.reset(); | 
| 410 |     QFile compare(file.fileName()); | 
| 411 |     compare.open(flags: QIODevice::ReadOnly); | 
| 412 |     QCOMPARE(compare.readAll() , data); | 
| 413 |     QCOMPARE(compare.fileTime(QFile::FileModificationTime), mtime); | 
| 414 | } | 
| 415 |  | 
| 416 | void tst_QTemporaryFile::openCloseOpenClose() | 
| 417 | { | 
| 418 |     QString fileName; | 
| 419 |     { | 
| 420 |         // Create a temp file | 
| 421 |         QTemporaryFile file("tempXXXXXX" ); | 
| 422 |         file.setAutoRemove(true); | 
| 423 |         QVERIFY(file.open()); | 
| 424 |         file.write(data: "OLE" ); | 
| 425 |         fileName = file.fileName(); | 
| 426 |         QVERIFY(QFile::exists(fileName)); | 
| 427 |         file.close(); | 
| 428 |  | 
| 429 |         // Check that it still exists after being closed | 
| 430 |         QVERIFY(QFile::exists(fileName)); | 
| 431 |         QVERIFY(!file.isOpen()); | 
| 432 |         QVERIFY(file.open()); | 
| 433 |         QCOMPARE(file.readAll(), QByteArray("OLE" )); | 
| 434 |         // Check that it's still the same file after being opened again. | 
| 435 |         QCOMPARE(file.fileName(), fileName); | 
| 436 |     } | 
| 437 |     QVERIFY(!QFile::exists(fileName)); | 
| 438 | } | 
| 439 |  | 
| 440 | void tst_QTemporaryFile::removeAndReOpen() | 
| 441 | { | 
| 442 |     QString fileName; | 
| 443 |     { | 
| 444 |         QTemporaryFile file; | 
| 445 |         file.open(); | 
| 446 |         fileName = file.fileName();     // materializes any unnamed file | 
| 447 |         QVERIFY(QFile::exists(fileName)); | 
| 448 |  | 
| 449 |         QVERIFY(file.remove()); | 
| 450 |         QVERIFY(file.fileName().isEmpty()); | 
| 451 |         QVERIFY(!QFile::exists(fileName)); | 
| 452 |         QVERIFY(!file.remove()); | 
| 453 |  | 
| 454 |         QVERIFY(file.open()); | 
| 455 |         QCOMPARE(QFileInfo(file.fileName()).path(), QFileInfo(fileName).path()); | 
| 456 |         fileName = file.fileName(); | 
| 457 |         QVERIFY(QFile::exists(fileName)); | 
| 458 |     } | 
| 459 |     QVERIFY(!QFile::exists(fileName)); | 
| 460 | } | 
| 461 |  | 
| 462 | void tst_QTemporaryFile::removeUnnamed() | 
| 463 | { | 
| 464 |     QTemporaryFile file; | 
| 465 |     file.open(); | 
| 466 |  | 
| 467 |     // we did not call fileName(), so the file name may not have a name | 
| 468 |     QVERIFY(file.remove()); | 
| 469 |     QVERIFY(file.fileName().isEmpty()); | 
| 470 |  | 
| 471 |     // if it was unnamed, this will succeed again, so we can't check the result | 
| 472 |     file.remove(); | 
| 473 | } | 
| 474 |  | 
| 475 | void tst_QTemporaryFile::size() | 
| 476 | { | 
| 477 |     QTemporaryFile file; | 
| 478 |     QVERIFY(file.open()); | 
| 479 |     QVERIFY(!file.isSequential()); | 
| 480 |     QByteArray str("foobar" ); | 
| 481 |     file.write(data: str); | 
| 482 |  | 
| 483 |     // On CE it takes more time for the filesystem to update | 
| 484 |     // the information. Usually you have to close it or seek | 
| 485 |     // to get latest information. flush() does not help either. | 
| 486 |     QCOMPARE(file.size(), qint64(6)); | 
| 487 |     file.seek(offset: 0); | 
| 488 |     QCOMPARE(file.size(), qint64(6)); | 
| 489 |  | 
| 490 |     QVERIFY(QFile::exists(file.fileName())); | 
| 491 |     QVERIFY(file.exists()); | 
| 492 | } | 
| 493 |  | 
| 494 | void tst_QTemporaryFile::resize() | 
| 495 | { | 
| 496 |     QTemporaryFile file; | 
| 497 |     file.setAutoRemove(true); | 
| 498 |     QVERIFY(file.open()); | 
| 499 |     QVERIFY(file.resize(100)); | 
| 500 |  | 
| 501 |     QCOMPARE(QFileInfo(file.fileName()).size(), qint64(100)); | 
| 502 |  | 
| 503 |     file.close(); | 
| 504 | } | 
| 505 |  | 
| 506 | void tst_QTemporaryFile::openOnRootDrives() | 
| 507 | { | 
| 508 | #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) | 
| 509 |     unsigned int lastErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); | 
| 510 | #endif | 
| 511 |     // If it's possible to create a file in the root directory, it | 
| 512 |     // must be possible to create a temp file there too. | 
| 513 |     foreach (QFileInfo driveInfo, QDir::drives()) { | 
| 514 |         QFile testFile(driveInfo.filePath() + "XXXXXX.txt" ); | 
| 515 |         if (testFile.open(flags: QIODevice::ReadWrite)) { | 
| 516 |             testFile.remove(); | 
| 517 |             QTemporaryFile file(driveInfo.filePath() + "XXXXXX.txt" ); | 
| 518 |             file.setAutoRemove(true); | 
| 519 |             QVERIFY(file.open()); | 
| 520 |  | 
| 521 |             QFileInfo fi(file.fileName()); | 
| 522 |             QCOMPARE(fi.absoluteDir(), driveInfo.filePath()); | 
| 523 |         } | 
| 524 |     } | 
| 525 | #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) | 
| 526 |     SetErrorMode(lastErrorMode); | 
| 527 | #endif | 
| 528 | } | 
| 529 |  | 
| 530 | void tst_QTemporaryFile::stressTest() | 
| 531 | { | 
| 532 |     const int iterations = 1000; | 
| 533 |  | 
| 534 |     QSet<QString> names; | 
| 535 |     for (int i = 0; i < iterations; ++i) { | 
| 536 |         QTemporaryFile file; | 
| 537 |         file.setAutoRemove(false); | 
| 538 |         QVERIFY2(file.open(), qPrintable(file.errorString())); | 
| 539 |         QVERIFY(!names.contains(file.fileName())); | 
| 540 |         names.insert(value: file.fileName()); | 
| 541 |     } | 
| 542 |     for (QSet<QString>::const_iterator it = names.constBegin(); it != names.constEnd(); ++it) { | 
| 543 |         QFile::remove(fileName: *it); | 
| 544 |     } | 
| 545 | } | 
| 546 |  | 
| 547 | void tst_QTemporaryFile::rename() | 
| 548 | { | 
| 549 |     // This test checks that the temporary file is deleted, even after a | 
| 550 |     // rename. | 
| 551 |  | 
| 552 |     QDir dir; | 
| 553 |     QVERIFY(!dir.exists("temporary-file.txt" )); | 
| 554 |  | 
| 555 |     QString tempname; | 
| 556 |     { | 
| 557 |         QTemporaryFile file(dir.filePath(fileName: "temporary-file.XXXXXX" )); | 
| 558 |  | 
| 559 |         QVERIFY(file.open()); | 
| 560 |         tempname = file.fileName(); | 
| 561 |         QVERIFY(dir.exists(tempname)); | 
| 562 |  | 
| 563 |         QVERIFY(file.rename("temporary-file.txt" )); | 
| 564 |         QVERIFY(!dir.exists(tempname)); | 
| 565 |         QVERIFY(dir.exists("temporary-file.txt" )); | 
| 566 |         QCOMPARE(file.fileName(), QString("temporary-file.txt" )); | 
| 567 |     } | 
| 568 |  | 
| 569 |     QVERIFY(!dir.exists(tempname)); | 
| 570 |     QVERIFY(!dir.exists("temporary-file.txt" )); | 
| 571 | } | 
| 572 |  | 
| 573 | void tst_QTemporaryFile::renameFdLeak() | 
| 574 | { | 
| 575 | #if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID) | 
| 576 |     const QByteArray sourceFile = QFile::encodeName(QFINDTESTDATA(__FILE__)); | 
| 577 |     QVERIFY(!sourceFile.isEmpty()); | 
| 578 |     // Test this on Unix only | 
| 579 |  | 
| 580 |     // Open a bunch of files to force the fd count to go up | 
| 581 |     static const int count = 10; | 
| 582 |     int bunch_of_files[count]; | 
| 583 |     for (int i = 0; i < count; ++i) { | 
| 584 |         bunch_of_files[i] = ::open(file: sourceFile.constData(), O_RDONLY); | 
| 585 |         QVERIFY(bunch_of_files[i] != -1); | 
| 586 |     } | 
| 587 |  | 
| 588 |     int fd; | 
| 589 |     { | 
| 590 |         QTemporaryFile file; | 
| 591 |         file.setAutoRemove(false); | 
| 592 |         QVERIFY(file.open()); | 
| 593 |  | 
| 594 |         // close the bunch of files | 
| 595 |         for (int i = 0; i < count; ++i) | 
| 596 |             ::close(fd: bunch_of_files[i]); | 
| 597 |  | 
| 598 |         // save the file descriptor for later | 
| 599 |         fd = file.handle(); | 
| 600 |  | 
| 601 |         // rename the file to something | 
| 602 |         QString newPath = QDir::tempPath() + "/tst_qtemporaryfile-renameFdLeak-"  + QString::number(getpid()); | 
| 603 |         file.rename(newName: newPath); | 
| 604 |         QFile::remove(fileName: newPath); | 
| 605 |     } | 
| 606 |  | 
| 607 |     // check if QTemporaryFile closed the file | 
| 608 |     QVERIFY(::close(fd) == -1 && errno == EBADF); | 
| 609 | #endif | 
| 610 | } | 
| 611 |  | 
| 612 | void tst_QTemporaryFile::reOpenThroughQFile() | 
| 613 | { | 
| 614 |     QByteArray data("abcdefghij" ); | 
| 615 |  | 
| 616 |     QTemporaryFile file; | 
| 617 |     QVERIFY(((QFile &)file).open(QIODevice::WriteOnly)); | 
| 618 |     QCOMPARE(file.write(data), (qint64)data.size()); | 
| 619 |  | 
| 620 |     file.close(); | 
| 621 |     QVERIFY(file.open()); | 
| 622 |     QCOMPARE(file.readAll(), data); | 
| 623 | } | 
| 624 |  | 
| 625 | void tst_QTemporaryFile::keepOpenMode() | 
| 626 | { | 
| 627 |     QByteArray data("abcdefghij" ); | 
| 628 |  | 
| 629 |     { | 
| 630 |         QTemporaryFile file; | 
| 631 |         QVERIFY(((QFile &)file).open(QIODevice::WriteOnly)); | 
| 632 |         QVERIFY(QIODevice::WriteOnly == file.openMode()); | 
| 633 |  | 
| 634 |         QCOMPARE(file.write(data), (qint64)data.size()); | 
| 635 |         file.close(); | 
| 636 |  | 
| 637 |         QVERIFY(((QFile &)file).open(QIODevice::ReadOnly)); | 
| 638 |         QVERIFY(QIODevice::ReadOnly == file.openMode()); | 
| 639 |         QCOMPARE(file.readAll(), data); | 
| 640 |     } | 
| 641 |  | 
| 642 |     { | 
| 643 |         QTemporaryFile file; | 
| 644 |         QVERIFY(file.open()); | 
| 645 |         QCOMPARE(file.openMode(), QIODevice::ReadWrite); | 
| 646 |         QCOMPARE(file.write(data), (qint64)data.size()); | 
| 647 |         QVERIFY(file.rename("temporary-file.txt" )); | 
| 648 |  | 
| 649 |         QVERIFY(((QFile &)file).open(QIODevice::ReadOnly)); | 
| 650 |         QCOMPARE(file.openMode(), QIODevice::ReadOnly); | 
| 651 |         QCOMPARE(file.readAll(), data); | 
| 652 |  | 
| 653 |         QVERIFY(((QFile &)file).open(QIODevice::WriteOnly)); | 
| 654 |         QCOMPARE(file.openMode(), QIODevice::WriteOnly); | 
| 655 |     } | 
| 656 | } | 
| 657 |  | 
| 658 | void tst_QTemporaryFile::resetTemplateAfterError() | 
| 659 | { | 
| 660 |     // calling setFileTemplate on a failed open | 
| 661 |  | 
| 662 |     QString tempPath = QDir::tempPath(); | 
| 663 |  | 
| 664 |     QString const fileTemplate("destination/qt_temp_file_test.XXXXXX" ); | 
| 665 |     QString const fileTemplate2(tempPath + "/qt_temp_file_test.XXXXXX" ); | 
| 666 |  | 
| 667 |     QVERIFY2( QDir(tempPath).exists() || QDir().mkpath(tempPath), "Test precondition"  ); | 
| 668 |     QVERIFY2( !QFile::exists("destination" ), "Test precondition"  ); | 
| 669 |     QVERIFY2( !QFile::exists(fileTemplate2) || QFile::remove(fileTemplate2), "Test precondition"  ); | 
| 670 |  | 
| 671 |     QFile file(fileTemplate2); | 
| 672 |     QByteArray fileContent("This file is intentionally NOT left empty." ); | 
| 673 |  | 
| 674 |     QVERIFY( file.open(QIODevice::ReadWrite | QIODevice::Truncate) ); | 
| 675 |     QCOMPARE( file.write(fileContent), (qint64)fileContent.size() ); | 
| 676 |     QVERIFY( file.flush() ); | 
| 677 |  | 
| 678 |     QString fileName; | 
| 679 |     { | 
| 680 |         QTemporaryFile temp; | 
| 681 |  | 
| 682 |         QVERIFY( temp.fileName().isEmpty() ); | 
| 683 |         QVERIFY( !temp.fileTemplate().isEmpty() ); | 
| 684 |  | 
| 685 |         temp.setFileTemplate( fileTemplate ); | 
| 686 |  | 
| 687 |         QVERIFY( temp.fileName().isEmpty() ); | 
| 688 |         QCOMPARE( temp.fileTemplate(), fileTemplate ); | 
| 689 |  | 
| 690 |         QVERIFY( !temp.open() ); | 
| 691 |  | 
| 692 |         QVERIFY( temp.fileName().isEmpty() ); | 
| 693 |         QCOMPARE( temp.fileTemplate(), fileTemplate ); | 
| 694 |  | 
| 695 |         temp.setFileTemplate( fileTemplate2 ); | 
| 696 |         QVERIFY( temp.open() ); | 
| 697 |  | 
| 698 |         fileName = temp.fileName(); | 
| 699 |         QVERIFY( QFile::exists(fileName) ); | 
| 700 |         QVERIFY( !fileName.isEmpty() ); | 
| 701 |         QVERIFY2( fileName != fileTemplate2, | 
| 702 |             ("Generated name shouldn't be same as template: "  + fileTemplate2).toLocal8Bit().constData() ); | 
| 703 |     } | 
| 704 |  | 
| 705 |     QVERIFY( !QFile::exists(fileName) ); | 
| 706 |  | 
| 707 |     file.seek(offset: 0); | 
| 708 |     QCOMPARE( QString(file.readAll()), QString(fileContent) ); | 
| 709 |     QVERIFY( file.remove() ); | 
| 710 | } | 
| 711 |  | 
| 712 | void tst_QTemporaryFile::setTemplateAfterOpen() | 
| 713 | { | 
| 714 |     QTemporaryFile temp; | 
| 715 |  | 
| 716 |     QVERIFY( temp.fileName().isEmpty() ); | 
| 717 |     QVERIFY( !temp.fileTemplate().isEmpty() ); | 
| 718 |  | 
| 719 |     QVERIFY( temp.open() ); | 
| 720 |  | 
| 721 |     QString const fileName = temp.fileName(); | 
| 722 |     QString const newTemplate("funny-path/funny-name-XXXXXX.tmp" ); | 
| 723 |  | 
| 724 |     QVERIFY( !fileName.isEmpty() ); | 
| 725 |     QVERIFY( QFile::exists(fileName) ); | 
| 726 |     QVERIFY( !temp.fileTemplate().isEmpty() ); | 
| 727 |     QVERIFY( temp.fileTemplate() != newTemplate ); | 
| 728 |  | 
| 729 |     temp.close(); // QTemporaryFile::setFileTemplate will assert on isOpen() up to 4.5.2 | 
| 730 |     temp.setFileTemplate(newTemplate); | 
| 731 |     QCOMPARE( temp.fileTemplate(), newTemplate ); | 
| 732 |  | 
| 733 |     QVERIFY( temp.open() ); | 
| 734 |     QCOMPARE( temp.fileName(), fileName ); | 
| 735 |     QCOMPARE( temp.fileTemplate(), newTemplate ); | 
| 736 | } | 
| 737 |  | 
| 738 | void tst_QTemporaryFile::autoRemoveAfterFailedRename() | 
| 739 | { | 
| 740 |     struct CleanOnReturn | 
| 741 |     { | 
| 742 |         ~CleanOnReturn() | 
| 743 |         { | 
| 744 |             if (!tempName.isEmpty()) | 
| 745 |                 QFile::remove(fileName: tempName); | 
| 746 |         } | 
| 747 |  | 
| 748 |         void reset() | 
| 749 |         { | 
| 750 |             tempName.clear(); | 
| 751 |         } | 
| 752 |  | 
| 753 |         QString tempName; | 
| 754 |     }; | 
| 755 |  | 
| 756 |     CleanOnReturn cleaner; | 
| 757 |  | 
| 758 |     { | 
| 759 |         QTemporaryFile file; | 
| 760 |         QVERIFY( file.open() ); | 
| 761 |         cleaner.tempName = file.fileName(); | 
| 762 |  | 
| 763 |         QVERIFY( QFile::exists(cleaner.tempName) ); | 
| 764 |         QVERIFY( !QFileInfo("i-do-not-exist" ).isDir() ); | 
| 765 |         QVERIFY( !file.rename("i-do-not-exist/file.txt" ) ); | 
| 766 |         QVERIFY( QFile::exists(cleaner.tempName) ); | 
| 767 |     } | 
| 768 |  | 
| 769 |     QVERIFY( !QFile::exists(cleaner.tempName) ); | 
| 770 |     cleaner.reset(); | 
| 771 | } | 
| 772 |  | 
| 773 | void tst_QTemporaryFile::createNativeFile_data() | 
| 774 | { | 
| 775 |     QTest::addColumn<QString>(name: "filePath" ); | 
| 776 |     QTest::addColumn<qint64>(name: "currentPos" ); | 
| 777 |     QTest::addColumn<bool>(name: "valid" ); | 
| 778 |     QTest::addColumn<QByteArray>(name: "content" ); | 
| 779 |  | 
| 780 | #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) | 
| 781 |     const QString nativeFilePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QStringLiteral("/resources/test.txt" ); | 
| 782 | #else | 
| 783 |     const QString nativeFilePath = QFINDTESTDATA("resources/test.txt" ); | 
| 784 | #endif | 
| 785 |  | 
| 786 |     // File might not exist locally in case of sandboxing or remote testing | 
| 787 |     if (!nativeFilePath.startsWith(s: QLatin1String(":/" ))) { | 
| 788 |         QTest::newRow(dataTag: "nativeFile" ) << nativeFilePath << (qint64)-1 << false << QByteArray(); | 
| 789 |         QTest::newRow(dataTag: "nativeFileWithPos" ) << nativeFilePath << (qint64)5 << false << QByteArray(); | 
| 790 |     } | 
| 791 |     QTest::newRow(dataTag: "resourceFile" ) << ":/resources/test.txt"  << (qint64)-1 << true << QByteArray("This is a test" ); | 
| 792 |     QTest::newRow(dataTag: "resourceFileWithPos" ) << ":/resources/test.txt"  << (qint64)5 << true << QByteArray("This is a test" ); | 
| 793 | } | 
| 794 |  | 
| 795 | void tst_QTemporaryFile::createNativeFile() | 
| 796 | { | 
| 797 |     QFETCH(QString, filePath); | 
| 798 |     QFETCH(qint64, currentPos); | 
| 799 |     QFETCH(bool, valid); | 
| 800 |     QFETCH(QByteArray, content); | 
| 801 |  | 
| 802 |     QFile f(filePath); | 
| 803 |     if (currentPos != -1) { | 
| 804 |         f.open(flags: QIODevice::ReadOnly); | 
| 805 |         f.seek(offset: currentPos); | 
| 806 |     } | 
| 807 |     QTemporaryFile *tempFile = QTemporaryFile::createNativeFile(file&: f); | 
| 808 |     QCOMPARE(valid, (bool)tempFile); | 
| 809 |     if (currentPos != -1) | 
| 810 |         QCOMPARE(currentPos, f.pos()); | 
| 811 |     if (valid) { | 
| 812 |         QCOMPARE(content, tempFile->readAll()); | 
| 813 |         delete tempFile; | 
| 814 |     } | 
| 815 | } | 
| 816 |  | 
| 817 | void tst_QTemporaryFile::QTBUG_4796_data() | 
| 818 | { | 
| 819 |     QTest::addColumn<QString>(name: "prefix" ); | 
| 820 |     QTest::addColumn<QString>(name: "suffix" ); | 
| 821 |     QTest::addColumn<bool>(name: "openResult" ); | 
| 822 |  | 
| 823 |     QString unicode = QString::fromUtf8(str: "\xc3\xa5\xc3\xa6\xc3\xb8" ); | 
| 824 |  | 
| 825 |     QTest::newRow(dataTag: "<empty>" ) << QString() << QString() << true; | 
| 826 |     QTest::newRow(dataTag: "." ) << QString("." ) << QString() << true; | 
| 827 |     QTest::newRow(dataTag: ".." ) << QString(".." ) << QString() << true; | 
| 828 |     QTest::newRow(dataTag: "blaXXXXXX" ) << QString("bla" ) << QString() << true; | 
| 829 |     QTest::newRow(dataTag: "XXXXXXbla" ) << QString() << QString("bla" ) << true; | 
| 830 |     QTest::newRow(dataTag: "does-not-exist/qt_temp.XXXXXX" ) << QString("does-not-exist/qt_temp" ) << QString() << false; | 
| 831 |  | 
| 832 |     if (QTestPrivate::canHandleUnicodeFileNames()) { | 
| 833 |         QTest::newRow(dataTag: "XXXXXX<unicode>" ) << QString() << unicode << true; | 
| 834 |         QTest::newRow(dataTag: "<unicode>XXXXXX" ) << unicode << QString() << true; | 
| 835 |         QTest::newRow(dataTag: "<unicode>XXXXXX<unicode>" ) << unicode << unicode << true; | 
| 836 |     } | 
| 837 | } | 
| 838 |  | 
| 839 | void tst_QTemporaryFile::QTBUG_4796() | 
| 840 | { | 
| 841 |     QVERIFY(QDir("test-XXXXXX" ).exists()); | 
| 842 |  | 
| 843 |     struct CleanOnReturn | 
| 844 |     { | 
| 845 |         ~CleanOnReturn() | 
| 846 |         { | 
| 847 |             Q_FOREACH(QString tempName, tempNames) | 
| 848 |                 QFile::remove(fileName: tempName); | 
| 849 |         } | 
| 850 |  | 
| 851 |         void reset() | 
| 852 |         { | 
| 853 |             tempNames.clear(); | 
| 854 |         } | 
| 855 |  | 
| 856 |         QStringList tempNames; | 
| 857 |     }; | 
| 858 |  | 
| 859 |     CleanOnReturn cleaner; | 
| 860 |  | 
| 861 |     QFETCH(QString, prefix); | 
| 862 |     QFETCH(QString, suffix); | 
| 863 |     QFETCH(bool, openResult); | 
| 864 |  | 
| 865 |     { | 
| 866 |         QString fileTemplate1 = prefix + QString("XX" ) + suffix; | 
| 867 |         QString fileTemplate2 = prefix + QString("XXXX" ) + suffix; | 
| 868 |         QString fileTemplate3 = prefix + QString("XXXXXX" ) + suffix; | 
| 869 |         QString fileTemplate4 = prefix + QString("XXXXXXXX" ) + suffix; | 
| 870 |  | 
| 871 |         QTemporaryFile file1(fileTemplate1); | 
| 872 |         QTemporaryFile file2(fileTemplate2); | 
| 873 |         QTemporaryFile file3(fileTemplate3); | 
| 874 |         QTemporaryFile file4(fileTemplate4); | 
| 875 |         QTemporaryFile file5("test-XXXXXX/"  + fileTemplate1); | 
| 876 |         QTemporaryFile file6("test-XXXXXX/"  + fileTemplate3); | 
| 877 |  | 
| 878 |         QCOMPARE(file1.open(), openResult); | 
| 879 |         QCOMPARE(file2.open(), openResult); | 
| 880 |         QCOMPARE(file3.open(), openResult); | 
| 881 |         QCOMPARE(file4.open(), openResult); | 
| 882 |         QCOMPARE(file5.open(), openResult); | 
| 883 |         QCOMPARE(file6.open(), openResult); | 
| 884 |  | 
| 885 |         // force the files to exist, if they are supposed to | 
| 886 |         QCOMPARE(!file1.fileName().isEmpty(), openResult); | 
| 887 |         QCOMPARE(!file2.fileName().isEmpty(), openResult); | 
| 888 |         QCOMPARE(!file3.fileName().isEmpty(), openResult); | 
| 889 |         QCOMPARE(!file4.fileName().isEmpty(), openResult); | 
| 890 |         QCOMPARE(!file5.fileName().isEmpty(), openResult); | 
| 891 |         QCOMPARE(!file6.fileName().isEmpty(), openResult); | 
| 892 |  | 
| 893 |         QCOMPARE(file1.exists(), openResult); | 
| 894 |         QCOMPARE(file2.exists(), openResult); | 
| 895 |         QCOMPARE(file3.exists(), openResult); | 
| 896 |         QCOMPARE(file4.exists(), openResult); | 
| 897 |         QCOMPARE(file5.exists(), openResult); | 
| 898 |         QCOMPARE(file6.exists(), openResult); | 
| 899 |  | 
| 900 |         // make sure the file exists under the *correct* name | 
| 901 |         if (openResult) { | 
| 902 |             cleaner.tempNames << file1.fileName() | 
| 903 |                 << file2.fileName() | 
| 904 |                 << file3.fileName() | 
| 905 |                 << file4.fileName() | 
| 906 |                 << file5.fileName() | 
| 907 |                 << file6.fileName(); | 
| 908 |  | 
| 909 |             QDir currentDir; | 
| 910 |             QString fileName1 = currentDir.relativeFilePath(fileName: file1.fileName()); | 
| 911 |             QString fileName2 = currentDir.relativeFilePath(fileName: file2.fileName()); | 
| 912 |             QString fileName3 = currentDir.relativeFilePath(fileName: file3.fileName()); | 
| 913 |             QString fileName4 = currentDir.relativeFilePath(fileName: file4.fileName()); | 
| 914 |             QString fileName5 = currentDir.relativeFilePath(fileName: file5.fileName()); | 
| 915 |             QString fileName6 = currentDir.relativeFilePath(fileName: file6.fileName()); | 
| 916 |  | 
| 917 |             QVERIFY(fileName1.startsWith(fileTemplate1 + QLatin1Char('.'))); | 
| 918 |             QVERIFY(fileName2.startsWith(fileTemplate2 + QLatin1Char('.'))); | 
| 919 |             QVERIFY(fileName5.startsWith("test-XXXXXX/"  + fileTemplate1 + QLatin1Char('.'))); | 
| 920 |             QVERIFY(fileName6.startsWith("test-XXXXXX/"  + prefix)); | 
| 921 |  | 
| 922 |             if (!prefix.isEmpty()) { | 
| 923 |                 QVERIFY(fileName3.startsWith(prefix)); | 
| 924 |                 QVERIFY(fileName4.startsWith(prefix)); | 
| 925 |             } | 
| 926 |  | 
| 927 |             if (!suffix.isEmpty()) { | 
| 928 |                 QVERIFY(fileName3.endsWith(suffix)); | 
| 929 |                 QVERIFY(fileName4.endsWith(suffix)); | 
| 930 |                 QVERIFY(fileName6.endsWith(suffix)); | 
| 931 |             } | 
| 932 |         } | 
| 933 |     } | 
| 934 |  | 
| 935 |     Q_FOREACH(QString const &tempName, cleaner.tempNames) | 
| 936 |         QVERIFY( !QFile::exists(tempName) ); | 
| 937 |  | 
| 938 |     cleaner.reset(); | 
| 939 | } | 
| 940 |  | 
| 941 | void tst_QTemporaryFile::guaranteeUnique() | 
| 942 | { | 
| 943 |     QDir dir(QDir::tempPath()); | 
| 944 |     QString takenFileName; | 
| 945 |  | 
| 946 |     // First pass. See which filename QTemporaryFile will try first. | 
| 947 |     { | 
| 948 |         QTemporaryFile tmpFile("testFile1.XXXXXX" ); | 
| 949 |         tmpFile.open(); | 
| 950 |         takenFileName = tmpFile.fileName(); | 
| 951 |         QVERIFY(QFile::exists(takenFileName)); | 
| 952 |     } | 
| 953 |  | 
| 954 |     QVERIFY(!QFile::exists(takenFileName)); | 
| 955 |  | 
| 956 |     // Create a directory with same name. | 
| 957 |     QVERIFY(dir.mkdir(takenFileName)); | 
| 958 |  | 
| 959 |     // Second pass, now we have blocked its first attempt with a directory. | 
| 960 |     { | 
| 961 |         QTemporaryFile tmpFile("testFile1.XXXXXX" ); | 
| 962 |         QVERIFY(tmpFile.open()); | 
| 963 |         QString uniqueFileName = tmpFile.fileName(); | 
| 964 |         QVERIFY(QFileInfo(uniqueFileName).isFile()); | 
| 965 |         QVERIFY(uniqueFileName != takenFileName); | 
| 966 |     } | 
| 967 |  | 
| 968 |     QVERIFY(dir.rmdir(takenFileName)); | 
| 969 | } | 
| 970 |  | 
| 971 | QTEST_MAIN(tst_QTemporaryFile) | 
| 972 | #include "tst_qtemporaryfile.moc" | 
| 973 |  |