1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the test suite of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
43
#include <QtTest/QtTest>
44
#include <qcoreapplication.h>
46
#include <qtemporarydir.h>
53
#ifdef Q_OS_UNIX // for geteuid()
54
# include <sys/types.h>
58
class tst_QTemporaryDir : public QObject
64
void cleanupTestCase();
69
void fileTemplate_data();
73
void nonWritableCurrentDir();
74
void openOnRootDrives();
78
void QTBUG_4796_data();
84
void tst_QTemporaryDir::initTestCase()
86
QVERIFY(QDir("test-XXXXXX").exists() || QDir().mkdir("test-XXXXXX"));
87
QCoreApplication::setApplicationName("tst_qtemporarydir");
90
void tst_QTemporaryDir::cleanupTestCase()
92
QVERIFY(QDir().rmdir("test-XXXXXX"));
95
void tst_QTemporaryDir::construction()
98
QString tmp = QDir::tempPath();
99
QCOMPARE(dir.path().left(tmp.size()), tmp);
100
QVERIFY(dir.path().contains("tst_qtemporarydir"));
101
QVERIFY(QFileInfo(dir.path()).isDir());
104
// Testing get/set functions
105
void tst_QTemporaryDir::getSetCheck()
108
// bool QTemporaryDir::autoRemove()
109
// void QTemporaryDir::setAutoRemove(bool)
110
obj1.setAutoRemove(false);
111
QCOMPARE(false, obj1.autoRemove());
112
obj1.setAutoRemove(true);
113
QCOMPARE(true, obj1.autoRemove());
116
void tst_QTemporaryDir::fileTemplate_data()
118
QTest::addColumn<QString>("constructorTemplate");
119
QTest::addColumn<QString>("prefix");
121
QTest::newRow("constructor default") << "" << "tst_qtemporarydir-";
123
QTest::newRow("constructor with xxx sufix") << "qt_XXXXXXxxx" << "qt_XXXXXXxxx";
124
QTest::newRow("constructor with xXx sufix") << "qt_XXXXXXxXx" << "qt_XXXXXXxXx";
125
QTest::newRow("constructor with no suffix") << "qt_XXXXXX" << "qt_";
126
QTest::newRow("constructor with >6 X's, no suffix") << "qt_XXXXXXXXXX" << "qt_";
127
// When more than 6 X are present at the end, linux and windows will only replace the last 6,
128
// while Mac OS will actually replace all of them so we can only expect "qt_" (and check isValid).
129
QTest::newRow("constructor with XXXX suffix") << "qt_XXXXXX_XXXX" << "qt_";
130
QTest::newRow("constructor with XXXX prefix") << "qt_XXXX" << "qt_";
131
QTest::newRow("constructor with XXXXX prefix") << "qt_XXXXX" << "qt_";
134
void tst_QTemporaryDir::fileTemplate()
136
QFETCH(QString, constructorTemplate);
137
QFETCH(QString, prefix);
139
QTemporaryDir tempDir(constructorTemplate);
141
QVERIFY(tempDir.isValid());
143
QString dirName = QDir(tempDir.path()).dirName();
145
QCOMPARE(dirName.left(prefix.length()), prefix);
150
This tests whether the temporary dir really gets placed in QDir::tempPath
152
void tst_QTemporaryDir::fileName()
154
// Get QDir::tempPath and make an absolute path.
155
QString tempPath = QDir::tempPath();
156
QString absoluteTempPath = QDir(tempPath).absolutePath();
158
dir.setAutoRemove(true);
159
QString fileName = dir.path();
160
QVERIFY2(fileName.contains("/tst_qtemporarydir-"), qPrintable(fileName));
161
QVERIFY(QDir(fileName).exists());
162
// Get path to the temp dir, without the file name.
163
QString absoluteFilePath = QFileInfo(fileName).absolutePath();
164
#if defined(Q_OS_WIN)
165
absoluteFilePath = absoluteFilePath.toLower();
166
absoluteTempPath = absoluteTempPath.toLower();
168
QCOMPARE(absoluteFilePath, absoluteTempPath);
171
void tst_QTemporaryDir::autoRemove()
176
QTemporaryDir dir("tempXXXXXX");
177
dir.setAutoRemove(true);
178
QVERIFY(dir.isValid());
179
dirName = dir.path();
182
// Windows seems unreliable here: sometimes it says the directory still exists,
183
// immediately after we deleted it.
184
QTRY_VERIFY(!QDir(dirName).exists());
186
QVERIFY(!QDir(dirName).exists());
189
// Test if disabling auto remove works.
191
QTemporaryDir dir("tempXXXXXX");
192
dir.setAutoRemove(false);
193
QVERIFY(dir.isValid());
194
dirName = dir.path();
196
QVERIFY(QDir(dirName).exists());
197
QVERIFY(QDir().rmdir(dirName));
198
QVERIFY(!QDir(dirName).exists());
200
// Do not explicitly call setAutoRemove (tests if it really is the default as documented)
202
QTemporaryDir dir("tempXXXXXX");
203
QVERIFY(dir.isValid());
204
dirName = dir.path();
207
QTRY_VERIFY(!QDir(dirName).exists());
209
QVERIFY(!QDir(dirName).exists());
212
// Test autoremove with files and subdirs in the temp dir
214
QTemporaryDir tempDir("tempXXXXXX");
215
QVERIFY(tempDir.isValid());
216
dirName = tempDir.path();
218
QVERIFY(dir.mkdir(QString::fromLatin1("dir1")));
219
QVERIFY(dir.mkdir(QString::fromLatin1("dir2")));
220
QVERIFY(dir.mkdir(QString::fromLatin1("dir2/nested")));
221
QFile file(dirName + "/dir1/file");
222
QVERIFY(file.open(QIODevice::WriteOnly));
223
QCOMPARE(file.write("Hello"), 5LL);
226
QTRY_VERIFY(!QDir(dirName).exists());
228
QVERIFY(!QDir(dirName).exists());
232
void tst_QTemporaryDir::nonWritableCurrentDir()
235
if (::geteuid() == 0)
236
QSKIP("not valid running this test as root");
240
ChdirOnReturn(const QString& d) : dir(d) {}
242
QDir::setCurrent(dir);
246
ChdirOnReturn cor(QDir::currentPath());
248
QDir::setCurrent("/home");
249
// QTemporaryDir("tempXXXXXX") is probably a bad idea in any app
250
// where the current dir could anything...
251
QTemporaryDir dir("tempXXXXXX");
252
dir.setAutoRemove(true);
253
QVERIFY(!dir.isValid());
254
QVERIFY(dir.path().isEmpty());
258
void tst_QTemporaryDir::openOnRootDrives()
260
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
261
unsigned int lastErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
263
// If it's possible to create a file in the root directory, it
264
// must be possible to create a temp dir there too.
265
foreach (const QFileInfo &driveInfo, QDir::drives()) {
266
QFile testFile(driveInfo.filePath() + "XXXXXX");
267
if (testFile.open(QIODevice::ReadWrite)) {
269
QTemporaryDir dir(driveInfo.filePath() + "XXXXXX");
270
dir.setAutoRemove(true);
271
QVERIFY(dir.isValid());
274
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
275
SetErrorMode(lastErrorMode);
279
void tst_QTemporaryDir::stressTest()
281
const int iterations = 1000;
284
for (int i = 0; i < iterations; ++i) {
286
dir.setAutoRemove(false);
287
QVERIFY2(dir.isValid(), qPrintable(QString::number(i)));
288
QVERIFY(!names.contains(dir.path()));
289
names.insert(dir.path());
291
for (QSet<QString>::const_iterator it = names.constBegin(); it != names.constEnd(); ++it)
292
QDir(*it).removeRecursively();
295
void tst_QTemporaryDir::rename()
297
// This test checks what happens if the temporary dir is renamed.
298
// Then the autodelete feature can't possibly find it.
301
QVERIFY(!dir.exists("temporary-dir.renamed"));
305
QTemporaryDir tempDir(dir.filePath("temporary-dir.XXXXXX"));
307
QVERIFY(tempDir.isValid());
308
tempname = tempDir.path();
310
QVERIFY(QDir().rename(tempname, "temporary-dir.renamed"));
311
QVERIFY(!QDir(tempname).exists());
312
dir.setPath("temporary-dir.renamed");
313
QCOMPARE(dir.path(), QString("temporary-dir.renamed"));
314
QVERIFY(dir.exists());
317
// Auto-delete couldn't find it
318
QVERIFY(dir.exists());
320
QVERIFY(dir.removeRecursively());
321
QVERIFY(!dir.exists());
324
void tst_QTemporaryDir::QTBUG_4796_data()
326
QTest::addColumn<QString>("prefix");
327
QTest::addColumn<QString>("suffix");
328
QTest::addColumn<bool>("openResult");
330
QString unicode = QString::fromUtf8("\xc3\xa5\xc3\xa6\xc3\xb8");
332
QTest::newRow("<empty>") << QString() << QString() << true;
333
QTest::newRow(".") << QString(".") << QString() << true;
334
QTest::newRow("..") << QString("..") << QString() << true;
335
QTest::newRow("blaXXXXXX") << QString("bla") << QString() << true;
336
QTest::newRow("does-not-exist/qt_temp.XXXXXX") << QString("does-not-exist/qt_temp") << QString() << false;
337
QTest::newRow("XXXXXX<unicode>") << QString() << unicode << true;
338
QTest::newRow("<unicode>XXXXXX") << unicode << QString() << true;
341
void tst_QTemporaryDir::QTBUG_4796() // unicode support
343
QVERIFY(QDir("test-XXXXXX").exists());
349
foreach (const QString &tempName, tempNames)
350
QVERIFY(QDir(tempName).removeRecursively());
358
QStringList tempNames;
361
CleanOnReturn cleaner;
363
QFETCH(QString, prefix);
364
QFETCH(QString, suffix);
365
QFETCH(bool, openResult);
368
QString fileTemplate1 = prefix + QString("XX") + suffix;
369
QString fileTemplate2 = prefix + QString("XXXX") + suffix;
370
QString fileTemplate3 = prefix + QString("XXXXXX") + suffix;
371
QString fileTemplate4 = prefix + QString("XXXXXXXX") + suffix;
373
QTemporaryDir dir1(fileTemplate1);
374
QTemporaryDir dir2(fileTemplate2);
375
QTemporaryDir dir3(fileTemplate3);
376
QTemporaryDir dir4(fileTemplate4);
377
QTemporaryDir dir5("test-XXXXXX/" + fileTemplate1);
378
QTemporaryDir dir6("test-XXXXXX/" + fileTemplate3);
380
QCOMPARE(dir1.isValid(), openResult);
381
QCOMPARE(dir2.isValid(), openResult);
382
QCOMPARE(dir3.isValid(), openResult);
383
QCOMPARE(dir4.isValid(), openResult);
384
QCOMPARE(dir5.isValid(), openResult);
385
QCOMPARE(dir6.isValid(), openResult);
387
// make sure the dir exists under the *correct* name
389
cleaner.tempNames << dir1.path()
397
QString fileName1 = currentDir.relativeFilePath(dir1.path());
398
QString fileName2 = currentDir.relativeFilePath(dir2.path());
399
QString fileName3 = currentDir.relativeFilePath(dir3.path());
400
QString fileName4 = currentDir.relativeFilePath(dir4.path());
401
QString fileName5 = currentDir.relativeFilePath(dir5.path());
402
QString fileName6 = currentDir.relativeFilePath(dir6.path());
404
QVERIFY(fileName1.startsWith(prefix));
405
QVERIFY(fileName2.startsWith(prefix));
406
QVERIFY(fileName5.startsWith("test-XXXXXX/" + prefix));
407
QVERIFY(fileName6.startsWith("test-XXXXXX/" + prefix));
409
if (!prefix.isEmpty()) {
410
QVERIFY(fileName3.startsWith(prefix));
411
QVERIFY(fileName4.startsWith(prefix));
419
foreach (const QString &tempName, cleaner.tempNames)
420
QVERIFY2(!QDir(tempName).exists(), qPrintable(tempName));
425
QTEST_MAIN(tst_QTemporaryDir)
426
#include "tst_qtemporarydir.moc"