summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/io
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/io')
-rw-r--r--tests/auto/corelib/io/io.pro8
-rw-r--r--tests/auto/corelib/io/qdatastream/tst_qdatastream.cpp2
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp54
-rw-r--r--tests/auto/corelib/io/qfile/stdinprocess/main.cpp2
-rw-r--r--tests/auto/corelib/io/qfile/tst_qfile.cpp33
-rw-r--r--tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp149
-rw-r--r--tests/auto/corelib/io/qlockfile/qlockfile.pro3
-rw-r--r--tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.cpp78
-rw-r--r--tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.pro7
-rw-r--r--tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp379
-rw-r--r--tests/auto/corelib/io/qlockfile/tst_qlockfile.pro6
-rw-r--r--tests/auto/corelib/io/qprocess/testForwarding/testForwarding.pro1
-rw-r--r--tests/auto/corelib/io/qprocess/testProcessEchoGui/main_win.cpp4
-rw-r--r--tests/auto/corelib/io/qprocess/testProcessNormal/testProcessNormal.pro1
-rw-r--r--tests/auto/corelib/io/qprocess/testProcessOutput/testProcessOutput.pro1
-rw-r--r--tests/auto/corelib/io/qprocess/testProcessSpacesArgs/twospaces.pro1
-rw-r--r--tests/auto/corelib/io/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro1
-rw-r--r--tests/auto/corelib/io/qprocess/testSoftExit/main_unix.cpp2
-rw-r--r--tests/auto/corelib/io/qprocess/testSoftExit/main_win.cpp2
-rw-r--r--tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro1
-rw-r--r--tests/auto/corelib/io/qprocess/testSpaceInName/testSpaceInName.pro1
-rw-r--r--tests/auto/corelib/io/qprocess/tst_qprocess.cpp21
-rw-r--r--tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp2
-rw-r--r--tests/auto/corelib/io/qsavefile/qsavefile.pro5
-rw-r--r--tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp339
-rw-r--r--tests/auto/corelib/io/qsettings/tst_qsettings.cpp2
-rw-r--r--tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp14
-rw-r--r--tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp35
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp48
-rw-r--r--tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp14
-rw-r--r--tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp13
31 files changed, 1136 insertions, 93 deletions
diff --git a/tests/auto/corelib/io/io.pro b/tests/auto/corelib/io/io.pro
index 03b42a2cbb..b3a51c6f6e 100644
--- a/tests/auto/corelib/io/io.pro
+++ b/tests/auto/corelib/io/io.pro
@@ -14,12 +14,14 @@ SUBDIRS=\
qfilesystemwatcher \
qiodevice \
qipaddress \
+ qlockfile \
qnodebug \
qprocess \
qprocess-noapplication \
qprocessenvironment \
qresourceengine \
qsettings \
+ qsavefile \
qstandardpaths \
qtemporarydir \
qtemporaryfile \
@@ -34,6 +36,12 @@ SUBDIRS=\
qwinoverlappedionotifier
}
+!qtHaveModule(network): SUBDIRS -= \
+ qfile \
+ qiodevice \
+ qprocess \
+ qtextstream
+
!contains(QT_CONFIG, private_tests): SUBDIRS -= \
qabstractfileengine \
qfileinfo \
diff --git a/tests/auto/corelib/io/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/io/qdatastream/tst_qdatastream.cpp
index 299d375c9c..d7fc76d980 100644
--- a/tests/auto/corelib/io/qdatastream/tst_qdatastream.cpp
+++ b/tests/auto/corelib/io/qdatastream/tst_qdatastream.cpp
@@ -883,7 +883,7 @@ static QBrush qBrushData(int index)
return custom;
}
case 7:
- QLinearGradient gradient(QPoint(2.718, 3.142), QPoint(3.1337, 42));
+ QLinearGradient gradient(QPointF(2.718, 3.142), QPointF(3.1337, 42));
gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
gradient.setSpread(QGradient::ReflectSpread);
gradient.setInterpolationMode(QGradient::ComponentInterpolation);
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
index 333ccc8e49..f452efc1b3 100644
--- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
+++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
@@ -52,7 +52,8 @@ private slots:
void warningWithoutDebug() const;
void criticalWithoutDebug() const;
void debugWithBool() const;
- void debugNoSpaces() const;
+ void debugSpaceHandling() const;
+ void stateSaver() const;
void veryLongWarningMessage() const;
void qDebugQStringRef() const;
void qDebugQLatin1String() const;
@@ -150,7 +151,36 @@ void tst_QDebug::debugWithBool() const
QCOMPARE(QString::fromLatin1(s_function), function);
}
-void tst_QDebug::debugNoSpaces() const
+class MyPoint
+{
+public:
+ MyPoint(int val1, int val2)
+ : v1(val1), v2(val2) {}
+ int v1;
+ int v2;
+};
+QDebug operator<< (QDebug s, const MyPoint& point)
+{
+ const QDebugStateSaver saver(s);
+ return s.nospace() << "MyPoint(" << point.v1 << ", " << point.v2 << ")";
+}
+
+class MyLine
+{
+public:
+ MyLine(const MyPoint& point1, const MyPoint& point2)
+ : p1(point1), p2(point2) {}
+ MyPoint p1;
+ MyPoint p2;
+};
+QDebug operator<< (QDebug s, const MyLine& line)
+{
+ const QDebugStateSaver saver(s);
+ s.nospace() << "MyLine(" << line.p1 << ", " << line.p2 << ")";
+ return s;
+}
+
+void tst_QDebug::debugSpaceHandling() const
{
MessageHandlerSetter mhs(myMessageHandler);
{
@@ -166,8 +196,26 @@ void tst_QDebug::debugNoSpaces() const
d << "key=" << "value";
d.space();
d << 1 << 2;
+ MyLine line(MyPoint(10, 11), MyPoint (12, 13));
+ d << line;
+ // With the old implementation of MyPoint doing dbg.nospace() << ...; dbg.space() we ended up with
+ // MyLine(MyPoint(10, 11) , MyPoint(12, 13) )
+ }
+ QCOMPARE(s_msg, QString::fromLatin1(" foo key=value 1 2 MyLine(MyPoint(10, 11), MyPoint(12, 13))"));
+}
+
+void tst_QDebug::stateSaver() const
+{
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ {
+ QDebugStateSaver saver(d);
+ d.nospace() << hex << right << qSetFieldWidth(3) << qSetPadChar('0') << 42;
+ }
+ d.space() << 42;
}
- QCOMPARE(s_msg, QString::fromLatin1(" foo key=value 1 2 "));
+ QCOMPARE(s_msg, QString::fromLatin1("02a 42 "));
}
void tst_QDebug::veryLongWarningMessage() const
diff --git a/tests/auto/corelib/io/qfile/stdinprocess/main.cpp b/tests/auto/corelib/io/qfile/stdinprocess/main.cpp
index 1c22da45b3..9ca531f615 100644
--- a/tests/auto/corelib/io/qfile/stdinprocess/main.cpp
+++ b/tests/auto/corelib/io/qfile/stdinprocess/main.cpp
@@ -50,7 +50,7 @@ int main(int argc, char *argv[])
printf("echos all its input to its output.\n");
return 1;
}
-
+
QFile file;
if (strcmp(argv[1], "all") == 0) {
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp
index df7b397481..929865d4d6 100644
--- a/tests/auto/corelib/io/qfile/tst_qfile.cpp
+++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp
@@ -80,6 +80,18 @@ QT_END_NAMESPACE
# include <sys/statfs.h>
#elif defined(Q_OS_WINCE)
# include <qplatformdefs.h>
+#elif defined(Q_OS_VXWORKS)
+# include <fcntl.h>
+#if defined(_WRS_KERNEL)
+#undef QT_OPEN
+#define QT_OPEN(path, oflag) ::open(path, oflag, 0)
+#endif
+#endif
+
+#ifdef Q_OS_QNX
+#ifdef open
+#undef open
+#endif
#endif
#include <stdio.h>
@@ -481,11 +493,6 @@ void tst_QFile::open_data()
QTest::addColumn<bool>("ok");
QTest::addColumn<QFile::FileError>("status");
-#ifdef Q_OS_MAC
- static const QString denied("Operation not permitted");
-#else
- static const QString denied("Permission denied");
-#endif
QTest::newRow( "exist_readOnly" )
<< m_testFile << int(QIODevice::ReadOnly)
<< true << QFile::NoError;
@@ -545,7 +552,7 @@ void tst_QFile::open()
QFETCH( bool, ok );
-#if defined(Q_OS_UNIX)
+#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
if (::getuid() == 0)
// root and Chuck Norris don't care for file permissions. Skip.
QSKIP("Running this test as root doesn't make sense");
@@ -1315,7 +1322,7 @@ void tst_QFile::copyFallback()
QVERIFY(QFile::exists("file-copy-destination.txt"));
QVERIFY(!file.isOpen());
- file.close();
+ file.close();
QFile::setPermissions("file-copy-destination.txt",
QFile::ReadOwner | QFile::WriteOwner);
}
@@ -2242,7 +2249,7 @@ static QByteArray getLargeDataBlock()
if (array.isNull())
{
-#if defined(Q_OS_WINCE)
+#if defined(Q_OS_WINCE) || defined(Q_OS_VXWORKS)
int resizeSize = 1024 * 1024; // WinCE does not have much space
#else
int resizeSize = 64 * 1024 * 1024;
@@ -2432,7 +2439,9 @@ void tst_QFile::rename()
#if defined(Q_OS_UNIX)
if (strcmp(QTest::currentDataTag(), "renamefile -> /etc/renamefile") == 0) {
+#if !defined(Q_OS_VXWORKS)
if (::getuid() == 0)
+#endif
QSKIP("Running this test as root doesn't make sense");
}
#endif
@@ -2919,8 +2928,8 @@ void tst_QFile::map()
// exotic test to make sure that multiple maps work
// note: windows ce does not reference count mutliple maps
- // it's essentially just the same reference but it
- // cause a resource lock on the file which prevents it
+ // it's essentially just the same reference but it
+ // cause a resource lock on the file which prevents it
// from being removed uchar *memory1 = file.map(0, file.size());
uchar *memory1 = file.map(0, file.size());
QCOMPARE(file.error(), QFile::NoError);
@@ -2941,6 +2950,7 @@ void tst_QFile::map()
file.close();
+#if !defined(Q_OS_VXWORKS)
#if defined(Q_OS_UNIX)
if (::getuid() != 0)
// root always has permissions
@@ -2955,6 +2965,7 @@ void tst_QFile::map()
QVERIFY(!memory);
QVERIFY(file.setPermissions(originalPermissions));
}
+#endif
QVERIFY(file.remove());
}
@@ -3336,7 +3347,7 @@ void tst_QFile::autocloseHandle()
{
QFile file("readonlyfile");
QVERIFY(openFile(file, QIODevice::ReadOnly, OpenStream, QFile::DontCloseHandle));
- QCOMPARE(file.handle(), QT_FILENO(stream_));
+ QCOMPARE(file.handle(), int(QT_FILENO(stream_)));
file.close();
QCOMPARE(file.handle(), -1);
//file is not closed, read should succeed
diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
index ded77c649f..bcc971bf4b 100644
--- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
@@ -46,6 +46,7 @@
#include <qcoreapplication.h>
#include <qlibrary.h>
#include <qtemporaryfile.h>
+#include <qtemporarydir.h>
#include <qdir.h>
#include <qfileinfo.h>
#ifdef Q_OS_UNIX
@@ -54,10 +55,11 @@
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
+#ifndef Q_OS_VXWORKS
#include <pwd.h>
#endif
+#endif
#ifdef Q_OS_WIN
-#define _WIN32_WINNT 0x500
#include <qt_windows.h>
#include <qlibrary.h>
#if !defined(Q_OS_WINCE)
@@ -72,6 +74,10 @@
#include <private/qfileinfo_p.h>
#include "../../../../shared/filesystem.h"
+#if defined(Q_OS_VXWORKS)
+#define Q_NO_SYMLINKS
+#endif
+
QT_BEGIN_NAMESPACE
extern Q_AUTOTEST_EXPORT bool qIsLikelyToBeNfs(int /* handle */);
QT_END_NAMESPACE
@@ -80,7 +86,11 @@ class tst_QFileInfo : public QObject
{
Q_OBJECT
+public:
+ tst_QFileInfo() : m_currentDir(QDir::currentPath()) {}
+
private slots:
+ void initTestCase();
void cleanupTestCase();
void getSetCheck();
@@ -190,32 +200,27 @@ private slots:
void invalidState();
void nonExistingFileDates();
+
+private:
+ const QString m_currentDir;
+ QString m_sourceFile;
+ QString m_resourcesDir;
+ QTemporaryDir m_dir;
};
-void tst_QFileInfo::cleanupTestCase()
+void tst_QFileInfo::initTestCase()
{
- QFile::remove("brokenlink.lnk");
- QFile::remove("link.lnk");
- QFile::remove("file1");
- QFile::remove("dummyfile");
- QFile::remove("simplefile.txt");
- QFile::remove("longFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileNamelongFileName.txt");
- QFile::remove("tempfile.txt");
+ m_sourceFile = QFINDTESTDATA("tst_qfileinfo.cpp");
+ QVERIFY(!m_sourceFile.isEmpty());
+ m_resourcesDir = QFINDTESTDATA("resources");
+ QVERIFY(!m_resourcesDir.isEmpty());
+ QVERIFY(m_dir.isValid());
+ QVERIFY(QDir::setCurrent(m_dir.path()));
+}
-#if defined(Q_OS_UNIX)
- QDir().rmdir("./.hidden-directory");
- QFile::remove("link_to_tst_qfileinfo");
-#endif
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
- QDir().rmdir("./hidden-directory");
- QDir().rmdir("abs_symlink");
- QDir().rmdir("rel_symlink");
- QDir().rmdir("junction_pwd");
- QDir().rmdir("junction_root");
- QDir().rmdir("mountpoint");
- QFile::remove("abs_symlink.cpp");
- QFile::remove("rel_symlink.cpp");
-#endif
+void tst_QFileInfo::cleanupTestCase()
+{
+ QDir::setCurrent(m_currentDir); // Release temporary directory so that it can be deleted on Windows
}
// Testing get/set functions
@@ -237,10 +242,9 @@ static QFileInfoPrivate* getPrivate(QFileInfo &info)
void tst_QFileInfo::copy()
{
- QTemporaryFile *t;
- t = new QTemporaryFile;
- t->open();
- QFileInfo info(t->fileName());
+ QTemporaryFile t;
+ t.open();
+ QFileInfo info(t.fileName());
QVERIFY(info.exists());
//copy constructor
@@ -287,7 +291,7 @@ void tst_QFileInfo::isFile_data()
QTest::addColumn<bool>("expected");
QTest::newRow("data0") << QDir::currentPath() << false;
- QTest::newRow("data1") << QFINDTESTDATA("tst_qfileinfo.cpp") << true;
+ QTest::newRow("data1") << m_sourceFile << true;
QTest::newRow("data2") << ":/tst_qfileinfo/resources/" << false;
QTest::newRow("data3") << ":/tst_qfileinfo/resources/file1" << true;
QTest::newRow("data4") << ":/tst_qfileinfo/resources/afilethatshouldnotexist" << false;
@@ -320,13 +324,13 @@ void tst_QFileInfo::isDir_data()
QTest::addColumn<bool>("expected");
QTest::newRow("data0") << QDir::currentPath() << true;
- QTest::newRow("data1") << QFINDTESTDATA("tst_qfileinfo.cpp") << false;
+ QTest::newRow("data1") << m_sourceFile << false;
QTest::newRow("data2") << ":/tst_qfileinfo/resources/" << true;
QTest::newRow("data3") << ":/tst_qfileinfo/resources/file1" << false;
QTest::newRow("data4") << ":/tst_qfileinfo/resources/afilethatshouldnotexist" << false;
- QTest::newRow("simple dir") << QFINDTESTDATA("resources") << true;
- QTest::newRow("simple dir with slash") << QFINDTESTDATA("resources/") << true;
+ QTest::newRow("simple dir") << m_resourcesDir << true;
+ QTest::newRow("simple dir with slash") << (m_resourcesDir + QLatin1Char('/')) << true;
QTest::newRow("broken link") << "brokenlink.lnk" << false;
@@ -366,8 +370,8 @@ void tst_QFileInfo::isRoot_data()
QTest::newRow("data4") << ":/tst_qfileinfo/resources/" << false;
QTest::newRow("data5") << ":/" << true;
- QTest::newRow("simple dir") << QFINDTESTDATA("resources") << false;
- QTest::newRow("simple dir with slash") << QFINDTESTDATA("resources/") << false;
+ QTest::newRow("simple dir") << m_resourcesDir << false;
+ QTest::newRow("simple dir with slash") << (m_resourcesDir + QLatin1Char('/')) << false;
#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE))
QTest::newRow("drive 1") << "c:" << false;
QTest::newRow("drive 2") << "c:/" << true;
@@ -398,21 +402,21 @@ void tst_QFileInfo::exists_data()
QTest::addColumn<bool>("expected");
QTest::newRow("data0") << QDir::currentPath() << true;
- QTest::newRow("data1") << QFINDTESTDATA("tst_qfileinfo.cpp") << true;
+ QTest::newRow("data1") << m_sourceFile << true;
QTest::newRow("data2") << "/I/do_not_expect_this_path_to_exist/" << false;
QTest::newRow("data3") << ":/tst_qfileinfo/resources/" << true;
QTest::newRow("data4") << ":/tst_qfileinfo/resources/file1" << true;
QTest::newRow("data5") << ":/I/do_not_expect_this_path_to_exist/" << false;
- QTest::newRow("data6") << (QFINDTESTDATA("resources/") + "*") << false;
- QTest::newRow("data7") << (QFINDTESTDATA("resources/") + "*.foo") << false;
- QTest::newRow("data8") << (QFINDTESTDATA("resources/") + "*.ext1") << false;
- QTest::newRow("data9") << (QFINDTESTDATA("resources/") + "file?.ext1") << false;
+ QTest::newRow("data6") << (m_resourcesDir + "/*") << false;
+ QTest::newRow("data7") << (m_resourcesDir + "/*.foo") << false;
+ QTest::newRow("data8") << (m_resourcesDir + "/*.ext1") << false;
+ QTest::newRow("data9") << (m_resourcesDir + "/file?.ext1") << false;
QTest::newRow("data10") << "." << true;
QTest::newRow("data11") << ". " << false;
QTest::newRow("empty") << "" << false;
- QTest::newRow("simple dir") << QFINDTESTDATA("resources") << true;
- QTest::newRow("simple dir with slash") << QFINDTESTDATA("resources/") << true;
+ QTest::newRow("simple dir") << m_resourcesDir << true;
+ QTest::newRow("simple dir with slash") << (m_resourcesDir + QLatin1Char('/')) << true;
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
QTest::newRow("unc 1") << "//" + QtNetworkSettings::winServerName() << true;
@@ -561,7 +565,7 @@ void tst_QFileInfo::canonicalFilePath()
// test symlinks
QFile::remove("link.lnk");
{
- QFile file(QFINDTESTDATA("tst_qfileinfo.cpp"));
+ QFile file(m_sourceFile);
if (file.link("link.lnk")) {
QFileInfo info1(file);
QFileInfo info2("link.lnk");
@@ -587,7 +591,7 @@ void tst_QFileInfo::canonicalFilePath()
QCOMPARE(info1.canonicalFilePath(), info2.canonicalFilePath());
QFileInfo info3(link + QDir::separator() + "link.lnk");
- QFileInfo info4(QFINDTESTDATA("tst_qfileinfo.cpp"));
+ QFileInfo info4(m_sourceFile);
QVERIFY(!info3.canonicalFilePath().isEmpty());
QCOMPARE(info4.canonicalFilePath(), info3.canonicalFilePath());
@@ -621,20 +625,21 @@ void tst_QFileInfo::canonicalFilePath()
// CreateSymbolicLink can return TRUE & still fail to create the link,
// the error code in that case is ERROR_PRIVILEGE_NOT_HELD (1314)
SetLastError(0);
- BOOL ret = ptrCreateSymbolicLink((wchar_t*)QString("res").utf16(), (wchar_t*)QString("resources").utf16(), 1);
+ const QString linkTarget = QStringLiteral("res");
+ BOOL ret = ptrCreateSymbolicLink((wchar_t*)linkTarget.utf16(), (wchar_t*)m_resourcesDir.utf16(), 1);
DWORD dwErr = GetLastError();
if (!ret)
QSKIP("Symbolic links aren't supported by FS");
QString currentPath = QDir::currentPath();
- bool is_res_Current = QDir::setCurrent("res");
+ bool is_res_Current = QDir::setCurrent(linkTarget);
if (!is_res_Current && dwErr == 1314)
QSKIP("Not enough privilages to create Symbolic links");
QCOMPARE(is_res_Current, true);
+ const QString actualCanonicalPath = QFileInfo("file1").canonicalFilePath();
+ QVERIFY(QDir::setCurrent(currentPath));
+ QCOMPARE(actualCanonicalPath, m_resourcesDir + QStringLiteral("/file1"));
- QCOMPARE(QFileInfo("file1").canonicalFilePath(), currentPath + "/resources/file1");
-
- QCOMPARE(QDir::setCurrent(currentPath), true);
- QDir::current().rmdir("res");
+ QDir::current().rmdir(linkTarget);
}
#endif
}
@@ -855,7 +860,7 @@ void tst_QFileInfo::permission_data()
QTest::addColumn<bool>("expected");
QTest::newRow("data0") << QCoreApplication::instance()->applicationFilePath() << int(QFile::ExeUser) << true;
- QTest::newRow("data1") << QFINDTESTDATA("tst_qfileinfo.cpp") << int(QFile::ReadUser) << true;
+ QTest::newRow("data1") << m_sourceFile << int(QFile::ReadUser) << true;
QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::ReadUser) << true;
QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::WriteUser) << false;
QTest::newRow("resource3") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::ExeUser) << false;
@@ -921,13 +926,15 @@ void tst_QFileInfo::compare_data()
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6)
caseSensitiveOnMac = false;
#endif
+ QString caseChangedSource = m_sourceFile;
+ caseChangedSource.replace("info", "Info");
QTest::newRow("data0")
- << QFINDTESTDATA("tst_qfileinfo.cpp")
- << QFINDTESTDATA("tst_qfileinfo.cpp")
+ << m_sourceFile
+ << m_sourceFile
<< true;
QTest::newRow("data1")
- << QFINDTESTDATA("tst_qfileinfo.cpp")
+ << m_sourceFile
<< QString::fromLatin1("/tst_qfileinfo.cpp")
<< false;
QTest::newRow("data2")
@@ -935,8 +942,8 @@ void tst_QFileInfo::compare_data()
<< QDir::currentPath() + QString::fromLatin1("/tst_qfileinfo.cpp")
<< true;
QTest::newRow("casesense1")
- << QFINDTESTDATA("tst_qfileinfo.cpp").replace("info", "Info")
- << QFINDTESTDATA("tst_qfileinfo.cpp")
+ << caseChangedSource
+ << m_sourceFile
#if defined(Q_OS_WIN)
<< true;
#elif defined(Q_OS_MAC)
@@ -1013,7 +1020,7 @@ void tst_QFileInfo::fileTimes()
QEXPECT_FAIL("longfile absolutepath", "No long filenames on WinCE", Abort);
#endif
QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
-#ifdef Q_OS_UNIX
+#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
if (qIsLikelyToBeNfs(file.handle()))
QSKIP("This Test doesn't work on NFS");
#endif
@@ -1140,7 +1147,7 @@ void tst_QFileInfo::isSymLink_data()
QFile::remove("brokenlink.lnk");
QFile::remove("dummyfile");
- QFile file1(QFINDTESTDATA("tst_qfileinfo.cpp"));
+ QFile file1(m_sourceFile);
QVERIFY(file1.link("link.lnk"));
QFile file2("dummyfile");
@@ -1152,8 +1159,8 @@ void tst_QFileInfo::isSymLink_data()
QTest::addColumn<bool>("isSymLink");
QTest::addColumn<QString>("linkTarget");
- QTest::newRow("existent file") << QFINDTESTDATA("tst_qfileinfo.cpp") << false << "";
- QTest::newRow("link") << "link.lnk" << true << QFileInfo(QFINDTESTDATA("tst_qfileinfo.cpp")).absoluteFilePath();
+ QTest::newRow("existent file") << m_sourceFile << false << "";
+ QTest::newRow("link") << "link.lnk" << true << QFileInfo(m_sourceFile).absoluteFilePath();
QTest::newRow("broken link") << "brokenlink.lnk" << true << QFileInfo("dummyfile").absoluteFilePath();
}
@@ -1390,7 +1397,7 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks_data()
}
{
//File symlinks
- QFileInfo target(QFINDTESTDATA("tst_qfileinfo.cpp"));
+ QFileInfo target(m_sourceFile);
QString absTarget = QDir::toNativeSeparators(target.absoluteFilePath());
QString absSymlink = QDir::toNativeSeparators(pwd.absolutePath()).append("\\abs_symlink.cpp");
QString relTarget = QDir::toNativeSeparators(pwd.relativeFilePath(target.absoluteFilePath()));
@@ -1447,10 +1454,22 @@ void tst_QFileInfo::ntfsJunctionPointsAndSymlinks()
QFETCH(QString, canonicalFilePath);
QFileInfo fi(path);
- QCOMPARE(fi.isSymLink(), isSymLink);
+ const bool actualIsSymLink = fi.isSymLink();
+ const QString actualSymLinkTarget = isSymLink ? fi.symLinkTarget() : QString();
+ const QString actualCanonicalFilePath = isSymLink ? fi.canonicalFilePath() : QString();
+ // Ensure that junctions, mountpoints are removed. If this fails, do not remove
+ // temporary directory to prevent it from trashing the system.
+ if (fi.isDir()) {
+ if (!QDir().rmdir(fi.fileName())) {
+ qWarning("Unable to remove NTFS junction '%s'', keeping '%s'.",
+ qPrintable(fi.fileName()), qPrintable(QDir::toNativeSeparators(m_dir.path())));
+ m_dir.setAutoRemove(false);
+ }
+ }
+ QCOMPARE(actualIsSymLink, isSymLink);
if (isSymLink) {
- QCOMPARE(fi.symLinkTarget(), linkTarget);
- QCOMPARE(fi.canonicalFilePath(), canonicalFilePath);
+ QCOMPARE(actualSymLinkTarget, linkTarget);
+ QCOMPARE(actualCanonicalFilePath, canonicalFilePath);
}
}
@@ -1499,7 +1518,7 @@ void tst_QFileInfo::isWritable()
#if defined (Q_OS_BLACKBERRY)
// The Blackberry filesystem is read-only
QVERIFY(!QFileInfo("/etc/passwd").isWritable());
-#elif defined (Q_OS_UNIX)
+#elif defined (Q_OS_UNIX) && !defined(Q_OS_VXWORKS) // VxWorks does not have users/groups
if (::getuid() == 0)
QVERIFY(QFileInfo("/etc/passwd").isWritable());
else
@@ -1698,7 +1717,7 @@ QT_END_NAMESPACE
void tst_QFileInfo::owner()
{
QString userName;
-#if defined(Q_OS_UNIX)
+#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
{
passwd *user = getpwuid(geteuid());
QVERIFY(user);
@@ -1761,7 +1780,7 @@ void tst_QFileInfo::owner()
void tst_QFileInfo::group()
{
QString expected;
-#if defined(Q_OS_UNIX)
+#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
struct group *gr;
gid_t gid = getegid();
diff --git a/tests/auto/corelib/io/qlockfile/qlockfile.pro b/tests/auto/corelib/io/qlockfile/qlockfile.pro
new file mode 100644
index 0000000000..91f104305c
--- /dev/null
+++ b/tests/auto/corelib/io/qlockfile/qlockfile.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+
+SUBDIRS += tst_qlockfile.pro qlockfiletesthelper/qlockfile_test_helper.pro
diff --git a/tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.cpp b/tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.cpp
new file mode 100644
index 0000000000..63f6291034
--- /dev/null
+++ b/tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include <QCoreApplication>
+#include <QLockFile>
+#include <QThread>
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+
+ if (argc <= 1)
+ return -1;
+
+ const QString lockName = QString::fromLocal8Bit(argv[1]);
+
+ QString option;
+ if (argc > 2)
+ option = QString::fromLocal8Bit(argv[2]);
+
+ if (option == "-crash") {
+ QLockFile *lockFile = new QLockFile(lockName);
+ lockFile->lock();
+ // leak the lockFile on purpose, so that the lock remains!
+ return 0;
+ } else if (option == "-busy") {
+ QLockFile lockFile(lockName);
+ lockFile.lock();
+ QThread::msleep(500);
+ return 0;
+ } else {
+ QLockFile lockFile(lockName);
+ if (lockFile.isLocked()) // cannot happen, before calling lock or tryLock
+ return QLockFile::UnknownError;
+
+ lockFile.tryLock();
+ return lockFile.error();
+ }
+}
diff --git a/tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.pro b/tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.pro
new file mode 100644
index 0000000000..3ac3be9c9b
--- /dev/null
+++ b/tests/auto/corelib/io/qlockfile/qlockfiletesthelper/qlockfile_test_helper.pro
@@ -0,0 +1,7 @@
+TARGET = qlockfile_test_helper
+SOURCES += qlockfile_test_helper.cpp
+
+CONFIG += console
+CONFIG -= app_bundle
+QT = core
+DESTDIR = ./
diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
new file mode 100644
index 0000000000..c0bf77cfb2
--- /dev/null
+++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.cpp
@@ -0,0 +1,379 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtConcurrentRun>
+#include <qlockfile.h>
+#include <qtemporarydir.h>
+
+class tst_QLockFile : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void lockUnlock();
+ void lockOutOtherProcess();
+ void lockOutOtherThread();
+ void waitForLock_data();
+ void waitForLock();
+ void staleLockFromCrashedProcess_data();
+ void staleLockFromCrashedProcess();
+ void staleShortLockFromBusyProcess();
+ void staleLongLockFromBusyProcess();
+ void staleLockRace();
+ void noPermissions();
+
+public:
+ QString m_helperApp;
+ QTemporaryDir dir;
+};
+
+void tst_QLockFile::initTestCase()
+{
+#ifdef QT_NO_PROCESS
+ QSKIP("This test requires QProcess support");
+#else
+ // chdir to our testdata path and execute helper apps relative to that.
+ QString testdata_dir = QFileInfo(QFINDTESTDATA("qlockfiletesthelper")).absolutePath();
+ QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir));
+ m_helperApp = "qlockfiletesthelper/qlockfile_test_helper";
+#endif
+}
+
+void tst_QLockFile::lockUnlock()
+{
+ const QString fileName = dir.path() + "/lock1";
+ QVERIFY(!QFile(fileName).exists());
+ QLockFile lockFile(fileName);
+ QVERIFY(lockFile.lock());
+ QVERIFY(lockFile.isLocked());
+ QCOMPARE(int(lockFile.error()), int(QLockFile::NoError));
+ QVERIFY(QFile::exists(fileName));
+
+ // Recursive locking is not allowed
+ // (can't test lock() here, it would wait forever)
+ QVERIFY(!lockFile.tryLock());
+ QCOMPARE(int(lockFile.error()), int(QLockFile::LockFailedError));
+ qint64 pid;
+ QString hostname, appname;
+ QVERIFY(lockFile.getLockInfo(&pid, &hostname, &appname));
+ QCOMPARE(pid, QCoreApplication::applicationPid());
+ QCOMPARE(appname, qAppName());
+ QVERIFY(!lockFile.tryLock(200));
+ QCOMPARE(int(lockFile.error()), int(QLockFile::LockFailedError));
+
+ // Unlock deletes the lock file
+ lockFile.unlock();
+ QCOMPARE(int(lockFile.error()), int(QLockFile::NoError));
+ QVERIFY(!lockFile.isLocked());
+ QVERIFY(!QFile::exists(fileName));
+}
+
+void tst_QLockFile::lockOutOtherProcess()
+{
+ // Lock
+ const QString fileName = dir.path() + "/lockOtherProcess";
+ QLockFile lockFile(fileName);
+ QVERIFY(lockFile.lock());
+
+ // Other process can't acquire lock
+ QProcess proc;
+ proc.start(m_helperApp, QStringList() << fileName);
+ QVERIFY2(proc.waitForStarted(), qPrintable(proc.errorString()));
+ QVERIFY(proc.waitForFinished());
+ QCOMPARE(proc.exitCode(), int(QLockFile::LockFailedError));
+
+ // Unlock
+ lockFile.unlock();
+ QVERIFY(!QFile::exists(fileName));
+
+ // Other process can now acquire lock
+ int ret = QProcess::execute(m_helperApp, QStringList() << fileName);
+ QCOMPARE(ret, int(QLockFile::NoError));
+ // Lock doesn't survive process though (on clean exit)
+ QVERIFY(!QFile::exists(fileName));
+}
+
+static QLockFile::LockError tryLockFromThread(const QString &fileName)
+{
+ QLockFile lockInThread(fileName);
+ lockInThread.tryLock();
+ return lockInThread.error();
+}
+
+void tst_QLockFile::lockOutOtherThread()
+{
+ const QString fileName = dir.path() + "/lockOtherThread";
+ QLockFile lockFile(fileName);
+ QVERIFY(lockFile.lock());
+
+ // Other thread can't acquire lock
+ QFuture<QLockFile::LockError> ret = QtConcurrent::run<QLockFile::LockError>(tryLockFromThread, fileName);
+ QCOMPARE(ret.result(), QLockFile::LockFailedError);
+
+ lockFile.unlock();
+
+ // Now other thread can acquire lock
+ QFuture<QLockFile::LockError> ret2 = QtConcurrent::run<QLockFile::LockError>(tryLockFromThread, fileName);
+ QCOMPARE(ret2.result(), QLockFile::NoError);
+}
+
+static bool lockFromThread(const QString &fileName, int sleepMs, QSemaphore *semThreadReady, QSemaphore *semMainThreadDone)
+{
+ QLockFile lockFile(fileName);
+ if (!lockFile.lock()) {
+ qWarning() << "Locking failed" << lockFile.error();
+ return false;
+ }
+ semThreadReady->release();
+ QThread::msleep(sleepMs);
+ semMainThreadDone->acquire();
+ lockFile.unlock();
+ return true;
+}
+
+void tst_QLockFile::waitForLock_data()
+{
+ QTest::addColumn<int>("testNumber");
+ QTest::addColumn<int>("threadSleepMs");
+ QTest::addColumn<bool>("releaseEarly");
+ QTest::addColumn<int>("tryLockTimeout");
+ QTest::addColumn<bool>("expectedResult");
+
+ int tn = 0; // test number
+ QTest::newRow("wait_forever_succeeds") << ++tn << 500 << true << -1 << true;
+ QTest::newRow("wait_longer_succeeds") << ++tn << 500 << true << 1000 << true;
+ QTest::newRow("wait_zero_fails") << ++tn << 500 << false << 0 << false;
+ QTest::newRow("wait_not_enough_fails") << ++tn << 500 << false << 100 << false;
+}
+
+void tst_QLockFile::waitForLock()
+{
+ QFETCH(int, testNumber);
+ QFETCH(int, threadSleepMs);
+ QFETCH(bool, releaseEarly);
+ QFETCH(int, tryLockTimeout);
+ QFETCH(bool, expectedResult);
+
+ const QString fileName = dir.path() + "/waitForLock" + QString::number(testNumber);
+ QLockFile lockFile(fileName);
+ QSemaphore semThreadReady, semMainThreadDone;
+ // Lock file from a thread
+ QFuture<bool> ret = QtConcurrent::run<bool>(lockFromThread, fileName, threadSleepMs, &semThreadReady, &semMainThreadDone);
+ semThreadReady.acquire();
+
+ if (releaseEarly) // let the thread release the lock after threadSleepMs
+ semMainThreadDone.release();
+
+ QCOMPARE(lockFile.tryLock(tryLockTimeout), expectedResult);
+ if (expectedResult)
+ QCOMPARE(int(lockFile.error()), int(QLockFile::NoError));
+ else
+ QCOMPARE(int(lockFile.error()), int(QLockFile::LockFailedError));
+
+ if (!releaseEarly) // only let the thread release the lock now
+ semMainThreadDone.release();
+
+ QVERIFY(ret); // waits for the thread to finish
+}
+
+void tst_QLockFile::staleLockFromCrashedProcess_data()
+{
+ QTest::addColumn<int>("staleLockTime");
+
+ // Test both use cases for QLockFile, should make no difference here.
+ QTest::newRow("short") << 30000;
+ QTest::newRow("long") << 0;
+}
+
+void tst_QLockFile::staleLockFromCrashedProcess()
+{
+ QFETCH(int, staleLockTime);
+ const QString fileName = dir.path() + "/staleLockFromCrashedProcess";
+
+ int ret = QProcess::execute(m_helperApp, QStringList() << fileName << "-crash");
+ QCOMPARE(ret, int(QLockFile::NoError));
+ QTRY_VERIFY(QFile::exists(fileName));
+
+ QLockFile secondLock(fileName);
+ secondLock.setStaleLockTime(staleLockTime);
+ // tryLock detects and removes the stale lock (since the PID is dead)
+#ifdef Q_OS_WIN
+ // It can take a bit of time on Windows, though.
+ QVERIFY(secondLock.tryLock(30000));
+#else
+ QVERIFY(secondLock.tryLock());
+#endif
+ QCOMPARE(int(secondLock.error()), int(QLockFile::NoError));
+}
+
+void tst_QLockFile::staleShortLockFromBusyProcess()
+{
+ const QString fileName = dir.path() + "/staleLockFromBusyProcess";
+
+ QProcess proc;
+ proc.start(m_helperApp, QStringList() << fileName << "-busy");
+ QVERIFY2(proc.waitForStarted(), qPrintable(proc.errorString()));
+ QTRY_VERIFY(QFile::exists(fileName));
+
+ QLockFile secondLock(fileName);
+ QVERIFY(!secondLock.tryLock()); // held by other process
+ QCOMPARE(int(secondLock.error()), int(QLockFile::LockFailedError));
+ qint64 pid;
+ QString hostname, appname;
+ QTRY_VERIFY(secondLock.getLockInfo(&pid, &hostname, &appname));
+#ifdef Q_OS_UNIX
+ QCOMPARE(pid, proc.pid());
+#endif
+
+ secondLock.setStaleLockTime(100);
+ QTest::qSleep(100); // make the lock stale
+ // We can't "steal" (delete+recreate) a lock file from a running process
+ // until the file descriptor is closed.
+ QVERIFY(!secondLock.tryLock());
+
+ proc.waitForFinished();
+ QVERIFY(secondLock.tryLock());
+}
+
+void tst_QLockFile::staleLongLockFromBusyProcess()
+{
+ const QString fileName = dir.path() + "/staleLockFromBusyProcess";
+
+ QProcess proc;
+ proc.start(m_helperApp, QStringList() << fileName << "-busy");
+ QVERIFY2(proc.waitForStarted(), qPrintable(proc.errorString()));
+ QTRY_VERIFY(QFile::exists(fileName));
+
+ QLockFile secondLock(fileName);
+ secondLock.setStaleLockTime(0);
+ QVERIFY(!secondLock.tryLock(100)); // never stale
+ QCOMPARE(int(secondLock.error()), int(QLockFile::LockFailedError));
+ qint64 pid;
+ QTRY_VERIFY(secondLock.getLockInfo(&pid, NULL, NULL));
+ QVERIFY(pid > 0);
+
+ // As long as the other process is running, we can't remove the lock file
+ QVERIFY(!secondLock.removeStaleLockFile());
+
+ proc.waitForFinished();
+}
+
+static QString tryStaleLockFromThread(const QString &fileName)
+{
+ QLockFile lockInThread(fileName + ".lock");
+ lockInThread.setStaleLockTime(1000);
+ if (!lockInThread.lock())
+ return "Error locking: " + QString::number(lockInThread.error());
+
+ // The concurrent use of the file below (write, read, delete) is protected by the lock file above.
+ // (provided that it doesn't become stale due to this operation taking too long)
+ QFile theFile(fileName);
+ if (!theFile.open(QIODevice::WriteOnly))
+ return "Couldn't open for write";
+ theFile.write("Hello world");
+ theFile.flush();
+ theFile.close();
+ QFile reader(fileName);
+ if (!reader.open(QIODevice::ReadOnly))
+ return "Couldn't open for read";
+ const QByteArray read = reader.readAll();
+ if (read != "Hello world")
+ return "File didn't have the expected contents:" + read;
+ reader.remove();
+ return QString();
+}
+
+void tst_QLockFile::staleLockRace()
+{
+ // Multiple threads notice a stale lock at the same time
+ // Only one thread should delete it, otherwise a race will ensue
+ const QString fileName = dir.path() + "/sharedFile";
+ const QString lockName = fileName + ".lock";
+ int ret = QProcess::execute(m_helperApp, QStringList() << lockName << "-crash");
+ QCOMPARE(ret, int(QLockFile::NoError));
+ QTRY_VERIFY(QFile::exists(lockName));
+
+ QThreadPool::globalInstance()->setMaxThreadCount(10);
+ QFutureSynchronizer<QString> synchronizer;
+ for (int i = 0; i < 8; ++i)
+ synchronizer.addFuture(QtConcurrent::run<QString>(tryStaleLockFromThread, fileName));
+ synchronizer.waitForFinished();
+ foreach (const QFuture<QString> &future, synchronizer.futures())
+ QVERIFY2(future.result().isEmpty(), qPrintable(future.result()));
+}
+
+void tst_QLockFile::noPermissions()
+{
+#ifdef Q_OS_WIN
+ // A readonly directory still allows us to create files, on Windows.
+ QSKIP("No permission testing on Windows");
+#endif
+ // Restore permissions so that the QTemporaryDir cleanup can happen
+ class PermissionRestorer
+ {
+ QString m_path;
+ public:
+ PermissionRestorer(const QString& path)
+ : m_path(path)
+ {}
+
+ ~PermissionRestorer()
+ {
+ QFile file(m_path);
+ file.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner));
+ }
+ };
+
+ const QString fileName = dir.path() + "/staleLock";
+ QFile dirAsFile(dir.path()); // I have to use QFile to change a dir's permissions...
+ QVERIFY2(dirAsFile.setPermissions(QFile::Permissions(0)), qPrintable(dir.path())); // no permissions
+ PermissionRestorer permissionRestorer(dir.path());
+
+ QLockFile lockFile(fileName);
+ QVERIFY(!lockFile.lock());
+ QCOMPARE(int(lockFile.error()), int(QLockFile::PermissionError));
+}
+
+QTEST_MAIN(tst_QLockFile)
+#include "tst_qlockfile.moc"
diff --git a/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro
new file mode 100644
index 0000000000..2f7009b736
--- /dev/null
+++ b/tests/auto/corelib/io/qlockfile/tst_qlockfile.pro
@@ -0,0 +1,6 @@
+CONFIG += testcase
+CONFIG -= app_bundle
+TARGET = tst_qlockfile
+SOURCES += tst_qlockfile.cpp
+
+QT = core testlib concurrent
diff --git a/tests/auto/corelib/io/qprocess/testForwarding/testForwarding.pro b/tests/auto/corelib/io/qprocess/testForwarding/testForwarding.pro
index 271c7ead13..45b498c32a 100644
--- a/tests/auto/corelib/io/qprocess/testForwarding/testForwarding.pro
+++ b/tests/auto/corelib/io/qprocess/testForwarding/testForwarding.pro
@@ -2,3 +2,4 @@ SOURCES = main.cpp
CONFIG -= app_bundle
CONFIG += console
DESTDIR = ./
+QT = core
diff --git a/tests/auto/corelib/io/qprocess/testProcessEchoGui/main_win.cpp b/tests/auto/corelib/io/qprocess/testProcessEchoGui/main_win.cpp
index 270666deb6..df96e1cbf3 100644
--- a/tests/auto/corelib/io/qprocess/testProcessEchoGui/main_win.cpp
+++ b/tests/auto/corelib/io/qprocess/testProcessEchoGui/main_win.cpp
@@ -50,8 +50,8 @@ int APIENTRY WinMain(HINSTANCE /* hInstance */,
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
-
- HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
+
+ HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
for (;;) {
diff --git a/tests/auto/corelib/io/qprocess/testProcessNormal/testProcessNormal.pro b/tests/auto/corelib/io/qprocess/testProcessNormal/testProcessNormal.pro
index f7c57abc37..f7bb0985a3 100644
--- a/tests/auto/corelib/io/qprocess/testProcessNormal/testProcessNormal.pro
+++ b/tests/auto/corelib/io/qprocess/testProcessNormal/testProcessNormal.pro
@@ -4,3 +4,4 @@ CONFIG -= qt app_bundle
DESTDIR = ./
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+QT = core
diff --git a/tests/auto/corelib/io/qprocess/testProcessOutput/testProcessOutput.pro b/tests/auto/corelib/io/qprocess/testProcessOutput/testProcessOutput.pro
index 3940ddbf98..2de4534896 100644
--- a/tests/auto/corelib/io/qprocess/testProcessOutput/testProcessOutput.pro
+++ b/tests/auto/corelib/io/qprocess/testProcessOutput/testProcessOutput.pro
@@ -3,3 +3,4 @@ CONFIG -= qt app_bundle
CONFIG += console
DESTDIR = ./
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+QT = core
diff --git a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/twospaces.pro b/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/twospaces.pro
index 43db95e675..8b16f65e34 100644
--- a/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/twospaces.pro
+++ b/tests/auto/corelib/io/qprocess/testProcessSpacesArgs/twospaces.pro
@@ -6,3 +6,4 @@ OBJECTS_DIR = $${OBJECTS_DIR}-twospaces
TARGET = "two space s"
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+QT = core
diff --git a/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro b/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro
index 86d26c2c4a..d425d5569e 100644
--- a/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro
+++ b/tests/auto/corelib/io/qprocess/testSetWorkingDirectory/testSetWorkingDirectory.pro
@@ -3,3 +3,4 @@ CONFIG += console
CONFIG -= app_bundle
DESTDIR = ./
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+QT = core
diff --git a/tests/auto/corelib/io/qprocess/testSoftExit/main_unix.cpp b/tests/auto/corelib/io/qprocess/testSoftExit/main_unix.cpp
index 02cc31168b..c7f5f88f9c 100644
--- a/tests/auto/corelib/io/qprocess/testSoftExit/main_unix.cpp
+++ b/tests/auto/corelib/io/qprocess/testSoftExit/main_unix.cpp
@@ -55,7 +55,7 @@ int main()
printf("Ready\n");
fflush(stdout);
-
+
for (int i = 0; i < 5; ++i)
sleep(1);
return 0;
diff --git a/tests/auto/corelib/io/qprocess/testSoftExit/main_win.cpp b/tests/auto/corelib/io/qprocess/testSoftExit/main_win.cpp
index bed8d921b3..e478a18bd6 100644
--- a/tests/auto/corelib/io/qprocess/testSoftExit/main_win.cpp
+++ b/tests/auto/corelib/io/qprocess/testSoftExit/main_win.cpp
@@ -53,6 +53,6 @@ int main()
if (msg.message == WM_CLOSE)
PostQuitMessage(0);
}
-
+
return int(msg.wParam);
}
diff --git a/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro b/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro
index c5fb286d0c..7f3b8ade3e 100644
--- a/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro
+++ b/tests/auto/corelib/io/qprocess/testSoftExit/testSoftExit.pro
@@ -10,3 +10,4 @@ CONFIG -= qt app_bundle
CONFIG += console
DESTDIR = ./
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+QT = core
diff --git a/tests/auto/corelib/io/qprocess/testSpaceInName/testSpaceInName.pro b/tests/auto/corelib/io/qprocess/testSpaceInName/testSpaceInName.pro
index d0848e3303..b7213ae507 100644
--- a/tests/auto/corelib/io/qprocess/testSpaceInName/testSpaceInName.pro
+++ b/tests/auto/corelib/io/qprocess/testSpaceInName/testSpaceInName.pro
@@ -7,3 +7,4 @@ mac {
CONFIG -= app_bundle
}
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+QT = core
diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
index 7965d1d431..f01e319872 100644
--- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
+++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
@@ -81,6 +81,7 @@ private slots:
void getSetCheck();
void constructing();
void simpleStart();
+ void startWithOpen();
void execute();
void startDetached();
void crashTest();
@@ -283,6 +284,25 @@ void tst_QProcess::simpleStart()
QCOMPARE(qvariant_cast<QProcess::ProcessState>(spy.at(1).at(0)), QProcess::Running);
QCOMPARE(qvariant_cast<QProcess::ProcessState>(spy.at(2).at(0)), QProcess::NotRunning);
}
+
+//-----------------------------------------------------------------------------
+void tst_QProcess::startWithOpen()
+{
+ QProcess p;
+ QTest::ignoreMessage(QtWarningMsg, "QProcess::start: program not set");
+ QCOMPARE(p.open(QIODevice::ReadOnly), false);
+
+ p.setProgram("testProcessNormal/testProcessNormal");
+ QCOMPARE(p.program(), QString("testProcessNormal/testProcessNormal"));
+
+ p.setArguments(QStringList() << "arg1" << "arg2");
+ QCOMPARE(p.arguments().size(), 2);
+
+ QVERIFY(p.open(QIODevice::ReadOnly));
+ QCOMPARE(p.openMode(), QIODevice::ReadOnly);
+ QVERIFY(p.waitForFinished(5000));
+}
+
//-----------------------------------------------------------------------------
void tst_QProcess::execute()
{
@@ -1256,7 +1276,6 @@ void tst_QProcess::waitForBytesWrittenInABytesWrittenSlot()
process->start("testProcessEcho/testProcessEcho");
QVERIFY(process->waitForStarted(5000));
- qRegisterMetaType<qint64>("qint64");
QSignalSpy spy(process, SIGNAL(bytesWritten(qint64)));
QVERIFY(spy.isValid());
process->write("f");
diff --git a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
index 11dbc1e9c1..515a10426c 100644
--- a/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
+++ b/tests/auto/corelib/io/qresourceengine/tst_qresourceengine.cpp
@@ -402,7 +402,7 @@ void tst_QResourceEngine::checkUnregisterResource_data()
QTest::addColumn<int>("size");
QTest::newRow("currentdir.txt") << QFINDTESTDATA("runtime_resource.rcc") << QString("/check_unregister/")
- << QString(":/check_unregister/runtime_resource/test/abc/123/+++/currentdir.txt")
+ << QString(":/check_unregister/runtime_resource/test/abc/123/+++/currentdir.txt")
<< (int)QFileInfo(QFINDTESTDATA("testqrc/currentdir.txt")).size();
}
diff --git a/tests/auto/corelib/io/qsavefile/qsavefile.pro b/tests/auto/corelib/io/qsavefile/qsavefile.pro
new file mode 100644
index 0000000000..36db000fa7
--- /dev/null
+++ b/tests/auto/corelib/io/qsavefile/qsavefile.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase parallel_test
+TARGET = tst_qsavefile
+QT = core testlib
+SOURCES = tst_qsavefile.cpp
+TESTDATA += tst_qsavefile.cpp
diff --git a/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp b/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp
new file mode 100644
index 0000000000..d9292b8460
--- /dev/null
+++ b/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp
@@ -0,0 +1,339 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 David Faure <faure@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <qcoreapplication.h>
+#include <qstring.h>
+#include <qtemporaryfile.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qset.h>
+
+#if defined(Q_OS_UNIX)
+# include <unistd.h> // for geteuid
+# include <sys/types.h>
+#endif
+
+#if defined(Q_OS_WIN)
+# include <windows.h>
+#endif
+
+class tst_QSaveFile : public QObject
+{
+ Q_OBJECT
+public slots:
+
+private slots:
+ void transactionalWrite();
+ void textStreamManualFlush();
+ void textStreamAutoFlush();
+ void saveTwice();
+ void transactionalWriteNoPermissionsOnDir_data();
+ void transactionalWriteNoPermissionsOnDir();
+ void transactionalWriteNoPermissionsOnFile();
+ void transactionalWriteCanceled();
+ void transactionalWriteErrorRenaming();
+};
+
+void tst_QSaveFile::transactionalWrite()
+{
+ QTemporaryDir dir;
+ const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
+ QFile::remove(targetFile);
+ QSaveFile file(targetFile);
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ QVERIFY(file.isOpen());
+ QCOMPARE(file.fileName(), targetFile);
+ QVERIFY(!QFile::exists(targetFile));
+
+ QCOMPARE(file.write("Hello"), Q_INT64_C(5));
+ QCOMPARE(file.error(), QFile::NoError);
+ QVERIFY(!QFile::exists(targetFile));
+
+ QVERIFY(file.commit());
+ QVERIFY(QFile::exists(targetFile));
+ QCOMPARE(file.fileName(), targetFile);
+
+ QFile reader(targetFile);
+ QVERIFY(reader.open(QIODevice::ReadOnly));
+ QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("Hello"));
+}
+
+void tst_QSaveFile::saveTwice()
+{
+ // Check that we can reuse a QSaveFile object
+ // (and test the case of an existing target file)
+ QTemporaryDir dir;
+ const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
+ QSaveFile file(targetFile);
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ QCOMPARE(file.write("Hello"), Q_INT64_C(5));
+ QVERIFY2(file.commit(), qPrintable(file.errorString()));
+
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ QCOMPARE(file.write("World"), Q_INT64_C(5));
+ QVERIFY2(file.commit(), qPrintable(file.errorString()));
+
+ QFile reader(targetFile);
+ QVERIFY(reader.open(QIODevice::ReadOnly));
+ QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("World"));
+}
+
+void tst_QSaveFile::textStreamManualFlush()
+{
+ QTemporaryDir dir;
+ const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
+ QSaveFile file(targetFile);
+ QVERIFY(file.open(QIODevice::WriteOnly));
+
+ QTextStream ts(&file);
+ ts << "Manual flush";
+ ts.flush();
+ QCOMPARE(file.error(), QFile::NoError);
+ QVERIFY(!QFile::exists(targetFile));
+
+ QVERIFY(file.commit());
+ QFile reader(targetFile);
+ QVERIFY(reader.open(QIODevice::ReadOnly));
+ QCOMPARE(QString::fromLatin1(reader.readAll().constData()), QString::fromLatin1("Manual flush"));
+ QFile::remove(targetFile);
+}
+
+void tst_QSaveFile::textStreamAutoFlush()
+{
+ QTemporaryDir dir;
+ const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
+ QSaveFile file(targetFile);
+ QVERIFY(file.open(QIODevice::WriteOnly));
+
+ QTextStream ts(&file);
+ ts << "Auto-flush.";
+ // no flush
+ QVERIFY(file.commit()); // QIODevice::close will emit aboutToClose, which will flush the stream
+ QFile reader(targetFile);
+ QVERIFY(reader.open(QIODevice::ReadOnly));
+ QCOMPARE(QString::fromLatin1(reader.readAll().constData()), QString::fromLatin1("Auto-flush."));
+ QFile::remove(targetFile);
+}
+
+void tst_QSaveFile::transactionalWriteNoPermissionsOnDir_data()
+{
+ QTest::addColumn<bool>("directWriteFallback");
+
+ QTest::newRow("default") << false;
+ QTest::newRow("directWriteFallback") << true;
+}
+
+void tst_QSaveFile::transactionalWriteNoPermissionsOnDir()
+{
+#ifdef Q_OS_UNIX
+ QFETCH(bool, directWriteFallback);
+ // Restore permissions so that the QTemporaryDir cleanup can happen
+ class PermissionRestorer
+ {
+ QString m_path;
+ public:
+ PermissionRestorer(const QString& path)
+ : m_path(path)
+ {}
+
+ ~PermissionRestorer()
+ {
+ restore();
+ }
+ void restore()
+ {
+ QFile file(m_path);
+ file.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner));
+ }
+ };
+
+
+ QTemporaryDir dir;
+ QVERIFY(QFile(dir.path()).setPermissions(QFile::ReadOwner | QFile::ExeOwner));
+ PermissionRestorer permissionRestorer(dir.path());
+
+ const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
+ QSaveFile firstTry(targetFile);
+ QVERIFY(!firstTry.open(QIODevice::WriteOnly));
+ QCOMPARE((int)firstTry.error(), (int)QFile::OpenError);
+ QVERIFY(!firstTry.commit());
+
+ // Now make an existing writable file
+ permissionRestorer.restore();
+ QFile f(targetFile);
+ QVERIFY(f.open(QIODevice::WriteOnly));
+ QCOMPARE(f.write("Hello"), Q_INT64_C(5));
+ f.close();
+
+ // Make the directory non-writable again
+ QVERIFY(QFile(dir.path()).setPermissions(QFile::ReadOwner | QFile::ExeOwner));
+
+ // And write to it again using QSaveFile; only works if directWriteFallback is enabled
+ QSaveFile file(targetFile);
+ file.setDirectWriteFallback(directWriteFallback);
+ QCOMPARE(file.directWriteFallback(), directWriteFallback);
+ if (directWriteFallback) {
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ QCOMPARE((int)file.error(), (int)QFile::NoError);
+ QCOMPARE(file.write("World"), Q_INT64_C(5));
+ QVERIFY(file.commit());
+
+ QFile reader(targetFile);
+ QVERIFY(reader.open(QIODevice::ReadOnly));
+ QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("World"));
+ reader.close();
+
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ QCOMPARE((int)file.error(), (int)QFile::NoError);
+ QCOMPARE(file.write("W"), Q_INT64_C(1));
+ file.cancelWriting(); // no effect, as per the documentation
+ QVERIFY(file.commit());
+
+ QVERIFY(reader.open(QIODevice::ReadOnly));
+ QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("W"));
+ } else {
+ QVERIFY(!file.open(QIODevice::WriteOnly));
+ QCOMPARE((int)file.error(), (int)QFile::OpenError);
+ }
+#endif
+}
+
+void tst_QSaveFile::transactionalWriteNoPermissionsOnFile()
+{
+ // Setup an existing but readonly file
+ QTemporaryDir dir;
+ const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
+ QFile file(targetFile);
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ QCOMPARE(file.write("Hello"), Q_INT64_C(5));
+ file.close();
+ file.setPermissions(QFile::ReadOwner);
+ QVERIFY(!file.open(QIODevice::WriteOnly));
+
+ // Try saving into it
+ {
+ QSaveFile saveFile(targetFile);
+ QVERIFY(!saveFile.open(QIODevice::WriteOnly)); // just like QFile
+ }
+ QVERIFY(file.exists());
+}
+
+void tst_QSaveFile::transactionalWriteCanceled()
+{
+ QTemporaryDir dir;
+ const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
+ QFile::remove(targetFile);
+ QSaveFile file(targetFile);
+ QVERIFY(file.open(QIODevice::WriteOnly));
+
+ QTextStream ts(&file);
+ ts << "This writing operation will soon be canceled.\n";
+ ts.flush();
+ QCOMPARE(file.error(), QFile::NoError);
+ QVERIFY(!QFile::exists(targetFile));
+
+ // We change our mind, let's abort writing
+ file.cancelWriting();
+
+ QVERIFY(!file.commit());
+
+ QVERIFY(!QFile::exists(targetFile)); // temp file was discarded
+ QCOMPARE(file.fileName(), targetFile);
+}
+
+void tst_QSaveFile::transactionalWriteErrorRenaming()
+{
+ QTemporaryDir dir;
+ const QString targetFile = dir.path() + QString::fromLatin1("/outfile");
+ QSaveFile file(targetFile);
+ QVERIFY(file.open(QIODevice::WriteOnly));
+ QCOMPARE(file.write("Hello"), qint64(5));
+ QVERIFY(!QFile::exists(targetFile));
+
+ // Restore permissions so that the QTemporaryDir cleanup can happen
+ class PermissionRestorer
+ {
+ public:
+ PermissionRestorer(const QString& path)
+ : m_path(path)
+ {}
+
+ ~PermissionRestorer()
+ {
+ QFile file(m_path);
+#ifdef Q_OS_UNIX
+ file.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner));
+#else
+ file.setPermissions(QFile::WriteOwner);
+ file.remove();
+#endif
+ }
+
+ private:
+ QString m_path;
+ };
+
+#ifdef Q_OS_UNIX
+ // Make rename() fail for lack of permissions in the directory
+ QFile dirAsFile(dir.path()); // yay, I have to use QFile to change a dir's permissions...
+ QVERIFY(dirAsFile.setPermissions(QFile::Permissions(0))); // no permissions
+ PermissionRestorer permissionRestorer(dir.path());
+#else
+ // Windows: Make rename() fail for lack of permissions on an existing target file
+ QFile existingTargetFile(targetFile);
+ QVERIFY(existingTargetFile.open(QIODevice::WriteOnly));
+ QCOMPARE(file.write("Target"), qint64(6));
+ existingTargetFile.close();
+ QVERIFY(existingTargetFile.setPermissions(QFile::ReadOwner));
+ PermissionRestorer permissionRestorer(targetFile);
+#endif
+
+ // The saving should fail.
+ QVERIFY(!file.commit());
+#ifdef Q_OS_UNIX
+ QVERIFY(!QFile::exists(targetFile)); // renaming failed
+#endif
+ QCOMPARE(file.error(), QFile::RenameError);
+}
+
+QTEST_MAIN(tst_QSaveFile)
+#include "tst_qsavefile.moc"
diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
index f152c48c7d..c2909cf7c5 100644
--- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
+++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
@@ -694,7 +694,9 @@ void tst_QSettings::testErrorHandling()
#ifdef Q_OS_WIN
QSKIP("Windows doesn't support most file modes, including read-only directories, so this test is moot.");
#elif defined(Q_OS_UNIX)
+#if !defined(Q_OS_VXWORKS) // VxWorks does not have users/groups
if (::getuid() == 0)
+#endif
QSKIP("Running this test as root doesn't work, since file perms do not bother him");
#else
QFETCH(int, filePerms);
diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
index c4453fd5f2..f94c8eac4f 100644
--- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
+++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp
@@ -45,6 +45,7 @@
#include <qstandardpaths.h>
#include <qfileinfo.h>
#include <qsysinfo.h>
+#include <qregexp.h>
#ifdef Q_OS_UNIX
#include <unistd.h>
@@ -72,6 +73,7 @@ private slots:
void testCustomRuntimeDirectory();
void testAllWritableLocations_data();
void testAllWritableLocations();
+ void testCleanPath();
private:
#ifdef Q_XDG_PLATFORM
@@ -430,6 +432,18 @@ void tst_qstandardpaths::testAllWritableLocations()
QCOMPARE(loc.endsWith(QLatin1Char('/')), false);
}
+void tst_qstandardpaths::testCleanPath()
+{
+ const QRegExp filter(QStringLiteral("\\\\"));
+ QVERIFY(filter.isValid());
+ for (int i = 0; i <= QStandardPaths::GenericCacheLocation; ++i) {
+ const QStringList paths = QStandardPaths::standardLocations(QStandardPaths::StandardLocation(i));
+ QVERIFY2(paths.filter(filter).isEmpty(),
+ qPrintable(QString::fromLatin1("Backslash found in %1 %2")
+ .arg(i).arg(paths.join(QLatin1Char(',')))));
+ }
+}
+
QTEST_MAIN(tst_qstandardpaths)
#include "tst_qstandardpaths.moc"
diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
index 28cf7a904a..6eb6f83d2a 100644
--- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
+++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
@@ -92,6 +92,7 @@ private slots:
void createNativeFile();
void QTBUG_4796_data();
void QTBUG_4796();
+ void guaranteeUnique();
};
void tst_QTemporaryFile::initTestCase()
@@ -782,5 +783,39 @@ void tst_QTemporaryFile::QTBUG_4796()
cleaner.reset();
}
+void tst_QTemporaryFile::guaranteeUnique()
+{
+ QDir dir(QDir::tempPath());
+ QString takenFileName;
+
+ // First pass. See which filename QTemporaryFile will try first.
+ {
+ // Fix the random seed.
+ qsrand(1135);
+ QTemporaryFile tmpFile("testFile1.XXXXXX");
+ tmpFile.open();
+ takenFileName = tmpFile.fileName();
+ QVERIFY(QFile::exists(takenFileName));
+ }
+
+ QVERIFY(!QFile::exists(takenFileName));
+
+ // Create a directory with same name.
+ QVERIFY(dir.mkdir(takenFileName));
+
+ // Second pass, now we have blocked its first attempt with a directory.
+ {
+ // Fix the random seed.
+ qsrand(1135);
+ QTemporaryFile tmpFile("testFile1.XXXXXX");
+ QVERIFY(tmpFile.open());
+ QString uniqueFileName = tmpFile.fileName();
+ QVERIFY(QFileInfo(uniqueFileName).isFile());
+ QVERIFY(uniqueFileName != takenFileName);
+ }
+
+ QVERIFY(dir.rmdir(takenFileName));
+}
+
QTEST_MAIN(tst_QTemporaryFile)
#include "tst_qtemporaryfile.moc"
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index 1f59336fc6..898aefffd3 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -79,6 +79,8 @@ private slots:
void toString();
void toString_constructed_data();
void toString_constructed();
+ void toAndFromStringList_data();
+ void toAndFromStringList();
void isParentOf_data();
void isParentOf();
void toLocalFile_data();
@@ -948,6 +950,25 @@ void tst_QUrl::toString()
QCOMPARE(url.toString(QUrl::FormattingOptions(options)), string);
}
+void tst_QUrl::toAndFromStringList_data()
+{
+ QTest::addColumn<QStringList>("strings");
+
+ QTest::newRow("empty") << QStringList();
+ QTest::newRow("local") << (QStringList() << "file:///tmp" << "file:///");
+ QTest::newRow("remote") << (QStringList() << "http://qt-project.org");
+}
+
+void tst_QUrl::toAndFromStringList()
+{
+ QFETCH(QStringList, strings);
+
+ const QList<QUrl> urls = QUrl::fromStringList(strings);
+ QCOMPARE(urls.count(), strings.count());
+ const QStringList converted = QUrl::toStringList(urls);
+ QCOMPARE(converted, strings);
+}
+
//### more tests ... what do we expect ...
void tst_QUrl::isParentOf_data()
{
@@ -2163,33 +2184,52 @@ void tst_QUrl::tldRestrictions_data()
// current whitelist
QTest::newRow("ac") << QString("ac") << true;
+ QTest::newRow("ar") << QString("ar") << true;
+ QTest::newRow("asia") << QString("asia") << true;
QTest::newRow("at") << QString("at") << true;
+ QTest::newRow("biz") << QString("biz") << true;
QTest::newRow("br") << QString("br") << true;
QTest::newRow("cat") << QString("cat") << true;
QTest::newRow("ch") << QString("ch") << true;
QTest::newRow("cl") << QString("cl") << true;
QTest::newRow("cn") << QString("cn") << true;
+ QTest::newRow("com") << QString("com") << true;
QTest::newRow("de") << QString("de") << true;
QTest::newRow("dk") << QString("dk") << true;
+ QTest::newRow("es") << QString("es") << true;
QTest::newRow("fi") << QString("fi") << true;
+ QTest::newRow("gr") << QString("gr") << true;
QTest::newRow("hu") << QString("hu") << true;
+ QTest::newRow("il") << QString("il") << true;
QTest::newRow("info") << QString("info") << true;
QTest::newRow("io") << QString("io") << true;
+ QTest::newRow("is") << QString("is") << true;
+ QTest::newRow("ir") << QString("ir") << true;
QTest::newRow("jp") << QString("jp") << true;
QTest::newRow("kr") << QString("kr") << true;
QTest::newRow("li") << QString("li") << true;
QTest::newRow("lt") << QString("lt") << true;
+ QTest::newRow("lu") << QString("lu") << true;
+ QTest::newRow("lv") << QString("lv") << true;
QTest::newRow("museum") << QString("museum") << true;
+ QTest::newRow("name") << QString("name") << true;
+ QTest::newRow("net") << QString("name") << true;
QTest::newRow("no") << QString("no") << true;
+ QTest::newRow("nu") << QString("nu") << true;
+ QTest::newRow("nz") << QString("nz") << true;
+ QTest::newRow("org") << QString("org") << true;
+ QTest::newRow("pl") << QString("pl") << true;
+ QTest::newRow("pr") << QString("pr") << true;
QTest::newRow("se") << QString("se") << true;
QTest::newRow("sh") << QString("sh") << true;
+ QTest::newRow("tel") << QString("tel") << true;
QTest::newRow("th") << QString("th") << true;
QTest::newRow("tm") << QString("tm") << true;
QTest::newRow("tw") << QString("tw") << true;
+ QTest::newRow("ua") << QString("ua") << true;
QTest::newRow("vn") << QString("vn") << true;
// known blacklists:
- QTest::newRow("com") << QString("com") << false;
QTest::newRow("foo") << QString("foo") << false;
}
@@ -2796,6 +2836,12 @@ void tst_QUrl::effectiveTLDs_data()
QTest::newRow("yes6") << QUrl::fromEncoded("http://www.com.com.cn") << ".com.cn";
QTest::newRow("yes7") << QUrl::fromEncoded("http://www.test.org.ws") << ".org.ws";
QTest::newRow("yes9") << QUrl::fromEncoded("http://www.com.co.uk.wallonie.museum") << ".wallonie.museum";
+ QTest::newRow("yes10") << QUrl::fromEncoded("http://www.com.evje-og-hornnes.no") << ".evje-og-hornnes.no";
+ QTest::newRow("yes11") << QUrl::fromEncoded("http://www.bla.kamijima.ehime.jp") << ".kamijima.ehime.jp";
+ QTest::newRow("yes12") << QUrl::fromEncoded("http://www.bla.kakuda.miyagi.jp") << ".kakuda.miyagi.jp";
+ QTest::newRow("yes13") << QUrl::fromEncoded("http://mypage.betainabox.com") << ".betainabox.com";
+ QTest::newRow("yes14") << QUrl::fromEncoded("http://mypage.rhcloud.com") << ".rhcloud.com";
+ QTest::newRow("yes15") << QUrl::fromEncoded("http://mypage.int.az") << ".int.az";
}
void tst_QUrl::effectiveTLDs()
diff --git a/tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp b/tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp
index 6ba659856c..fa3dec620a 100644
--- a/tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp
+++ b/tests/auto/corelib/io/qurlinternal/tst_qurlinternal.cpp
@@ -649,6 +649,20 @@ void tst_QUrlInternal::ace_testsuite_data()
<< "xn----rmckbbajlc6dj7bxne2c.xn--wgbh1c"
<< "."
<< egyptianIDN;
+
+ QString russianIDN = QString::fromUtf8("\321\217\320\275\320\264\320\265\320\272\321\201.\321\200\321\204");
+ QTest::newRow("russian-tld-ace")
+ << "xn--d1acpjx3f.xn--p1ai"
+ << "xn--d1acpjx3f.xn--p1ai"
+ << "."
+ << russianIDN;
+
+ QString taiwaneseIDN = QString::fromUtf8("\345\217\260\345\214\227\346\214\211\346\221\251.\345\217\260\347\201\243");
+ QTest::newRow("taiwanese-tld-ace")
+ << "xn--djrptm67aikb.xn--kpry57d"
+ << "xn--djrptm67aikb.xn--kpry57d"
+ << "."
+ << taiwaneseIDN;
}
void tst_QUrlInternal::ace_testsuite()
diff --git a/tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp b/tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp
index 6e2eeced05..bad77b1e06 100644
--- a/tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp
+++ b/tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp
@@ -251,21 +251,24 @@ void tst_QWinOverlappedIoNotifier::multipleOperations()
// start async read on client
QByteArray clientReadBuffer(377, Qt::Uninitialized);
- OVERLAPPED clientReadOverlapped = {0};
+ OVERLAPPED clientReadOverlapped;
+ ZeroMemory(&clientReadOverlapped, sizeof(clientReadOverlapped));
BOOL readSuccess = ReadFile(hClient, clientReadBuffer.data(), clientReadBuffer.size(),
NULL, &clientReadOverlapped);
QVERIFY(readSuccess || GetLastError() == ERROR_IO_PENDING);
// start async write client -> server
QByteArray clientDataToWrite(233, 'B');
- OVERLAPPED clientWriteOverlapped = {0};
+ OVERLAPPED clientWriteOverlapped;
+ ZeroMemory(&clientWriteOverlapped, sizeof(clientWriteOverlapped));
BOOL writeSuccess = WriteFile(hClient, clientDataToWrite.data(), clientDataToWrite.size(),
NULL, &clientWriteOverlapped);
QVERIFY(writeSuccess || GetLastError() == ERROR_IO_PENDING);
// start async write server -> client
QByteArray serverDataToWrite(144, 'A');
- OVERLAPPED serverOverlapped = {0};
+ OVERLAPPED serverOverlapped;
+ ZeroMemory(&serverOverlapped, sizeof(serverOverlapped));
writeSuccess = WriteFile(hServer, serverDataToWrite.data(), serverDataToWrite.size(),
NULL, &serverOverlapped);
QVERIFY(writeSuccess || GetLastError() == ERROR_IO_PENDING);
@@ -284,9 +287,9 @@ void tst_QWinOverlappedIoNotifier::multipleOperations()
QTRY_COMPARE(sink.notifications.count(), 2);
foreach (const NotifierSink::IOResult &r, sink.notifications) {
QCOMPARE(r.errorCode, DWORD(ERROR_SUCCESS));
- if (r.bytes == serverDataToWrite.count())
+ if (r.bytes == DWORD(serverDataToWrite.count()))
QCOMPARE(r.overlapped, &clientReadOverlapped);
- else if (r.bytes == clientDataToWrite.count())
+ else if (r.bytes == DWORD(clientDataToWrite.count()))
QCOMPARE(r.overlapped, &clientWriteOverlapped);
else
QVERIFY2(false, "Unexpected number of bytes received.");