diff options
Diffstat (limited to 'tests/auto')
32 files changed, 678 insertions, 174 deletions
diff --git a/tests/auto/corelib/io/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/io/qdatastream/tst_qdatastream.cpp index f5a546ebf1..ea4c557574 100644 --- a/tests/auto/corelib/io/qdatastream/tst_qdatastream.cpp +++ b/tests/auto/corelib/io/qdatastream/tst_qdatastream.cpp @@ -2748,10 +2748,11 @@ void tst_QDataStream::status_QBitArray() QCOMPARE(str, expectedString); } -#define MAP_TEST(byteArray, expectedStatus, expectedHash) \ +#define MAP_TEST(byteArray, initialStatus, expectedStatus, expectedHash) \ { \ QByteArray ba = byteArray; \ QDataStream stream(&ba, QIODevice::ReadOnly); \ + stream.setStatus(initialStatus); \ stream >> hash; \ QCOMPARE((int)stream.status(), (int)expectedStatus); \ QCOMPARE(hash.size(), expectedHash.size()); \ @@ -2764,6 +2765,7 @@ void tst_QDataStream::status_QBitArray() for (; it != expectedHash.constEnd(); ++it) \ expectedMap.insert(it.key(), it.value()); \ QDataStream stream(&ba, QIODevice::ReadOnly); \ + stream.setStatus(initialStatus); \ stream >> map; \ QCOMPARE((int)stream.status(), (int)expectedStatus); \ QCOMPARE(map.size(), expectedMap.size()); \ @@ -2785,25 +2787,30 @@ void tst_QDataStream::status_QHash_QMap() hash2.insert("L", "MN"); // ok - MAP_TEST(QByteArray("\x00\x00\x00\x00", 4), QDataStream::Ok, StringHash()); - MAP_TEST(QByteArray("\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00", 12), QDataStream::Ok, hash1); + MAP_TEST(QByteArray("\x00\x00\x00\x00", 4), QDataStream::Ok, QDataStream::Ok, StringHash()); + MAP_TEST(QByteArray("\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00", 12), QDataStream::Ok, QDataStream::Ok, hash1); MAP_TEST(QByteArray("\x00\x00\x00\x02\x00\x00\x00\x02\x00J\x00\x00\x00\x02\x00K" - "\x00\x00\x00\x02\x00L\x00\x00\x00\x04\x00M\x00N", 30), QDataStream::Ok, hash2); + "\x00\x00\x00\x02\x00L\x00\x00\x00\x04\x00M\x00N", 30), QDataStream::Ok, QDataStream::Ok, hash2); // past end - MAP_TEST(QByteArray(), QDataStream::ReadPastEnd, StringHash()); - MAP_TEST(QByteArray("\x00", 1), QDataStream::ReadPastEnd, StringHash()); - MAP_TEST(QByteArray("\x00\x00", 2), QDataStream::ReadPastEnd, StringHash()); - MAP_TEST(QByteArray("\x00\x00\x00", 3), QDataStream::ReadPastEnd, StringHash()); - MAP_TEST(QByteArray("\x00\x00\x00\x01", 4), QDataStream::ReadPastEnd, StringHash()); + MAP_TEST(QByteArray(), QDataStream::Ok, QDataStream::ReadPastEnd, StringHash()); + MAP_TEST(QByteArray("\x00", 1), QDataStream::Ok, QDataStream::ReadPastEnd, StringHash()); + MAP_TEST(QByteArray("\x00\x00", 2), QDataStream::Ok, QDataStream::ReadPastEnd, StringHash()); + MAP_TEST(QByteArray("\x00\x00\x00", 3), QDataStream::Ok, QDataStream::ReadPastEnd, StringHash()); + MAP_TEST(QByteArray("\x00\x00\x00\x01", 4), QDataStream::Ok, QDataStream::ReadPastEnd, StringHash()); for (int i = 4; i < 12; ++i) { - MAP_TEST(QByteArray("\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00", i), QDataStream::ReadPastEnd, StringHash()); + MAP_TEST(QByteArray("\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00", i), QDataStream::Ok, QDataStream::ReadPastEnd, StringHash()); } // corrupt data - MAP_TEST(QByteArray("\x00\x00\x00\x01\x00\x00\x00\x01", 8), QDataStream::ReadCorruptData, StringHash()); + MAP_TEST(QByteArray("\x00\x00\x00\x01\x00\x00\x00\x01", 8), QDataStream::Ok, QDataStream::ReadCorruptData, StringHash()); MAP_TEST(QByteArray("\x00\x00\x00\x02\x00\x00\x00\x01\x00J\x00\x00\x00\x01\x00K" - "\x00\x00\x00\x01\x00L\x00\x00\x00\x02\x00M\x00N", 30), QDataStream::ReadCorruptData, StringHash()); + "\x00\x00\x00\x01\x00L\x00\x00\x00\x02\x00M\x00N", 30), QDataStream::Ok, QDataStream::ReadCorruptData, StringHash()); + + // test the previously latched error status is not affected by reading + MAP_TEST(QByteArray("\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00", 12), QDataStream::ReadPastEnd, QDataStream::ReadPastEnd, hash1); + MAP_TEST(QByteArray("\x00\x00\x00\x01", 4), QDataStream::ReadCorruptData, QDataStream::ReadCorruptData, StringHash()); + MAP_TEST(QByteArray("\x00\x00\x00\x01\x00\x00\x00\x01", 8), QDataStream::ReadPastEnd, QDataStream::ReadPastEnd, StringHash()); } #define LIST_TEST(byteArray, expectedStatus, expectedList) \ diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp index abec4e7aba..7147405f3b 100644 --- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp +++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp @@ -359,14 +359,14 @@ void tst_QDebug::qDebugQChar() const MessageHandlerSetter mhs(myMessageHandler); { QDebug d = qDebug(); - d << QChar('f'); - d.nospace().noquote() << QChar('o') << QChar('o'); + d << QChar('f') << QChar(QLatin1Char('\xE4')); // f, ä + d.nospace().noquote() << QChar('o') << QChar('o') << QChar(QLatin1Char('\xC4')); // o, o, Ä } #ifndef QT_NO_MESSAGELOGCONTEXT file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO; #endif QCOMPARE(s_msgType, QtDebugMsg); - QCOMPARE(s_msg, QString::fromLatin1("'f' oo")); + QCOMPARE(s_msg, QString::fromLatin1("'f' '\\u00e4' oo\\u00c4")); QCOMPARE(QString::fromLatin1(s_file), file); QCOMPARE(s_line, line); QCOMPARE(QString::fromLatin1(s_function), function); diff --git a/tests/auto/corelib/io/qdir/qdir.pro b/tests/auto/corelib/io/qdir/qdir.pro index e5739f7e0a..4870922312 100644 --- a/tests/auto/corelib/io/qdir/qdir.pro +++ b/tests/auto/corelib/io/qdir/qdir.pro @@ -11,5 +11,3 @@ contains(CONFIG, builtin_testdata): DEFINES += BUILTIN_TESTDATA android { RESOURCES += android_testdata.qrc } - -win32: CONFIG += insignificant_test # Crashes on Windows in release builds diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index 703e9c5b07..48b8db949f 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -208,6 +208,7 @@ private slots: void cdNonreadable(); + void cdBelowRoot_data(); void cdBelowRoot(); private: @@ -2259,31 +2260,37 @@ void tst_QDir::cdNonreadable() #endif } +void tst_QDir::cdBelowRoot_data() +{ + QTest::addColumn<QString>("rootPath"); + QTest::addColumn<QString>("cdInto"); + QTest::addColumn<QString>("targetPath"); + +#if defined(Q_OS_ANDROID) + QTest::newRow("android") << "/" << "system" << "/system"; +#elif defined(Q_OS_UNIX) + QTest::newRow("unix") << "/" << "tmp" << "/tmp"; +#elif defined(Q_OS_WINRT) + QTest::newRow("winrt") << QDir::rootPath() << QDir::rootPath() << QDir::rootPath(); +#else // Windows+CE + const QString systemDrive = QString::fromLocal8Bit(qgetenv("SystemDrive")) + QLatin1Char('/'); + const QString systemRoot = QString::fromLocal8Bit(qgetenv("SystemRoot")); + QTest::newRow("windows-drive") + << systemDrive << systemRoot.mid(3) << QDir::cleanPath(systemRoot); +#endif // Windows +} + void tst_QDir::cdBelowRoot() { -#if defined (Q_OS_ANDROID) -#define ROOT QString("/") -#define DIR QString("/system") -#define CD_INTO "system" -#elif defined (Q_OS_UNIX) -#define ROOT QString("/") -#define DIR QString("/tmp") -#define CD_INTO "tmp" -#elif defined (Q_OS_WINRT) -#define ROOT QDir::rootPath() -#define DIR QDir::rootPath() -#define CD_INTO QDir::rootPath() -#else -#define ROOT QString::fromLocal8Bit(qgetenv("SystemDrive"))+"/" -#define DIR QString::fromLocal8Bit(qgetenv("SystemRoot")).replace('\\', '/') -#define CD_INTO QString::fromLocal8Bit(qgetenv("SystemRoot")).mid(3) -#endif + QFETCH(QString, rootPath); + QFETCH(QString, cdInto); + QFETCH(QString, targetPath); - QDir root(ROOT); - QVERIFY(!root.cd("..")); - QCOMPARE(root.path(), ROOT); - QVERIFY(root.cd(CD_INTO)); - QCOMPARE(root.path(), DIR); + QDir root(rootPath); + QVERIFY2(!root.cd(".."), qPrintable(root.absolutePath())); + QCOMPARE(root.path(), rootPath); + QVERIFY(root.cd(cdInto)); + QCOMPARE(root.path(), targetPath); #ifdef Q_OS_UNIX if (::getuid() == 0) QSKIP("Running this test as root doesn't make sense"); @@ -2291,13 +2298,13 @@ void tst_QDir::cdBelowRoot() #ifdef Q_OS_WINRT QSKIP("WinRT has no concept of system root"); #endif - QDir dir(DIR); - QVERIFY(!dir.cd("../..")); - QCOMPARE(dir.path(), DIR); - QVERIFY(!dir.cd("../abs/../..")); - QCOMPARE(dir.path(), DIR); + QDir dir(targetPath); + QVERIFY2(!dir.cd("../.."), qPrintable(dir.absolutePath())); + QCOMPARE(dir.path(), targetPath); + QVERIFY2(!dir.cd("../abs/../.."), qPrintable(dir.absolutePath())); + QCOMPARE(dir.path(), targetPath); QVERIFY(dir.cd("..")); - QCOMPARE(dir.path(), ROOT); + QCOMPARE(dir.path(), rootPath); } QTEST_MAIN(tst_QDir) diff --git a/tests/auto/corelib/io/qdiriterator/qdiriterator.pro b/tests/auto/corelib/io/qdiriterator/qdiriterator.pro index 2d8dfba996..5404e9058f 100644 --- a/tests/auto/corelib/io/qdiriterator/qdiriterator.pro +++ b/tests/auto/corelib/io/qdiriterator/qdiriterator.pro @@ -8,5 +8,3 @@ TESTDATA += entrylist contains(CONFIG, builtin_testdata): DEFINES += BUILTIN_TESTDATA wince*mips*|wincewm50smart-msvc200*: DEFINES += WINCE_BROKEN_ITERATE=1 - -win32: CONFIG += insignificant_test # Crashes on Windows in release builds diff --git a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro index 8aa81896cc..48673b20a9 100644 --- a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro +++ b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro @@ -6,5 +6,3 @@ RESOURCES += qfileinfo.qrc \ testdata.qrc win32:!wince:!winrt:LIBS += -ladvapi32 -lnetapi32 - -win32: CONFIG += insignificant_test # Crashes on Windows in release builds diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp index 9645ca9ba2..4cfbdf8c16 100644 --- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp +++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp @@ -29,6 +29,7 @@ #include <QtTest/QtTest> #include <qcoreapplication.h> #include <qstring.h> +#include <qtemporarydir.h> #include <qtemporaryfile.h> #include <qfile.h> #include <qdir.h> @@ -81,13 +82,15 @@ private slots: void QTBUG_4796(); void guaranteeUnique(); private: + QTemporaryDir m_temporaryDir; QString m_previousCurrent; }; void tst_QTemporaryFile::initTestCase() { + QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString())); m_previousCurrent = QDir::currentPath(); - QDir::setCurrent(QDir::tempPath()); + QVERIFY(QDir::setCurrent(m_temporaryDir.path())); // For QTBUG_4796 QVERIFY(QDir("test-XXXXXX").exists() || QDir().mkdir("test-XXXXXX")); @@ -114,9 +117,6 @@ void tst_QTemporaryFile::initTestCase() void tst_QTemporaryFile::cleanupTestCase() { - // From QTBUG_4796 - QVERIFY(QDir().rmdir("test-XXXXXX")); - QDir::setCurrent(m_previousCurrent); } diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 1902687eef..b605b89f34 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -129,11 +129,13 @@ private slots: void returnValue2_data(); void returnValue2(); void connectVirtualSlots(); + void connectSlotsVMIClass(); // VMI = Virtual or Multiple Inheritance void connectPrivateSlots(); void connectFunctorArgDifference(); void connectFunctorOverloads(); void connectFunctorQueued(); void connectFunctorWithContext(); + void connectFunctorWithContextUnique(); void connectFunctorDeadlock(); void connectStaticSlotWithObject(); void disconnectDoesNotLeakFunctor(); @@ -5606,6 +5608,112 @@ void tst_QObject::connectVirtualSlots() */ } +struct VirtualBase +{ + int virtual_base_count; + VirtualBase() : virtual_base_count(0) {} + virtual ~VirtualBase() {} + virtual void slot2() = 0; +}; + +class ObjectWithVirtualBase : public VirtualSlotsObject, public virtual VirtualBase +{ + Q_OBJECT +public: + ObjectWithVirtualBase() : regular_call_count(0), derived_counter2(0) {} + int regular_call_count; + int derived_counter2; + +public slots: + void regularSlot() { ++regular_call_count; } + virtual void slot1() { ++derived_counter2; } + virtual void slot2() { ++virtual_base_count; } +}; + +// VMI = Virtual or Multiple Inheritance +// (in this case, both) +void tst_QObject::connectSlotsVMIClass() +{ + // test connecting by the base + { + ObjectWithVirtualBase obj; + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 1); + QCOMPARE(obj.virtual_base_count, 0); + + QVERIFY(QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); + QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 1); + QCOMPARE(obj.virtual_base_count, 0); + } + + // test connecting with the actual class + { + ObjectWithVirtualBase obj; + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot, Qt::UniqueConnection)); + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 1); + QCOMPARE(obj.regular_call_count, 1); + QCOMPARE(obj.virtual_base_count, 0); + + QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot)); + QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot)); + QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1)); + QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 1); + QCOMPARE(obj.regular_call_count, 1); + QCOMPARE(obj.virtual_base_count, 0); + + /* the C++ standard say the comparison between pointer to virtual member function is unspecified + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); + */ + } + + // test connecting a slot that is virtual from the virtual base + { + ObjectWithVirtualBase obj; + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2, Qt::UniqueConnection)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 0); + QCOMPARE(obj.virtual_base_count, 1); + QCOMPARE(obj.regular_call_count, 0); + + QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2)); + QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 0); + QCOMPARE(obj.virtual_base_count, 1); + QCOMPARE(obj.regular_call_count, 0); + } +} + #ifndef QT_BUILD_INTERNAL void tst_QObject::connectPrivateSlots() {QSKIP("Needs QT_BUILD_INTERNAL");} @@ -5892,6 +6000,22 @@ void tst_QObject::deleteLaterInAboutToBlockHandler() QCOMPARE(statusAboutToBlock, 2); } +void tst_QObject::connectFunctorWithContextUnique() +{ + // Qt::UniqueConnections currently don't work for functors, but we need to + // be sure that they don't crash. If that is implemented, change this test. + + SenderObject sender; + ReceiverObject receiver; + QObject::connect(&sender, &SenderObject::signal1, &receiver, &ReceiverObject::slot1); + receiver.count_slot1 = 0; + + QObject::connect(&sender, &SenderObject::signal1, &receiver, SlotFunctor(), Qt::UniqueConnection); + + sender.emitSignal1(); + QCOMPARE(receiver.count_slot1, 1); +} + class MyFunctor { public: diff --git a/tests/auto/corelib/plugin/qplugin/qplugin.pro b/tests/auto/corelib/plugin/qplugin/qplugin.pro index 918ffb44bd..5283c2d52b 100644 --- a/tests/auto/corelib/plugin/qplugin/qplugin.pro +++ b/tests/auto/corelib/plugin/qplugin/qplugin.pro @@ -1,27 +1,17 @@ -QT = core TEMPLATE = subdirs +TESTPLUGINS = + win32 { - exists($$[QT_INSTALL_LIBS/get]/QtCore4.dll) { - SUBDIRS = releaseplugin - } - exists($$[QT_INSTALL_LIBS/get]/QtCored4.dll) { - SUBDIRS += debugplugin - } -} -mac { - CONFIG(debug, debug|release): { - SUBDIRS += debugplugin - tst_qplugin_pro.depends += debugplugin - } - CONFIG(release, debug|release): { - SUBDIRS += releaseplugin - tst_qplugin_pro.depends += releaseplugin - } + contains(QT_CONFIG, debug): TESTPLUGINS += debugplugin + contains(QT_CONFIG, release): TESTPLUGINS += releaseplugin +} else:osx { + CONFIG(debug, debug|release): TESTPLUGINS += debugplugin + CONFIG(release, debug|release): TESTPLUGINS += releaseplugin +} else { + TESTPLUGINS = debugplugin releaseplugin } -!win32:!mac:{ - SUBDIRS = debugplugin releaseplugin - tst_qplugin_pro.depends += debugplugin releaseplugin -} -SUBDIRS += tst_qplugin.pro +SUBDIRS += main $$TESTPLUGINS +main.file = tst_qplugin.pro +main.depends = $$TESTPLUGINS diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp index 910d7abf51..a460afcfa2 100644 --- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp @@ -107,7 +107,7 @@ private slots: void number(); void toInt_data(); void toInt(); - void qAllocMore(); + void blockSizeCalculations(); void resizeAfterFromRawData(); void appendAfterFromRawData(); @@ -1346,28 +1346,80 @@ void tst_QByteArray::toULongLong() QCOMPARE(b, ok); } -// global function defined in qbytearray.cpp -void tst_QByteArray::qAllocMore() +static bool checkSize(size_t value, uint min) { - using QT_PREPEND_NAMESPACE(qAllocMore); + return value >= min && value <= INT_MAX; +} +// global functions defined in qbytearray.cpp +void tst_QByteArray::blockSizeCalculations() +{ // Not very important, but please behave :-) - QVERIFY(qAllocMore(0, 0) >= 0); - - for (int i = 1; i < 1 << 8; i <<= 1) - QVERIFY(qAllocMore(i, 0) >= i); - - for (int i = 1 << 8; i < 1 << 30; i <<= 1) { - const int alloc = qAllocMore(i, 0); + QCOMPARE(qCalculateBlockSize(0, 1), size_t(0)); + QVERIFY(qCalculateGrowingBlockSize(0, 1).size <= MaxAllocSize); + QVERIFY(qCalculateGrowingBlockSize(0, 1).elementCount <= MaxAllocSize); + + // boundary condition + QCOMPARE(qCalculateBlockSize(MaxAllocSize, 1), size_t(MaxAllocSize)); + QCOMPARE(qCalculateBlockSize(MaxAllocSize/2, 2), size_t(MaxAllocSize) - 1); + QCOMPARE(qCalculateBlockSize(MaxAllocSize/2, 2, 1), size_t(MaxAllocSize)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize, 1).size, size_t(MaxAllocSize)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize, 1).elementCount, size_t(MaxAllocSize)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize/2, 2, 1).size, size_t(MaxAllocSize)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize/2, 2, 1).elementCount, size_t(MaxAllocSize)/2); + + // error conditions + QCOMPARE(qCalculateBlockSize(uint(MaxAllocSize) + 1, 1), size_t(~0)); + QCOMPARE(qCalculateBlockSize(size_t(-1), 1), size_t(~0)); + QCOMPARE(qCalculateBlockSize(MaxAllocSize, 1, 1), size_t(~0)); + QCOMPARE(qCalculateBlockSize(MaxAllocSize/2 + 1, 2), size_t(~0)); + QCOMPARE(qCalculateGrowingBlockSize(uint(MaxAllocSize) + 1, 1).size, size_t(~0)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize/2 + 1, 2).size, size_t(~0)); + + // overflow conditions + // on 32-bit platforms, (1 << 16) * (1 << 16) = (1 << 32) which is zero + QCOMPARE(qCalculateBlockSize(1 << 16, 1 << 16), size_t(~0)); + QCOMPARE(qCalculateBlockSize(MaxAllocSize/4, 16), size_t(~0)); + // on 32-bit platforms, (1 << 30) * 3 + (1 << 30) would overflow to zero + QCOMPARE(qCalculateBlockSize(1U << 30, 3, 1U << 30), size_t(~0)); + + // exact block sizes + for (int i = 1; i < 1 << 31; i <<= 1) { + QCOMPARE(qCalculateBlockSize(0, 1, i), size_t(i)); + QCOMPARE(qCalculateBlockSize(i, 1), size_t(i)); + QCOMPARE(qCalculateBlockSize(i + i/2, 1), size_t(i + i/2)); + } + for (int i = 1; i < 1 << 30; i <<= 1) { + QCOMPARE(qCalculateBlockSize(i, 2), 2 * size_t(i)); + QCOMPARE(qCalculateBlockSize(i, 2, 1), 2 * size_t(i) + 1); + QCOMPARE(qCalculateBlockSize(i, 2, 16), 2 * size_t(i) + 16); + } - QVERIFY(alloc >= i); - QCOMPARE(qAllocMore(i - 8, 8), alloc - 8); - QCOMPARE(qAllocMore(i - 16, 16), alloc - 16); - QCOMPARE(qAllocMore(i - 24, 24), alloc - 24); - QCOMPARE(qAllocMore(i - 32, 32), alloc - 32); + // growing sizes + for (int i = 1; i < 1 << 31; i <<= 1) { + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1).size, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1).elementCount, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1, 16).size, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1, 16).elementCount, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1, 24).size, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1, 16).elementCount, i)); + } - QVERIFY(qAllocMore(i - 1, 0) >= i - 1); - QVERIFY(qAllocMore(i + 1, 0) >= i + 1); + // growth should be limited + for (int elementSize = 1; elementSize < (1<<8); elementSize <<= 1) { + size_t alloc = 1; + forever { + QVERIFY(checkSize(qCalculateGrowingBlockSize(alloc, elementSize).size, alloc * elementSize)); + size_t newAlloc = qCalculateGrowingBlockSize(alloc, elementSize).elementCount; + QVERIFY(checkSize(newAlloc, alloc)); + if (newAlloc == alloc) + break; // no growth, we're at limit + alloc = newAlloc; + } + QVERIFY(checkSize(alloc, size_t(MaxAllocSize) / elementSize)); + + // the next allocation should be invalid + QCOMPARE(qCalculateGrowingBlockSize(alloc + 1, elementSize).size, size_t(~0)); } } diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp index 9fd418742c..c631b395f8 100644 --- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp @@ -842,6 +842,16 @@ void tst_QTimeZone::tzTest() QTzTimeZonePrivate::Data datatz2 = tztz2.data(std); QTzTimeZonePrivate::Data datautc2 = tzutc2.data(std); QCOMPARE(datatz2.offsetFromUtc, datautc2.offsetFromUtc); + + // Test a timezone with a name that isn't all letters + QTzTimeZonePrivate tzBarnaul("Asia/Barnaul"); + if (tzBarnaul.isValid()) { + QCOMPARE(tzBarnaul.data(std).abbreviation, QString("+07")); + + // first full day of the new rule (tzdata2016b) + QDateTime dt(QDate(2016, 3, 28), QTime(0, 0, 0), Qt::UTC); + QCOMPARE(tzBarnaul.data(dt.toMSecsSinceEpoch()).abbreviation, QString("+07")); + } #endif // Q_OS_UNIX } diff --git a/tests/auto/corelib/xml/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/xml/qxmlstream/tst_qxmlstream.cpp index 8a153a4599..26d443c2c6 100644 --- a/tests/auto/corelib/xml/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/corelib/xml/qxmlstream/tst_qxmlstream.cpp @@ -556,6 +556,7 @@ private slots: void checkCommentIndentation() const; void checkCommentIndentation_data() const; void crashInXmlStreamReader() const; + void write8bitCodec() const; void hasError() const; private: @@ -1576,5 +1577,43 @@ void tst_QXmlStream::hasError() const } +void tst_QXmlStream::write8bitCodec() const +{ + QBuffer outBuffer; + QVERIFY(outBuffer.open(QIODevice::WriteOnly)); + QXmlStreamWriter writer(&outBuffer); + writer.setAutoFormatting(false); + + QTextCodec *codec = QTextCodec::codecForName("IBM500"); + if (!codec) { + QSKIP("Encoding IBM500 not available."); + } + writer.setCodec(codec); + + writer.writeStartDocument(); + writer.writeStartElement("root"); + writer.writeAttribute("attrib", "1"); + writer.writeEndElement(); + writer.writeEndDocument(); + outBuffer.close(); + + // test 8 bit encoding + QByteArray values = outBuffer.data(); + QVERIFY(values.size() > 1); + // check '<' + QCOMPARE(values[0] & 0x00FF, 0x4c); + // check '?' + QCOMPARE(values[1] & 0x00FF, 0x6F); + + // convert the start of the XML + const QString expected = ("<?xml version=\"1.0\" encoding=\"IBM500\"?>"); + QTextDecoder *decoder = codec->makeDecoder(); + QVERIFY(decoder); + QString decodedText = decoder->toUnicode(values); + delete decoder; + QVERIFY(decodedText.startsWith(expected)); +} + + #include "tst_qxmlstream.moc" // vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index 851ef6cc1f..4a09dca544 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -35,6 +35,11 @@ #include <QtTest/QtTest> #include <QtDBus/QtDBus> +#ifdef Q_OS_UNIX +# include <sys/types.h> +# include <signal.h> +#endif + void MyObject::method(const QDBusMessage &msg) { path = msg.path(); @@ -1352,23 +1357,39 @@ void tst_QDBusConnection::callVirtualObjectLocal() void tst_QDBusConnection::pendingCallWhenDisconnected() { +#ifdef QT_NO_PROCESS + QSKIP("Test requires QProcess"); +#else if (!QCoreApplication::instance()) QSKIP("Test requires a QCoreApplication"); - QDBusServer *server = new QDBusServer; - QDBusConnection con = QDBusConnection::connectToPeer(server->address(), "disconnect"); - QTestEventLoop::instance().enterLoop(2); - QVERIFY(con.isConnected()); - QDBusMessage message = QDBusMessage::createMethodCall("", "/", QString(), "method"); - QDBusPendingCall reply = con.asyncCall(message); + QProcess daemon; + daemon.start("dbus-daemon", QStringList() << "--session" << "--nofork" << "--print-address"); + QVERIFY2(daemon.waitForReadyRead(2000), + "Daemon didn't print its address in time; error: \"" + daemon.errorString().toLocal8Bit() + + "\"; stderr:\n" + daemon.readAllStandardError()); - delete server; + QString address = QString::fromLocal8Bit(daemon.readAll().trimmed()); + QDBusConnection con = QDBusConnection::connectToBus(address, "disconnect"); + QVERIFY2(con.isConnected(), (con.lastError().name() + ": " + con.lastError().message()).toLocal8Bit()); - QTestEventLoop::instance().enterLoop(2); + // confirm we're connected and we're alone in this bus + QCOMPARE(con.baseService(), QString(":1.0")); + + // kill the bus + daemon.terminate(); + daemon.waitForFinished(); + + // send something, which we should get an error with + QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/", QString(), "ListNames"); + QDBusPendingCall reply = con.asyncCall(message); + + reply.waitForFinished(); QVERIFY(!con.isConnected()); QVERIFY(reply.isFinished()); QVERIFY(reply.isError()); - QVERIFY(reply.error().type() == QDBusError::Disconnected); + QCOMPARE(reply.error().type(), QDBusError::Disconnected); +#endif } QString MyObject::path; diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST index 0cf16b043e..0fe40e8db3 100644 --- a/tests/auto/gui/kernel/qwindow/BLACKLIST +++ b/tests/auto/gui/kernel/qwindow/BLACKLIST @@ -8,3 +8,5 @@ ubuntu-14.04 ubuntu-14.04 [modalWindowEnterEventOnHide_QTBUG35109] ubuntu-14.04 +[modalDialogClosingOneOfTwoModal] +osx diff --git a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp index 27796cda51..54bc802cf0 100644 --- a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp +++ b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp @@ -101,8 +101,6 @@ void tst_QFontCache::engineData() } if (req.pointSize < 0) req.pointSize = req.pixelSize*72.0/d->dpi; - if (req.weight == 0) - req.weight = QFont::Normal; if (req.stretch == 0) req.stretch = 100; diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp index 69cd5f00dd..4d5af44ff1 100644 --- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp @@ -134,6 +134,7 @@ private slots: void xToCursorForLigatures(); void cursorInNonStopChars(); void nbsp(); + void noModificationOfInputString(); private: QFont testFont; @@ -2164,5 +2165,37 @@ void tst_QTextLayout::layoutWithCustomTabStops() QVERIFY(longWidth > shortWidth); } +void tst_QTextLayout::noModificationOfInputString() +{ + QString s = QString(QChar(QChar::LineSeparator)); + { + QTextLayout layout; + layout.setText(s); + + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QCOMPARE(s.size(), 1); + QCOMPARE(s.at(0), QChar(QChar::LineSeparator)); + } + + { + QTextLayout layout; + layout.setText(s); + + QTextOption option; + option.setFlags(QTextOption::ShowLineAndParagraphSeparators); + layout.setTextOption(option); + + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QCOMPARE(s.size(), 1); + QCOMPARE(s.at(0), QChar(QChar::LineSeparator)); + } +} + QTEST_MAIN(tst_QTextLayout) #include "tst_qtextlayout.moc" diff --git a/tests/auto/network/access/qnetworkreply/BLACKLIST b/tests/auto/network/access/qnetworkreply/BLACKLIST index efa9cb61a8..1d56c78bbc 100644 --- a/tests/auto/network/access/qnetworkreply/BLACKLIST +++ b/tests/auto/network/access/qnetworkreply/BLACKLIST @@ -1,3 +1,4 @@ +# See qtbase/src/testlib/qtestblacklist.cpp for format osx [ioGetFromBuiltinHttp:http+limited] ubuntu-14.04 @@ -7,9 +8,3 @@ ubuntu-14.04 * [backgroundRequestInterruption:ftp, bg, nobg] * -[authenticationCacheAfterCancel:http+socksauth] -rhel-7.1 -rhel-7.2 -[authenticationCacheAfterCancel:https+socksauth] -rhel-7.1 -rhel-7.2 diff --git a/tests/auto/network/ssl/qsslsocket/BLACKLIST b/tests/auto/network/ssl/qsslsocket/BLACKLIST index 4146a352e9..52c023b78f 100644 --- a/tests/auto/network/ssl/qsslsocket/BLACKLIST +++ b/tests/auto/network/ssl/qsslsocket/BLACKLIST @@ -1,3 +1,7 @@ windows [waitForConnectedEncryptedReadyRead:WithSocks5ProxyAuth] * +[protocolServerSide:ssl3-any] +rhel-7.2 +[protocolServerSide:tls1.0-any] +rhel-7.2 diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index f8c5b8b67b..17a3f3a4d0 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -222,7 +222,6 @@ private slots: void ecdhServer(); void verifyClientCertificate_data(); void verifyClientCertificate(); - void setEmptyDefaultConfiguration(); // this test should be last #ifndef QT_NO_OPENSSL void simplePskConnect_data(); @@ -231,6 +230,10 @@ private slots: void ephemeralServerKey(); #endif + void setEmptyDefaultConfiguration(); // this test should be last + +protected slots: + static void exitLoop() { // Safe exit - if we aren't in an event loop, don't @@ -241,7 +244,6 @@ private slots: } } -protected slots: void ignoreErrorSlot() { socket->ignoreSslErrors(); diff --git a/tests/auto/opengl/qgl/BLACKLIST b/tests/auto/opengl/qgl/BLACKLIST index fa7c829b30..a7aaa04900 100644 --- a/tests/auto/opengl/qgl/BLACKLIST +++ b/tests/auto/opengl/qgl/BLACKLIST @@ -10,6 +10,7 @@ windows windows [clipTest] windows +opensuse-13.1 [graphicsViewClipping] windows [glFBOUseInGLWidget] diff --git a/tests/auto/other/compiler/tst_compiler.cpp b/tests/auto/other/compiler/tst_compiler.cpp index 50cfe48cdf..55fab00156 100644 --- a/tests/auto/other/compiler/tst_compiler.cpp +++ b/tests/auto/other/compiler/tst_compiler.cpp @@ -631,9 +631,10 @@ void tst_Compiler::cxx11_alignas() #ifndef Q_COMPILER_ALIGNAS QSKIP("Compiler does not support C++11 feature"); #else - alignas(double) char c; - Q_UNUSED(c); - QCOMPARE(Q_ALIGNOF(c), Q_ALIGNOF(double)); + struct S { + alignas(double) char c; + }; + QCOMPARE(Q_ALIGNOF(S), Q_ALIGNOF(double)); #endif } diff --git a/tests/auto/tools/moc/no-keywords.h b/tests/auto/tools/moc/no-keywords.h index 56a906e6a9..d31063665b 100644 --- a/tests/auto/tools/moc/no-keywords.h +++ b/tests/auto/tools/moc/no-keywords.h @@ -70,9 +70,9 @@ private: double slots; }; -#define signals public -#define slots -#define emit +#define signals Q_SIGNALS +#define slots Q_SLOTS +#define emit Q_EMIT #undef QT_NO_KEYWORDS #endif // NO_KEYWORDS_H diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index ff840a9e5a..ad7600c784 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -104,10 +104,6 @@ private slots: void caseSensitivity(); -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - void Win32LongFileName(); -#endif - void drives_data(); void drives(); void dirsBeforeFiles(); @@ -928,20 +924,6 @@ void tst_QFileSystemModel::caseSensitivity() } } -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) -void tst_QFileSystemModel::Win32LongFileName() -{ - QString tmp = flatDirTestPath; - QStringList files; - files << "aaaaaaaaaa" << "bbbbbbbbbb" << "cccccccccc"; - QVERIFY(createFiles(tmp, files)); - QModelIndex root = model->setRootPath(tmp); - QTRY_VERIFY(model->index(tmp + QLatin1String("/aaaaaa~1")).isValid()); - QTRY_VERIFY(model->index(tmp + QLatin1String("/bbbbbb~1")).isValid()); - QTRY_VERIFY(model->index(tmp + QLatin1String("/cccccc~1")).isValid()); -} -#endif - void tst_QFileSystemModel::drives_data() { QTest::addColumn<QString>("path"); diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index 10f5a9161e..1df9a9434c 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -49,6 +49,9 @@ #include <QtWidgets/QStyle> #include <QtWidgets/QPushButton> #include <QtWidgets/QDesktopWidget> +#ifndef QT_NO_OPENGL +#include <QtWidgets/QOpenGLWidget> +#endif #include <private/qgraphicsscene_p.h> #include <private/qgraphicsview_p.h> #include "../../../shared/platforminputcontext.h" @@ -156,6 +159,9 @@ private slots: void sceneRect_growing(); void setSceneRect(); void viewport(); +#ifndef QT_NO_OPENGL + void openGLViewport(); +#endif void dragMode_scrollHand(); void dragMode_rubberBand(); void rubberBandSelectionMode(); @@ -664,6 +670,45 @@ void tst_QGraphicsView::viewport() QTest::qWait(25); } +#ifndef QT_NO_OPENGL +void tst_QGraphicsView::openGLViewport() +{ + QGraphicsScene scene; + scene.setBackgroundBrush(Qt::white); + scene.addText("GraphicsView"); + scene.addEllipse(QRectF(400, 50, 50, 50)); + scene.addEllipse(QRectF(-100, -400, 50, 50)); + scene.addEllipse(QRectF(50, -100, 50, 50)); + scene.addEllipse(QRectF(-100, 50, 50, 50)); + + QGraphicsView view(&scene); + view.setSceneRect(-400, -400, 800, 800); + view.resize(400, 400); + + QOpenGLWidget *glw = new QOpenGLWidget; + QSignalSpy spy1(glw, SIGNAL(resized())); + QSignalSpy spy2(glw, SIGNAL(frameSwapped())); + + view.setViewport(glw); + + view.show(); + QTest::qWaitForWindowExposed(&view); + QTRY_VERIFY(spy1.count() > 0); + QTRY_VERIFY(spy2.count() >= spy1.count()); + spy1.clear(); + spy2.clear(); + + // Now test for resize (QTBUG-52419). This is special when the viewport is + // a QOpenGLWidget since the underlying FBO must also be maintained. + view.resize(300, 300); + QTRY_VERIFY(spy1.count() > 0); + QTRY_VERIFY(spy2.count() >= spy1.count()); + // There is no sane way to check if the framebuffer contents got updated + // (grabFramebuffer is no good for the viewport case as that does not go + // through paintGL). So skip the actual verification. +} +#endif + void tst_QGraphicsView::dragMode_scrollHand() { for (int j = 0; j < 2; ++j) { diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 958bef3e6e..98b630b49d 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -373,7 +373,6 @@ private slots: void setMaskInResizeEvent(); void moveInResizeEvent(); - void immediateRepaintAfterShow(); void immediateRepaintAfterInvalidateBuffer(); void effectiveWinId(); @@ -8140,25 +8139,6 @@ void tst_QWidget::moveInResizeEvent() QTRY_COMPARE(testWidget.geometry(), expectedGeometry); } -void tst_QWidget::immediateRepaintAfterShow() -{ - if (m_platform == QStringLiteral("xcb")) - QSKIP("QTBUG-26424"); - if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows")) - QSKIP("We don't support immediate repaint right after show on other platforms."); - - UpdateWidget widget; - centerOnScreen(&widget); - widget.show(); - qApp->processEvents(); - // On X11 in particular, we are now waiting for a MapNotify event before - // syncing the backing store. However, if someone request a repaint() - // we must repaint immediately regardless of the current state. - widget.numPaintEvents = 0; - widget.repaint(); - QCOMPARE(widget.numPaintEvents, 1); -} - void tst_QWidget::immediateRepaintAfterInvalidateBuffer() { if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows")) diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp index 200c8a6ced..35b1596003 100644 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -83,6 +83,7 @@ private slots: void tst_showWithoutActivating(); void tst_paintEventOnSecondShow(); + void tst_paintEventOnResize_QTBUG50796(); #ifndef QT_NO_DRAGANDDROP void tst_dnd(); @@ -364,6 +365,29 @@ void tst_QWidget_window::tst_paintEventOnSecondShow() QTRY_VERIFY(w.paintEventCount > 0); } +void tst_QWidget_window::tst_paintEventOnResize_QTBUG50796() +{ + const QRect availableGeo = QGuiApplication::primaryScreen()->availableGeometry(); + + QWidget root; + root.setGeometry(availableGeo.width()/2 - 100, availableGeo.height()/2 - 100, + 200, 200); + + PaintTestWidget *native = new PaintTestWidget(&root); + native->winId(); // We're testing native widgets + native->setGeometry(10, 10, 50, 50); + + root.show(); + QVERIFY(QTest::qWaitForWindowExposed(&root)); + QVERIFY(QTest::qWaitForWindowActive(&root)); + QVERIFY(native->isVisible()); + + native->paintEventCount = 0; + native->resize(native->width() + 10, native->height() + 10); + QTest::qWait(50); // Wait for paint events + QTRY_COMPARE(native->paintEventCount, 1); // Only one paint event must occur +} + #ifndef QT_NO_DRAGANDDROP /* DnD test for QWidgetWindow (handleDrag*Event() functions). diff --git a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp index d4f398a61c..5c213fea04 100644 --- a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp +++ b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp @@ -930,17 +930,14 @@ private: void tst_QStyle::testStyleOptionInit() { QStringList keys = QStyleFactory::keys(); - QVector<QStyle*> styles; - styles.reserve(keys.size() + 1); - - styles << new QCommonStyle(); + keys.prepend(QString()); // QCommonStyle marker - Q_FOREACH (QStyle *style, styles) { + Q_FOREACH (const QString &key, keys) { + QStyle* style = key.isEmpty() ? new QCommonStyle : QStyleFactory::create(key); TestStyleOptionInitProxy testStyle; testStyle.setBaseStyle(style); testAllFunctions(style); QVERIFY(!testStyle.invalidOptionsDetected); - delete style; } } diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index c3b432788b..741d6839db 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -85,6 +85,7 @@ private slots: void mouseActivation(); #endif void tearOff(); + void submenuTearOffDontClose(); void layoutDirection(); void task208001_stylesheet(); @@ -655,6 +656,51 @@ void tst_QMenu::tearOff() #endif // QT_NO_CURSOR } +void tst_QMenu::submenuTearOffDontClose() +{ + QWidget widget; + QMenu *menu = new QMenu(&widget); + QVERIFY(!menu->isTearOffEnabled()); //default value + menu->setTearOffEnabled(true); + QVERIFY(menu->isTearOffEnabled()); + QMenu *submenu = new QMenu(&widget); + submenu->addAction("aaa"); + submenu->addAction("bbb"); + QVERIFY(!submenu->isTearOffEnabled()); //default value + submenu->setTearOffEnabled(true); + QVERIFY(submenu->isTearOffEnabled()); + menu->addMenu(submenu); + + widget.resize(300, 200); + centerOnScreen(&widget); + widget.show(); + widget.activateWindow(); + QVERIFY(QTest::qWaitForWindowActive(&widget)); + // Show parent menu + menu->popup(widget.geometry().topRight() + QPoint(50, 0)); + QVERIFY(QTest::qWaitForWindowActive(menu)); + // Then its submenu + const QRect submenuRect = menu->actionGeometry(menu->actions().at(0)); + const QPoint submenuPos(submenuRect.topLeft() + QPoint(3, 3)); + // Move then click to avoid the submenu moves from causing it to close + QTest::mouseMove(menu, submenuPos, 100); + QTest::mouseClick(menu, Qt::LeftButton, 0, submenuPos, 100); + QTRY_VERIFY(QTest::qWaitForWindowActive(submenu)); + // Make sure we enter the submenu frame directly on the tear-off area + QTest::mouseMove(submenu, QPoint(10, 3), 100); + if (submenu->style()->styleHint(QStyle::SH_Menu_SubMenuDontStartSloppyOnLeave)) { + qWarning("Sloppy menu timer disabled by the style: %s", qPrintable(QApplication::style()->objectName())); + // Submenu must get the enter event + QTRY_VERIFY(submenu->underMouse()); + } else { + const int closeTimeout = submenu->style()->styleHint(QStyle::SH_Menu_SubMenuSloppyCloseTimeout); + QTest::qWait(closeTimeout + 100); + // Menu must not disappear and it must get the enter event + QVERIFY(submenu->isVisible()); + QVERIFY(submenu->underMouse()); + } +} + void tst_QMenu::layoutDirection() { QMainWindow win; diff --git a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST index 86c7141268..fa326a6ea5 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST +++ b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST @@ -12,3 +12,6 @@ windows msvc-2010 32bit developer-build #QTBUG-31611 [reparentToNotYetCreated] windows msvc-2010 32bit developer-build + +[stackWidgetOpaqueChildIsVisible] +windows diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp index c76c4d927b..e3e26d612f 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp +++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp @@ -29,11 +29,14 @@ #include <QtWidgets/QOpenGLWidget> #include <QtGui/QOpenGLFunctions> #include <QtGui/QPainter> +#include <QtGui/QScreen> +#include <QtWidgets/QDesktopWidget> #include <QtWidgets/QGraphicsView> #include <QtWidgets/QGraphicsScene> #include <QtWidgets/QGraphicsRectItem> #include <QtWidgets/QVBoxLayout> #include <QtWidgets/QPushButton> +#include <QtWidgets/QStackedWidget> #include <QtTest/QtTest> #include <QSignalSpy> @@ -54,6 +57,7 @@ private slots: void fboRedirect(); void showHide(); void nativeWindow(); + void stackWidgetOpaqueChildIsVisible(); }; void tst_QOpenGLWidget::create() @@ -420,6 +424,135 @@ void tst_QOpenGLWidget::nativeWindow() QVERIFY(image.pixel(30, 40) == qRgb(0, 255, 0)); } +static inline QString msgRgbMismatch(unsigned actual, unsigned expected) +{ + return QString::asprintf("Color mismatch, %#010x != %#010x", actual, expected); +} + +static QPixmap grabWidgetWithoutRepaint(const QWidget *widget, QRect clipArea) +{ + const QWidget *targetWidget = widget; +#ifdef Q_OS_WIN + // OpenGL content is not properly grabbed on Windows when passing a top level widget window, + // because GDI functions can't grab OpenGL layer content. + // Instead the whole screen should be captured, with an adjusted clip area, which contains + // the final composited content. + QDesktopWidget *desktopWidget = QApplication::desktop(); + const QWidget *mainScreenWidget = desktopWidget->screen(); + targetWidget = mainScreenWidget; + clipArea = QRect(widget->mapToGlobal(clipArea.topLeft()), + widget->mapToGlobal(clipArea.bottomRight())); +#endif + + const QWindow *window = targetWidget->window()->windowHandle(); + Q_ASSERT(window); + WId windowId = window->winId(); + + QScreen *screen = window->screen(); + Q_ASSERT(screen); + + const QSize size = clipArea.size(); + const QPixmap result = screen->grabWindow(windowId, + clipArea.x(), + clipArea.y(), + size.width(), + size.height()); + return result; +} + +#define VERIFY_COLOR(child, region, color) verifyColor(child, region, color, __LINE__) + +bool verifyColor(const QWidget *widget, const QRect &clipArea, const QColor &color, int callerLine) +{ + for (int t = 0; t < 6; t++) { + const QPixmap pixmap = grabWidgetWithoutRepaint(widget, clipArea); + if (!QTest::qCompare(pixmap.size(), + clipArea.size(), + "pixmap.size()", + "rect.size()", + __FILE__, + callerLine)) + return false; + + + const QImage image = pixmap.toImage(); + QPixmap expectedPixmap(pixmap); /* ensure equal formats */ + expectedPixmap.detach(); + expectedPixmap.fill(color); + + uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; + uint firstPixel = image.pixel(0,0) | alphaCorrection; + + // Retry a couple of times. Some window managers have transparency animation, or are + // just slow to render. + if (t < 5) { + if (firstPixel == QColor(color).rgb() + && image == expectedPixmap.toImage()) + return true; + else + QTest::qWait(200); + } else { + if (!QTest::qVerify(firstPixel == QColor(color).rgb(), + "firstPixel == QColor(color).rgb()", + qPrintable(msgRgbMismatch(firstPixel, QColor(color).rgb())), + __FILE__, callerLine)) { + return false; + } + if (!QTest::qVerify(image == expectedPixmap.toImage(), + "image == expectedPixmap.toImage()", + "grabbed pixmap differs from expected pixmap", + __FILE__, callerLine)) { + return false; + } + } + } + + return false; +} + +void tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible() +{ +#ifdef Q_OS_OSX + QSKIP("QScreen::grabWindow() doesn't work properly on OSX HighDPI screen: QTBUG-46803"); + return; +#endif + + QStackedWidget stack; + + QWidget* emptyWidget = new QWidget(&stack); + stack.addWidget(emptyWidget); + + // Create an opaque red QOpenGLWidget. + const int dimensionSize = 400; + ClearWidget* clearWidget = new ClearWidget(&stack, dimensionSize, dimensionSize); + clearWidget->setAttribute(Qt::WA_OpaquePaintEvent); + stack.addWidget(clearWidget); + + // Show initial QWidget. + stack.setCurrentIndex(0); + stack.resize(dimensionSize, dimensionSize); + stack.show(); + QTest::qWaitForWindowExposed(&stack); + QTest::qWaitForWindowActive(&stack); + + // Switch to the QOpenGLWidget. + stack.setCurrentIndex(1); + QTRY_COMPARE(clearWidget->m_paintCalled, true); + + // Resize the tested region to be half size in the middle, because some OSes make the widget + // have rounded corners (e.g. OSX), and the grabbed window pixmap will not coincide perfectly + // with what was actually painted. + QRect clipArea = stack.rect(); + clipArea.setSize(clipArea.size() / 2); + const int translationOffsetToMiddle = dimensionSize / 4; + clipArea.translate(translationOffsetToMiddle, translationOffsetToMiddle); + + // Verify that the QOpenGLWidget was actually painted AND displayed. + const QColor red(255, 0, 0, 255); + VERIFY_COLOR(&stack, clipArea, red); + #undef VERIFY_COLOR +} + QTEST_MAIN(tst_QOpenGLWidget) #include "tst_qopenglwidget.moc" diff --git a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp index 6ad13cd781..b58d236a91 100644 --- a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp +++ b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp @@ -1179,12 +1179,19 @@ void tst_QPlainTextEdit::selectWordsFromStringsContainingSeparators_data() QTest::addColumn<QString>("testString"); QTest::addColumn<QString>("selectedWord"); - QStringList wordSeparators; - wordSeparators << "." << "," << "?" << "!" << ":" << ";" << "-" << "<" << ">" << "[" - << "]" << "(" << ")" << "{" << "}" << "=" << "\t"<< QString(QChar::Nbsp); - - foreach (QString s, wordSeparators) - QTest::newRow(QString("separator: " + s).toLocal8Bit()) << QString("foo") + s + QString("bar") << QString("foo"); + const ushort wordSeparators[] = + {'.', ',', '?', '!', ':', ';', '-', '<', '>', '[', ']', '(', ')', '{', '}', + '=', '\t', ushort(QChar::Nbsp)}; + + for (size_t i = 0, count = sizeof(wordSeparators) / sizeof(wordSeparators[0]); i < count; ++i) { + const ushort u = wordSeparators[i]; + QByteArray rowName = QByteArrayLiteral("separator: "); + if (u >= 32 && u < 128) + rowName += char(u); + else + rowName += QByteArrayLiteral("0x") + QByteArray::number(u, 16); + QTest::newRow(rowName.constData()) << QString("foo") + QChar(u) + QString("bar") << QString("foo"); + } } void tst_QPlainTextEdit::selectWordsFromStringsContainingSeparators() diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp index f1ebfda88b..69f0ff0f7e 100644 --- a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp +++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp @@ -1525,12 +1525,19 @@ void tst_QTextEdit::selectWordsFromStringsContainingSeparators_data() QTest::addColumn<QString>("testString"); QTest::addColumn<QString>("selectedWord"); - QStringList wordSeparators; - wordSeparators << "." << "," << "?" << "!" << ":" << ";" << "-" << "<" << ">" << "[" - << "]" << "(" << ")" << "{" << "}" << "=" << "\t"<< QString(QChar::Nbsp); - - foreach (QString s, wordSeparators) - QTest::newRow(QString("separator: " + s).toLocal8Bit()) << QString("foo") + s + QString("bar") << QString("foo"); + const ushort wordSeparators[] = + {'.', ',', '?', '!', ':', ';', '-', '<', '>', '[', ']', '(', ')', '{', '}', + '=', '\t', ushort(QChar::Nbsp)}; + + for (size_t i = 0, count = sizeof(wordSeparators) / sizeof(wordSeparators[0]); i < count; ++i) { + const ushort u = wordSeparators[i]; + QByteArray rowName = QByteArrayLiteral("separator: "); + if (u >= 32 && u < 128) + rowName += char(u); + else + rowName += QByteArrayLiteral("0x") + QByteArray::number(u, 16); + QTest::newRow(rowName.constData()) << QString("foo") + QChar(u) + QString("bar") << QString("foo"); + } } void tst_QTextEdit::selectWordsFromStringsContainingSeparators() |