New class QTemporaryDir.
As discussed on qt5-feedback / development lists. Change-Id: If1733369d12daa29054776ec2cbd78e63679768e Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
This commit is contained in:
parent
4d696d53b0
commit
e999c543a0
53
doc/src/snippets/code/src_corelib_io_qtemporarydir.cpp
Normal file
53
doc/src/snippets/code/src_corelib_io_qtemporarydir.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
** All rights reserved.
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
** This file is part of the documentation of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:BSD$
|
||||||
|
** You may use this file under the terms of the BSD license as follows:
|
||||||
|
**
|
||||||
|
** "Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are
|
||||||
|
** met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in
|
||||||
|
** the documentation and/or other materials provided with the
|
||||||
|
** distribution.
|
||||||
|
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||||
|
** the names of its contributors may be used to endorse or promote
|
||||||
|
** products derived from this software without specific prior written
|
||||||
|
** permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
{
|
||||||
|
//! [0]
|
||||||
|
// Within a function/method...
|
||||||
|
|
||||||
|
QTemporaryDir dir;
|
||||||
|
if (dir.isValid()) {
|
||||||
|
// dir.path() returns the unique directory path
|
||||||
|
}
|
||||||
|
|
||||||
|
// The QTemporaryDir destructor removes the temporary directory
|
||||||
|
// as it goes out of scope.
|
||||||
|
//! [0]
|
||||||
|
}
|
@ -20,6 +20,7 @@ HEADERS += \
|
|||||||
io/qprocess.h \
|
io/qprocess.h \
|
||||||
io/qprocess_p.h \
|
io/qprocess_p.h \
|
||||||
io/qtextstream.h \
|
io/qtextstream.h \
|
||||||
|
io/qtemporarydir.h \
|
||||||
io/qtemporaryfile.h \
|
io/qtemporaryfile.h \
|
||||||
io/qresource_p.h \
|
io/qresource_p.h \
|
||||||
io/qresource_iterator_p.h \
|
io/qresource_iterator_p.h \
|
||||||
@ -54,6 +55,7 @@ SOURCES += \
|
|||||||
io/qnoncontiguousbytedevice.cpp \
|
io/qnoncontiguousbytedevice.cpp \
|
||||||
io/qprocess.cpp \
|
io/qprocess.cpp \
|
||||||
io/qtextstream.cpp \
|
io/qtextstream.cpp \
|
||||||
|
io/qtemporarydir.cpp \
|
||||||
io/qtemporaryfile.cpp \
|
io/qtemporaryfile.cpp \
|
||||||
io/qresource.cpp \
|
io/qresource.cpp \
|
||||||
io/qresource_iterator.cpp \
|
io/qresource_iterator.cpp \
|
||||||
|
@ -67,11 +67,11 @@ public:
|
|||||||
|
|
||||||
static inline QStringList splitFilters(const QString &nameFilter, QChar sep = 0);
|
static inline QStringList splitFilters(const QString &nameFilter, QChar sep = 0);
|
||||||
|
|
||||||
inline void setPath(const QString &path);
|
void setPath(const QString &path);
|
||||||
|
|
||||||
inline void clearFileLists();
|
void clearFileLists();
|
||||||
|
|
||||||
inline void resolveAbsoluteEntry() const;
|
void resolveAbsoluteEntry() const;
|
||||||
|
|
||||||
QStringList nameFilters;
|
QStringList nameFilters;
|
||||||
QDir::SortFlags sort;
|
QDir::SortFlags sort;
|
||||||
|
258
src/corelib/io/qtemporarydir.cpp
Normal file
258
src/corelib/io/qtemporarydir.cpp
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
** All rights reserved.
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
** This file is part of the QtCore module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||||
|
** file. Please review the following information to ensure the GNU Lesser
|
||||||
|
** General Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU General
|
||||||
|
** Public License version 3.0 as published by the Free Software Foundation
|
||||||
|
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||||
|
** file. Please review the following information to ensure the GNU General
|
||||||
|
** Public License version 3.0 requirements will be met:
|
||||||
|
** http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qtemporarydir.h"
|
||||||
|
|
||||||
|
#ifndef QT_NO_TEMPORARYFILE
|
||||||
|
|
||||||
|
#include "qdiriterator.h"
|
||||||
|
#include "qplatformdefs.h"
|
||||||
|
#include "private/qdir_p.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#if defined(QT_BUILD_CORE_LIB)
|
||||||
|
#include "qcoreapplication.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h> // mkdtemp
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <private/qfsfileengine_p.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
//************* QTemporaryDirPrivate
|
||||||
|
class QTemporaryDirPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QTemporaryDirPrivate();
|
||||||
|
~QTemporaryDirPrivate();
|
||||||
|
|
||||||
|
QString defaultTemplateName() const;
|
||||||
|
void create(const QString &templateName);
|
||||||
|
|
||||||
|
QString path;
|
||||||
|
bool autoRemove;
|
||||||
|
bool success;
|
||||||
|
};
|
||||||
|
|
||||||
|
QTemporaryDirPrivate::QTemporaryDirPrivate()
|
||||||
|
: autoRemove(true),
|
||||||
|
success(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QTemporaryDirPrivate::~QTemporaryDirPrivate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QTemporaryDirPrivate::defaultTemplateName() const
|
||||||
|
{
|
||||||
|
QString baseName;
|
||||||
|
#if defined(QT_BUILD_CORE_LIB)
|
||||||
|
baseName = QCoreApplication::applicationName();
|
||||||
|
if (baseName.isEmpty())
|
||||||
|
#endif
|
||||||
|
baseName = QLatin1String("qt_temp");
|
||||||
|
|
||||||
|
return QDir::tempPath() + QLatin1Char('/') + baseName + QLatin1String("-XXXXXX");
|
||||||
|
}
|
||||||
|
|
||||||
|
void QTemporaryDirPrivate::create(const QString &templateName)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QString buffer = templateName;
|
||||||
|
// Windows' mktemp believes 26 temp files per process ought to be enough for everyone (!)
|
||||||
|
// Let's add a few random chars then, before the XXXXXX template.
|
||||||
|
for (int i = 0 ; i < 4 ; ++i)
|
||||||
|
buffer += QChar((qrand() & 0xffff) % (26) + 'A');
|
||||||
|
if (!buffer.endsWith(QLatin1String("XXXXXX")))
|
||||||
|
buffer += QLatin1String("XXXXXX");
|
||||||
|
QFileSystemEntry baseEntry(buffer);
|
||||||
|
QFileSystemEntry::NativePath basePath = baseEntry.nativeFilePath();
|
||||||
|
wchar_t* array = (wchar_t*)basePath.utf16();
|
||||||
|
if (_wmktemp(array) && ::CreateDirectory(array, 0)) {
|
||||||
|
success = true;
|
||||||
|
QFileSystemEntry entry(QString::fromWCharArray(array), QFileSystemEntry::FromNativePath());
|
||||||
|
path = entry.filePath();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
QByteArray buffer = QFile::encodeName(templateName);
|
||||||
|
if (!buffer.endsWith("XXXXXX"))
|
||||||
|
buffer += "XXXXXX";
|
||||||
|
if (mkdtemp(buffer.data())) { // modifies buffer
|
||||||
|
success = true;
|
||||||
|
path = QFile::decodeName(buffer.constData());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//************* QTemporaryDir
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QTemporaryDir
|
||||||
|
\reentrant
|
||||||
|
\brief The QTemporaryDir class creates a unique directory for temporary use.
|
||||||
|
|
||||||
|
\ingroup io
|
||||||
|
|
||||||
|
|
||||||
|
QTemporaryDir is used to create unique temporary dirs safely.
|
||||||
|
The dir itself is created by the constructor. The name of the
|
||||||
|
temporary directory is guaranteed to be unique (i.e., you are
|
||||||
|
guaranteed to not overwrite an existing dir), and the directory will
|
||||||
|
subsequently be removed upon destruction of the QTemporaryDir
|
||||||
|
object. The directory name is either auto-generated, or created based
|
||||||
|
on a template, which is passed to QTemporaryDir's constructor.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
\snippet doc/src/snippets/code/src_corelib_io_qtemporarydir.cpp 0
|
||||||
|
|
||||||
|
It is very important to test that the temporary directory could be
|
||||||
|
created, using isValid(). Do not use exists(), since a default-constructed
|
||||||
|
QDir represents the current directory, which exists.
|
||||||
|
|
||||||
|
The path to the temporary dir can be found by calling path().
|
||||||
|
|
||||||
|
A temporary directory will have some static part of the name and some
|
||||||
|
part that is calculated to be unique. The default path will be
|
||||||
|
determined from QCoreApplication::applicationName() (otherwise \c qt_temp) and will
|
||||||
|
be placed into the temporary path as returned by QDir::tempPath().
|
||||||
|
If you specify your own path, a relative path will not be placed in the
|
||||||
|
temporary directory by default, but be relative to the current working directory.
|
||||||
|
In all cases, a random string will be appended to the path in order to make it unique.
|
||||||
|
|
||||||
|
\sa QDir::tempPath(), QDir, QTemporaryFile
|
||||||
|
*/
|
||||||
|
|
||||||
|
QTemporaryDir::QTemporaryDir()
|
||||||
|
: d_ptr(new QTemporaryDirPrivate)
|
||||||
|
{
|
||||||
|
d_ptr->create(d_ptr->defaultTemplateName());
|
||||||
|
}
|
||||||
|
|
||||||
|
QTemporaryDir::QTemporaryDir(const QString &templateName)
|
||||||
|
: d_ptr(new QTemporaryDirPrivate)
|
||||||
|
{
|
||||||
|
if (templateName.isEmpty())
|
||||||
|
d_ptr->create(d_ptr->defaultTemplateName());
|
||||||
|
else
|
||||||
|
d_ptr->create(templateName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Destroys the temporary directory object.
|
||||||
|
If auto remove mode was set, it will automatically delete the directory
|
||||||
|
including all its contents.
|
||||||
|
|
||||||
|
\sa autoRemove()
|
||||||
|
*/
|
||||||
|
QTemporaryDir::~QTemporaryDir()
|
||||||
|
{
|
||||||
|
if (d_ptr->success && d_ptr->autoRemove)
|
||||||
|
remove();
|
||||||
|
delete d_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns true if the QTemporaryDir was created successfully.
|
||||||
|
*/
|
||||||
|
bool QTemporaryDir::isValid() const
|
||||||
|
{
|
||||||
|
return d_ptr->success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the path to the temporary directory.
|
||||||
|
Empty if the QTemporaryDir could not be created.
|
||||||
|
*/
|
||||||
|
QString QTemporaryDir::path() const
|
||||||
|
{
|
||||||
|
return d_ptr->path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns true if the QTemporaryDir is in auto remove
|
||||||
|
mode. Auto-remove mode will automatically delete the directory from
|
||||||
|
disk upon destruction. This makes it very easy to create your
|
||||||
|
QTemporaryDir object on the stack, fill it with files, do something with
|
||||||
|
the files, and finally on function return it will automatically clean up
|
||||||
|
after itself.
|
||||||
|
|
||||||
|
Auto-remove is on by default.
|
||||||
|
|
||||||
|
\sa setAutoRemove(), remove()
|
||||||
|
*/
|
||||||
|
bool QTemporaryDir::autoRemove() const
|
||||||
|
{
|
||||||
|
return d_ptr->autoRemove;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sets the QTemporaryDir into auto-remove mode if \a b is true.
|
||||||
|
|
||||||
|
Auto-remove is on by default.
|
||||||
|
|
||||||
|
\sa autoRemove(), remove()
|
||||||
|
*/
|
||||||
|
void QTemporaryDir::setAutoRemove(bool b)
|
||||||
|
{
|
||||||
|
d_ptr->autoRemove = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Removes the temporary directory, including all its contents.
|
||||||
|
*/
|
||||||
|
bool QTemporaryDir::remove()
|
||||||
|
{
|
||||||
|
if (!d_ptr->success)
|
||||||
|
return false;
|
||||||
|
Q_ASSERT(!path().isEmpty());
|
||||||
|
Q_ASSERT(path() != QLatin1String("."));
|
||||||
|
|
||||||
|
return QDir(path()).removeRecursively();
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // QT_NO_TEMPORARYFILE
|
84
src/corelib/io/qtemporarydir.h
Normal file
84
src/corelib/io/qtemporarydir.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
** All rights reserved.
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
** This file is part of the QtCore module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||||
|
** file. Please review the following information to ensure the GNU Lesser
|
||||||
|
** General Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU General
|
||||||
|
** Public License version 3.0 as published by the Free Software Foundation
|
||||||
|
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||||
|
** file. Please review the following information to ensure the GNU General
|
||||||
|
** Public License version 3.0 requirements will be met:
|
||||||
|
** http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QTEMPORARYDIR_H
|
||||||
|
#define QTEMPORARYDIR_H
|
||||||
|
|
||||||
|
#include <QtCore/qdir.h>
|
||||||
|
|
||||||
|
QT_BEGIN_HEADER
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
QT_MODULE(Core)
|
||||||
|
|
||||||
|
#ifndef QT_NO_TEMPORARYFILE
|
||||||
|
|
||||||
|
class QTemporaryDirPrivate;
|
||||||
|
|
||||||
|
class Q_CORE_EXPORT QTemporaryDir
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QTemporaryDir();
|
||||||
|
explicit QTemporaryDir(const QString &templateName);
|
||||||
|
~QTemporaryDir();
|
||||||
|
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
|
bool autoRemove() const;
|
||||||
|
void setAutoRemove(bool b);
|
||||||
|
bool remove();
|
||||||
|
|
||||||
|
QString path() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTemporaryDirPrivate* const d_ptr;
|
||||||
|
|
||||||
|
Q_DISABLE_COPY(QTemporaryDir)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QT_NO_TEMPORARYFILE
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
QT_END_HEADER
|
||||||
|
|
||||||
|
#endif // QTEMPORARYDIR_H
|
@ -16,6 +16,7 @@ SUBDIRS=\
|
|||||||
qresourceengine \
|
qresourceengine \
|
||||||
qsettings \
|
qsettings \
|
||||||
qstandardpaths \
|
qstandardpaths \
|
||||||
|
qtemporarydir \
|
||||||
qtemporaryfile \
|
qtemporaryfile \
|
||||||
qtextstream \
|
qtextstream \
|
||||||
qurl \
|
qurl \
|
||||||
|
7
tests/auto/corelib/io/qtemporarydir/qtemporarydir.pro
Normal file
7
tests/auto/corelib/io/qtemporarydir/qtemporarydir.pro
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
CONFIG += testcase
|
||||||
|
TARGET = tst_qtemporarydir
|
||||||
|
SOURCES += tst_qtemporarydir.cpp
|
||||||
|
|
||||||
|
QT = core testlib
|
||||||
|
|
||||||
|
CONFIG += parallel_test
|
471
tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp
Normal file
471
tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp
Normal file
@ -0,0 +1,471 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
** All rights reserved.
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
** This file is part of the test suite of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
** This file may be used under the terms of the GNU Lesser General Public
|
||||||
|
** License version 2.1 as published by the Free Software Foundation and
|
||||||
|
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||||
|
** file. Please review the following information to ensure the GNU Lesser
|
||||||
|
** General Public License version 2.1 requirements will be met:
|
||||||
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** In addition, as a special exception, Nokia gives you certain additional
|
||||||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU General
|
||||||
|
** Public License version 3.0 as published by the Free Software Foundation
|
||||||
|
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||||
|
** file. Please review the following information to ensure the GNU General
|
||||||
|
** Public License version 3.0 requirements will be met:
|
||||||
|
** http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
**
|
||||||
|
** Other Usage
|
||||||
|
** Alternatively, this file may be used in accordance with the terms and
|
||||||
|
** conditions contained in a signed written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include <QtTest/QtTest>
|
||||||
|
#include <qcoreapplication.h>
|
||||||
|
#include <qstring.h>
|
||||||
|
#include <qtemporarydir.h>
|
||||||
|
#include <qfile.h>
|
||||||
|
#include <qdir.h>
|
||||||
|
#include <qset.h>
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//TESTED_CLASS=QTemporaryDir
|
||||||
|
//TESTED_FILES=qtemporarydir.cpp
|
||||||
|
|
||||||
|
class tst_QTemporaryDir : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
tst_QTemporaryDir();
|
||||||
|
virtual ~tst_QTemporaryDir();
|
||||||
|
public slots:
|
||||||
|
void init();
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
|
void initTestCase();
|
||||||
|
void cleanupTestCase();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void construction();
|
||||||
|
void fileTemplate();
|
||||||
|
void fileTemplate_data();
|
||||||
|
void getSetCheck();
|
||||||
|
void fileName();
|
||||||
|
void autoRemove();
|
||||||
|
void nonWritableCurrentDir();
|
||||||
|
void openOnRootDrives();
|
||||||
|
void stressTest();
|
||||||
|
void rename();
|
||||||
|
void autoRemoveAfterFailedRename();
|
||||||
|
|
||||||
|
void QTBUG_4796_data();
|
||||||
|
void QTBUG_4796();
|
||||||
|
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::initTestCase()
|
||||||
|
{
|
||||||
|
QVERIFY(QDir("test-XXXXXX").exists() || QDir().mkdir("test-XXXXXX"));
|
||||||
|
QCoreApplication::setApplicationName("tst_qtemporarydir");
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::cleanupTestCase()
|
||||||
|
{
|
||||||
|
QVERIFY(QDir().rmdir("test-XXXXXX"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::construction()
|
||||||
|
{
|
||||||
|
QTemporaryDir dir;
|
||||||
|
QString tmp = QDir::tempPath();
|
||||||
|
QCOMPARE(dir.path().left(tmp.size()), tmp);
|
||||||
|
QVERIFY(dir.path().contains("tst_qtemporarydir"));
|
||||||
|
QVERIFY(QFileInfo(dir.path()).isDir());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Testing get/set functions
|
||||||
|
void tst_QTemporaryDir::getSetCheck()
|
||||||
|
{
|
||||||
|
QTemporaryDir obj1;
|
||||||
|
// bool QTemporaryDir::autoRemove()
|
||||||
|
// void QTemporaryDir::setAutoRemove(bool)
|
||||||
|
obj1.setAutoRemove(false);
|
||||||
|
QCOMPARE(false, obj1.autoRemove());
|
||||||
|
obj1.setAutoRemove(true);
|
||||||
|
QCOMPARE(true, obj1.autoRemove());
|
||||||
|
}
|
||||||
|
|
||||||
|
tst_QTemporaryDir::tst_QTemporaryDir()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
tst_QTemporaryDir::~tst_QTemporaryDir()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::init()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::cleanup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::fileTemplate_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("constructorTemplate");
|
||||||
|
QTest::addColumn<QString>("prefix");
|
||||||
|
|
||||||
|
QTest::newRow("constructor default") << "" << "tst_qtemporarydir-";
|
||||||
|
|
||||||
|
QTest::newRow("constructor with xxx sufix") << "qt_XXXXXXxxx" << "qt_XXXXXXxxx";
|
||||||
|
QTest::newRow("constructor with xXx sufix") << "qt_XXXXXXxXx" << "qt_XXXXXXxXx";
|
||||||
|
QTest::newRow("constructor with no suffix") << "qt_XXXXXX" << "qt_";
|
||||||
|
QTest::newRow("constructor with >6 X's, no suffix") << "qt_XXXXXXXXXX" << "qt_XXXX";
|
||||||
|
QTest::newRow("constructor with XXXX suffix") << "qt_XXXXXX_XXXX" << "qt_";
|
||||||
|
QTest::newRow("constructor with XXXX prefix") << "qt_XXXX" << "qt_XXXX";
|
||||||
|
QTest::newRow("constructor with XXXXX prefix") << "qt_XXXXX" << "qt_XXXXX";
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::fileTemplate()
|
||||||
|
{
|
||||||
|
QFETCH(QString, constructorTemplate);
|
||||||
|
QFETCH(QString, prefix);
|
||||||
|
|
||||||
|
QTemporaryDir tempDir(constructorTemplate);
|
||||||
|
|
||||||
|
QVERIFY(tempDir.isValid());
|
||||||
|
|
||||||
|
QString dirName = QDir(tempDir.path()).dirName();
|
||||||
|
if (prefix.length())
|
||||||
|
QCOMPARE(dirName.left(prefix.length()), prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
This tests whether the temporary dir really gets placed in QDir::tempPath
|
||||||
|
*/
|
||||||
|
void tst_QTemporaryDir::fileName()
|
||||||
|
{
|
||||||
|
// Get QDir::tempPath and make an absolute path.
|
||||||
|
QString tempPath = QDir::tempPath();
|
||||||
|
QString absoluteTempPath = QDir(tempPath).absolutePath();
|
||||||
|
QTemporaryDir dir;
|
||||||
|
dir.setAutoRemove(true);
|
||||||
|
QString fileName = dir.path();
|
||||||
|
QVERIFY2(fileName.contains("/tst_qtemporarydir-"), qPrintable(fileName));
|
||||||
|
QVERIFY(QFile::exists(fileName));
|
||||||
|
// Get path to the temp dir, without the file name.
|
||||||
|
QString absoluteFilePath = QFileInfo(fileName).absolutePath();
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
absoluteFilePath = absoluteFilePath.toLower();
|
||||||
|
absoluteTempPath = absoluteTempPath.toLower();
|
||||||
|
#endif
|
||||||
|
QCOMPARE(absoluteFilePath, absoluteTempPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::autoRemove()
|
||||||
|
{
|
||||||
|
// Test auto remove
|
||||||
|
QString dirName;
|
||||||
|
{
|
||||||
|
QTemporaryDir dir("tempXXXXXX");
|
||||||
|
dir.setAutoRemove(true);
|
||||||
|
QVERIFY(dir.isValid());
|
||||||
|
dirName = dir.path();
|
||||||
|
}
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// Windows seems unreliable here: sometimes it says the directory still exists,
|
||||||
|
// immediately after we deleted it.
|
||||||
|
QTRY_VERIFY(!QFile::exists(dirName));
|
||||||
|
#else
|
||||||
|
QVERIFY(!QFile::exists(dirName));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Test if disabling auto remove works.
|
||||||
|
{
|
||||||
|
QTemporaryDir dir("tempXXXXXX");
|
||||||
|
dir.setAutoRemove(false);
|
||||||
|
QVERIFY(dir.isValid());
|
||||||
|
dirName = dir.path();
|
||||||
|
}
|
||||||
|
QVERIFY(QFile::exists(dirName));
|
||||||
|
QVERIFY(QDir().rmdir(dirName));
|
||||||
|
QVERIFY(!QFile::exists(dirName));
|
||||||
|
|
||||||
|
// Do not explicitly call setAutoRemove (tests if it really is the default as documented)
|
||||||
|
{
|
||||||
|
QTemporaryDir dir("tempXXXXXX");
|
||||||
|
QVERIFY(dir.isValid());
|
||||||
|
dirName = dir.path();
|
||||||
|
}
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QTRY_VERIFY(!QFile::exists(dirName));
|
||||||
|
#else
|
||||||
|
QVERIFY(!QFile::exists(dirName));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Test autoremove with files and subdirs in the temp dir
|
||||||
|
{
|
||||||
|
QTemporaryDir tempDir("tempXXXXXX");
|
||||||
|
QVERIFY(tempDir.isValid());
|
||||||
|
dirName = tempDir.path();
|
||||||
|
QDir dir(dirName);
|
||||||
|
QVERIFY(dir.mkdir(QString::fromLatin1("dir1")));
|
||||||
|
QVERIFY(dir.mkdir(QString::fromLatin1("dir2")));
|
||||||
|
QVERIFY(dir.mkdir(QString::fromLatin1("dir2/nested")));
|
||||||
|
QFile file(dirName + "/dir1/file");
|
||||||
|
QVERIFY(file.open(QIODevice::WriteOnly));
|
||||||
|
QCOMPARE(file.write("Hello"), 5LL);
|
||||||
|
}
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QTRY_VERIFY(!QFile::exists(dirName));
|
||||||
|
#else
|
||||||
|
QVERIFY(!QFile::exists(dirName));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::nonWritableCurrentDir()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
QString cwd = QDir::currentPath();
|
||||||
|
QDir::setCurrent("/");
|
||||||
|
// QTemporaryDir("tempXXXXXX") is probably a bad idea in any app
|
||||||
|
// where the current dir could anything...
|
||||||
|
QString fileName;
|
||||||
|
QTemporaryDir dir("tempXXXXXX");
|
||||||
|
dir.setAutoRemove(true);
|
||||||
|
QVERIFY(!dir.isValid());
|
||||||
|
fileName = dir.path();
|
||||||
|
QDir::setCurrent(cwd);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::openOnRootDrives()
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
|
||||||
|
unsigned int lastErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||||
|
#endif
|
||||||
|
// If it's possible to create a dir in the root directory, it
|
||||||
|
// must be possible to create a temp dir there too.
|
||||||
|
foreach (const QFileInfo &driveInfo, QDir::drives()) {
|
||||||
|
QFile testFile(driveInfo.filePath() + "XXXXXX.txt");
|
||||||
|
if (testFile.open(QIODevice::ReadWrite)) {
|
||||||
|
testFile.remove();
|
||||||
|
QTemporaryDir dir(driveInfo.filePath() + "XXXXXX.txt");
|
||||||
|
dir.setAutoRemove(true);
|
||||||
|
QVERIFY(dir.isValid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
|
||||||
|
SetErrorMode(lastErrorMode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::stressTest()
|
||||||
|
{
|
||||||
|
const int iterations = 1000;
|
||||||
|
|
||||||
|
QSet<QString> names;
|
||||||
|
for (int i = 0; i < iterations; ++i) {
|
||||||
|
QTemporaryDir dir;
|
||||||
|
dir.setAutoRemove(false);
|
||||||
|
QVERIFY2(dir.isValid(), qPrintable(QString::number(i)));
|
||||||
|
QVERIFY(!names.contains(dir.path()));
|
||||||
|
names.insert(dir.path());
|
||||||
|
}
|
||||||
|
for (QSet<QString>::const_iterator it = names.constBegin(); it != names.constEnd(); ++it)
|
||||||
|
QDir(*it).removeRecursively();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::rename()
|
||||||
|
{
|
||||||
|
// This test checks what happens if the temporary dir is renamed.
|
||||||
|
// Then the autodelete feature can't possibly find it.
|
||||||
|
|
||||||
|
QDir dir;
|
||||||
|
QVERIFY(!dir.exists("temporary-dir.renamed"));
|
||||||
|
|
||||||
|
QString tempname;
|
||||||
|
{
|
||||||
|
QTemporaryDir tempDir(dir.filePath("temporary-dir.XXXXXX"));
|
||||||
|
|
||||||
|
QVERIFY(tempDir.isValid());
|
||||||
|
tempname = tempDir.path();
|
||||||
|
|
||||||
|
QVERIFY(QDir().rename(tempname, "temporary-dir.renamed"));
|
||||||
|
QVERIFY(!QDir(tempname).exists());
|
||||||
|
dir.setPath("temporary-dir.renamed");
|
||||||
|
QCOMPARE(dir.path(), QString("temporary-dir.renamed"));
|
||||||
|
QVERIFY(dir.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-delete couldn't find it
|
||||||
|
QVERIFY(dir.exists());
|
||||||
|
// Clean up by hand
|
||||||
|
QVERIFY(dir.removeRecursively());
|
||||||
|
QVERIFY(!dir.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::autoRemoveAfterFailedRename()
|
||||||
|
{
|
||||||
|
struct CleanOnReturn
|
||||||
|
{
|
||||||
|
~CleanOnReturn()
|
||||||
|
{
|
||||||
|
if (!tempName.isEmpty())
|
||||||
|
QVERIFY(QDir(tempName).removeRecursively());
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
tempName.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString tempName;
|
||||||
|
};
|
||||||
|
|
||||||
|
CleanOnReturn cleaner;
|
||||||
|
|
||||||
|
{
|
||||||
|
QTemporaryDir dir;
|
||||||
|
QVERIFY(dir.isValid());
|
||||||
|
cleaner.tempName = dir.path();
|
||||||
|
|
||||||
|
QVERIFY(QFile::exists(cleaner.tempName));
|
||||||
|
QVERIFY(!QFileInfo("i-do-not-exist").isDir());
|
||||||
|
QVERIFY(!QDir().rename(cleaner.tempName, "i-do-not-exist/dir.txt"));
|
||||||
|
QVERIFY(QFile::exists(cleaner.tempName));
|
||||||
|
}
|
||||||
|
|
||||||
|
QVERIFY(!QFile::exists(cleaner.tempName));
|
||||||
|
cleaner.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::QTBUG_4796_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("prefix");
|
||||||
|
QTest::addColumn<QString>("suffix");
|
||||||
|
QTest::addColumn<bool>("openResult");
|
||||||
|
|
||||||
|
QString unicode = QString::fromUtf8("\xc3\xa5\xc3\xa6\xc3\xb8");
|
||||||
|
|
||||||
|
QTest::newRow("<empty>") << QString() << QString() << true;
|
||||||
|
QTest::newRow(".") << QString(".") << QString() << true;
|
||||||
|
QTest::newRow("..") << QString("..") << QString() << true;
|
||||||
|
QTest::newRow("blaXXXXXX") << QString("bla") << QString() << true;
|
||||||
|
QTest::newRow("does-not-exist/qt_temp.XXXXXX") << QString("does-not-exist/qt_temp") << QString() << false;
|
||||||
|
QTest::newRow("XXXXXX<unicode>") << QString() << unicode << true;
|
||||||
|
QTest::newRow("<unicode>XXXXXX") << unicode << QString() << true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QTemporaryDir::QTBUG_4796()
|
||||||
|
{
|
||||||
|
QVERIFY(QDir("test-XXXXXX").exists());
|
||||||
|
|
||||||
|
struct CleanOnReturn
|
||||||
|
{
|
||||||
|
~CleanOnReturn()
|
||||||
|
{
|
||||||
|
foreach (const QString &tempName, tempNames)
|
||||||
|
QVERIFY(QDir(tempName).removeRecursively());
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
tempNames.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList tempNames;
|
||||||
|
};
|
||||||
|
|
||||||
|
CleanOnReturn cleaner;
|
||||||
|
|
||||||
|
QFETCH(QString, prefix);
|
||||||
|
QFETCH(QString, suffix);
|
||||||
|
QFETCH(bool, openResult);
|
||||||
|
|
||||||
|
{
|
||||||
|
QString fileTemplate1 = prefix + QString("XX") + suffix;
|
||||||
|
QString fileTemplate2 = prefix + QString("XXXX") + suffix;
|
||||||
|
QString fileTemplate3 = prefix + QString("XXXXXX") + suffix;
|
||||||
|
QString fileTemplate4 = prefix + QString("XXXXXXXX") + suffix;
|
||||||
|
|
||||||
|
QTemporaryDir dir1(fileTemplate1);
|
||||||
|
QTemporaryDir dir2(fileTemplate2);
|
||||||
|
QTemporaryDir dir3(fileTemplate3);
|
||||||
|
QTemporaryDir dir4(fileTemplate4);
|
||||||
|
QTemporaryDir dir5("test-XXXXXX/" + fileTemplate1);
|
||||||
|
QTemporaryDir dir6("test-XXXXXX/" + fileTemplate3);
|
||||||
|
|
||||||
|
QCOMPARE(dir1.isValid(), openResult);
|
||||||
|
QCOMPARE(dir2.isValid(), openResult);
|
||||||
|
QCOMPARE(dir3.isValid(), openResult);
|
||||||
|
QCOMPARE(dir4.isValid(), openResult);
|
||||||
|
QCOMPARE(dir5.isValid(), openResult);
|
||||||
|
QCOMPARE(dir6.isValid(), openResult);
|
||||||
|
|
||||||
|
// make sure the dir exists under the *correct* name
|
||||||
|
if (openResult) {
|
||||||
|
cleaner.tempNames << dir1.path()
|
||||||
|
<< dir2.path()
|
||||||
|
<< dir3.path()
|
||||||
|
<< dir4.path()
|
||||||
|
<< dir5.path()
|
||||||
|
<< dir6.path();
|
||||||
|
|
||||||
|
QDir currentDir;
|
||||||
|
QString fileName1 = currentDir.relativeFilePath(dir1.path());
|
||||||
|
QString fileName2 = currentDir.relativeFilePath(dir2.path());
|
||||||
|
QString fileName3 = currentDir.relativeFilePath(dir3.path());
|
||||||
|
QString fileName4 = currentDir.relativeFilePath(dir4.path());
|
||||||
|
QString fileName5 = currentDir.relativeFilePath(dir5.path());
|
||||||
|
QString fileName6 = currentDir.relativeFilePath(dir6.path());
|
||||||
|
|
||||||
|
QVERIFY(fileName1.startsWith(fileTemplate1));
|
||||||
|
QVERIFY(fileName2.startsWith(fileTemplate2));
|
||||||
|
QVERIFY(fileName5.startsWith("test-XXXXXX/" + fileTemplate1));
|
||||||
|
QVERIFY(fileName6.startsWith("test-XXXXXX/" + prefix));
|
||||||
|
|
||||||
|
if (!prefix.isEmpty()) {
|
||||||
|
QVERIFY(fileName3.startsWith(prefix));
|
||||||
|
QVERIFY(fileName4.startsWith(prefix));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QTest::qWait(20);
|
||||||
|
#endif
|
||||||
|
foreach (const QString &tempName, cleaner.tempNames)
|
||||||
|
QVERIFY2(!QFile::exists(tempName), qPrintable(tempName));
|
||||||
|
|
||||||
|
cleaner.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
QTEST_MAIN(tst_QTemporaryDir)
|
||||||
|
#include "tst_qtemporarydir.moc"
|
Loading…
Reference in New Issue
Block a user