diff options
Diffstat (limited to 'tests')
122 files changed, 2228 insertions, 826 deletions
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp index 16a30af892..350bff0652 100644 --- a/tests/auto/corelib/io/qfile/tst_qfile.cpp +++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp @@ -279,6 +279,9 @@ private slots: void reuseQFile(); + void moveToTrash_data(); + void moveToTrash(); + private: #ifdef BUILTIN_TESTDATA QSharedPointer<QTemporaryDir> m_dataDir; @@ -3672,5 +3675,142 @@ void tst_QFile::reuseQFile() } } +void tst_QFile::moveToTrash_data() +{ + QTest::addColumn<QString>("source"); + QTest::addColumn<bool>("create"); + QTest::addColumn<bool>("result"); + + // success cases + { + QTemporaryFile temp; + QVERIFY(temp.open()); + QTest::newRow("temporary file") << temp.fileName() << true << true; + } + { + QTemporaryDir tempDir; + tempDir.setAutoRemove(false); + QTest::newRow("temporary dir") + << tempDir.path() + QLatin1Char('/') + << true << true; + } + { + QTemporaryDir homeDir(QDir::homePath() + QLatin1String("/XXXXXX")); + homeDir.setAutoRemove(false); + QTemporaryFile homeFile(homeDir.path() + + QLatin1String("/tst_qfile-XXXXXX")); + homeFile.open(); + QTest::newRow("home file") + << homeFile.fileName() + << true << true; + + QTest::newRow("home dir") + << homeDir.path() + QLatin1Char('/') + << true << true; + } + QTest::newRow("relative") << QStringLiteral("tst_qfile_moveToTrash.tmp") << true << true; + + // failure cases + QTest::newRow("root") << QDir::rootPath() << false << false; + QTest::newRow("no-such-file") << QString::fromLatin1("no/such/file") << false << false; +} + +void tst_QFile::moveToTrash() +{ + QFETCH(QString, source); + QFETCH(bool, create); + QFETCH(bool, result); + + /* This test makes assumptions about the file system layout + which might be wrong - moveToTrash may fail if the file lives + on a file system that is different from the home file system, and + has no .Trash directory. + */ + const bool mayFail = QStorageInfo(source) != QStorageInfo(QDir::home()); + +#if defined(Q_OS_WINRT) + QSKIP("WinRT does not have a trash", SkipAll); +#endif + + auto ensureFile = [](const QString &source, bool create) { + if (QFileInfo::exists(source) || !create) + return; + if (source.endsWith(QLatin1Char('/'))) { + QDir::root().mkdir(source); + QFile file(source + QLatin1String("test")); + if (!file.open(QIODevice::WriteOnly)) + QSKIP("Couldn't create directory with file"); + } else { + QFile sourceFile(source); + QVERIFY2(sourceFile.open(QFile::WriteOnly | QFile::Text), qPrintable(sourceFile.errorString())); + sourceFile.close(); + } + }; + auto cleanupFile = [source, create]() { + if (!QFileInfo::exists(source) || !create) + return; + if (source.endsWith(QLatin1Char('/'))) { + QDir(source).removeRecursively(); + } else { + QFile sourceFile(source); + sourceFile.remove(); + } + }; + // non-static version + { + ensureFile(source, create); + QFile sourceFile(source); + const bool success = sourceFile.moveToTrash(); + + // tolerate moveToTrash failing + if (result && !success && mayFail) + result = false; + + if (result) { + // if any of the test fails, we still want to remove the file + auto onFailure = qScopeGuard(cleanupFile); + QVERIFY2(success, qPrintable(sourceFile.errorString())); + QCOMPARE(sourceFile.error(), QFile::NoError); + QVERIFY(source != sourceFile.fileName()); + if (!sourceFile.fileName().isEmpty()) { + QVERIFY2(sourceFile.exists(), qPrintable(sourceFile.fileName())); + // remove file/dir in trash as well, don't fill disk + if (source.endsWith(QLatin1Char('/'))) + QDir(sourceFile.fileName()).removeRecursively(); + else + sourceFile.remove(); + } + } else { + QVERIFY(!success); + QVERIFY(!sourceFile.errorString().isEmpty()); + QCOMPARE(source, sourceFile.fileName()); + } + } + + // don't retry + if (mayFail) + return; + + // static version + { + ensureFile(source, create); + QString pathInTrash; + const bool success = QFile::moveToTrash(source, &pathInTrash); + QCOMPARE(success, result); + if (result) { + auto onFailure = qScopeGuard(cleanupFile); + QVERIFY(source != pathInTrash); + if (!pathInTrash.isEmpty()) { + // remove file/dir in trash as well, don't fill disk + QVERIFY2(QFile::exists(pathInTrash), qPrintable(pathInTrash)); + if (source.endsWith(QLatin1Char('/'))) + QDir(pathInTrash).removeRecursively(); + else + QFile::remove(pathInTrash); + } + } + } +} + QTEST_MAIN(tst_QFile) #include "tst_qfile.moc" diff --git a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp index 365508024b..85a2dae3b6 100644 --- a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp +++ b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp @@ -45,8 +45,10 @@ class tst_QEventDispatcher : public QObject Q_OBJECT QAbstractEventDispatcher *eventDispatcher; - int receivedEventType; - int timerIdFromEvent; + + int receivedEventType = -1; + int timerIdFromEvent = -1; + bool doubleTimer = false; protected: bool event(QEvent *e); @@ -54,9 +56,7 @@ protected: public: inline tst_QEventDispatcher() : QObject(), - eventDispatcher(QAbstractEventDispatcher::instance(thread())), - receivedEventType(-1), - timerIdFromEvent(-1) + eventDispatcher(QAbstractEventDispatcher::instance(thread())) { } private slots: @@ -75,6 +75,9 @@ bool tst_QEventDispatcher::event(QEvent *e) switch (receivedEventType = e->type()) { case QEvent::Timer: { + // sometimes, two timers fire during a single QTRY_xxx wait loop + if (timerIdFromEvent != -1) + doubleTimer = true; timerIdFromEvent = static_cast<QTimerEvent *>(e)->timerId(); return true; } @@ -206,10 +209,31 @@ void tst_QEventDispatcher::registerTimer() QVERIFY(timers.foundCoarse()); QVERIFY(timers.foundVeryCoarse()); +#ifdef Q_OS_DARWIN + /* + We frequently experience flaky failures on macOS. Assumption is that this is + due to undeterministic VM scheduling, making us process events for significantly + longer than expected and resulting in timers firing in undefined order. + To detect this condition, we use a QElapsedTimer, and skip the test. + */ + QElapsedTimer elapsedTimer; + elapsedTimer.start(); +#endif + // process events, waiting for the next event... this should only fire the precise timer receivedEventType = -1; timerIdFromEvent = -1; + doubleTimer = false; QTRY_COMPARE_WITH_TIMEOUT(receivedEventType, int(QEvent::Timer), PreciseTimerInterval * 2); + +#ifdef Q_OS_DARWIN + if (doubleTimer) + QSKIP("Double timer during a single timeout - aborting test as flaky on macOS"); + if (timerIdFromEvent != timers.preciseTimerId() + && elapsedTimer.elapsed() > PreciseTimerInterval * 3) + QSKIP("Ignore flaky test behavior due to VM scheduling on macOS"); +#endif + QCOMPARE(timerIdFromEvent, timers.preciseTimerId()); // now unregister it and make sure it's gone timers.unregister(timers.preciseTimerId()); @@ -223,7 +247,17 @@ void tst_QEventDispatcher::registerTimer() // do the same again for the coarse timer receivedEventType = -1; timerIdFromEvent = -1; + doubleTimer = false; QTRY_COMPARE_WITH_TIMEOUT(receivedEventType, int(QEvent::Timer), CoarseTimerInterval * 2); + +#ifdef Q_OS_DARWIN + if (doubleTimer) + QSKIP("Double timer during a single timeout - aborting test as flaky on macOS"); + if (timerIdFromEvent != timers.coarseTimerId() + && elapsedTimer.elapsed() > CoarseTimerInterval * 3) + QSKIP("Ignore flaky test behavior due to VM scheduling on macOS"); +#endif + QCOMPARE(timerIdFromEvent, timers.coarseTimerId()); // now unregister it and make sure it's gone timers.unregister(timers.coarseTimerId()); diff --git a/tests/auto/corelib/kernel/qsignalmapper/tst_qsignalmapper.cpp b/tests/auto/corelib/kernel/qsignalmapper/tst_qsignalmapper.cpp index c03e3e8e9f..78b0b5dc55 100644 --- a/tests/auto/corelib/kernel/qsignalmapper/tst_qsignalmapper.cpp +++ b/tests/auto/corelib/kernel/qsignalmapper/tst_qsignalmapper.cpp @@ -41,8 +41,8 @@ class QtTestObject : public QObject { Q_OBJECT public slots: - void myslot(int id); - void myslot(const QString &str); + void myIntSlot(int id); + void myStringSlot(const QString &str); signals: void mysignal(int); @@ -54,12 +54,12 @@ public: QString str; }; -void QtTestObject::myslot(int id) +void QtTestObject::myIntSlot(int id) { this->id = id; } -void QtTestObject::myslot(const QString &str) +void QtTestObject::myStringSlot(const QString &str) { this->str = str; } @@ -71,7 +71,7 @@ void QtTestObject::emit_mysignal(int value) void tst_QSignalMapper::mapped() { - QSignalMapper mapper(0); + QSignalMapper mapper; QtTestObject target; QtTestObject src1; @@ -88,8 +88,8 @@ void tst_QSignalMapper::mapped() mapper.setMapping(&src2, "two"); mapper.setMapping(&src3, "three"); - connect(&mapper, SIGNAL(mapped(int)), &target, SLOT(myslot(int))); - connect(&mapper, SIGNAL(mapped(QString)), &target, SLOT(myslot(QString))); + connect(&mapper, &QSignalMapper::mappedInt, &target, &QtTestObject::myIntSlot); + connect(&mapper, &QSignalMapper::mappedString, &target, &QtTestObject::myStringSlot); src1.emit_mysignal(20); QCOMPARE(target.id, 1); diff --git a/tests/auto/corelib/kernel/qtranslator/hellotr_la.qm b/tests/auto/corelib/kernel/qtranslator/hellotr_la.qm Binary files differindex cc42afe05c..25c0aad583 100644 --- a/tests/auto/corelib/kernel/qtranslator/hellotr_la.qm +++ b/tests/auto/corelib/kernel/qtranslator/hellotr_la.qm diff --git a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp index b3efa97dbd..9fde7da816 100644 --- a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp +++ b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp @@ -110,9 +110,10 @@ void tst_QTranslator::load_data() QTest::addColumn<QString>("filepath"); QTest::addColumn<bool>("isEmpty"); QTest::addColumn<QString>("translation"); + QTest::addColumn<QString>("language"); - QTest::newRow("hellotr_la") << "hellotr_la.qm" << false << "Hallo Welt!"; - QTest::newRow("hellotr_empty") << "hellotr_empty.qm" << true << ""; + QTest::newRow("hellotr_la") << "hellotr_la.qm" << false << "Hallo Welt!" << "de"; + QTest::newRow("hellotr_empty") << "hellotr_empty.qm" << true << "" << ""; } void tst_QTranslator::load() @@ -120,12 +121,15 @@ void tst_QTranslator::load() QFETCH(QString, filepath); QFETCH(bool, isEmpty); QFETCH(QString, translation); + QFETCH(QString, language); { QTranslator tor; QVERIFY(tor.load(QFileInfo(filepath).baseName())); QCOMPARE(tor.isEmpty(), isEmpty); QCOMPARE(tor.translate("QPushButton", "Hello world!"), translation); + QCOMPARE(tor.filePath(), filepath); + QCOMPARE(tor.language(), language); } { @@ -136,13 +140,18 @@ void tst_QTranslator::load() QVERIFY(tor.load((const uchar *)data.constData(), data.length())); QCOMPARE(tor.isEmpty(), isEmpty); QCOMPARE(tor.translate("QPushButton", "Hello world!"), translation); + QCOMPARE(tor.filePath(), ""); + QCOMPARE(tor.language(), language); } { QTranslator tor; - QVERIFY(tor.load(QString(":/tst_qtranslator/%1").arg(filepath))); + QString path = QString(":/tst_qtranslator/%1").arg(filepath); + QVERIFY(tor.load(path)); QCOMPARE(tor.isEmpty(), isEmpty); QCOMPARE(tor.translate("QPushButton", "Hello world!"), translation); + QCOMPARE(tor.filePath(), path); + QCOMPARE(tor.language(), language); } } diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 91733bea90..b8baa1cde1 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -276,6 +276,8 @@ private slots: void shouldDeleteVariantDataWorksForAssociative(); void fromStdVariant(); void qt4UuidDataStream(); + void sequentialIterableEndianessSanityCheck(); + void sequentialIterableAppend(); void preferDirectConversionOverInterfaces(); @@ -4698,6 +4700,28 @@ void tst_QVariant::qt4UuidDataStream() QCOMPARE(result.value<QUuid>(), source); } +void tst_QVariant::sequentialIterableEndianessSanityCheck() +{ + namespace QMTP = QtMetaTypePrivate; + uint oldIteratorCaps = QMTP::ForwardCapability | QMTP::BiDirectionalCapability | QMTP::RandomAccessCapability; + QMTP::QSequentialIterableImpl seqImpl {}; + QCOMPARE(seqImpl.revision(), 1u); + memcpy(&seqImpl._iteratorCapabilities, &oldIteratorCaps, sizeof(oldIteratorCaps)); + QCOMPARE(seqImpl.revision(), 0u); +} + +void tst_QVariant::sequentialIterableAppend() +{ + QVector<int> container {1, 2}; + auto variant = QVariant::fromValue(container); + QVERIFY(variant.canConvert<QtMetaTypePrivate::QSequentialIterableImpl>()); + auto asIterable = variant.value<QtMetaTypePrivate::QSequentialIterableImpl>(); + const int i = 3, j = 4; + asIterable.append(&i); + asIterable.append(&j); + QCOMPARE(variant.value<QVector<int>>(), QVector<int> ({1, 2, 3, 4})); +} + void tst_QVariant::preferDirectConversionOverInterfaces() { using namespace QtMetaTypePrivate; diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp index d1a77173c3..2f812a9952 100644 --- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp +++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp @@ -1276,18 +1276,18 @@ void tst_QDataStream::readQCursor(QDataStream *s) QVERIFY(d5.shape() == test.shape()); //## lacks operator== QCOMPARE(d5.hotSpot(), test.hotSpot()); - QVERIFY((d5.bitmap() != 0 && test.bitmap() != 0) || (d5.bitmap() == 0 && test.bitmap() == 0)); - if (d5.bitmap() != 0) { - QPixmap actual = *(d5.bitmap()); - QPixmap expected = *(test.bitmap()); - QCOMPARE(actual, expected); - } - QVERIFY((d5.mask() != 0 && test.mask() != 0) || (d5.mask() == 0 && test.mask() == 0)); - if (d5.mask() != 0) { - QPixmap actual = *(d5.mask()); - QPixmap expected = *(test.mask()); - QCOMPARE(actual, expected); - } + + // Comparing non-null QBitmaps will fail. Upcast them first to pass. + QCOMPARE(d5.bitmap(Qt::ReturnByValue).isNull(), test.bitmap(Qt::ReturnByValue).isNull()); + QCOMPARE( + static_cast<QPixmap>(d5.bitmap(Qt::ReturnByValue)), + static_cast<QPixmap>(test.bitmap(Qt::ReturnByValue)) + ); + QCOMPARE(d5.mask(Qt::ReturnByValue).isNull(), test.mask(Qt::ReturnByValue).isNull()); + QCOMPARE( + static_cast<QPixmap>(d5.mask(Qt::ReturnByValue)), + static_cast<QPixmap>(test.mask(Qt::ReturnByValue)) + ); } #endif diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp index 4b13ac45cc..b1f6090585 100644 --- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp @@ -253,6 +253,10 @@ private slots: void qtbug_46703(); void postEventFromBeginSelectTransitions(); void dontProcessSlotsWhenMachineIsNotRunning(); + + void cancelDelayedEventWithChrono(); + void postDelayedEventWithChronoAndStop(); + void postDelayedEventWithChronoFromThread(); }; class TestState : public QState @@ -6702,5 +6706,163 @@ void tst_QStateMachine::dontProcessSlotsWhenMachineIsNotRunning() QTRY_VERIFY(emitter.thread.isFinished()); } +void tst_QStateMachine::cancelDelayedEventWithChrono() +{ +#if __has_include(<chrono>) + QStateMachine machine; + QTest::ignoreMessage(QtWarningMsg, + "QStateMachine::cancelDelayedEvent: the machine is not running"); + QVERIFY(!machine.cancelDelayedEvent(-1)); + + QState *s1 = new QState(&machine); + DEFINE_ACTIVE_SPY(s1); + QFinalState *s2 = new QFinalState(&machine); + s1->addTransition(new StringTransition("a", s2)); + machine.setInitialState(s1); + + QSignalSpy startedSpy(&machine, &QStateMachine::started); + QSignalSpy runningSpy(&machine, &QStateMachine::runningChanged); + QVERIFY(startedSpy.isValid()); + QVERIFY(runningSpy.isValid()); + machine.start(); + QTRY_COMPARE(startedSpy.count(), 1); + TEST_RUNNING_CHANGED(true); + TEST_ACTIVE_CHANGED(s1, 1); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + int id1 = machine.postDelayedEvent(new StringEvent("c"), std::chrono::seconds{50}); + QVERIFY(id1 != -1); + int id2 = machine.postDelayedEvent(new StringEvent("b"), std::chrono::seconds{25}); + QVERIFY(id2 != -1); + QVERIFY(id2 != id1); + int id3 = machine.postDelayedEvent(new StringEvent("a"), std::chrono::milliseconds{100}); + QVERIFY(id3 != -1); + QVERIFY(id3 != id2); + QVERIFY(machine.cancelDelayedEvent(id1)); + QVERIFY(!machine.cancelDelayedEvent(id1)); + QVERIFY(machine.cancelDelayedEvent(id2)); + QVERIFY(!machine.cancelDelayedEvent(id2)); + + QSignalSpy finishedSpy(&machine, &QStateMachine::finished); + QVERIFY(finishedSpy.isValid()); + QTRY_COMPARE(finishedSpy.count(), 1); + TEST_RUNNING_CHANGED(false); + TEST_ACTIVE_CHANGED(s1, 2); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s2)); +#endif +} + +void tst_QStateMachine::postDelayedEventWithChronoAndStop() +{ +#if __has_include(<chrono>) + QStateMachine machine; + QState *s1 = new QState(&machine); + DEFINE_ACTIVE_SPY(s1); + QFinalState *s2 = new QFinalState(&machine); + s1->addTransition(new StringTransition("a", s2)); + machine.setInitialState(s1); + + QSignalSpy runningSpy(&machine, &QStateMachine::runningChanged); + QVERIFY(runningSpy.isValid()); + QSignalSpy startedSpy(&machine, &QStateMachine::started); + QVERIFY(startedSpy.isValid()); + machine.start(); + QTRY_COMPARE(startedSpy.count(), 1); + TEST_RUNNING_CHANGED(true); + TEST_ACTIVE_CHANGED(s1, 1); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + + int id1 = machine.postDelayedEvent(new StringEvent("a"), std::chrono::milliseconds{0}); + QVERIFY(id1 != -1); + QSignalSpy stoppedSpy(&machine, &QStateMachine::stopped); + QVERIFY(stoppedSpy.isValid()); + machine.stop(); + QTRY_COMPARE(stoppedSpy.count(), 1); + TEST_RUNNING_CHANGED(false); + TEST_ACTIVE_CHANGED(s1, 1); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + + machine.start(); + QTRY_COMPARE(startedSpy.count(), 2); + TEST_RUNNING_CHANGED(true); + TEST_ACTIVE_CHANGED(s1, 3); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + + int id2 = machine.postDelayedEvent(new StringEvent("a"), std::chrono::seconds{1}); + QVERIFY(id2 != -1); + machine.stop(); + QTRY_COMPARE(stoppedSpy.count(), 2); + TEST_RUNNING_CHANGED(false); + TEST_ACTIVE_CHANGED(s1, 3); + machine.start(); + QTRY_COMPARE(startedSpy.count(), 3); + TEST_RUNNING_CHANGED(true); + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + TEST_ACTIVE_CHANGED(s1, 5); + QVERIFY(machine.isRunning()); +#endif +} + +class DelayedEventWithChronoPosterThread : public QThread +{ + Q_OBJECT +public: + DelayedEventWithChronoPosterThread(QStateMachine *machine, QObject *parent = 0) + : QThread(parent), firstEventWasCancelled(false), m_machine(machine) + { + moveToThread(this); + QObject::connect(m_machine, SIGNAL(started()), this, SLOT(postEvent())); + } + + mutable bool firstEventWasCancelled; + +private Q_SLOTS: + void postEvent() + { +#if __has_include(<chrono>) + int id = m_machine->postDelayedEvent(new QEvent(QEvent::User), std::chrono::seconds{1}); + firstEventWasCancelled = m_machine->cancelDelayedEvent(id); + + m_machine->postDelayedEvent(new QEvent(QEvent::User), std::chrono::milliseconds{1}); + + quit(); +#endif + } + +private: + QStateMachine *m_machine; +}; + +void tst_QStateMachine::postDelayedEventWithChronoFromThread() +{ +#if __has_include(<chrono>) + QStateMachine machine; + QState *s1 = new QState(&machine); + DEFINE_ACTIVE_SPY(s1); + QFinalState *f = new QFinalState(&machine); + s1->addTransition(new EventTransition(QEvent::User, f)); + machine.setInitialState(s1); + + DelayedEventWithChronoPosterThread poster(&machine); + poster.start(); + + QSignalSpy runningSpy(&machine, &QStateMachine::runningChanged); + QVERIFY(runningSpy.isValid()); + QSignalSpy finishedSpy(&machine, &QStateMachine::finished); + QVERIFY(finishedSpy.isValid()); + machine.start(); + QTRY_COMPARE(finishedSpy.count(), 1); + TEST_RUNNING_CHANGED_STARTED_STOPPED; + TEST_ACTIVE_CHANGED(s1, 2); + QVERIFY(poster.firstEventWasCancelled); +#endif +} + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" diff --git a/tests/auto/corelib/text/qcollator/tst_qcollator.cpp b/tests/auto/corelib/text/qcollator/tst_qcollator.cpp index 2ae9c6e159..6806aa09b5 100644 --- a/tests/auto/corelib/text/qcollator/tst_qcollator.cpp +++ b/tests/auto/corelib/text/qcollator/tst_qcollator.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -105,6 +105,8 @@ void tst_QCollator::compare_data() QTest::newRow("english6") << QString("en_US") << QString("test 9") << QString("test_19") << -1 << -1 << true << true << -1; QTest::newRow("english7") << QString("en_US") << QString("test_19") << QString("test 19") << 1 << 1 << true << false << 1; QTest::newRow("english8") << QString("en_US") << QString("test.19") << QString("test,19") << 1 << 1 << true << true << 0; + QTest::newRow("en-empty-word") << QString("en_US") << QString() << QString("non-empty") << -1 << -1 << false << true << -1; + QTest::newRow("en-empty-number") << QString("en_US") << QString() << QString("42") << -1 << -1 << true << true << -1; /* In Swedish, a with ring above (E5) comes before a with @@ -119,6 +121,8 @@ void tst_QCollator::compare_data() QTest::newRow("swedish6") << QString("sv_SE") << QString("Test 9") << QString("Test_19") << -1 << -1 << true << true << -1; QTest::newRow("swedish7") << QString("sv_SE") << QString("test_19") << QString("test 19") << 1 << 1 << true << false << 1; QTest::newRow("swedish8") << QString("sv_SE") << QString("test.19") << QString("test,19") << 1 << 1 << true << true << 0; + QTest::newRow("sv-empty-word") << QString("sv_SE") << QString() << QString("mett") << -1 << -1 << false << true << -1; + QTest::newRow("sv-empty-number") << QString("sv_SE") << QString() << QString("42") << -1 << -1 << true << true << -1; /* @@ -133,6 +137,8 @@ void tst_QCollator::compare_data() QTest::newRow("norwegian6") << QString("no_NO") << QString("Test 9") << QString("Test_19") << -1 << -1 << true << true << -1; QTest::newRow("norwegian7") << QString("no_NO") << QString("test_19") << QString("test 19") << 1 << 1 << true << false << 1; QTest::newRow("norwegian8") << QString("no_NO") << QString("test.19") << QString("test,19") << 1 << 1 << true << true << 0; + QTest::newRow("nb-empty-word") << QString("nb_NO") << QString() << QString("mett") << -1 << -1 << false << true << -1; + QTest::newRow("nb-empty-number") << QString("nb_NO") << QString() << QString("42") << -1 << -1 << true << true << -1; /* In German, z comes *after* a with diaresis (E4), @@ -151,6 +157,8 @@ void tst_QCollator::compare_data() QTest::newRow("german11") << QString("de_DE") << QString("Test 9") << QString("Test_19") << -1 << -1 << true << true << -1; QTest::newRow("german12") << QString("de_DE") << QString("test_19") << QString("test 19") << 1 << 1 << true << false << 1; QTest::newRow("german13") << QString("de_DE") << QString("test.19") << QString("test,19") << 1 << 1 << true << true << 0; + QTest::newRow("de-empty-word") << QString("de_DE") << QString() << QString("satt") << -1 << -1 << false << true << -1; + QTest::newRow("de-empty-number") << QString("de_DE") << QString() << QString("42") << -1 << -1 << true << true << -1; /* French sorting of e and e with acute accent @@ -163,11 +171,15 @@ void tst_QCollator::compare_data() QTest::newRow("french6") << QString("fr_FR") << QString("Test 9") << QString("Test_19") << -1 << -1 << true << true << -1; QTest::newRow("french7") << QString("fr_FR") << QString("test_19") << QString("test 19") << 1 << 1 << true << false << 1; QTest::newRow("french8") << QString("fr_FR") << QString("test.19") << QString("test,19") << 1 << 1 << true << true << 0; + QTest::newRow("fr-empty-word") << QString("fr_FR") << QString() << QString("plein") << -1 << -1 << false << true << -1; + QTest::newRow("fr-empty-number") << QString("fr_FR") << QString() << QString("42") << -1 << -1 << true << true << -1; // C locale: case sensitive [A-Z] < [a-z] but case insensitive [Aa] < [Bb] <...< [Zz] const QString C = QStringLiteral("C"); QTest::newRow("C:ABBA:AaaA") << C << QStringLiteral("ABBA") << QStringLiteral("AaaA") << -1 << 1 << false << false << 1; QTest::newRow("C:AZa:aAZ") << C << QStringLiteral("AZa") << QStringLiteral("aAZ") << -1 << 1 << false << false << 1; + QTest::newRow("C-empty-word") << QString(C) << QString() << QString("non-empty") << -1 << -1 << false << true << -1; + QTest::newRow("C-empty-number") << QString(C) << QString() << QString("42") << -1 << -1 << true << true << -1; } void tst_QCollator::compare() diff --git a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp index f19b66be37..e4144a376e 100644 --- a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -1887,14 +1887,16 @@ void tst_QLocale::toDateTime() // Format number string according to system locale settings. // Expected in format is US "1,234.56". -QString systemLocaleFormatNumber(const QString &numberString) +QString systemLocaleFormatNumber(QString &&numberString) { QLocale locale = QLocale::system(); - QString numberStringCopy = numberString; - return numberStringCopy.replace(QChar(','), QChar('G')) - .replace(QChar('.'), QChar('D')) - .replace(QChar('G'), locale.groupSeparator()) - .replace(QChar('D'), locale.decimalPoint()); + QString numberStringMunged = + numberString.replace(QChar(','), QChar('G')).replace(QChar('.'), QChar('D')); + if (locale.numberOptions() & QLocale::OmitGroupSeparator) + numberStringMunged.remove(QLatin1Char('G')); + else + numberStringMunged.replace(QChar('G'), locale.groupSeparator()); + return numberStringMunged.replace(QChar('D'), locale.decimalPoint()); } void tst_QLocale::macDefaultLocale() @@ -1917,12 +1919,14 @@ void tst_QLocale::macDefaultLocale() // independently of the locale. Verify that they have one of the // allowed values and are not the same. QVERIFY(locale.decimalPoint() == QChar('.') || locale.decimalPoint() == QChar(',')); - QVERIFY(locale.groupSeparator() == QChar(',') - || locale.groupSeparator() == QChar('.') - || locale.groupSeparator() == QChar('\xA0') // no-breaking space - || locale.groupSeparator() == QChar('\'') - || locale.groupSeparator() == QChar()); - QVERIFY(locale.decimalPoint() != locale.groupSeparator()); + if (!(locale.numberOptions() & QLocale::OmitGroupSeparator)) { + QVERIFY(locale.groupSeparator() == QChar(',') + || locale.groupSeparator() == QChar('.') + || locale.groupSeparator() == QChar('\xA0') // no-breaking space + || locale.groupSeparator() == QChar('\'') + || locale.groupSeparator() == QChar()); + QVERIFY(locale.decimalPoint() != locale.groupSeparator()); + } // make sure we are using the system to parse them QCOMPARE(locale.toString(1234.56), systemLocaleFormatNumber(QString("1,234.56"))); @@ -2056,6 +2060,8 @@ void tst_QLocale::windowsDefaultLocale() setWinLocaleInfo(LOCALE_SLONGDATE, longDateFormat); const QString shortTimeFormat = QStringLiteral("h^m^s"); setWinLocaleInfo(LOCALE_SSHORTTIME, shortTimeFormat); + const QString longTimeFormat = QStringLiteral("HH%mm%ss"); + setWinLocaleInfo(LOCALE_STIMEFORMAT, longTimeFormat); QSystemLocale dummy; // to provoke a refresh of the system locale QLocale locale = QLocale::system(); @@ -2069,7 +2075,7 @@ void tst_QLocale::windowsDefaultLocale() QCOMPARE(locale.dateTimeFormat(QLocale::ShortFormat), shortDateFormat + QLatin1Char(' ') + shortTimeFormat); const QString expectedLongDateTimeFormat - = longDateFormat + QLatin1Char(' ') + QStringLiteral("h:mm:ss AP"); + = longDateFormat + QLatin1Char(' ') + longTimeFormat; QCOMPARE(locale.dateTimeFormat(QLocale::LongFormat), expectedLongDateTimeFormat); // make sure we are using the system to parse them @@ -2083,7 +2089,7 @@ void tst_QLocale::windowsDefaultLocale() QCOMPARE(locale.toString(QTime(1,2,3), QLocale::ShortFormat), expectedFormattedShortTime); QCOMPARE(locale.toString(QTime(1,2,3), QLocale::NarrowFormat), locale.toString(QTime(1,2,3), QLocale::ShortFormat)); - const QString expectedFormattedLongTime = QStringLiteral("1:02:03 AM"); + const QString expectedFormattedLongTime = QStringLiteral("01%02%03"); QCOMPARE(locale.toString(QTime(1,2,3), QLocale::LongFormat), expectedFormattedLongTime); QCOMPARE(locale.toString(QDateTime(QDate(1974, 12, 1), QTime(1,2,3)), QLocale::ShortFormat), QStringLiteral("1*12*1974 ") + expectedFormattedShortTime); @@ -2091,7 +2097,6 @@ void tst_QLocale::windowsDefaultLocale() locale.toString(QDateTime(QDate(1974, 12, 1), QTime(1,2,3)), QLocale::ShortFormat)); QCOMPARE(locale.toString(QDateTime(QDate(1974, 12, 1), QTime(1,2,3)), QLocale::LongFormat), QStringLiteral("1@12@1974 ") + expectedFormattedLongTime); - QCOMPARE(locale.toString(QTime(1,2,3), QLocale::LongFormat), expectedFormattedLongTime); } #endif // Q_OS_WIN but !Q_OS_WINRT diff --git a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp index 24382a2b61..bcf4e73108 100644 --- a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp +++ b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> +** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> ** Copyright (C) 2019 Mail.ru Group. ** Contact: https://www.qt.io/licensing/ ** @@ -80,6 +80,13 @@ MAKE_ALL(const char*, QChar) #undef MAKE_RELOP // END FIXME +static Q_DECL_CONSTEXPR int sign(int i) noexcept +{ + return i < 0 ? -1 : + i > 0 ? +1 : + /*else*/ 0 ; +} + // Return a plain ASCII row name consisting of maximum 16 chars and the // size for data static QByteArray rowName(const QByteArray &data) @@ -162,6 +169,12 @@ private Q_SLOTS: void compare_QStringView_QStringView() { compare_impl<QStringView, QStringView>(); } void compare_QStringView_QLatin1String_data() { compare_data(); } void compare_QStringView_QLatin1String() { compare_impl<QStringView, QLatin1String>(); } +#ifdef NOT_YET_IMPLMENTED + void compare_QStringView_QByteArray_data() { compare_data(); } + void compare_QStringView_QByteArray() { compare_impl<QStringView, QByteArray>(); } + void compare_QStringView_const_char_star_data() { compare_data(); } + void compare_QStringView_const_char_star() { compare_impl<QStringView, const char *>(); } +#endif void compare_QLatin1String_QChar_data() { compare_data(false); } void compare_QLatin1String_QChar() { compare_impl<QLatin1String, QChar>(); } @@ -205,6 +218,111 @@ private Q_SLOTS: //void compare_const_char_star_const_char_star() { compare_impl<const char *, const char *>(); } private: + void member_compare_data(bool hasConceptOfNullAndEmpty=true) { compare_data(hasConceptOfNullAndEmpty); } + template <typename LHS, typename RHS> + void member_compare_impl() const; + +private Q_SLOTS: + // test all combinations of {QChar, QStringRef, QString, QStringView, QLatin1String, QByteArray, const char*} +#ifdef NOT_YET_IMPLEMENTED // probably never will be - what's the point of QChar::compare(QStringView)? + void member_compare_QChar_QChar_data() { member_compare_data(false); } + void member_compare_QChar_QChar() { member_compare_impl<QChar, QChar>(); } + void member_compare_QChar_QStringRef_data() { member_compare_data(false); } + void member_compare_QChar_QStringRef() { member_compare_impl<QChar, QStringRef>(); } + void member_compare_QChar_QString_data() { member_compare_data(false); } + void member_compare_QChar_QString() { member_compare_impl<QChar, QString>(); } + void member_compare_QChar_QStringView_data() { member_compare_data(false); } + void member_compare_QChar_QStringView() { member_compare_impl<QChar, QStringView>(); } + void member_compare_QChar_QLatin1String_data() { member_compare_data(false); } + void member_compare_QChar_QLatin1String() { member_compare_impl<QChar, QLatin1String>(); } + void member_compare_QChar_QByteArray_data() { member_compare_data(false); } + void member_compare_QChar_QByteArray() { member_compare_impl<QChar, QByteArray>(); } + void member_compare_QChar_const_char_star_data() { member_compare_data(false); } + void member_compare_QChar_const_char_star() { member_compare_impl<QChar, const char *>(); } +#endif + + void member_compare_QStringRef_QChar_data() { member_compare_data(false); } + void member_compare_QStringRef_QChar() { member_compare_impl<QStringRef, QChar>(); } + void member_compare_QStringRef_QStringRef_data() { member_compare_data(); } + void member_compare_QStringRef_QStringRef() { member_compare_impl<QStringRef, QStringRef>(); } + void member_compare_QStringRef_QString_data() { member_compare_data(); } + void member_compare_QStringRef_QString() { member_compare_impl<QStringRef, QString>(); } +#ifdef NOT_YET_IMPLEMENTED + void member_compare_QStringRef_QStringView_data() { member_compare_data(); } + void member_compare_QStringRef_QStringView() { member_compare_impl<QStringRef, QStringView>(); } +#endif + void member_compare_QStringRef_QLatin1String_data() { member_compare_data(); } + void member_compare_QStringRef_QLatin1String() { member_compare_impl<QStringRef, QLatin1String>(); } + void member_compare_QStringRef_QByteArray_data() { member_compare_data(); } + void member_compare_QStringRef_QByteArray() { member_compare_impl<QStringRef, QByteArray>(); } +#ifdef NOT_YET_IMPLEMENTED + void member_compare_QStringRef_const_char_star_data() { member_compare_data(); } + void member_compare_QStringRef_const_char_star() { member_compare_impl<QStringRef, const char *>(); } +#endif + + void member_compare_QString_QChar_data() { member_compare_data(false); } + void member_compare_QString_QChar() { member_compare_impl<QString, QChar>(); } + void member_compare_QString_QStringRef_data() { member_compare_data(); } + void member_compare_QString_QStringRef() { member_compare_impl<QString, QStringRef>(); } + void member_compare_QString_QString_data() { member_compare_data(); } + void member_compare_QString_QString() { member_compare_impl<QString, QString>(); } + void member_compare_QString_QStringView_data() { member_compare_data(); } + void member_compare_QString_QStringView() { member_compare_impl<QString, QStringView>(); } + void member_compare_QString_QLatin1String_data() { member_compare_data(); } + void member_compare_QString_QLatin1String() { member_compare_impl<QString, QLatin1String>(); } + void member_compare_QString_QByteArray_data() { member_compare_data(); } + void member_compare_QString_QByteArray() { member_compare_impl<QString, QByteArray>(); } + void member_compare_QString_const_char_star_data() { member_compare_data(); } + void member_compare_QString_const_char_star() { member_compare_impl<QString, const char *>(); } + +#ifdef NOT_YET_IMPLEMENTED // QChar doesn't implicitly convert to QStringView + void member_compare_QStringView_QChar_data() { member_compare_data(false); } + void member_compare_QStringView_QChar() { member_compare_impl<QStringView, QChar>(); } +#endif + void member_compare_QStringView_QStringRef_data() { member_compare_data(); } + void member_compare_QStringView_QStringRef() { member_compare_impl<QStringView, QStringRef>(); } + void member_compare_QStringView_QString_data() { member_compare_data(); } + void member_compare_QStringView_QString() { member_compare_impl<QStringView, QString>(); } + void member_compare_QStringView_QStringView_data() { member_compare_data(); } + void member_compare_QStringView_QStringView() { member_compare_impl<QStringView, QStringView>(); } +#ifdef NOT_YET_IMPLEMENTED + void member_compare_QStringView_QLatin1String_data() { member_compare_data(); } + void member_compare_QStringView_QLatin1String() { member_compare_impl<QStringView, QLatin1String>(); } + void member_compare_QStringView_QByteArray_data() { member_compare_data(); } + void member_compare_QStringView_QByteArray() { member_compare_impl<QStringView, QByteArray>(); } + void member_compare_QStringView_const_char_star_data() { member_compare_data(); } + void member_compare_QStringView_const_char_star() { member_compare_impl<QStringView, const char *>(); } + + void member_compare_QLatin1String_QChar_data() { member_compare_data(false); } + void member_compare_QLatin1String_QChar() { member_compare_impl<QLatin1String, QChar>(); } + void member_compare_QLatin1String_QStringRef_data() { member_compare_data(); } + void member_compare_QLatin1String_QStringRef() { member_compare_impl<QLatin1String, QStringRef>(); } + void member_compare_QLatin1String_QString_data() { member_compare_data(); } + void member_compare_QLatin1String_QString() { member_compare_impl<QLatin1String, QString>(); } + void member_compare_QLatin1String_QStringView_data() { member_compare_data(); } + void member_compare_QLatin1String_QStringView() { member_compare_impl<QLatin1String, QStringView>(); } + void member_compare_QLatin1String_QLatin1String_data() { member_compare_data(); } + void member_compare_QLatin1String_QLatin1String() { member_compare_impl<QLatin1String, QLatin1String>(); } + void member_compare_QLatin1String_QByteArray_data() { member_compare_data(); } + void member_compare_QLatin1String_QByteArray() { member_compare_impl<QLatin1String, QByteArray>(); } + void member_compare_QLatin1String_const_char_star_data() { member_compare_data(); } + void member_compare_QLatin1String_const_char_star() { member_compare_impl<QLatin1String, const char *>(); } + + void member_compare_QByteArray_QChar_data() { member_compare_data(false); } + void member_compare_QByteArray_QChar() { member_compare_impl<QByteArray, QChar>(); } + void member_compare_QByteArray_QStringRef_data() { member_compare_data(); } + void member_compare_QByteArray_QStringRef() { member_compare_impl<QByteArray, QStringRef>(); } + void member_compare_QByteArray_QString_data() { member_compare_data(); } + void member_compare_QByteArray_QString() { member_compare_impl<QByteArray, QString>(); } + void member_compare_QByteArray_QLatin1String_data() { member_compare_data(); } + void member_compare_QByteArray_QLatin1String() { member_compare_impl<QByteArray, QLatin1String>(); } +#endif + void member_compare_QByteArray_QByteArray_data() { member_compare_data(); } + void member_compare_QByteArray_QByteArray() { member_compare_impl<QByteArray, QByteArray>(); } + void member_compare_QByteArray_const_char_star_data() { member_compare_data(); } + void member_compare_QByteArray_const_char_star() { member_compare_impl<QByteArray, const char *>(); } + +private: void startsWith_data(bool rhsIsQChar = false); template <typename Haystack, typename Needle> void startsWith_impl() const; @@ -601,7 +719,7 @@ void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty) QTest::newRow(qUtf8Printable(QLatin1String("'" lhs "' <> '" rhs "': "))) \ << QStringRef(&pinned[0]) << QLatin1String(lhs) \ << QStringRef(&pinned[1]) << QLatin1String(rhs) \ - << qstrcmp(lhs, rhs) << qstricmp(lhs, rhs); \ + << sign(qstrcmp(lhs, rhs)) << sign(qstricmp(lhs, rhs)); \ } while (false) ROW("", "0"); ROW("0", ""); @@ -691,6 +809,44 @@ void tst_QStringApiSymmetry::compare_impl() const #undef CHECK } +template <typename LHS, typename RHS> +void tst_QStringApiSymmetry::member_compare_impl() const +{ + QFETCH(QStringRef, lhsUnicode); + QFETCH(QLatin1String, lhsLatin1); + QFETCH(QStringRef, rhsUnicode); + QFETCH(QLatin1String, rhsLatin1); + QFETCH(const int, caseSensitiveCompareResult); + QFETCH(const int, caseInsensitiveCompareResult); + + const auto lhsU8 = lhsUnicode.toUtf8(); + const auto rhsU8 = rhsUnicode.toUtf8(); + + const auto lhs = make<LHS>(lhsUnicode, lhsLatin1, lhsU8); + const auto rhs = make<RHS>(rhsUnicode, rhsLatin1, rhsU8); + +#define QVERIFY_NOEXCEPT(expr) do { \ + if (has_nothrow_compare<LHS, RHS>::value) {} else \ + QEXPECT_FAIL("", "Qt is missing a nothrow utf8-utf16 comparator", Continue); \ + QVERIFY(noexcept(expr)); } while (0) + + if (std::is_same<LHS, QByteArray>::value || // needs to simply be marked as noexcept + ((std::is_same<LHS, QString>::value || std::is_same<LHS, QStringRef>::value) + && std::is_same<RHS, QChar>::value)) // implict QChar -> QString conversion kills noexcept + QEXPECT_FAIL("", "known issues, will be fixed before 5.14 release", Continue); + QVERIFY_NOEXCEPT(lhs.compare(rhs, Qt::CaseSensitive)); + + QCOMPARE(sign(lhs.compare(rhs)), caseSensitiveCompareResult); + QCOMPARE(sign(lhs.compare(rhs, Qt::CaseSensitive)), caseSensitiveCompareResult); + if (is_utf8_encoded<LHS>::value && is_utf8_encoded<RHS>::value && + caseSensitiveCompareResult != caseInsensitiveCompareResult && + (!QtPrivate::isAscii(lhsUnicode) || !QtPrivate::isAscii(rhsUnicode))) + { + QEXPECT_FAIL("", "Qt is missing a case-insensitive UTF-8/UTF-8 comparator", Continue); + } + QCOMPARE(sign(lhs.compare(rhs, Qt::CaseInsensitive)), caseInsensitiveCompareResult); +} + static QString empty = QLatin1String(""); static QString null; // the tests below rely on the fact that these objects' names match their contents: diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp index 60e8d8cba2..49ce918caf 100644 --- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp +++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp @@ -64,6 +64,7 @@ public: private slots: void runFunction(); + void runFunction2(); void createThreadRunFunction(); void runMultiple(); void waitcomplete(); @@ -160,17 +161,27 @@ void tst_QThreadPool::runFunction() { QThreadPool manager; testFunctionCount = 0; - manager.start(createTask(noSleepTestFunction)); + manager.start(noSleepTestFunction); } QCOMPARE(testFunctionCount, 1); } +void tst_QThreadPool::runFunction2() +{ + int localCount = 0; + { + QThreadPool manager; + manager.start([&]() { ++localCount; }); + } + QCOMPARE(localCount, 1); +} + void tst_QThreadPool::createThreadRunFunction() { { QThreadPool manager; testFunctionCount = 0; - manager.start(createTask(noSleepTestFunction)); + manager.start(noSleepTestFunction); } QCOMPARE(testFunctionCount, 1); @@ -184,7 +195,7 @@ void tst_QThreadPool::runMultiple() QThreadPool manager; testFunctionCount = 0; for (int i = 0; i < runs; ++i) { - manager.start(createTask(sleepTestFunctionMutex)); + manager.start(sleepTestFunctionMutex); } } QCOMPARE(testFunctionCount, runs); @@ -193,7 +204,7 @@ void tst_QThreadPool::runMultiple() QThreadPool manager; testFunctionCount = 0; for (int i = 0; i < runs; ++i) { - manager.start(createTask(noSleepTestFunctionMutex)); + manager.start(noSleepTestFunctionMutex); } } QCOMPARE(testFunctionCount, runs); @@ -201,7 +212,7 @@ void tst_QThreadPool::runMultiple() { QThreadPool manager; for (int i = 0; i < 500; ++i) - manager.start(createTask(emptyFunct)); + manager.start(emptyFunct); } } @@ -211,7 +222,7 @@ void tst_QThreadPool::waitcomplete() const int runs = 500; for (int i = 0; i < 500; ++i) { QThreadPool pool; - pool.start(createTask(noSleepTestFunction)); + pool.start(noSleepTestFunction); } QCOMPARE(testFunctionCount, runs); } diff --git a/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp b/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp index 9b41014394..5da69e76a5 100644 --- a/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp +++ b/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -40,6 +40,8 @@ private: private slots: void basic_data(); void basic(); + void unspecified_data() { basic_data(); } + void unspecified(); void nameCase(); void specific_data(); void specific(); @@ -145,6 +147,27 @@ void tst_QCalendar::basic() NORMALYEAR(cal, year); } +void tst_QCalendar::unspecified() +{ + QFETCH(QCalendar::System, system); + QCalendar cal(system); + + const QDate today = QDate::currentDate(); + const int thisYear = today.year(); + QCOMPARE(cal.monthsInYear(QCalendar::Unspecified), cal.maximumMonthsInYear()); + for (int month = cal.maximumMonthsInYear(); month > 0; month--) { + const int days = cal.daysInMonth(month); + int count = 0; + // 19 years = one Metonic cycle (used by some lunar calendars) + for (int i = 19; i > 0; --i) { + if (cal.daysInMonth(month, thisYear - i) == days) + count++; + } + // Require a majority of the years tested: + QVERIFY2(count > 9, "Default daysInMonth() should be for a normal year"); + } +} + void tst_QCalendar::nameCase() { QVERIFY(QCalendar::availableCalendars().contains(QStringLiteral("Gregorian"))); diff --git a/tests/auto/corelib/time/qdate/tst_qdate.cpp b/tests/auto/corelib/time/qdate/tst_qdate.cpp index 567209dcf6..274bf4f6f0 100644 --- a/tests/auto/corelib/time/qdate/tst_qdate.cpp +++ b/tests/auto/corelib/time/qdate/tst_qdate.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -1352,6 +1352,7 @@ void tst_QDate::toStringDateFormat() QFETCH(Qt::DateFormat, format); QFETCH(QString, expectedStr); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QCOMPARE(date.toString(Qt::SystemLocaleShortDate), QLocale::system().toString(date, QLocale::ShortFormat)); QCOMPARE(date.toString(Qt::DefaultLocaleShortDate), QLocale().toString(date, QLocale::ShortFormat)); QCOMPARE(date.toString(Qt::SystemLocaleLongDate), QLocale::system().toString(date, QLocale::LongFormat)); @@ -1361,6 +1362,7 @@ void tst_QDate::toStringDateFormat() QCOMPARE(date.toString(Qt::DefaultLocaleShortDate), QLocale().toString(date, QLocale::ShortFormat)); QCOMPARE(date.toString(Qt::SystemLocaleLongDate), QLocale::system().toString(date, QLocale::LongFormat)); QCOMPARE(date.toString(Qt::DefaultLocaleLongDate), QLocale().toString(date, QLocale::LongFormat)); +#endif // ### Qt 6: remove QCOMPARE(date.toString(format), expectedStr); } diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp index 6aae91f62f..26ad91271d 100644 --- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp @@ -127,8 +127,10 @@ private slots: #ifdef Q_OS_WIN void fromString_LOCALE_ILDATE(); #endif +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) void fromStringToStringLocale_data(); void fromStringToStringLocale(); +#endif // ### Qt 6: remove void offsetFromUtc(); void setOffsetFromUtc(); @@ -295,9 +297,9 @@ void tst_QDateTime::initTestCase() void tst_QDateTime::init() { -#if defined(Q_OS_WIN32) +#if defined(Q_OS_WIN32) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0) SetThreadLocale(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)); -#endif +#endif // ### Qt 6: remove } QString tst_QDateTime::str( int y, int month, int d, int h, int min, int s ) @@ -834,8 +836,10 @@ void tst_QDateTime::toString_isoDate() QFETCH(Qt::DateFormat, format); QFETCH(QString, expected); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QLocale oldLocale; QLocale::setDefault(QLocale("en_US")); +#endif // ### Qt 6: remove QString result = datetime.toString(format); QCOMPARE(result, expected); @@ -854,7 +858,9 @@ void tst_QDateTime::toString_isoDate() QCOMPARE(resultDatetime, QDateTime()); } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QLocale::setDefault(oldLocale); +#endif // ### Qt 6: remove } void tst_QDateTime::toString_isoDate_extra() @@ -1763,7 +1769,7 @@ void tst_QDateTime::daylightSavingsTimeChange() // because some functions did not reset the flag when moving in or out of DST. // WARNING: This only tests anything if there's a Daylight Savings Time change - // in the current locale between inDST and outDST. + // in the current time-zone between inDST and outDST. // This is true for Central European Time and may be elsewhere. QFETCH(QDate, inDST); @@ -2612,6 +2618,9 @@ void tst_QDateTime::fromString_LOCALE_ILDATE() } #endif +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED + void tst_QDateTime::fromStringToStringLocale_data() { QTest::addColumn<QLocale>("locale"); @@ -2643,6 +2652,8 @@ void tst_QDateTime::fromStringToStringLocale() #undef ROUNDTRIP QLocale::setDefault(def); } +QT_WARNING_POP +#endif // ### Qt 6: remove void tst_QDateTime::offsetFromUtc() { @@ -2941,19 +2952,19 @@ void tst_QDateTime::fewDigitsInYear() const void tst_QDateTime::printNegativeYear() const { { - QDateTime date(QDate(-20, 10, 11)); + QDateTime date(QDate(-20, 10, 11).startOfDay()); QVERIFY(date.isValid()); QCOMPARE(date.toString(QLatin1String("yyyy")), QString::fromLatin1("-0020")); } { - QDateTime date(QDate(-3, 10, 11)); + QDateTime date(QDate(-3, 10, 11).startOfDay()); QVERIFY(date.isValid()); QCOMPARE(date.toString(QLatin1String("yyyy")), QString::fromLatin1("-0003")); } { - QDateTime date(QDate(-400, 10, 11)); + QDateTime date(QDate(-400, 10, 11).startOfDay()); QVERIFY(date.isValid()); QCOMPARE(date.toString(QLatin1String("yyyy")), QString::fromLatin1("-0400")); } diff --git a/tests/auto/corelib/time/qtime/tst_qtime.cpp b/tests/auto/corelib/time/qtime/tst_qtime.cpp index f85e0ea74e..027232f6d5 100644 --- a/tests/auto/corelib/time/qtime/tst_qtime.cpp +++ b/tests/auto/corelib/time/qtime/tst_qtime.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -77,7 +77,9 @@ private slots: void toStringDateFormat(); void toStringFormat_data(); void toStringFormat(); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) void toStringLocale(); +#endif // ### Qt 6: remove void msecsSinceStartOfDay_data(); void msecsSinceStartOfDay(); @@ -770,6 +772,7 @@ void tst_QTime::toStringFormat() QCOMPARE( t.toString( format ), str ); } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) void tst_QTime::toStringLocale() { QTime time(18, 30); @@ -791,6 +794,7 @@ void tst_QTime::toStringLocale() QCOMPARE(time.toString(Qt::DefaultLocaleLongDate), QLocale().toString(time, QLocale::LongFormat)); } +#endif // ### Qt 6: remove void tst_QTime::msecsSinceStartOfDay_data() { diff --git a/tests/auto/corelib/tools/qscopeguard/CMakeLists.txt b/tests/auto/corelib/tools/qscopeguard/CMakeLists.txt index 243efdd0b2..11b425448b 100644 --- a/tests/auto/corelib/tools/qscopeguard/CMakeLists.txt +++ b/tests/auto/corelib/tools/qscopeguard/CMakeLists.txt @@ -8,3 +8,6 @@ add_qt_test(tst_qscopeguard SOURCES tst_qscopeguard.cpp ) + +## Scopes: +##################################################################### diff --git a/tests/auto/corelib/tools/qscopeguard/qscopeguard.pro b/tests/auto/corelib/tools/qscopeguard/qscopeguard.pro index 070d4b077c..e3645befcf 100644 --- a/tests/auto/corelib/tools/qscopeguard/qscopeguard.pro +++ b/tests/auto/corelib/tools/qscopeguard/qscopeguard.pro @@ -2,3 +2,6 @@ CONFIG += testcase TARGET = tst_qscopeguard QT = core testlib SOURCES = tst_qscopeguard.cpp + +# Force C++17 if available +contains(QT_CONFIG, c++1z): CONFIG += c++1z diff --git a/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp index 01181ce20e..4bb4113845 100644 --- a/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp +++ b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com> +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -30,24 +31,130 @@ #include <QtCore/QScopeGuard> /*! - \class tst_QScopedGuard + \class tst_QScopeGuard \internal \since 5.11 - \brief Tests class QScopedCleanup and function qScopeGuard + \brief Tests class QScopeGuard and function qScopeGuard */ -class tst_QScopedGuard : public QObject +class tst_QScopeGuard : public QObject { Q_OBJECT private Q_SLOTS: + void construction(); + void constructionFromLvalue(); + void constructionFromRvalue(); void leavingScope(); void exceptions(); }; +void func() +{ +} + +int intFunc() +{ + return 0; +} + +Q_REQUIRED_RESULT int noDiscardFunc() +{ + return 0; +} + +struct Callable +{ + Callable() { } + Callable(const Callable &other) + { + Q_UNUSED(other); + ++copied; + } + Callable(Callable &&other) + { + Q_UNUSED(other); + ++moved; + } + void operator()() { } + + static int copied; + static int moved; + static void resetCounts() + { + copied = 0; + moved = 0; + } +}; + +int Callable::copied = 0; +int Callable::moved = 0; + static int s_globalState = 0; -void tst_QScopedGuard::leavingScope() +void tst_QScopeGuard::construction() +{ +#ifdef __cpp_deduction_guides + QScopeGuard fromLambda([] { }); + QScopeGuard fromFunction(func); + QScopeGuard fromFunctionPointer(&func); + QScopeGuard fromNonVoidFunction(intFunc); + QScopeGuard fromNoDiscardFunction(noDiscardFunc); +#ifndef __apple_build_version__ + QScopeGuard fromStdFunction{std::function(func)}; + std::function stdFunction(func); + QScopeGuard fromNamedStdFunction(stdFunction); +#endif +#else + QSKIP("This test requires C++17 Class Template Argument Deduction support enabled in the compiler."); +#endif +} + +void tst_QScopeGuard::constructionFromLvalue() +{ +#ifdef __cpp_deduction_guides + Callable::resetCounts(); + { + Callable callable; + QScopeGuard guard(callable); + } + QCOMPARE(Callable::copied, 1); + QCOMPARE(Callable::moved, 0); + Callable::resetCounts(); + { + Callable callable; + auto guard = qScopeGuard(callable); + } + QCOMPARE(Callable::copied, 1); + QCOMPARE(Callable::moved, 0); +#else + QSKIP("This test requires C++17 Class Template Argument Deduction support enabled in the compiler."); +#endif +} + +void tst_QScopeGuard::constructionFromRvalue() +{ +#ifdef __cpp_deduction_guides + Callable::resetCounts(); + { + Callable callable; + QScopeGuard guard(std::move(callable)); + } + QCOMPARE(Callable::copied, 0); + QCOMPARE(Callable::moved, 1); + Callable::resetCounts(); + { + Callable callable; + auto guard = qScopeGuard(std::move(callable)); + } + QCOMPARE(Callable::copied, 0); + QCOMPARE(Callable::moved, 1); +#else + QSKIP("This test requires C++17 Class Template Argument Deduction support enabled in the compiler."); +#endif +} + +void tst_QScopeGuard::leavingScope() { auto cleanup = qScopeGuard([] { s_globalState++; QCOMPARE(s_globalState, 3); }); QCOMPARE(s_globalState, 0); @@ -61,7 +168,7 @@ void tst_QScopedGuard::leavingScope() s_globalState++; } -void tst_QScopedGuard::exceptions() +void tst_QScopeGuard::exceptions() { s_globalState = 0; bool caught = false; @@ -81,5 +188,5 @@ void tst_QScopedGuard::exceptions() } -QTEST_MAIN(tst_QScopedGuard) +QTEST_MAIN(tst_QScopeGuard) #include "tst_qscopeguard.moc" diff --git a/tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp b/tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp index 8e6ca486d5..758aeb42b9 100644 --- a/tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp +++ b/tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp @@ -42,6 +42,19 @@ class TstWidget; class TstDialog; QT_FORWARD_DECLARE_CLASS(QPushButton) +class TestButton : public QPushButton +{ +public: + TestButton(const QString &title, QWidget *parent = nullptr) + : QPushButton(title, parent) + {} +protected: + bool hitButton(const QPoint &pos) const override + { + return rect().contains(pos); + } +}; + class tst_qmouseevent_modal : public QObject { Q_OBJECT @@ -63,7 +76,7 @@ public: public slots: void buttonPressed(); public: - QPushButton *pb; + TestButton *pb; TstDialog *d; }; @@ -135,7 +148,7 @@ void tst_qmouseevent_modal::mousePressRelease() TstWidget::TstWidget() { - pb = new QPushButton( "Press me", this ); + pb = new TestButton( "Press me", this ); pb->setObjectName("testbutton"); QSize s = pb->sizeHint(); pb->setGeometry( 5, 5, s.width(), s.height() ); diff --git a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp index 945a4772f3..99fb3d3e72 100644 --- a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp +++ b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp @@ -413,6 +413,7 @@ void tst_QColorSpace::primaries2() void tst_QColorSpace::invalidPrimaries() { + QTest::ignoreMessage(QtWarningMsg, QRegularExpression("QColorSpace attempted constructed from invalid primaries")); QColorSpace custom(QPointF(), QPointF(), QPointF(), QPointF(), QColorSpace::TransferFunction::Linear); QVERIFY(!custom.isValid()); } @@ -444,8 +445,15 @@ void tst_QColorSpace::changeTransferFunction() QColorSpace undefined; QCOMPARE(undefined.withTransferFunction(QColorSpace::TransferFunction::Linear), undefined); - undefined.setTransferFunction(QColorSpace::TransferFunction::SRgb); - QCOMPARE(undefined, QColorSpace()); + + QColorSpace partial; + partial.setTransferFunction(QColorSpace::TransferFunction::SRgb); + QCOMPARE(partial.transferFunction(), QColorSpace::TransferFunction::SRgb); + QVERIFY(!partial.isValid()); + + partial.setPrimaries(QColorSpace::Primaries::SRgb); + QVERIFY(partial.isValid()); + QCOMPARE(partial, QColorSpace(QColorSpace::SRgb)); } void tst_QColorSpace::changePrimaries() diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/links.md b/tests/auto/gui/text/qtextmarkdownwriter/data/links.md new file mode 100644 index 0000000000..33cdb2b3ab --- /dev/null +++ b/tests/auto/gui/text/qtextmarkdownwriter/data/links.md @@ -0,0 +1,25 @@ +A series of links. + +[link](/uri) + +[link]() + +[link](/uri "title") + +[link](/uri "à bcdè") + +[link](/uri "title title \" title title") + +[link](/url "title \""") + +[link](/url "title +title +title title +\"title\" title \" +title") + +* [link](/url "title") +* [link](/url) +* [link](/url "title +title title") +* nonlink diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp index d15e856a20..31592c7f0f 100644 --- a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp +++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp @@ -368,6 +368,7 @@ void tst_QTextMarkdownWriter::rewriteDocument_data() QTest::newRow("example") << "example.md"; QTest::newRow("list items after headings") << "headingsAndLists.md"; QTest::newRow("word wrap") << "wordWrap.md"; + QTest::newRow("links") << "links.md"; } void tst_QTextMarkdownWriter::rewriteDocument() diff --git a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp index 120b1c4b66..752655ee94 100644 --- a/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp +++ b/tests/auto/network/access/qnetworkaccessmanager/tst_qnetworkaccessmanager.cpp @@ -58,7 +58,7 @@ tst_QNetworkAccessManager::tst_QNetworkAccessManager() void tst_QNetworkAccessManager::networkAccessible() { -#ifndef QT_NO_BEARERMANAGEMENT +#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section QNetworkAccessManager manager; qRegisterMetaType<QNetworkAccessManager::NetworkAccessibility>("QNetworkAccessManager::NetworkAccessibility"); diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index b8f69cb393..83fe83fe3d 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -1316,9 +1316,9 @@ tst_QNetworkReply::tst_QNetworkReply() "+socksauth", true); } else { #endif // !QT_NO_NETWORKPROXY - printf("==================================================================\n"); - printf("Proxy could not be looked up. No proxy will be used while testing!\n"); - printf("==================================================================\n"); + fprintf(stderr, "==================================================================\n"); + fprintf(stderr, "Proxy could not be looked up. No proxy will be used while testing!\n"); + fprintf(stderr, "==================================================================\n"); #ifndef QT_NO_NETWORKPROXY } #endif // !QT_NO_NETWORKPROXY diff --git a/tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp b/tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp index 6355fea6ab..272e837ac5 100644 --- a/tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp +++ b/tests/auto/network/socket/qlocalsocket/socketprocess/main.cpp @@ -65,8 +65,8 @@ bool runServer(int numberOfConnections) return false; } printf("server: data written\n"); - if (socket->socketError() != QLocalSocket::UnknownSocketError) { - fprintf(stderr, "server: socket error %d\n", socket->socketError()); + if (socket->error() != QLocalSocket::UnknownSocketError) { + fprintf(stderr, "server: socket error %d\n", socket->error()); return false; } } @@ -83,8 +83,8 @@ bool runClient() socket.connectToServer(serverName, QLocalSocket::ReadWrite); if (socket.waitForConnected()) break; - if (socket.socketError() == QLocalSocket::ServerNotFoundError - || socket.socketError() == QLocalSocket::ConnectionRefusedError) { + if (socket.error() == QLocalSocket::ServerNotFoundError + || socket.error() == QLocalSocket::ConnectionRefusedError) { if (connectTimer.elapsed() > 5000) { fprintf(stderr, "client: server not found or connection refused. Giving up.\n"); return false; diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp index 0c1536bd59..baf841d237 100644 --- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp +++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp @@ -174,7 +174,7 @@ public: this, SLOT(slotConnected())); connect(this, SIGNAL(disconnected()), this, SLOT(slotDisconnected())); - connect(this, SIGNAL(error(QLocalSocket::LocalSocketError)), + connect(this, SIGNAL(errorOccurred(QLocalSocket::LocalSocketError)), this, SLOT(slotError(QLocalSocket::LocalSocketError))); connect(this, SIGNAL(stateChanged(QLocalSocket::LocalSocketState)), this, SLOT(slotStateChanged(QLocalSocket::LocalSocketState))); @@ -192,10 +192,10 @@ private slots: { QCOMPARE(state(), QLocalSocket::UnconnectedState); } - void slotError(QLocalSocket::LocalSocketError newError) + void slotErrorOccurred(QLocalSocket::LocalSocketError newError) { QVERIFY(errorString() != QLatin1String("Unknown error")); - QCOMPARE(socketError(), newError); + QCOMPARE(error(), newError); } void slotStateChanged(QLocalSocket::LocalSocketState newState) { @@ -244,7 +244,7 @@ void tst_QLocalSocket::socket_basic() LocalSocket socket; QSignalSpy spyConnected(&socket, SIGNAL(connected())); QSignalSpy spyDisconnected(&socket, SIGNAL(disconnected())); - QSignalSpy spyError(&socket, SIGNAL(error(QLocalSocket::LocalSocketError))); + QSignalSpy spyError(&socket, SIGNAL(errorOccurred(QLocalSocket::LocalSocketError))); QSignalSpy spyStateChanged(&socket, SIGNAL(stateChanged(QLocalSocket::LocalSocketState))); QSignalSpy spyReadyRead(&socket, SIGNAL(readyRead())); @@ -256,7 +256,7 @@ void tst_QLocalSocket::socket_basic() QCOMPARE(socket.canReadLine(), false); socket.close(); socket.disconnectFromServer(); - QCOMPARE(QLocalSocket::UnknownSocketError, socket.socketError()); + QCOMPARE(QLocalSocket::UnknownSocketError, socket.error()); QVERIFY(!socket.errorString().isEmpty()); QCOMPARE(socket.flush(), false); QCOMPARE(socket.isValid(), false); @@ -359,7 +359,7 @@ void tst_QLocalSocket::listenAndConnect() QSignalSpy spyConnected(socket, SIGNAL(connected())); QSignalSpy spyDisconnected(socket, SIGNAL(disconnected())); - QSignalSpy spyError(socket, SIGNAL(error(QLocalSocket::LocalSocketError))); + QSignalSpy spyError(socket, SIGNAL(errorOccurred(QLocalSocket::LocalSocketError))); QSignalSpy spyStateChanged(socket, SIGNAL(stateChanged(QLocalSocket::LocalSocketState))); QSignalSpy spyReadyRead(socket, SIGNAL(readyRead())); @@ -375,13 +375,13 @@ void tst_QLocalSocket::listenAndConnect() QVERIFY(socket->waitForConnected()); QVERIFY(socket->isValid()); QCOMPARE(socket->errorString(), QString("Unknown error")); - QCOMPARE(socket->socketError(), QLocalSocket::UnknownSocketError); + QCOMPARE(socket->error(), QLocalSocket::UnknownSocketError); QCOMPARE(socket->state(), QLocalSocket::ConnectedState); //QVERIFY(socket->socketDescriptor() != -1); QCOMPARE(spyError.count(), 0); } else { QVERIFY(!socket->errorString().isEmpty()); - QVERIFY(socket->socketError() != QLocalSocket::UnknownSocketError); + QVERIFY(socket->error() != QLocalSocket::UnknownSocketError); QCOMPARE(socket->state(), QLocalSocket::UnconnectedState); //QCOMPARE(socket->socketDescriptor(), -1); QCOMPARE(qvariant_cast<QLocalSocket::LocalSocketError>(spyError.first()[0]), @@ -525,7 +525,7 @@ void tst_QLocalSocket::sendData() LocalSocket socket; QSignalSpy spyConnected(&socket, SIGNAL(connected())); QSignalSpy spyDisconnected(&socket, SIGNAL(disconnected())); - QSignalSpy spyError(&socket, SIGNAL(error(QLocalSocket::LocalSocketError))); + QSignalSpy spyError(&socket, SIGNAL(errorOccurred(QLocalSocket::LocalSocketError))); QSignalSpy spyStateChanged(&socket, SIGNAL(stateChanged(QLocalSocket::LocalSocketState))); QSignalSpy spyReadyRead(&socket, SIGNAL(readyRead())); @@ -1104,7 +1104,7 @@ void tst_QLocalSocket::recycleClientSocket() QVERIFY(server.listen(serverName)); QLocalSocket client; QSignalSpy clientReadyReadSpy(&client, SIGNAL(readyRead())); - QSignalSpy clientErrorSpy(&client, SIGNAL(error(QLocalSocket::LocalSocketError))); + QSignalSpy clientErrorSpy(&client, SIGNAL(errorOccurred(QLocalSocket::LocalSocketError))); for (int i = 0; i < lines.count(); ++i) { client.abort(); clientReadyReadSpy.clear(); diff --git a/tests/auto/testlib/CMakeLists.txt b/tests/auto/testlib/CMakeLists.txt index fe80927327..fd342e82a4 100644 --- a/tests/auto/testlib/CMakeLists.txt +++ b/tests/auto/testlib/CMakeLists.txt @@ -2,7 +2,7 @@ # add_subdirectory(outformat) # special case missing project add_subdirectory(qsignalspy) -add_subdirectory(selftests) +# add_subdirectory(selftests) # special case disable because the conversion is broken and hard to fix atm if(TARGET Qt::Widgets) add_subdirectory(qabstractitemmodeltester) endif() diff --git a/tests/auto/testlib/selftests/badxml/tst_badxml.cpp b/tests/auto/testlib/selftests/badxml/tst_badxml.cpp index 164dc7eaa9..d82765311b 100644 --- a/tests/auto/testlib/selftests/badxml/tst_badxml.cpp +++ b/tests/auto/testlib/selftests/badxml/tst_badxml.cpp @@ -194,6 +194,9 @@ int main(int argc, char** argv) args << argv[i]; } } + + args << "-eventcounter"; + /* We just want testlib to output a benchmark result, we don't actually care about the value, so just do one iteration to save time. diff --git a/tests/auto/testlib/selftests/benchlibcallgrind/tst_benchlibcallgrind.cpp b/tests/auto/testlib/selftests/benchlibcallgrind/tst_benchlibcallgrind.cpp index fe83ee6608..f2176612ad 100644 --- a/tests/auto/testlib/selftests/benchlibcallgrind/tst_benchlibcallgrind.cpp +++ b/tests/auto/testlib/selftests/benchlibcallgrind/tst_benchlibcallgrind.cpp @@ -79,6 +79,14 @@ void tst_BenchlibCallgrind::twoHundredMillionInstructions() #endif } -QTEST_MAIN(tst_BenchlibCallgrind) +int main(int argc, char *argv[]) +{ + std::vector<const char*> args(argv, argv + argc); + args.push_back("-callgrind"); + argc = args.size(); + argv = const_cast<char**>(&args[0]); + + QTEST_MAIN_IMPL(tst_BenchlibCallgrind) +} #include "tst_benchlibcallgrind.moc" diff --git a/tests/auto/testlib/selftests/benchlibcounting/tst_benchlibcounting.cpp b/tests/auto/testlib/selftests/benchlibcounting/tst_benchlibcounting.cpp index 58df127f3a..56b6d92f67 100644 --- a/tests/auto/testlib/selftests/benchlibcounting/tst_benchlibcounting.cpp +++ b/tests/auto/testlib/selftests/benchlibcounting/tst_benchlibcounting.cpp @@ -59,5 +59,14 @@ void tst_BenchlibCounting::failingBenchmark() }; } -QTEST_MAIN(tst_BenchlibCounting) +int main(int argc, char *argv[]) +{ + std::vector<const char*> args(argv, argv + argc); + args.push_back("-eventcounter"); + argc = args.size(); + argv = const_cast<char**>(&args[0]); + + QTEST_MAIN_IMPL(tst_BenchlibCounting) +} + #include "tst_benchlibcounting.moc" diff --git a/tests/auto/testlib/selftests/benchlibeventcounter/tst_benchlibeventcounter.cpp b/tests/auto/testlib/selftests/benchlibeventcounter/tst_benchlibeventcounter.cpp index e8015acb95..e3f4720a5e 100644 --- a/tests/auto/testlib/selftests/benchlibeventcounter/tst_benchlibeventcounter.cpp +++ b/tests/auto/testlib/selftests/benchlibeventcounter/tst_benchlibeventcounter.cpp @@ -94,6 +94,11 @@ void tst_BenchlibEventCounter::events_data() int main(int argc, char** argv) { + std::vector<const char*> args(argv, argv + argc); + args.push_back("-eventcounter"); + argc = args.size(); + argv = const_cast<char**>(&args[0]); + TestEventDispatcher dispatcher; QCoreApplication app(argc, argv); tst_BenchlibEventCounter test; diff --git a/tests/auto/testlib/selftests/benchliboptions/tst_benchliboptions.cpp b/tests/auto/testlib/selftests/benchliboptions/tst_benchliboptions.cpp index c1acf5a6e8..b89ca28ff2 100644 --- a/tests/auto/testlib/selftests/benchliboptions/tst_benchliboptions.cpp +++ b/tests/auto/testlib/selftests/benchliboptions/tst_benchliboptions.cpp @@ -83,6 +83,9 @@ void tst_BenchlibOptions::threeEvents() int main(int argc, char** argv) { + std::vector<const char*> args(argv, argv + argc); + args.push_back("-eventcounter"); + int ret = 0; TestEventDispatcher dispatcher; @@ -91,29 +94,27 @@ int main(int argc, char** argv) /* Run with no special arguments. */ { tst_BenchlibOptions test; - ret += QTest::qExec(&test, argc, argv); + ret += QTest::qExec(&test, args.size(), const_cast<char**>(&args[0])); } /* Run with an exact number of iterations. */ { - QVector<char const*> args; - for (int i = 0; i < argc; ++i) args << argv[i]; - args << "-iterations"; - args << "15"; + auto extraArgs = args; + extraArgs.push_back("-iterations"); + extraArgs.push_back("15"); tst_BenchlibFifteenIterations test; - ret += QTest::qExec(&test, args.count(), const_cast<char**>(args.data())); + ret += QTest::qExec(&test, extraArgs.size(), const_cast<char**>(&extraArgs[0])); } /* Run until getting a value of at least 100. */ { - QVector<char const*> args; - for (int i = 0; i < argc; ++i) args << argv[i]; - args << "-minimumvalue"; - args << "100"; + auto extraArgs = args; + extraArgs.push_back("-minimumvalue"); + extraArgs.push_back("100"); tst_BenchlibOneHundredMinimum test; - ret += QTest::qExec(&test, args.count(), const_cast<char**>(args.data())); + ret += QTest::qExec(&test, extraArgs.size(), const_cast<char**>(&extraArgs[0])); } return ret; diff --git a/tests/auto/testlib/selftests/benchlibtickcounter/tst_benchlibtickcounter.cpp b/tests/auto/testlib/selftests/benchlibtickcounter/tst_benchlibtickcounter.cpp index b37f63f20a..2cb7dfd77f 100644 --- a/tests/auto/testlib/selftests/benchlibtickcounter/tst_benchlibtickcounter.cpp +++ b/tests/auto/testlib/selftests/benchlibtickcounter/tst_benchlibtickcounter.cpp @@ -62,6 +62,14 @@ void tst_BenchlibTickCounter::threeBillionTicks() #endif } -QTEST_MAIN(tst_BenchlibTickCounter) +int main(int argc, char *argv[]) +{ + std::vector<const char*> args(argv, argv + argc); + args.push_back("-tickcounter"); + argc = args.size(); + argv = const_cast<char**>(&args[0]); + + QTEST_MAIN_IMPL(tst_BenchlibTickCounter) +} #include "tst_benchlibtickcounter.moc" diff --git a/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp b/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp index 49c08982ad..cb3ac4fc2d 100644 --- a/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp +++ b/tests/auto/testlib/selftests/blacklisted/tst_blacklisted.cpp @@ -80,7 +80,7 @@ void tst_Blacklisted::xpass() #include <setjmp.h> static jmp_buf state; -static void abort_handler(int signal) +static void abort_handler(int) { longjmp(state, 1); } diff --git a/tests/auto/testlib/selftests/commandlinedata/tst_commandlinedata.cpp b/tests/auto/testlib/selftests/commandlinedata/tst_commandlinedata.cpp index 8cb1192ea2..a916fd7f1e 100644 --- a/tests/auto/testlib/selftests/commandlinedata/tst_commandlinedata.cpp +++ b/tests/auto/testlib/selftests/commandlinedata/tst_commandlinedata.cpp @@ -63,6 +63,16 @@ void tst_DataTable::fiveTablePasses_data() const QTest::newRow("fiveTablePasses_data5") << true; } -QTEST_MAIN(tst_DataTable) +int main(int argc, char *argv[]) +{ + std::vector<const char*> args(argv, argv + argc); + args.push_back("fiveTablePasses"); + args.push_back("fiveTablePasses:fiveTablePasses_data1"); + args.push_back("-v2"); + argc = args.size(); + argv = const_cast<char**>(&args[0]); + + QTEST_MAIN_IMPL(tst_DataTable) +} #include "tst_commandlinedata.moc" diff --git a/tests/auto/testlib/selftests/counting/tst_counting.cpp b/tests/auto/testlib/selftests/counting/tst_counting.cpp index da5595b04f..56933c78b7 100644 --- a/tests/auto/testlib/selftests/counting/tst_counting.cpp +++ b/tests/auto/testlib/selftests/counting/tst_counting.cpp @@ -287,5 +287,15 @@ void tst_Counting::testSkipInCleanup() qDebug() << "This test function should execute and then QSKIP in cleanup()"; } -QTEST_MAIN(tst_Counting) +int main(int argc, char *argv[]) +{ +#ifdef TESTLIB_VERBOSITY_ARG + std::vector<const char*> args(argv, argv + argc); + args.push_back(QT_STRINGIFY(TESTLIB_VERBOSITY_ARG)); + argc = args.size(); + argv = const_cast<char**>(&args[0]); +#endif + + QTEST_MAIN_IMPL(tst_Counting) +} #include "tst_counting.moc" diff --git a/tests/auto/testlib/selftests/deleteLater/deleteLater.pro b/tests/auto/testlib/selftests/deleteLater/deleteLater.pro index 9a10096461..1b057eccde 100644 --- a/tests/auto/testlib/selftests/deleteLater/deleteLater.pro +++ b/tests/auto/testlib/selftests/deleteLater/deleteLater.pro @@ -4,6 +4,6 @@ QT = core testlib CONFIG -= app_bundle CONFIG -= debug_and_release_target -TARGET = tst_deleteLater +TARGET = deleteLater include($$QT_SOURCE_TREE/src/testlib/selfcover.pri) diff --git a/tests/auto/testlib/selftests/deleteLater_noApp/deleteLater_noApp.pro b/tests/auto/testlib/selftests/deleteLater_noApp/deleteLater_noApp.pro index 6f2b253c14..90440109e7 100644 --- a/tests/auto/testlib/selftests/deleteLater_noApp/deleteLater_noApp.pro +++ b/tests/auto/testlib/selftests/deleteLater_noApp/deleteLater_noApp.pro @@ -4,6 +4,6 @@ QT = core testlib CONFIG -= app_bundle CONFIG -= debug_and_release_target -TARGET = tst_deleteLater_noApp +TARGET = deleteLater_noApp include($$QT_SOURCE_TREE/src/testlib/selfcover.pri) diff --git a/tests/auto/testlib/selftests/expected_assert.xunitxml b/tests/auto/testlib/selftests/expected_assert.junitxml index ca12a45e20..ca12a45e20 100644 --- a/tests/auto/testlib/selftests/expected_assert.xunitxml +++ b/tests/auto/testlib/selftests/expected_assert.junitxml diff --git a/tests/auto/testlib/selftests/expected_badxml.xunitxml b/tests/auto/testlib/selftests/expected_badxml.junitxml index 49048fdad6..49048fdad6 100644 --- a/tests/auto/testlib/selftests/expected_badxml.xunitxml +++ b/tests/auto/testlib/selftests/expected_badxml.junitxml diff --git a/tests/auto/testlib/selftests/expected_benchlibcallgrind.xunitxml b/tests/auto/testlib/selftests/expected_benchlibcallgrind.junitxml index 95d90e6ee7..95d90e6ee7 100644 --- a/tests/auto/testlib/selftests/expected_benchlibcallgrind.xunitxml +++ b/tests/auto/testlib/selftests/expected_benchlibcallgrind.junitxml diff --git a/tests/auto/testlib/selftests/expected_benchlibcounting.xunitxml b/tests/auto/testlib/selftests/expected_benchlibcounting.junitxml index 05d1da9874..05d1da9874 100644 --- a/tests/auto/testlib/selftests/expected_benchlibcounting.xunitxml +++ b/tests/auto/testlib/selftests/expected_benchlibcounting.junitxml diff --git a/tests/auto/testlib/selftests/expected_benchlibeventcounter.xunitxml b/tests/auto/testlib/selftests/expected_benchlibeventcounter.junitxml index ce0a81110d..ce0a81110d 100644 --- a/tests/auto/testlib/selftests/expected_benchlibeventcounter.xunitxml +++ b/tests/auto/testlib/selftests/expected_benchlibeventcounter.junitxml diff --git a/tests/auto/testlib/selftests/expected_benchliboptions.xunitxml b/tests/auto/testlib/selftests/expected_benchliboptions.junitxml index 370d1c7c5c..370d1c7c5c 100644 --- a/tests/auto/testlib/selftests/expected_benchliboptions.xunitxml +++ b/tests/auto/testlib/selftests/expected_benchliboptions.junitxml diff --git a/tests/auto/testlib/selftests/expected_benchlibtickcounter.xunitxml b/tests/auto/testlib/selftests/expected_benchlibtickcounter.junitxml index 779d3bdcbc..779d3bdcbc 100644 --- a/tests/auto/testlib/selftests/expected_benchlibtickcounter.xunitxml +++ b/tests/auto/testlib/selftests/expected_benchlibtickcounter.junitxml diff --git a/tests/auto/testlib/selftests/expected_benchlibwalltime.xunitxml b/tests/auto/testlib/selftests/expected_benchlibwalltime.junitxml index 6a0510c4c9..6a0510c4c9 100644 --- a/tests/auto/testlib/selftests/expected_benchlibwalltime.xunitxml +++ b/tests/auto/testlib/selftests/expected_benchlibwalltime.junitxml diff --git a/tests/auto/testlib/selftests/expected_blacklisted.xunitxml b/tests/auto/testlib/selftests/expected_blacklisted.junitxml index 6e192687fb..6e192687fb 100644 --- a/tests/auto/testlib/selftests/expected_blacklisted.xunitxml +++ b/tests/auto/testlib/selftests/expected_blacklisted.junitxml diff --git a/tests/auto/testlib/selftests/expected_cmptest.xunitxml b/tests/auto/testlib/selftests/expected_cmptest.junitxml index 397db4c3e4..397db4c3e4 100644 --- a/tests/auto/testlib/selftests/expected_cmptest.xunitxml +++ b/tests/auto/testlib/selftests/expected_cmptest.junitxml diff --git a/tests/auto/testlib/selftests/expected_commandlinedata.xunitxml b/tests/auto/testlib/selftests/expected_commandlinedata.junitxml index 5072a7e6f4..5072a7e6f4 100644 --- a/tests/auto/testlib/selftests/expected_commandlinedata.xunitxml +++ b/tests/auto/testlib/selftests/expected_commandlinedata.junitxml diff --git a/tests/auto/testlib/selftests/expected_counting.xunitxml b/tests/auto/testlib/selftests/expected_counting.junitxml index cb3a7815af..cb3a7815af 100644 --- a/tests/auto/testlib/selftests/expected_counting.xunitxml +++ b/tests/auto/testlib/selftests/expected_counting.junitxml diff --git a/tests/auto/testlib/selftests/expected_datatable.xunitxml b/tests/auto/testlib/selftests/expected_datatable.junitxml index 89fc7ee819..89fc7ee819 100644 --- a/tests/auto/testlib/selftests/expected_datatable.xunitxml +++ b/tests/auto/testlib/selftests/expected_datatable.junitxml diff --git a/tests/auto/testlib/selftests/expected_datetime.xunitxml b/tests/auto/testlib/selftests/expected_datetime.junitxml index 6fc95719f3..6fc95719f3 100644 --- a/tests/auto/testlib/selftests/expected_datetime.xunitxml +++ b/tests/auto/testlib/selftests/expected_datetime.junitxml diff --git a/tests/auto/testlib/selftests/expected_differentexec.xunitxml b/tests/auto/testlib/selftests/expected_differentexec.junitxml index 30ee50bc08..30ee50bc08 100644 --- a/tests/auto/testlib/selftests/expected_differentexec.xunitxml +++ b/tests/auto/testlib/selftests/expected_differentexec.junitxml diff --git a/tests/auto/testlib/selftests/expected_exceptionthrow.xunitxml b/tests/auto/testlib/selftests/expected_exceptionthrow.junitxml index 7d10bf6f04..7d10bf6f04 100644 --- a/tests/auto/testlib/selftests/expected_exceptionthrow.xunitxml +++ b/tests/auto/testlib/selftests/expected_exceptionthrow.junitxml diff --git a/tests/auto/testlib/selftests/expected_expectfail.xunitxml b/tests/auto/testlib/selftests/expected_expectfail.junitxml index 47483d71bf..47483d71bf 100644 --- a/tests/auto/testlib/selftests/expected_expectfail.xunitxml +++ b/tests/auto/testlib/selftests/expected_expectfail.junitxml diff --git a/tests/auto/testlib/selftests/expected_failcleanup.xunitxml b/tests/auto/testlib/selftests/expected_failcleanup.junitxml index 813e284ee0..813e284ee0 100644 --- a/tests/auto/testlib/selftests/expected_failcleanup.xunitxml +++ b/tests/auto/testlib/selftests/expected_failcleanup.junitxml diff --git a/tests/auto/testlib/selftests/expected_faildatatype.xunitxml b/tests/auto/testlib/selftests/expected_faildatatype.junitxml index fcc0db3892..fcc0db3892 100644 --- a/tests/auto/testlib/selftests/expected_faildatatype.xunitxml +++ b/tests/auto/testlib/selftests/expected_faildatatype.junitxml diff --git a/tests/auto/testlib/selftests/expected_failfetchtype.xunitxml b/tests/auto/testlib/selftests/expected_failfetchtype.junitxml index a54a37a913..a54a37a913 100644 --- a/tests/auto/testlib/selftests/expected_failfetchtype.xunitxml +++ b/tests/auto/testlib/selftests/expected_failfetchtype.junitxml diff --git a/tests/auto/testlib/selftests/expected_failinit.xunitxml b/tests/auto/testlib/selftests/expected_failinit.junitxml index 3715725ea5..3715725ea5 100644 --- a/tests/auto/testlib/selftests/expected_failinit.xunitxml +++ b/tests/auto/testlib/selftests/expected_failinit.junitxml diff --git a/tests/auto/testlib/selftests/expected_failinitdata.xunitxml b/tests/auto/testlib/selftests/expected_failinitdata.junitxml index d245bc0dff..d245bc0dff 100644 --- a/tests/auto/testlib/selftests/expected_failinitdata.xunitxml +++ b/tests/auto/testlib/selftests/expected_failinitdata.junitxml diff --git a/tests/auto/testlib/selftests/expected_fetchbogus.xunitxml b/tests/auto/testlib/selftests/expected_fetchbogus.junitxml index 77ccbd896a..77ccbd896a 100644 --- a/tests/auto/testlib/selftests/expected_fetchbogus.xunitxml +++ b/tests/auto/testlib/selftests/expected_fetchbogus.junitxml diff --git a/tests/auto/testlib/selftests/expected_findtestdata.xunitxml b/tests/auto/testlib/selftests/expected_findtestdata.junitxml index c1138da6cb..c1138da6cb 100644 --- a/tests/auto/testlib/selftests/expected_findtestdata.xunitxml +++ b/tests/auto/testlib/selftests/expected_findtestdata.junitxml diff --git a/tests/auto/testlib/selftests/expected_float.xunitxml b/tests/auto/testlib/selftests/expected_float.junitxml index 602f9252a4..602f9252a4 100644 --- a/tests/auto/testlib/selftests/expected_float.xunitxml +++ b/tests/auto/testlib/selftests/expected_float.junitxml diff --git a/tests/auto/testlib/selftests/expected_globaldata.xunitxml b/tests/auto/testlib/selftests/expected_globaldata.junitxml index de184c2fdd..de184c2fdd 100644 --- a/tests/auto/testlib/selftests/expected_globaldata.xunitxml +++ b/tests/auto/testlib/selftests/expected_globaldata.junitxml diff --git a/tests/auto/testlib/selftests/expected_keyboard.xunitxml b/tests/auto/testlib/selftests/expected_keyboard.junitxml index 93b5f7bfff..93b5f7bfff 100644 --- a/tests/auto/testlib/selftests/expected_keyboard.xunitxml +++ b/tests/auto/testlib/selftests/expected_keyboard.junitxml diff --git a/tests/auto/testlib/selftests/expected_longstring.xunitxml b/tests/auto/testlib/selftests/expected_longstring.junitxml index 269c06fe08..269c06fe08 100644 --- a/tests/auto/testlib/selftests/expected_longstring.xunitxml +++ b/tests/auto/testlib/selftests/expected_longstring.junitxml diff --git a/tests/auto/testlib/selftests/expected_maxwarnings.xunitxml b/tests/auto/testlib/selftests/expected_maxwarnings.junitxml index 329fae5f1d..329fae5f1d 100644 --- a/tests/auto/testlib/selftests/expected_maxwarnings.xunitxml +++ b/tests/auto/testlib/selftests/expected_maxwarnings.junitxml diff --git a/tests/auto/testlib/selftests/expected_multiexec.xunitxml b/tests/auto/testlib/selftests/expected_multiexec.junitxml index 8ab914842b..8ab914842b 100644 --- a/tests/auto/testlib/selftests/expected_multiexec.xunitxml +++ b/tests/auto/testlib/selftests/expected_multiexec.junitxml diff --git a/tests/auto/testlib/selftests/expected_pairdiagnostics.xunitxml b/tests/auto/testlib/selftests/expected_pairdiagnostics.junitxml index cf2a30b84a..cf2a30b84a 100644 --- a/tests/auto/testlib/selftests/expected_pairdiagnostics.xunitxml +++ b/tests/auto/testlib/selftests/expected_pairdiagnostics.junitxml diff --git a/tests/auto/testlib/selftests/expected_qexecstringlist.xunitxml b/tests/auto/testlib/selftests/expected_qexecstringlist.junitxml index b352b8e6b9..b352b8e6b9 100644 --- a/tests/auto/testlib/selftests/expected_qexecstringlist.xunitxml +++ b/tests/auto/testlib/selftests/expected_qexecstringlist.junitxml diff --git a/tests/auto/testlib/selftests/expected_signaldumper.xunitxml b/tests/auto/testlib/selftests/expected_signaldumper.junitxml index 6609f518a2..6609f518a2 100644 --- a/tests/auto/testlib/selftests/expected_signaldumper.xunitxml +++ b/tests/auto/testlib/selftests/expected_signaldumper.junitxml diff --git a/tests/auto/testlib/selftests/expected_silent.xunitxml b/tests/auto/testlib/selftests/expected_silent.junitxml index ea229d1dc7..ea229d1dc7 100644 --- a/tests/auto/testlib/selftests/expected_silent.xunitxml +++ b/tests/auto/testlib/selftests/expected_silent.junitxml diff --git a/tests/auto/testlib/selftests/expected_singleskip.xunitxml b/tests/auto/testlib/selftests/expected_singleskip.junitxml index 2b2da2f504..2b2da2f504 100644 --- a/tests/auto/testlib/selftests/expected_singleskip.xunitxml +++ b/tests/auto/testlib/selftests/expected_singleskip.junitxml diff --git a/tests/auto/testlib/selftests/expected_skip.xunitxml b/tests/auto/testlib/selftests/expected_skip.junitxml index 63e582f96a..63e582f96a 100644 --- a/tests/auto/testlib/selftests/expected_skip.xunitxml +++ b/tests/auto/testlib/selftests/expected_skip.junitxml diff --git a/tests/auto/testlib/selftests/expected_skipcleanup.xunitxml b/tests/auto/testlib/selftests/expected_skipcleanup.junitxml index 9934584ec5..9934584ec5 100644 --- a/tests/auto/testlib/selftests/expected_skipcleanup.xunitxml +++ b/tests/auto/testlib/selftests/expected_skipcleanup.junitxml diff --git a/tests/auto/testlib/selftests/expected_skipinit.xunitxml b/tests/auto/testlib/selftests/expected_skipinit.junitxml index bab08c375c..bab08c375c 100644 --- a/tests/auto/testlib/selftests/expected_skipinit.xunitxml +++ b/tests/auto/testlib/selftests/expected_skipinit.junitxml diff --git a/tests/auto/testlib/selftests/expected_skipinitdata.xunitxml b/tests/auto/testlib/selftests/expected_skipinitdata.junitxml index e61d50b06b..e61d50b06b 100644 --- a/tests/auto/testlib/selftests/expected_skipinitdata.xunitxml +++ b/tests/auto/testlib/selftests/expected_skipinitdata.junitxml diff --git a/tests/auto/testlib/selftests/expected_sleep.xunitxml b/tests/auto/testlib/selftests/expected_sleep.junitxml index e4ed66bcb8..e4ed66bcb8 100644 --- a/tests/auto/testlib/selftests/expected_sleep.xunitxml +++ b/tests/auto/testlib/selftests/expected_sleep.junitxml diff --git a/tests/auto/testlib/selftests/expected_strcmp.xunitxml b/tests/auto/testlib/selftests/expected_strcmp.junitxml index 66dce857c9..66dce857c9 100644 --- a/tests/auto/testlib/selftests/expected_strcmp.xunitxml +++ b/tests/auto/testlib/selftests/expected_strcmp.junitxml diff --git a/tests/auto/testlib/selftests/expected_subtest.xunitxml b/tests/auto/testlib/selftests/expected_subtest.junitxml index b49c006940..b49c006940 100644 --- a/tests/auto/testlib/selftests/expected_subtest.xunitxml +++ b/tests/auto/testlib/selftests/expected_subtest.junitxml diff --git a/tests/auto/testlib/selftests/expected_testlib.xunitxml b/tests/auto/testlib/selftests/expected_testlib.junitxml index c9c67c7c9a..c9c67c7c9a 100644 --- a/tests/auto/testlib/selftests/expected_testlib.xunitxml +++ b/tests/auto/testlib/selftests/expected_testlib.junitxml diff --git a/tests/auto/testlib/selftests/expected_tuplediagnostics.xunitxml b/tests/auto/testlib/selftests/expected_tuplediagnostics.junitxml index 0a276a17f5..0a276a17f5 100644 --- a/tests/auto/testlib/selftests/expected_tuplediagnostics.xunitxml +++ b/tests/auto/testlib/selftests/expected_tuplediagnostics.junitxml diff --git a/tests/auto/testlib/selftests/expected_verbose1.xunitxml b/tests/auto/testlib/selftests/expected_verbose1.junitxml index cb3a7815af..cb3a7815af 100644 --- a/tests/auto/testlib/selftests/expected_verbose1.xunitxml +++ b/tests/auto/testlib/selftests/expected_verbose1.junitxml diff --git a/tests/auto/testlib/selftests/expected_verbose2.xunitxml b/tests/auto/testlib/selftests/expected_verbose2.junitxml index 6764a5564f..6764a5564f 100644 --- a/tests/auto/testlib/selftests/expected_verbose2.xunitxml +++ b/tests/auto/testlib/selftests/expected_verbose2.junitxml diff --git a/tests/auto/testlib/selftests/expected_verifyexceptionthrown.xunitxml b/tests/auto/testlib/selftests/expected_verifyexceptionthrown.junitxml index 003a31a1cc..003a31a1cc 100644 --- a/tests/auto/testlib/selftests/expected_verifyexceptionthrown.xunitxml +++ b/tests/auto/testlib/selftests/expected_verifyexceptionthrown.junitxml diff --git a/tests/auto/testlib/selftests/expected_warnings.xunitxml b/tests/auto/testlib/selftests/expected_warnings.junitxml index 5cca215f12..5cca215f12 100644 --- a/tests/auto/testlib/selftests/expected_warnings.xunitxml +++ b/tests/auto/testlib/selftests/expected_warnings.junitxml diff --git a/tests/auto/testlib/selftests/expected_watchdog.xunitxml b/tests/auto/testlib/selftests/expected_watchdog.junitxml index 7e16ab2c34..7e16ab2c34 100644 --- a/tests/auto/testlib/selftests/expected_watchdog.xunitxml +++ b/tests/auto/testlib/selftests/expected_watchdog.junitxml diff --git a/tests/auto/testlib/selftests/expected_xunit.xunitxml b/tests/auto/testlib/selftests/expected_xunit.junitxml index 395b6efdd9..395b6efdd9 100644 --- a/tests/auto/testlib/selftests/expected_xunit.xunitxml +++ b/tests/auto/testlib/selftests/expected_xunit.junitxml diff --git a/tests/auto/testlib/selftests/generate_expected_output.py b/tests/auto/testlib/selftests/generate_expected_output.py index 48ecbf0289..96fab44408 100755 --- a/tests/auto/testlib/selftests/generate_expected_output.py +++ b/tests/auto/testlib/selftests/generate_expected_output.py @@ -86,7 +86,7 @@ class Cleaner (object): # Build details: (r'(Config: Using QtTest library).*', r'\1'), # txt (r'( *<QtBuild)>[^<]+</QtBuild>', r'\1/>'), # xml, lightxml - (r'(<property value=")[^"]+(" name="QtBuild"/>)', r'\1\2'), # xunitxml + (r'(<property value=")[^"]+(" name="QtBuild"/>)', r'\1\2'), # junitxml # Line numbers in source files: (r'(ASSERT: ".*" in file .*, line) \d+', r'\1 0'), # lightxml (r'(Loc: \[[^[\]()]+)\(\d+\)', r'\1(0)'), # txt @@ -295,23 +295,7 @@ def testEnv(testname, return data def generateTestData(testname, clean, - formats = ('xml', 'txt', 'xunitxml', 'lightxml', 'teamcity', 'tap'), - # Make sure this matches tst_Selftests::runSubTest_data(): - extraArgs = { - "commandlinedata": "fiveTablePasses fiveTablePasses:fiveTablePasses_data1 -v2", - "benchlibcallgrind": "-callgrind", - "benchlibeventcounter": "-eventcounter", - "benchliboptions": "-eventcounter", - "benchlibtickcounter": "-tickcounter", - "badxml": "-eventcounter", - "benchlibcounting": "-eventcounter", - "printdatatags": "-datatags", - "printdatatagswithglobaltags": "-datatags", - "signaldumper": "-vs", - "silent": "-silent", - "verbose1": "-v1", - "verbose2": "-v2", - }): + formats = ('xml', 'txt', 'junitxml', 'lightxml', 'teamcity', 'tap')): """Run one test and save its cleaned results. Required arguments are the name of the test directory (the binary @@ -330,9 +314,6 @@ def generateTestData(testname, clean, print(" running", testname) for format in formats: cmd = [path, '-' + format] - if testname in extraArgs: - cmd += extraArgs[testname].split() - data = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=env, universal_newlines=True).communicate()[0] with open('expected_' + testname + '.' + format, 'w') as out: diff --git a/tests/auto/testlib/selftests/mouse/tst_mouse.cpp b/tests/auto/testlib/selftests/mouse/tst_mouse.cpp index d097027e7e..43dda31daf 100644 --- a/tests/auto/testlib/selftests/mouse/tst_mouse.cpp +++ b/tests/auto/testlib/selftests/mouse/tst_mouse.cpp @@ -42,6 +42,8 @@ class tst_Mouse : public QObject Q_OBJECT private slots: + void timestampBetweenTestFunction_data(); + void timestampBetweenTestFunction(); void stateHandlingPart1_data(); void stateHandlingPart1(); void stateHandlingPart2(); @@ -55,20 +57,83 @@ public: Qt::MouseButtons stateInMouseMove = Qt::NoButton; int moveCount = 0; int pressCount = 0; + int doubleClickCount = 0; + ulong lastTimeStamp = 0; protected: - void mousePressEvent(QMouseEvent *) + void mousePressEvent(QMouseEvent *e) { pressCount++; + processEvent(e); } void mouseMoveEvent(QMouseEvent *e) { moveCount++; stateInMouseMove = e->buttons(); + processEvent(e); } + + void mouseReleaseEvent(QMouseEvent *e) + { + processEvent(e); + } + + void mouseDoubleClickEvent(QMouseEvent *e) + { + doubleClickCount++; + processEvent(e); + } + + void processEvent(QMouseEvent *e) + { + lastTimeStamp = e->timestamp(); + } + }; +static ulong lastTimeStampInPreviousTestFunction = 0; + +void tst_Mouse::timestampBetweenTestFunction_data() +{ + QTest::addColumn<bool>("hoverLast"); + QTest::addColumn<bool>("pressAndRelease"); + QTest::newRow("press, release") << true << false; + QTest::newRow("press, release, hover") << true << true; + QTest::newRow("hover") << false << true; + QTest::newRow("hover #2") << false << true; + QTest::newRow("press, release #2") << true << false; + QTest::newRow("press, release, hover #2") << true << true; +} + +void tst_Mouse::timestampBetweenTestFunction() +{ + QFETCH(bool, hoverLast); + QFETCH(bool, pressAndRelease); + + MouseWindow w; + w.show(); + w.setGeometry(100, 100, 200, 200); + QVERIFY(QTest::qWaitForWindowActive(&w)); + + QPoint point(10, 10); + QCOMPARE(w.pressCount, 0); + if (pressAndRelease) { + QTest::mousePress(&w, Qt::LeftButton, { }, point); + QVERIFY(w.lastTimeStamp - lastTimeStampInPreviousTestFunction > 500); // Should be at least 500 ms timestamp between each test case + QCOMPARE(w.pressCount, 1); + QTest::mouseRelease(&w, Qt::LeftButton, { }, point); + } + QCOMPARE(w.doubleClickCount, 0); + if (hoverLast) { + static int xMove = 0; + xMove += 5; // Just make sure we generate different hover coordinates + point.rx() += xMove; + QTest::mouseMove(&w, point); // a hover move. This doesn't generate a timestamp delay of 500 ms + } + lastTimeStampInPreviousTestFunction = w.lastTimeStamp; +} + void tst_Mouse::stateHandlingPart1_data() { QTest::addColumn<bool>("dummy"); diff --git a/tests/auto/testlib/selftests/printdatatags/tst_printdatatags.cpp b/tests/auto/testlib/selftests/printdatatags/tst_printdatatags.cpp index 5c9f5c5898..60a295c0f7 100644 --- a/tests/auto/testlib/selftests/printdatatags/tst_printdatatags.cpp +++ b/tests/auto/testlib/selftests/printdatatags/tst_printdatatags.cpp @@ -72,6 +72,14 @@ void tst_PrintDataTags::c() const { } -QTEST_MAIN(tst_PrintDataTags) +int main(int argc, char *argv[]) +{ + std::vector<const char*> args(argv, argv + argc); + args.push_back("-datatags"); + argc = args.size(); + argv = const_cast<char**>(&args[0]); + + QTEST_MAIN_IMPL(tst_PrintDataTags) +} #include "tst_printdatatags.moc" diff --git a/tests/auto/testlib/selftests/printdatatagswithglobaltags/tst_printdatatagswithglobaltags.cpp b/tests/auto/testlib/selftests/printdatatagswithglobaltags/tst_printdatatagswithglobaltags.cpp index b68daae538..6fea34467a 100644 --- a/tests/auto/testlib/selftests/printdatatagswithglobaltags/tst_printdatatagswithglobaltags.cpp +++ b/tests/auto/testlib/selftests/printdatatagswithglobaltags/tst_printdatatagswithglobaltags.cpp @@ -88,6 +88,14 @@ void tst_PrintDataTagsWithGlobalTags::c() const { } -QTEST_MAIN(tst_PrintDataTagsWithGlobalTags) +int main(int argc, char *argv[]) +{ + std::vector<const char*> args(argv, argv + argc); + args.push_back("-datatags"); + argc = args.size(); + argv = const_cast<char**>(&args[0]); + + QTEST_MAIN_IMPL(tst_PrintDataTagsWithGlobalTags) +} #include "tst_printdatatagswithglobaltags.moc" diff --git a/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp b/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp index 08592e222d..c60260f109 100644 --- a/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp +++ b/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp @@ -424,5 +424,14 @@ void tst_Signaldumper::deletingSender() emit signalSlotOwner->signalWithoutParameters(); } -QTEST_MAIN(tst_Signaldumper) +int main(int argc, char *argv[]) +{ + std::vector<const char*> args(argv, argv + argc); + args.push_back("-vs"); + argc = args.size(); + argv = const_cast<char**>(&args[0]); + + QTEST_MAIN_IMPL(tst_Signaldumper) +} + #include "tst_signaldumper.moc" diff --git a/tests/auto/testlib/selftests/silent/tst_silent.cpp b/tests/auto/testlib/selftests/silent/tst_silent.cpp index cf3c35dec4..7d64efffa2 100644 --- a/tests/auto/testlib/selftests/silent/tst_silent.cpp +++ b/tests/auto/testlib/selftests/silent/tst_silent.cpp @@ -77,7 +77,7 @@ void tst_Silent::xpass() #include <setjmp.h> static jmp_buf state; -static void abort_handler(int signal) +static void abort_handler(int) { longjmp(state, 1); } @@ -102,5 +102,14 @@ void tst_Silent::messages() qFatal("This is a fatal error message that should still appear in silent test output"); } -QTEST_MAIN(tst_Silent) +int main(int argc, char *argv[]) +{ + std::vector<const char*> args(argv, argv + argc); + args.push_back("-silent"); + argc = args.size(); + argv = const_cast<char**>(&args[0]); + + QTEST_MAIN_IMPL(tst_Silent) +} + #include "tst_silent.moc" diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp index 331ae48135..be64752ceb 100644 --- a/tests/auto/testlib/selftests/tst_selftests.cpp +++ b/tests/auto/testlib/selftests/tst_selftests.cpp @@ -76,8 +76,6 @@ private: QList<LoggerSet> allLoggerSets() const; QTemporaryDir tempDir; - QRegularExpression durationRegExp; - QRegularExpression teamcityLocRegExp; }; struct BenchmarkResult @@ -280,13 +278,17 @@ QList<LoggerSet> tst_Selftests::allLoggerSets() const QStringList() << "xml", QStringList() << "-xml" << "-o" << logName("xml") ) - << LoggerSet("old stdout xunitxml", - QStringList() << "stdout xunitxml", - QStringList() << "-xunitxml" + << LoggerSet("old stdout junitxml", + QStringList() << "stdout junitxml", + QStringList() << "-junitxml" ) - << LoggerSet("old xunitxml", - QStringList() << "xunitxml", - QStringList() << "-xunitxml" << "-o" << logName("xunitxml") + << LoggerSet("old junitxml", + QStringList() << "junitxml", + QStringList() << "-junitxml" << "-o" << logName("junitxml") + ) + << LoggerSet("old xunitxml compatibility", + QStringList() << "junitxml", + QStringList() << "-xunitxml" << "-o" << logName("junitxml") ) << LoggerSet("old stdout lightxml", QStringList() << "stdout lightxml", @@ -335,13 +337,17 @@ QList<LoggerSet> tst_Selftests::allLoggerSets() const QStringList() << "xml", QStringList() << "-o" << logName("xml")+",xml" ) - << LoggerSet("new stdout xunitxml", - QStringList() << "stdout xunitxml", + << LoggerSet("new stdout junitxml", + QStringList() << "stdout junitxml", + QStringList() << "-o" << "-,junitxml" + ) + << LoggerSet("new stdout xunitxml compatibility", + QStringList() << "stdout junitxml", QStringList() << "-o" << "-,xunitxml" ) - << LoggerSet("new xunitxml", - QStringList() << "xunitxml", - QStringList() << "-o" << logName("xunitxml")+",xunitxml" + << LoggerSet("new junitxml", + QStringList() << "junitxml", + QStringList() << "-o" << logName("junitxml")+",junitxml" ) << LoggerSet("new stdout lightxml", QStringList() << "stdout lightxml", @@ -384,24 +390,24 @@ QList<LoggerSet> tst_Selftests::allLoggerSets() const QStringList() << "-o" << logName("xml")+",xml" << "-o" << "-,txt" ) - << LoggerSet("txt + xunitxml", - QStringList() << "txt" << "xunitxml", + << LoggerSet("txt + junitxml", + QStringList() << "txt" << "junitxml", QStringList() << "-o" << logName("txt")+",txt" - << "-o" << logName("xunitxml")+",xunitxml" + << "-o" << logName("junitxml")+",junitxml" ) - << LoggerSet("lightxml + stdout xunitxml", - QStringList() << "lightxml" << "stdout xunitxml", + << LoggerSet("lightxml + stdout junitxml", + QStringList() << "lightxml" << "stdout junitxml", QStringList() << "-o" << logName("lightxml")+",lightxml" - << "-o" << "-,xunitxml" + << "-o" << "-,junitxml" ) // All loggers at the same time (except csv) << LoggerSet("all loggers", - QStringList() << "txt" << "xml" << "lightxml" << "stdout txt" << "xunitxml" << "tap", + QStringList() << "txt" << "xml" << "lightxml" << "stdout txt" << "junitxml" << "tap", QStringList() << "-o" << logName("txt")+",txt" << "-o" << logName("xml")+",xml" << "-o" << logName("lightxml")+",lightxml" << "-o" << "-,txt" - << "-o" << logName("xunitxml")+",xunitxml" + << "-o" << logName("junitxml")+",junitxml" << "-o" << logName("teamcity")+",teamcity" << "-o" << logName("tap")+",tap" ) @@ -410,8 +416,6 @@ QList<LoggerSet> tst_Selftests::allLoggerSets() const tst_Selftests::tst_Selftests() : tempDir(QDir::tempPath() + "/tst_selftests.XXXXXX") - , durationRegExp("<Duration msecs=\"[\\d\\.]+\"/>") - , teamcityLocRegExp("\\|\\[Loc: .*\\(\\d*\\)\\|\\]") {} void tst_Selftests::initTestCase() @@ -524,49 +528,6 @@ void tst_Selftests::runSubTest_data() QStringList loggers = loggerSet.loggers; foreach (QString const& subtest, tests) { - QStringList arguments = loggerSet.arguments; - // Keep in sync with generateTestData()'s extraArgs in generate_expected_output.py: - if (subtest == "commandlinedata") { - arguments << QString("fiveTablePasses fiveTablePasses:fiveTablePasses_data1 -v2").split(' '); - } - else if (subtest == "benchlibcallgrind") { - arguments << "-callgrind"; - } - else if (subtest == "benchlibeventcounter") { - arguments << "-eventcounter"; - } - else if (subtest == "benchliboptions") { - arguments << "-eventcounter"; - } - else if (subtest == "benchlibtickcounter") { - arguments << "-tickcounter"; - } - else if (subtest == "badxml") { - arguments << "-eventcounter"; - } - else if (subtest == "benchlibcounting") { - arguments << "-eventcounter"; - } - else if (subtest == "printdatatags") { - arguments << "-datatags"; - } - else if (subtest == "printdatatagswithglobaltags") { - arguments << "-datatags"; - } - else if (subtest == "signaldumper") { - arguments << "-vs"; - } - else if (subtest == "silent") { - arguments << "-silent"; - } - else if (subtest == "verbose1") { - arguments << "-v1"; - } - else if (subtest == "verbose2") { - arguments << "-v2"; - } - - // These tests don't work right unless logging plain text to // standard output, either because they execute multiple test // objects or because they internally supply arguments to @@ -630,7 +591,7 @@ void tst_Selftests::runSubTest_data() QTest::newRow(qPrintable(QString("%1 %2").arg(subtest).arg(loggerSet.name))) << subtest << loggers - << arguments + << loggerSet.arguments << crashes ; } @@ -686,7 +647,7 @@ static inline QByteArray msgProcessError(const QString &binary, const QStringLis void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& loggers, QStringList const& arguments, bool crashes) { #if defined(__GNUC__) && defined(__i386) && defined(Q_OS_LINUX) - if (arguments.contains("-callgrind")) { + if (subdir == "benchlibcallgrind") { QProcess checkProcess; QStringList args; args << QLatin1String("--version"); @@ -839,8 +800,8 @@ bool tst_Selftests::compareOutput(const QString &logger, const QString &subdir, { if (actual.size() != expected.size()) { - *errorMessage = QString::fromLatin1("Mismatch in line count: %1 != %2.") - .arg(actual.size()).arg(expected.size()); + *errorMessage = QString::fromLatin1("Mismatch in line count. Expected %1 but got %2.") + .arg(expected.size()).arg(actual.size()); return false; } @@ -873,6 +834,7 @@ bool tst_Selftests::compareOutput(const QString &logger, const QString &subdir, // Special handling for ignoring _FILE_ and _LINE_ if logger is teamcity if (logger.endsWith(QLatin1String("teamcity"))) { + static QRegularExpression teamcityLocRegExp("\\|\\[Loc: .*\\(\\d*\\)\\|\\]"); actualLine.replace(teamcityLocRegExp, teamCityLocation()); expectedLine.replace(teamcityLocRegExp, teamCityLocation()); } @@ -943,6 +905,7 @@ bool tst_Selftests::compareLine(const QString &logger, const QString &subdir, if (actualLine.startsWith(QLatin1String(" <Duration msecs=")) || actualLine.startsWith(QLatin1String("<Duration msecs="))) { + static QRegularExpression durationRegExp("<Duration msecs=\"[\\d\\.]+\"/>"); QRegularExpressionMatch match = durationRegExp.match(actualLine); if (match.hasMatch()) return true; diff --git a/tests/auto/testlib/selftests/verbose1/verbose1.pro b/tests/auto/testlib/selftests/verbose1/verbose1.pro index 1f16d70d66..f50ce83ea6 100644 --- a/tests/auto/testlib/selftests/verbose1/verbose1.pro +++ b/tests/auto/testlib/selftests/verbose1/verbose1.pro @@ -4,6 +4,8 @@ SOURCES += ../counting/tst_counting.cpp QT = core testlib +DEFINES += TESTLIB_VERBOSITY_ARG="-v1" + mac:CONFIG -= app_bundle CONFIG -= debug_and_release_target diff --git a/tests/auto/testlib/selftests/verbose2/verbose2.pro b/tests/auto/testlib/selftests/verbose2/verbose2.pro index bf54904488..d4765f01b5 100644 --- a/tests/auto/testlib/selftests/verbose2/verbose2.pro +++ b/tests/auto/testlib/selftests/verbose2/verbose2.pro @@ -4,6 +4,8 @@ SOURCES += ../counting/tst_counting.cpp QT = core testlib +DEFINES += TESTLIB_VERBOSITY_ARG="-v2" + mac:CONFIG -= app_bundle CONFIG -= debug_and_release_target diff --git a/tests/auto/tools/uic/baseline/config.ui.py b/tests/auto/tools/uic/baseline/config.ui.py index 5fd558bb01..b3b6e09373 100644 --- a/tests/auto/tools/uic/baseline/config.ui.py +++ b/tests/auto/tools/uic/baseline/config.ui.py @@ -36,11 +36,11 @@ ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ -from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint, - QRect, QSize, QUrl, Qt) +from PySide2.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject, + QObject, QPoint, QRect, QSize, QTime, QUrl, Qt) from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, - QFontDatabase, QIcon, QLinearGradient, QPalette, QPainter, QPixmap, - QRadialGradient) + QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter, + QPixmap, QRadialGradient) from PySide2.QtWidgets import * from gammaview import GammaView @@ -48,7 +48,7 @@ from gammaview import GammaView class Ui_Config(object): def setupUi(self, Config): - if Config.objectName(): + if not Config.objectName(): Config.setObjectName(u"Config") Config.resize(600, 650) Config.setSizeGripEnabled(True) diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 4e31c3e57c..63bf103725 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -1014,30 +1014,38 @@ void tst_QFileSystemModel::drives() void tst_QFileSystemModel::dirsBeforeFiles() { - QDir dir(flatDirTestPath); + auto diagnosticMsg = [](int row, const QFileInfo &left, const QFileInfo &right) -> QByteArray { + QString message; + QDebug(&message).noquote() << "Unexpected sort order at #" << row << ':' << left << right; + return message.toLocal8Bit(); + }; + QTemporaryDir testDir(flatDirTestPath); + QVERIFY2(testDir.isValid(), qPrintable(testDir.errorString())); + QDir dir(testDir.path()); const int itemCount = 3; for (int i = 0; i < itemCount; ++i) { QLatin1Char c('a' + char(i)); QVERIFY(dir.mkdir(c + QLatin1String("-dir"))); - QFile file(flatDirTestPath + QLatin1Char('/') + c + QLatin1String("-file")); + QFile file(dir.filePath(c + QLatin1String("-file"))); QVERIFY(file.open(QIODevice::ReadWrite)); file.close(); } QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QModelIndex root = model->setRootPath(flatDirTestPath); + QModelIndex root = model->setRootPath(dir.absolutePath()); // Wait for model to be notified by the file system watcher QTRY_COMPARE(model->rowCount(root), 2 * itemCount); - - // Ensure that no file occurs before any directory: - for (int i = 1; i < model->rowCount(root); ++i) { + // sort explicitly - dirs before files (except on macOS), and then by name + model->sort(0); + // Ensure that no file occurs before any directory (see QFileSystemModelSorter): + for (int i = 1, count = model->rowCount(root); i < count; ++i) { + const QFileInfo previous = model->fileInfo(model->index(i - 1, 0, root)); + const QFileInfo current = model->fileInfo(model->index(i, 0, root)); #ifndef Q_OS_MAC - QVERIFY(!(model->fileInfo(model->index(i - 1, 0, root)).isFile() - && model->fileInfo(model->index(i, 0, root)).isDir())); + QVERIFY2(!(previous.isFile() && current.isDir()), diagnosticMsg(i, previous, current).constData()); #else - QVERIFY(model->fileInfo(model->index(i - 1, 0, root)).fileName() < - model->fileInfo(model->index(i, 0, root)).fileName()); + QVERIFY2(previous.fileName() < current.fileName(), diagnosticMsg(i, previous, current).constData()); #endif } } diff --git a/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp b/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp index 259de49c67..877784041b 100644 --- a/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp +++ b/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp @@ -326,7 +326,7 @@ void tst_QInputDialog::getDouble() // rounded off to 10.03) const double value = static_cast<int>(min + (max - min) / 2); const double result = - QInputDialog::getDouble(parent, "", "", value, min, max, decimals, &ok); + QInputDialog::getDouble(parent, "", "", value, min, max, decimals, &ok, Qt::WindowFlags(), 1); QVERIFY(ok); QCOMPARE(result, value); delete parent; @@ -395,7 +395,8 @@ void tst_QInputDialog::taskQTBUG_54693_crashWhenParentIsDeletedWhileDialogIsOpen const double initial = 7; QAutoPointer<SelfDestructParent> dialog(new SelfDestructParent); bool ok = true; - const double result = QInputDialog::getDouble(dialog.get(), "Title", "Label", initial, -10, +10, 2, &ok); + const double result = QInputDialog::getDouble(dialog.get(), "Title", "Label", initial, -10, +10, 2, &ok, + Qt::WindowFlags(), 1); QVERIFY(!dialog); QVERIFY(!ok); QCOMPARE(result, initial); @@ -411,7 +412,7 @@ void tst_QInputDialog::task255502getDouble() bool ok = false; const double value = 0.001; const double result = - QInputDialog::getDouble(parent, "", "", value, -1, 1, 4, &ok); + QInputDialog::getDouble(parent, "", "", value, -1, 1, 4, &ok, Qt::WindowFlags(), 1); QVERIFY(ok); QCOMPARE(result, value); delete parent; diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST index e760042def..31dbb38a5d 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST @@ -1,3 +1,4 @@ # QTBUG-74760 [sorting] opensuse-42.3 +osx diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index a437b05479..8c2d89e34b 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -89,6 +89,7 @@ private slots: void focusNextPrevChild(); void focusOutEvent_data(); void focusOutEvent(); + void focusProxy_QTBUG_51856(); void hoverEnterLeaveEvent_data(); void hoverEnterLeaveEvent(); void hoverMoveEvent_data(); @@ -864,6 +865,75 @@ void tst_QGraphicsProxyWidget::focusOutEvent() } } +void tst_QGraphicsProxyWidget::focusProxy_QTBUG_51856() +{ + // QSpinBox has an internal QLineEdit; this QLineEdit has the spinbox + // as its focus proxy. + struct FocusedSpinBox : QSpinBox + { + int focusCount = 0; + + bool event(QEvent *event) override + { + switch (event->type()) { + case QEvent::FocusIn: + ++focusCount; + break; + case QEvent::FocusOut: + --focusCount; + break; + default: + break; + } + return QSpinBox::event(event); + } + }; + + QGraphicsScene scene; + QGraphicsView view(&scene); + SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget; + scene.addItem(proxy); + view.show(); + view.raise(); + view.activateWindow(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + FocusedSpinBox *spinBox = new FocusedSpinBox; + + proxy->setWidget(spinBox); + proxy->show(); + proxy->setFocus(); + QVERIFY(proxy->hasFocus()); + QEXPECT_FAIL("", "Widget should have focus but doesn't", Continue); + QVERIFY(spinBox->hasFocus()); + QEXPECT_FAIL("", "Widget should have focus but doesn't", Continue); + QCOMPARE(spinBox->focusCount, 1); + + enum { Count = 10 }; + + for (int i = 0; i < Count; ++i) { + for (int clickCount = 0; clickCount < Count; ++clickCount) { + auto proxyCenter = proxy->boundingRect().center(); + auto proxyCenterInScene = proxy->mapToScene(proxyCenter); + auto proxyCenterInView = view.mapFromScene(proxyCenterInScene); + + QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, proxyCenterInView); + QTRY_COMPARE(spinBox->focusCount, 1); + } + + QLineEdit *edit = new QLineEdit(&view); + edit->show(); + QTRY_VERIFY(edit->isVisible()); + edit->setFocus(); + QTRY_VERIFY(edit->hasFocus()); + QTRY_VERIFY(!proxy->hasFocus()); + QTRY_COMPARE(proxy->focusOut, i + 1); + QTRY_VERIFY(!spinBox->hasFocus()); + QTRY_COMPARE(spinBox->focusCount, 0); + delete edit; + } +} + class EventLogger : public QWidget { public: diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST index 9b76ea02ff..f59544f336 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicsview/BLACKLIST @@ -16,3 +16,5 @@ opensuse-42.3 [itemsInRect_cosmeticAdjust] # QTBUG-66815 ubuntu-16.04 +[fitInView] +osx diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index c015bf85d0..9c16b1a00a 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -409,6 +409,8 @@ private slots: void closeEvent(); void closeWithChildWindow(); + void winIdAfterClose(); + private: bool ensureScreenSize(int width, int height); @@ -11309,5 +11311,54 @@ void tst_QWidget::closeWithChildWindow() QVERIFY(!childWidget->isVisible()); } +class WinIdChangeSpy : public QObject +{ + Q_OBJECT +public: + QWidget *widget = nullptr; + WId winId = 0; + explicit WinIdChangeSpy(QWidget *w, QObject *parent = nullptr) + : QObject(parent) + , widget(w) + , winId(widget->winId()) + { + } + +public slots: + bool eventFilter(QObject *obj, QEvent *event) override + { + if (obj == widget) { + if (event->type() == QEvent::WinIdChange) { + winId = widget->winId(); + return true; + } + } + return false; + } +}; + +void tst_QWidget::winIdAfterClose() +{ + auto widget = new QWidget; + auto notifier = new QObject(widget); + auto deleteWidget = new QWidget(new QWidget(widget)); + auto spy = new WinIdChangeSpy(deleteWidget); + deleteWidget->installEventFilter(spy); + connect(notifier, &QObject::destroyed, [&] { delete deleteWidget; }); + + widget->setAttribute(Qt::WA_NativeWindow); + widget->windowHandle()->create(); + widget->show(); + + QVERIFY(QTest::qWaitForWindowExposed(widget)); + QVERIFY(spy->winId); + + widget->windowHandle()->close(); + delete widget; + + QCOMPARE(spy->winId, WId(0)); + delete spy; +} + QTEST_MAIN(tst_QWidget) #include "tst_qwidget.moc" diff --git a/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp b/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp index 5d52acd1a2..999cf4a941 100644 --- a/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp +++ b/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp @@ -58,6 +58,23 @@ protected: } }; +class TestPushButton : public QPushButton +{ +public: + TestPushButton(QWidget *parent = nullptr) + : QPushButton(parent) + {} + TestPushButton(const QString &title, QWidget *parent = nullptr) + : QPushButton(title, parent) + {} + +protected: + bool hitButton(const QPoint &pos) const override + { + return rect().contains(pos); + } +}; + #include <qbuttongroup.h> class tst_QButtonGroup : public QObject @@ -97,7 +114,7 @@ void tst_QButtonGroup::arrowKeyNavigation() QGroupBox g1("1", &dlg); QHBoxLayout g1layout(&g1); QRadioButton bt1("Radio1", &g1); - QPushButton pb("PB", &g1); + TestPushButton pb("PB", &g1); QLineEdit le(&g1); QRadioButton bt2("Radio2", &g1); g1layout.addWidget(&bt1); @@ -231,9 +248,9 @@ void tst_QButtonGroup::exclusive() { QDialog dlg(0); QHBoxLayout layout(&dlg); - QPushButton *pushButton1 = new QPushButton(&dlg); - QPushButton *pushButton2 = new QPushButton(&dlg); - QPushButton *pushButton3 = new QPushButton(&dlg); + TestPushButton *pushButton1 = new TestPushButton(&dlg); + TestPushButton *pushButton2 = new TestPushButton(&dlg); + TestPushButton *pushButton3 = new TestPushButton(&dlg); pushButton1->setCheckable(true); pushButton2->setCheckable(true); pushButton3->setCheckable(true); @@ -271,9 +288,9 @@ void tst_QButtonGroup::exclusive() void tst_QButtonGroup::testSignals() { QButtonGroup buttons; - QPushButton pb1; - QPushButton pb2; - QPushButton pb3; + TestPushButton pb1; + TestPushButton pb2; + TestPushButton pb3; buttons.addButton(&pb1); buttons.addButton(&pb2, 23); buttons.addButton(&pb3); @@ -363,9 +380,9 @@ void tst_QButtonGroup::checkedButton() { QButtonGroup buttons; buttons.setExclusive(false); - QPushButton pb1; + TestPushButton pb1; pb1.setCheckable(true); - QPushButton pb2; + TestPushButton pb2; pb2.setCheckable(true); buttons.addButton(&pb1); buttons.addButton(&pb2, 23); @@ -430,7 +447,7 @@ void tst_QButtonGroup::task209485_removeFromGroupInEventHandler() QFETCH(int, signalCount); qRegisterMetaType<QAbstractButton *>("QAbstractButton *"); - QPushButton *button = new QPushButton; + TestPushButton *button = new TestPushButton; QButtonGroup group; group.addButton(button); diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp index 1f301fd60f..6aca84e3cd 100644 --- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp @@ -47,6 +47,7 @@ #include <qtablewidget.h> #include <qscrollbar.h> #include <qboxlayout.h> +#include <qstackedwidget.h> #include <qstandarditemmodel.h> #include <qstringlistmodel.h> @@ -164,6 +165,7 @@ private slots: void task_QTBUG_56693_itemFontFromModel(); void inputMethodUpdate(); void task_QTBUG_52027_mapCompleterIndex(); + void checkMenuItemPosWhenStyleSheetIsSet(); private: PlatformInputContext m_platformInputContext; @@ -1206,8 +1208,7 @@ void tst_QComboBox::currentIndex() QVERIFY(testWidget->currentText().isEmpty()); // spy on currentIndexChanged - QSignalSpy indexChangedInt(testWidget, SIGNAL(currentIndexChanged(int))); - QSignalSpy indexChangedString(testWidget, SIGNAL(currentIndexChanged(QString))); + QSignalSpy indexChangedSpy(testWidget, SIGNAL(currentIndexChanged(int, QString))); // stuff items into it foreach(QString text, initialItems) { @@ -1231,16 +1232,12 @@ void tst_QComboBox::currentIndex() QCOMPARE(testWidget->currentText(), expectedCurrentText); // check that signal count is correct - QCOMPARE(indexChangedInt.count(), expectedSignalCount); - QCOMPARE(indexChangedString.count(), expectedSignalCount); + QCOMPARE(indexChangedSpy.count(), expectedSignalCount); // compare with last sent signal values - if (indexChangedInt.count()) - QCOMPARE(indexChangedInt.at(indexChangedInt.count() - 1).at(0).toInt(), - testWidget->currentIndex()); - if (indexChangedString.count()) - QCOMPARE(indexChangedString.at(indexChangedString.count() - 1).at(0).toString(), - testWidget->currentText()); + if (indexChangedSpy.count()) + QCOMPARE(indexChangedSpy.at(indexChangedSpy.count() - 1).at(0).toInt(), + testWidget->currentIndex()); if (edit) { testWidget->setCurrentIndex(-1); @@ -2339,7 +2336,8 @@ public: { QStringList list; list << "one" << "two"; - connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int))); + connect(this, SIGNAL(currentIndexChanged(int, QString)), + this, SLOT(onCurrentIndexChanged(int))); addItems(list); } public slots: @@ -2765,7 +2763,7 @@ void tst_QComboBox::resetModel() }; QComboBox cb; StringListModel model({"1", "2"}); - QSignalSpy spy(&cb, QOverload<int>::of(&QComboBox::currentIndexChanged)); + QSignalSpy spy(&cb, QOverload<int, const QString &>::of(&QComboBox::currentIndexChanged)); QCOMPARE(spy.count(), 0); QCOMPARE(cb.currentIndex(), -1); //no selection @@ -3515,5 +3513,46 @@ void tst_QComboBox::task_QTBUG_52027_mapCompleterIndex() QCOMPARE(arguments.at(0).toInt(), 1); } +void tst_QComboBox::checkMenuItemPosWhenStyleSheetIsSet() +{ + QString newCss = "QComboBox {font-size: 18pt;}"; + QString oldCss = qApp->styleSheet(); + qApp->setStyleSheet(newCss); + + QWidget topLevel; + QVBoxLayout *layout = new QVBoxLayout(&topLevel); + QStackedWidget *stack = new QStackedWidget(&topLevel); + layout->addWidget(stack); + QWidget *container = new QWidget(&topLevel); + QHBoxLayout *cLayout = new QHBoxLayout(container); + QComboBox *cBox = new QComboBox; + + QStandardItemModel *model = new QStandardItemModel(cBox); + QStandardItem *item = new QStandardItem(QStringLiteral("Item1")); + model->appendRow(item); + item = new QStandardItem(QStringLiteral("Item2")); + model->appendRow(item); + item = new QStandardItem(QStringLiteral("Item3")); + model->appendRow(item); + item = new QStandardItem(QStringLiteral("Item4")); + model->appendRow(item); + cBox->setModel(model); + + cLayout->addWidget(cBox); + stack->addWidget(container); + topLevel.show(); + cBox->showPopup(); + + QTRY_VERIFY(cBox->view()); + QTRY_VERIFY(cBox->view()->isVisible()); + + int menuHeight = cBox->view()->geometry().height(); + QRect menuItemRect = cBox->view()->visualRect(model->indexFromItem(item)); + + QCOMPARE(menuHeight, menuItemRect.y() + menuItemRect.height()); + + qApp->setStyleSheet(oldCss); +} + QTEST_MAIN(tst_QComboBox) #include "tst_qcombobox.moc" diff --git a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp index 2c5cb88ed6..1c19bf96d6 100644 --- a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp +++ b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp @@ -152,6 +152,22 @@ Q_DECLARE_METATYPE(Qt::WindowType); Q_DECLARE_METATYPE(Qt::WindowFlags); Q_DECLARE_METATYPE(QMdiSubWindow*); +class TestPushButton : public QPushButton +{ +public: + TestPushButton(const QString &title, QWidget *parent = nullptr) + : QPushButton(title, parent) + { + } + +protected: + // don't rely on style-specific button behavior in test + bool hitButton(const QPoint &point) const override + { + return rect().contains(point); + } +}; + class tst_QMdiSubWindow : public QObject { Q_OBJECT @@ -390,7 +406,7 @@ void tst_QMdiSubWindow::mainWindowSupport() // the maximized subwindow's title is imposed onto the main window's titlebar. if (!nativeMenuBar) { QCOMPARE(mainWindow.windowTitle(), QString()); - QMdiSubWindow *window = workspace->addSubWindow(new QPushButton(QLatin1String("Test"))); + QMdiSubWindow *window = workspace->addSubWindow(new TestPushButton(QLatin1String("Test"))); QString expectedTitle = QLatin1String("MainWindow's title is empty"); window->setWindowTitle(expectedTitle); QCOMPARE(window->windowTitle(), expectedTitle); @@ -1298,7 +1314,7 @@ void tst_QMdiSubWindow::changeFocusWithTab() QTest::keyPress(widget, Qt::Key_Backtab); QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(firstLineEdit)); - QMdiSubWindow *window = mdiArea.addSubWindow(new QPushButton); + QMdiSubWindow *window = mdiArea.addSubWindow(new TestPushButton(QLatin1String("test"))); window->show(); QCOMPARE(mdiArea.activeSubWindow(), window); @@ -1907,7 +1923,7 @@ void tst_QMdiSubWindow::setFont() QSKIP("This test function is unstable in CI, please see QTBUG-22544"); QMdiArea mdiArea; mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction())); - QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QPushButton(QLatin1String("test"))); + QMdiSubWindow *subWindow = mdiArea.addSubWindow(new TestPushButton(QLatin1String("test"))); subWindow->resize(300, 100); subWindow->setWindowTitle(QLatin1String("Window title")); mdiArea.show(); @@ -2057,19 +2073,19 @@ void tst_QMdiSubWindow::task_233197() QMenuBar *menuBar = mainWindow->menuBar(); // force creation of a menubar Q_UNUSED(menuBar); - QPushButton *focus1 = new QPushButton(QLatin1String("Focus 1"), mainWindow); + QPushButton *focus1 = new TestPushButton(QLatin1String("Focus 1"), mainWindow); QObject::connect(focus1, &QAbstractButton::clicked, subWindow1, QOverload<>::of(&QWidget::setFocus)); focus1->move(5, 30); focus1->show(); - QPushButton *focus2 = new QPushButton(QLatin1String("Focus 2"), mainWindow); + QPushButton *focus2 = new TestPushButton(QLatin1String("Focus 2"), mainWindow); QObject::connect(focus2, &QAbstractButton::clicked, subWindow2, QOverload<>::of(&QWidget::setFocus)); focus2->move(5, 60); focus2->show(); - QPushButton *close = new QPushButton(QLatin1String("Close"), mainWindow); + QPushButton *close = new TestPushButton(QLatin1String("Close"), mainWindow); QObject::connect(close, &QAbstractButton::clicked, mainWindow, &QWidget::close); close->move(5, 90); close->show(); diff --git a/tests/manual/foreignwindows/main.cpp b/tests/manual/foreignwindows/main.cpp index 44aff54773..5e882b6d9c 100644 --- a/tests/manual/foreignwindows/main.cpp +++ b/tests/manual/foreignwindows/main.cpp @@ -59,9 +59,9 @@ QT_USE_NAMESPACE -typedef QSharedPointer<QWidget> WidgetPtr; -typedef QList<WidgetPtr> WidgetPtrList; -typedef QList<WId> WIdList; +using WidgetPtr = QSharedPointer<QWidget>; +using WidgetPtrList = QVector<WidgetPtr>; +using WIdList = QVector<WId>; // Create some pre-defined Windows controls by class name static WId createInternalWindow(const QString &name) @@ -74,7 +74,7 @@ static WId createInternalWindow(const QString &name) CreateWindowEx(0, reinterpret_cast<const wchar_t *>(name.utf16()), L"NativeCtrl", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - 0, 0, GetModuleHandle(NULL), NULL); + nullptr, nullptr, GetModuleHandle(nullptr), nullptr); if (hwnd) { SetWindowText(hwnd, L"Demo"); result = WId(hwnd); @@ -179,7 +179,7 @@ void WindowDumper::dump() const debug << '#' << n++; if (m_watchedWindows.size() > 1) debug << '\n'; - foreach (const QWindow *w, m_watchedWindows) { + for (const QWindow *w : m_watchedWindows) { const QPoint globalPos = w->mapToGlobal(QPoint()); debug << " " << w << " pos=" << globalPos.x() << ',' << globalPos.y() << '\n'; } @@ -212,7 +212,7 @@ struct EventFilterOption QtDiag::EventFilter::EventCategories categories; }; -EventFilterOption eventFilterOptions[] = { +static EventFilterOption eventFilterOptions[] = { {"mouse-events", "Dump mouse events.", QtDiag::EventFilter::MouseEvents}, {"keyboard-events", "Dump keyboard events.", QtDiag::EventFilter::KeyEvents}, {"state-events", "Dump state/focus change events.", QtDiag::EventFilter::StateChangeEvents | QtDiag::EventFilter::FocusEvents} @@ -248,11 +248,10 @@ int main(int argc, char *argv[]) parser.addOption(outputAllOption); QCommandLineOption continuousOption(QStringList() << QStringLiteral("c") << QStringLiteral("continuous"), QStringLiteral("Output continuously.")); - parser.addOption(outputAllOption); + parser.addOption(continuousOption); QCommandLineOption moveOption(QStringList() << QStringLiteral("m") << QStringLiteral("move"), QStringLiteral("Move window to top left corner.")); parser.addOption(moveOption); - parser.addOption(continuousOption); QCommandLineOption embedOption(QStringList() << QStringLiteral("e") << QStringLiteral("embed"), QStringLiteral("Embed a foreign window into a Qt widget.")); parser.addOption(embedOption); @@ -271,7 +270,7 @@ int main(int argc, char *argv[]) } QWindowList windows; - foreach (const QString &argument, parser.positionalArguments()) { + for (const QString &argument : parser.positionalArguments()) { bool ok = true; WId wid = createInternalWindow(argument); if (!wid) @@ -295,7 +294,7 @@ int main(int argc, char *argv[]) int exitCode = 0; if (parser.isSet(embedOption)) { - QtDiag::EventFilter::EventCategories eventCategories = 0; + QtDiag::EventFilter::EventCategories eventCategories; for (int i = 0; i < eventFilterOptionCount; ++i) { if (parser.isSet(QLatin1String(eventFilterOptions[i].name))) eventCategories |= eventFilterOptions[i].categories; @@ -303,11 +302,11 @@ int main(int argc, char *argv[]) if (eventCategories) app.installEventFilter(new QtDiag::EventFilter(eventCategories, &app)); - const QRect availableGeometry = QApplication::desktop()->availableGeometry(0); + const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); QPoint pos = availableGeometry.topLeft() + QPoint(availableGeometry.width(), availableGeometry.height()) / 3; WidgetPtrList mainWindows; - foreach (QWindow *window, windows) { + for (QWindow *window : qAsConst(windows)) { WidgetPtr mainWindow(new EmbeddingWindow(window)); mainWindow->move(pos); mainWindow->resize(availableGeometry.size() / 4); @@ -324,7 +323,6 @@ int main(int argc, char *argv[]) QObject::connect(timer, &QTimer::timeout, &dumper, &WindowDumper::dump); timer->start(1000); exitCode = app.exec(); - } else { WindowDumper(windows).dump(); } diff --git a/tests/manual/qlocale/calendar.cpp b/tests/manual/qlocale/calendar.cpp index 4295e13342..f127c81656 100644 --- a/tests/manual/qlocale/calendar.cpp +++ b/tests/manual/qlocale/calendar.cpp @@ -94,13 +94,13 @@ void CalendarWidget::selectedDateChanged() currentDateEdit->setDate(calendar->selectedDate()); } -void CalendarWidget::minimumDateChanged(const QDate &date) +void CalendarWidget::minimumDateChanged(QDate date) { calendar->setMinimumDate(date); maximumDateEdit->setDate(calendar->maximumDate()); } -void CalendarWidget::maximumDateChanged(const QDate &date) +void CalendarWidget::maximumDateChanged(QDate date) { calendar->setMaximumDate(date); minimumDateEdit->setDate(calendar->minimumDate()); diff --git a/tests/manual/qlocale/calendar.h b/tests/manual/qlocale/calendar.h index aee73ef82a..6a72a4e2d2 100644 --- a/tests/manual/qlocale/calendar.h +++ b/tests/manual/qlocale/calendar.h @@ -55,8 +55,8 @@ private slots: void horizontalHeaderChanged(int index); void verticalHeaderChanged(int index); void selectedDateChanged(); - void minimumDateChanged(const QDate &date); - void maximumDateChanged(const QDate &date); + void minimumDateChanged(QDate date); + void maximumDateChanged(QDate date); void updateWeekendDays(); void weekdayFormatChanged(); void weekendFormatChanged(); diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/CMakeLists.txt b/tests/manual/rhi/hellominimalcrossgfxtriangle/CMakeLists.txt index d933d8ae88..8b9d3389f8 100644 --- a/tests/manual/rhi/hellominimalcrossgfxtriangle/CMakeLists.txt +++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/CMakeLists.txt @@ -5,13 +5,13 @@ ##################################################################### add_qt_manual_test(hellominimalcrossgfxtriangle - GUI SOURCES - hellominimalcrossgfxtriangle.cpp - LIBRARIES - Qt::GuiPrivate + hellowindow.cpp hellowindow.h + main.cpp + window.cpp window.h PUBLIC_LIBRARIES Qt::Gui + Qt::GuiPrivate ) # Resources: diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.cpp b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.cpp deleted file mode 100644 index 9b03a48bfe..0000000000 --- a/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.cpp +++ /dev/null @@ -1,550 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// This is a compact, minimal, single-file demo of deciding the backend at -// runtime while using the exact same shaders and rendering code without any -// branching whatsoever once the QWindow is up and the RHI is initialized. - -#include <QGuiApplication> -#include <QCommandLineParser> -#include <QWindow> -#include <QPlatformSurfaceEvent> -#include <QElapsedTimer> - -#include <QtGui/private/qshader_p.h> -#include <QFile> - -#include <QtGui/private/qrhinull_p.h> - -#ifndef QT_NO_OPENGL -#include <QtGui/private/qrhigles2_p.h> -#include <QOffscreenSurface> -#endif - -#if QT_CONFIG(vulkan) -#include <QLoggingCategory> -#include <QtGui/private/qrhivulkan_p.h> -#endif - -#ifdef Q_OS_WIN -#include <QtGui/private/qrhid3d11_p.h> -#endif - -#if defined(Q_OS_MACOS) || defined(Q_OS_IOS) -#include <QtGui/private/qrhimetal_p.h> -#endif - -static float vertexData[] = { - // Y up (note clipSpaceCorrMatrix in m_proj), CCW - 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, -}; - -static QShader getShader(const QString &name) -{ - QFile f(name); - if (f.open(QIODevice::ReadOnly)) - return QShader::fromSerialized(f.readAll()); - - return QShader(); -} - -enum GraphicsApi -{ - OpenGL, - Vulkan, - D3D11, - Metal, - Null -}; - -static GraphicsApi graphicsApi; - -static QString graphicsApiName() -{ - switch (graphicsApi) { - case OpenGL: - return QLatin1String("OpenGL 2.x"); - case Vulkan: - return QLatin1String("Vulkan"); - case D3D11: - return QLatin1String("Direct3D 11"); - case Metal: - return QLatin1String("Metal"); - case Null: - return QLatin1String("Null"); - default: - break; - } - return QString(); -} - -class Window : public QWindow -{ -public: - Window(); - ~Window(); - - void init(); - void releaseResources(); - void resizeSwapChain(); - void releaseSwapChain(); - void render(); - - void exposeEvent(QExposeEvent *) override; - bool event(QEvent *) override; - -private: - bool m_running = false; - bool m_notExposed = false; - bool m_newlyExposed = false; - - QRhi *m_r = nullptr; - bool m_hasSwapChain = false; - QRhiSwapChain *m_sc = nullptr; - QRhiRenderBuffer *m_ds = nullptr; - QRhiRenderPassDescriptor *m_rp = nullptr; - QRhiBuffer *m_vbuf = nullptr; - bool m_vbufReady = false; - QRhiBuffer *m_ubuf = nullptr; - QRhiShaderResourceBindings *m_srb = nullptr; - QRhiGraphicsPipeline *m_ps = nullptr; - QVector<QRhiResource *> releasePool; - - QMatrix4x4 m_proj; - float m_rotation = 0; - float m_opacity = 1; - int m_opacityDir = -1; - - QElapsedTimer m_timer; - qint64 m_elapsedMs; - int m_elapsedCount; - -#ifndef QT_NO_OPENGL - QOffscreenSurface *m_fallbackSurface = nullptr; -#endif -}; - -Window::Window() -{ - // Tell the platform plugin what we want. - switch (graphicsApi) { - case OpenGL: -#if QT_CONFIG(opengl) - setSurfaceType(OpenGLSurface); - setFormat(QRhiGles2InitParams::adjustedFormat()); -#endif - break; - case Vulkan: - setSurfaceType(VulkanSurface); - break; - case D3D11: - setSurfaceType(OpenGLSurface); // not a typo - break; - case Metal: -#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) - setSurfaceType(MetalSurface); -#endif - break; - default: - break; - } -} - -Window::~Window() -{ - releaseResources(); -} - -void Window::exposeEvent(QExposeEvent *) -{ - // initialize and start rendering when the window becomes usable for graphics purposes - if (isExposed() && !m_running) { - m_running = true; - init(); - resizeSwapChain(); - } - - // stop pushing frames when not exposed (or size is 0) - if ((!isExposed() || (m_hasSwapChain && m_sc->surfacePixelSize().isEmpty())) && m_running) - m_notExposed = true; - - // continue when exposed again and the surface has a valid size. - // note that the surface size can be (0, 0) even though size() reports a valid one... - if (isExposed() && m_running && m_notExposed && !m_sc->surfacePixelSize().isEmpty()) { - m_notExposed = false; - m_newlyExposed = true; - } - - // always render a frame on exposeEvent() (when exposed) in order to update - // immediately on window resize. - if (isExposed() && !m_sc->surfacePixelSize().isEmpty()) - render(); -} - -bool Window::event(QEvent *e) -{ - switch (e->type()) { - case QEvent::UpdateRequest: - render(); - break; - - case QEvent::PlatformSurface: - // this is the proper time to tear down the swapchain (while the native window and surface are still around) - if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) - releaseSwapChain(); - break; - - default: - break; - } - - return QWindow::event(e); -} - -void Window::init() -{ - if (graphicsApi == Null) { - QRhiNullInitParams params; - m_r = QRhi::create(QRhi::Null, ¶ms); - } - -#ifndef QT_NO_OPENGL - if (graphicsApi == OpenGL) { - m_fallbackSurface = QRhiGles2InitParams::newFallbackSurface(); - QRhiGles2InitParams params; - params.fallbackSurface = m_fallbackSurface; - params.window = this; - m_r = QRhi::create(QRhi::OpenGLES2, ¶ms); - } -#endif - -#if QT_CONFIG(vulkan) - if (graphicsApi == Vulkan) { - QRhiVulkanInitParams params; - params.inst = vulkanInstance(); - params.window = this; - m_r = QRhi::create(QRhi::Vulkan, ¶ms); - } -#endif - -#ifdef Q_OS_WIN - if (graphicsApi == D3D11) { - QRhiD3D11InitParams params; - m_r = QRhi::create(QRhi::D3D11, ¶ms); - } -#endif - -#if defined(Q_OS_MACOS) || defined(Q_OS_IOS) - if (graphicsApi == Metal) { - QRhiMetalInitParams params; - m_r = QRhi::create(QRhi::Metal, ¶ms); - } -#endif - - if (!m_r) - qFatal("Failed to create RHI backend"); - - // now onto the backend-independent init - - m_sc = m_r->newSwapChain(); - // allow depth-stencil, although we do not actually enable depth test/write for the triangle - m_ds = m_r->newRenderBuffer(QRhiRenderBuffer::DepthStencil, - QSize(), // no need to set the size here, due to UsedWithSwapChainOnly - 1, - QRhiRenderBuffer::UsedWithSwapChainOnly); - releasePool << m_ds; - m_sc->setWindow(this); - m_sc->setDepthStencil(m_ds); - m_rp = m_sc->newCompatibleRenderPassDescriptor(); - releasePool << m_rp; - m_sc->setRenderPassDescriptor(m_rp); - - m_vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData)); - releasePool << m_vbuf; - m_vbuf->build(); - m_vbufReady = false; - - m_ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68); - releasePool << m_ubuf; - m_ubuf->build(); - - m_srb = m_r->newShaderResourceBindings(); - releasePool << m_srb; - m_srb->setBindings({ - QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, m_ubuf) - }); - m_srb->build(); - - m_ps = m_r->newGraphicsPipeline(); - releasePool << m_ps; - - QRhiGraphicsPipeline::TargetBlend premulAlphaBlend; - premulAlphaBlend.enable = true; - m_ps->setTargetBlends({ premulAlphaBlend }); - - const QShader vs = getShader(QLatin1String(":/color.vert.qsb")); - if (!vs.isValid()) - qFatal("Failed to load shader pack (vertex)"); - const QShader fs = getShader(QLatin1String(":/color.frag.qsb")); - if (!fs.isValid()) - qFatal("Failed to load shader pack (fragment)"); - - m_ps->setShaderStages({ - { QRhiShaderStage::Vertex, vs }, - { QRhiShaderStage::Fragment, fs } - }); - - QRhiVertexInputLayout inputLayout; - inputLayout.setBindings({ - { 5 * sizeof(float) } - }); - inputLayout.setAttributes({ - { 0, 0, QRhiVertexInputAttribute::Float2, 0 }, - { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) } - }); - - m_ps->setVertexInputLayout(inputLayout); - m_ps->setShaderResourceBindings(m_srb); - m_ps->setRenderPassDescriptor(m_rp); - - m_ps->build(); -} - -void Window::releaseResources() -{ - qDeleteAll(releasePool); - releasePool.clear(); - - delete m_sc; // native swapchain is likely released already - m_sc = nullptr; - - delete m_r; - -#ifndef QT_NO_OPENGL - delete m_fallbackSurface; -#endif -} - -void Window::resizeSwapChain() -{ - m_hasSwapChain = m_sc->buildOrResize(); // also handles m_ds - - m_elapsedMs = 0; - m_elapsedCount = 0; - - const QSize outputSize = m_sc->currentPixelSize(); - m_proj = m_r->clipSpaceCorrMatrix(); - m_proj.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 100.0f); - m_proj.translate(0, 0, -4); -} - -void Window::releaseSwapChain() -{ - if (m_hasSwapChain) { - m_hasSwapChain = false; - m_sc->release(); - } -} - -void Window::render() -{ - if (!m_hasSwapChain || m_notExposed) - return; - - // If the window got resized or got newly exposed, resize the swapchain. - // (the newly-exposed case is not actually required by some - // platforms/backends, but f.ex. Vulkan on Windows seems to need it) - if (m_sc->currentPixelSize() != m_sc->surfacePixelSize() || m_newlyExposed) { - resizeSwapChain(); - if (!m_hasSwapChain) - return; - m_newlyExposed = false; - } - - // Start a new frame. This is where we block when too far ahead of - // GPU/present, and that's what throttles the thread to the refresh rate. - // (except for OpenGL where it happens either in endFrame or somewhere else - // depending on the GL implementation) - QRhi::FrameOpResult r = m_r->beginFrame(m_sc); - if (r == QRhi::FrameOpSwapChainOutOfDate) { - resizeSwapChain(); - if (!m_hasSwapChain) - return; - r = m_r->beginFrame(m_sc); - } - if (r != QRhi::FrameOpSuccess) { - requestUpdate(); - return; - } - - if (m_elapsedCount) - m_elapsedMs += m_timer.elapsed(); - m_timer.restart(); - m_elapsedCount += 1; - if (m_elapsedMs >= 4000) { - qDebug("%f", m_elapsedCount / 4.0f); - m_elapsedMs = 0; - m_elapsedCount = 0; - } - - // Set up buffer updates. - QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch(); - if (!m_vbufReady) { - m_vbufReady = true; - u->uploadStaticBuffer(m_vbuf, vertexData); - } - m_rotation += 1.0f; - QMatrix4x4 mvp = m_proj; - mvp.rotate(m_rotation, 0, 1, 0); - u->updateDynamicBuffer(m_ubuf, 0, 64, mvp.constData()); - m_opacity += m_opacityDir * 0.005f; - if (m_opacity < 0.0f || m_opacity > 1.0f) { - m_opacityDir *= -1; - m_opacity = qBound(0.0f, m_opacity, 1.0f); - } - u->updateDynamicBuffer(m_ubuf, 64, 4, &m_opacity); - - QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer(); - const QSize outputSizeInPixels = m_sc->currentPixelSize(); - - // Apply buffer updates, clear, start the renderpass (where applicable). - cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u); - - cb->setGraphicsPipeline(m_ps); - cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) }); - cb->setShaderResources(); - - const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf, 0); - cb->setVertexInput(0, 1, &vbufBinding); - cb->draw(3); - - cb->endPass(); - - // Submit. - m_r->endFrame(m_sc); - - requestUpdate(); // render continuously, throttled by the presentation rate (due to beginFrame above) -} - -int main(int argc, char **argv) -{ - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QGuiApplication app(argc, argv); - - // Defaults. -#if defined(Q_OS_WIN) - graphicsApi = D3D11; -#elif defined(Q_OS_MACOS) || defined(Q_OS_IOS) - graphicsApi = Metal; -#elif QT_CONFIG(vulkan) - graphicsApi = Vulkan; -#else - graphicsApi = OpenGL; -#endif - - // Allow overriding via the command line. - QCommandLineParser cmdLineParser; - cmdLineParser.addHelpOption(); - QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)")); - cmdLineParser.addOption(glOption); - QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan")); - cmdLineParser.addOption(vkOption); - QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11")); - cmdLineParser.addOption(d3dOption); - QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal")); - cmdLineParser.addOption(mtlOption); - QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null")); - cmdLineParser.addOption(nullOption); - cmdLineParser.process(app); - if (cmdLineParser.isSet(glOption)) - graphicsApi = OpenGL; - if (cmdLineParser.isSet(vkOption)) - graphicsApi = Vulkan; - if (cmdLineParser.isSet(d3dOption)) - graphicsApi = D3D11; - if (cmdLineParser.isSet(mtlOption)) - graphicsApi = Metal; - if (cmdLineParser.isSet(nullOption)) - graphicsApi = Null; - - // Vulkan setup. -#if QT_CONFIG(vulkan) - QVulkanInstance inst; - if (graphicsApi == Vulkan) { - if (!inst.create()) { - qWarning("Failed to create Vulkan instance, switching to OpenGL"); - graphicsApi = OpenGL; - } - } -#endif - - // Create and show the window. - Window w; -#if QT_CONFIG(vulkan) - if (graphicsApi == Vulkan) - w.setVulkanInstance(&inst); -#endif - w.resize(1280, 720); - w.setTitle(graphicsApiName()); - w.show(); - - // Window::event() will not get invoked when the - // PlatformSurfaceAboutToBeDestroyed event is sent during the QWindow - // destruction. That happens only when exiting via app::quit() instead of - // the more common QWindow::close(). Take care of it: if the - // QPlatformWindow is still around (there was no close() yet), get rid of - // the swapchain while it's not too late. - if (w.handle()) - w.releaseSwapChain(); - - return app.exec(); -} diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.pro b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.pro index eeef33ff6a..a1093fdaec 100644 --- a/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.pro +++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellominimalcrossgfxtriangle.pro @@ -1,8 +1,14 @@ TEMPLATE = app - +CONFIG += console QT += gui-private SOURCES = \ - hellominimalcrossgfxtriangle.cpp + main.cpp \ + window.cpp \ + hellowindow.cpp + +HEADERS = \ + window.h \ + hellowindow.h RESOURCES = hellominimalcrossgfxtriangle.qrc diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/hellowindow.cpp b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellowindow.cpp new file mode 100644 index 0000000000..96a088adf4 --- /dev/null +++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellowindow.cpp @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "hellowindow.h" +#include <QFile> +#include <QtGui/private/qshader_p.h> + +static float vertexData[] = { + // Y up (note clipSpaceCorrMatrix in m_proj), CCW + 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, +}; + +HelloWindow::HelloWindow(QRhi::Implementation graphicsApi) + : Window(graphicsApi) +{ +} + +QShader HelloWindow::getShader(const QString &name) +{ + QFile f(name); + if (f.open(QIODevice::ReadOnly)) + return QShader::fromSerialized(f.readAll()); + + return QShader(); +} + +void HelloWindow::customInit() +{ + m_vbuf.reset(m_rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData))); + m_vbuf->build(); + m_vbufReady = false; + + m_ubuf.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68)); + m_ubuf->build(); + + m_srb.reset(m_rhi->newShaderResourceBindings()); + m_srb->setBindings({ + QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, + m_ubuf.get()) + }); + m_srb->build(); + + m_ps.reset(m_rhi->newGraphicsPipeline()); + + QRhiGraphicsPipeline::TargetBlend premulAlphaBlend; + premulAlphaBlend.enable = true; + m_ps->setTargetBlends({ premulAlphaBlend }); + + const QShader vs = getShader(QLatin1String(":/color.vert.qsb")); + if (!vs.isValid()) + qFatal("Failed to load shader pack (vertex)"); + const QShader fs = getShader(QLatin1String(":/color.frag.qsb")); + if (!fs.isValid()) + qFatal("Failed to load shader pack (fragment)"); + + m_ps->setShaderStages({ + { QRhiShaderStage::Vertex, vs }, + { QRhiShaderStage::Fragment, fs } + }); + + QRhiVertexInputLayout inputLayout; + inputLayout.setBindings({ + { 5 * sizeof(float) } + }); + inputLayout.setAttributes({ + { 0, 0, QRhiVertexInputAttribute::Float2, 0 }, + { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) } + }); + + m_ps->setVertexInputLayout(inputLayout); + m_ps->setShaderResourceBindings(m_srb.get()); + m_ps->setRenderPassDescriptor(m_rp.get()); + + m_ps->build(); +} + +// called once per frame +void HelloWindow::customRender() +{ + QRhiResourceUpdateBatch *u = m_rhi->nextResourceUpdateBatch(); + if (!m_vbufReady) { + m_vbufReady = true; + u->uploadStaticBuffer(m_vbuf.get(), vertexData); + } + m_rotation += 1.0f; + QMatrix4x4 mvp = m_proj; + mvp.rotate(m_rotation, 0, 1, 0); + u->updateDynamicBuffer(m_ubuf.get(), 0, 64, mvp.constData()); + m_opacity += m_opacityDir * 0.005f; + if (m_opacity < 0.0f || m_opacity > 1.0f) { + m_opacityDir *= -1; + m_opacity = qBound(0.0f, m_opacity, 1.0f); + } + u->updateDynamicBuffer(m_ubuf.get(), 64, 4, &m_opacity); + + QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer(); + const QSize outputSizeInPixels = m_sc->currentPixelSize(); + + cb->beginPass(m_sc->currentFrameRenderTarget(), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f), { 1.0f, 0 }, u); + + cb->setGraphicsPipeline(m_ps.get()); + cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) }); + cb->setShaderResources(); + + const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), 0); + cb->setVertexInput(0, 1, &vbufBinding); + cb->draw(3); + + cb->endPass(); +} diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/hellowindow.h b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellowindow.h new file mode 100644 index 0000000000..dd9890f11c --- /dev/null +++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/hellowindow.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef HELLOWINDOW_H +#define HELLOWINDOW_H + +#include "window.h" + +class HelloWindow : public Window +{ +public: + HelloWindow(QRhi::Implementation graphicsApi); + + void customInit() override; + void customRender() override; + +private: + QShader getShader(const QString &name); + + std::unique_ptr<QRhiBuffer> m_vbuf; + bool m_vbufReady = false; + std::unique_ptr<QRhiBuffer> m_ubuf; + std::unique_ptr<QRhiShaderResourceBindings> m_srb; + std::unique_ptr<QRhiGraphicsPipeline> m_ps; + + float m_rotation = 0; + float m_opacity = 1; + int m_opacityDir = -1; +}; + +#endif diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/main.cpp b/tests/manual/rhi/hellominimalcrossgfxtriangle/main.cpp new file mode 100644 index 0000000000..4ef3359ed0 --- /dev/null +++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/main.cpp @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// This is a compact, minimal demo of deciding the backend at runtime while +// using the exact same shaders and rendering code without any branching +// whatsoever once the QWindow is up and the RHI is initialized. + +#include <QGuiApplication> +#include <QCommandLineParser> +#include "hellowindow.h" + +QString graphicsApiName(QRhi::Implementation graphicsApi) +{ + switch (graphicsApi) { + case QRhi::Null: + return QLatin1String("Null (no output)"); + case QRhi::OpenGLES2: + return QLatin1String("OpenGL 2.x"); + case QRhi::Vulkan: + return QLatin1String("Vulkan"); + case QRhi::D3D11: + return QLatin1String("Direct3D 11"); + case QRhi::Metal: + return QLatin1String("Metal"); + default: + break; + } + return QString(); +} + +int main(int argc, char **argv) +{ + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QGuiApplication app(argc, argv); + + QRhi::Implementation graphicsApi; +#if defined(Q_OS_WIN) + graphicsApi = QRhi::D3D11; +#elif defined(Q_OS_MACOS) || defined(Q_OS_IOS) + graphicsApi = QRhi::Metal; +#elif QT_CONFIG(vulkan) + graphicsApi = QRhi::Vulkan; +#else + graphicsApi = QRhi::OpenGLES2; +#endif + + QCommandLineParser cmdLineParser; + cmdLineParser.addHelpOption(); + QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null")); + cmdLineParser.addOption(nullOption); + QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL (2.x)")); + cmdLineParser.addOption(glOption); + QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan")); + cmdLineParser.addOption(vkOption); + QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11")); + cmdLineParser.addOption(d3dOption); + QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal")); + cmdLineParser.addOption(mtlOption); + + cmdLineParser.process(app); + if (cmdLineParser.isSet(nullOption)) + graphicsApi = QRhi::Null; + if (cmdLineParser.isSet(glOption)) + graphicsApi = QRhi::OpenGLES2; + if (cmdLineParser.isSet(vkOption)) + graphicsApi = QRhi::Vulkan; + if (cmdLineParser.isSet(d3dOption)) + graphicsApi = QRhi::D3D11; + if (cmdLineParser.isSet(mtlOption)) + graphicsApi = QRhi::Metal; + + qDebug("Selected graphics API is %s", qPrintable(graphicsApiName(graphicsApi))); + qDebug("This is a multi-api example, use command line arguments to override:\n%s", qPrintable(cmdLineParser.helpText())); + + QSurfaceFormat fmt; + fmt.setDepthBufferSize(24); + fmt.setStencilBufferSize(8); + QSurfaceFormat::setDefaultFormat(fmt); + +#if QT_CONFIG(vulkan) + QVulkanInstance inst; + if (graphicsApi == QRhi::Vulkan) { +#ifndef Q_OS_ANDROID + inst.setLayers({ "VK_LAYER_LUNARG_standard_validation" }); +#else + inst.setLayers({ + "VK_LAYER_GOOGLE_threading", + "VK_LAYER_LUNARG_parameter_validation", + "VK_LAYER_LUNARG_object_tracker", + "VK_LAYER_LUNARG_core_validation", + "VK_LAYER_LUNARG_image", + "VK_LAYER_LUNARG_swapchain", + "VK_LAYER_GOOGLE_unique_objects"}); +#endif + inst.setExtensions({ "VK_KHR_get_physical_device_properties2" }); + if (!inst.create()) { + qWarning("Failed to create Vulkan instance, switching to OpenGL"); + graphicsApi = QRhi::OpenGLES2; + } + } +#endif + + HelloWindow w(graphicsApi); +#if QT_CONFIG(vulkan) + if (graphicsApi == QRhi::Vulkan) + w.setVulkanInstance(&inst); +#endif + w.resize(1280, 720); + w.setTitle(QCoreApplication::applicationName() + QLatin1String(" - ") + graphicsApiName(graphicsApi)); + w.show(); + + int ret = app.exec(); + + // Window::event() will not get invoked when the + // PlatformSurfaceAboutToBeDestroyed event is sent during the QWindow + // destruction. That happens only when exiting via app::quit() instead of + // the more common QWindow::close(). Take care of it: if the QPlatformWindow + // is still around (there was no close() yet), get rid of the swapchain + // while it's not too late. + if (w.handle()) + w.releaseSwapChain(); + + return ret; +} diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/window.cpp b/tests/manual/rhi/hellominimalcrossgfxtriangle/window.cpp new file mode 100644 index 0000000000..f3f00e0255 --- /dev/null +++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/window.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "window.h" +#include <QPlatformSurfaceEvent> + +Window::Window(QRhi::Implementation graphicsApi) + : m_graphicsApi(graphicsApi) +{ + switch (graphicsApi) { + case QRhi::OpenGLES2: + setSurfaceType(OpenGLSurface); +#if QT_CONFIG(opengl) + setFormat(QRhiGles2InitParams::adjustedFormat()); +#endif + break; + case QRhi::Vulkan: + setSurfaceType(VulkanSurface); + break; + case QRhi::D3D11: + setSurfaceType(OpenGLSurface); + break; + case QRhi::Metal: + setSurfaceType(MetalSurface); + break; + default: + break; + } +} + +void Window::exposeEvent(QExposeEvent *) +{ + // initialize and start rendering when the window becomes usable for graphics purposes + if (isExposed() && !m_running) { + qDebug("init"); + m_running = true; + init(); + resizeSwapChain(); + } + + const QSize surfaceSize = m_hasSwapChain ? m_sc->surfacePixelSize() : QSize(); + + // stop pushing frames when not exposed (or size is 0) + if ((!isExposed() || (m_hasSwapChain && surfaceSize.isEmpty())) && m_running && !m_notExposed) { + qDebug("not exposed"); + m_notExposed = true; + } + + // Continue when exposed again and the surface has a valid size. Note that + // surfaceSize can be (0, 0) even though size() reports a valid one, hence + // trusting surfacePixelSize() and not QWindow. + if (isExposed() && m_running && m_notExposed && !surfaceSize.isEmpty()) { + qDebug("exposed again"); + m_notExposed = false; + m_newlyExposed = true; + } + + // always render a frame on exposeEvent() (when exposed) in order to update + // immediately on window resize. + if (isExposed() && !surfaceSize.isEmpty()) + render(); +} + +bool Window::event(QEvent *e) +{ + switch (e->type()) { + case QEvent::UpdateRequest: + render(); + break; + + case QEvent::PlatformSurface: + // this is the proper time to tear down the swapchain (while the native window and surface are still around) + if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) + releaseSwapChain(); + break; + + default: + break; + } + + return QWindow::event(e); +} + +void Window::init() +{ + QRhi::Flags rhiFlags = QRhi::EnableDebugMarkers | QRhi::EnableProfiling; + + if (m_graphicsApi == QRhi::Null) { + QRhiNullInitParams params; + m_rhi.reset(QRhi::create(QRhi::Null, ¶ms, rhiFlags)); + } + +#if QT_CONFIG(opengl) + if (m_graphicsApi == QRhi::OpenGLES2) { + m_fallbackSurface.reset(QRhiGles2InitParams::newFallbackSurface()); + QRhiGles2InitParams params; + params.fallbackSurface = m_fallbackSurface.get(); + params.window = this; + m_rhi.reset(QRhi::create(QRhi::OpenGLES2, ¶ms, rhiFlags)); + } +#endif + +#if QT_CONFIG(vulkan) + if (m_graphicsApi == QRhi::Vulkan) { + QRhiVulkanInitParams params; + params.inst = vulkanInstance(); + params.window = this; + m_rhi.reset(QRhi::create(QRhi::Vulkan, ¶ms, rhiFlags)); + } +#endif + +#ifdef Q_OS_WIN + if (m_graphicsApi == QRhi::D3D11) { + QRhiD3D11InitParams params; + params.enableDebugLayer = true; + m_rhi.reset(QRhi::create(QRhi::D3D11, ¶ms, rhiFlags)); + } +#endif + +#if defined(Q_OS_MACOS) || defined(Q_OS_IOS) + if (m_graphicsApi == QRhi::Metal) { + QRhiMetalInitParams params; + m_rhi = QRhi::create(QRhi::Metal, ¶ms, rhiFlags); + } +#endif + + if (!m_rhi) + qFatal("Failed to create RHI backend"); + + m_sc.reset(m_rhi->newSwapChain()); + m_ds.reset(m_rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, + QSize(), // no need to set the size here, due to UsedWithSwapChainOnly + 1, + QRhiRenderBuffer::UsedWithSwapChainOnly)); + m_sc->setWindow(this); + m_sc->setDepthStencil(m_ds.get()); + m_rp.reset(m_sc->newCompatibleRenderPassDescriptor()); + m_sc->setRenderPassDescriptor(m_rp.get()); + + customInit(); +} + +void Window::resizeSwapChain() +{ + m_hasSwapChain = m_sc->buildOrResize(); // also handles m_ds + + const QSize outputSize = m_sc->currentPixelSize(); + m_proj = m_rhi->clipSpaceCorrMatrix(); + m_proj.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 1000.0f); + m_proj.translate(0, 0, -4); +} + +void Window::releaseSwapChain() +{ + if (m_hasSwapChain) { + m_hasSwapChain = false; + m_sc->release(); + } +} + +void Window::render() +{ + if (!m_hasSwapChain || m_notExposed) + return; + + // If the window got resized or newly exposed, resize the swapchain. (the + // newly-exposed case is not actually required by some platforms, but + // f.ex. Vulkan on Windows seems to need it) + // + // This (exposeEvent + the logic here) is the only safe way to perform + // resize handling. Note the usage of the RHI's surfacePixelSize(), and + // never QWindow::size(). (the two may or may not be the same under the hood, + // depending on the backend and platform) + // + if (m_sc->currentPixelSize() != m_sc->surfacePixelSize() || m_newlyExposed) { + resizeSwapChain(); + if (!m_hasSwapChain) + return; + m_newlyExposed = false; + } + + QRhi::FrameOpResult r = m_rhi->beginFrame(m_sc.get()); + if (r == QRhi::FrameOpSwapChainOutOfDate) { + resizeSwapChain(); + if (!m_hasSwapChain) + return; + r = m_rhi->beginFrame(m_sc.get()); + } + if (r != QRhi::FrameOpSuccess) { + qDebug("beginFrame failed with %d, retry", r); + requestUpdate(); + return; + } + + customRender(); + + m_rhi->endFrame(m_sc.get()); + + requestUpdate(); +} + +void Window::customInit() +{ +} + +void Window::customRender() +{ +} diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/window.h b/tests/manual/rhi/hellominimalcrossgfxtriangle/window.h new file mode 100644 index 0000000000..30bfa2492c --- /dev/null +++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/window.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WINDOW_H +#define WINDOW_H + +#include <QWindow> + +#include <QtGui/private/qrhinull_p.h> +#if QT_CONFIG(opengl) +#include <QtGui/private/qrhigles2_p.h> +#include <QOffscreenSurface> +#endif +#if QT_CONFIG(vulkan) +#include <QtGui/private/qrhivulkan_p.h> +#endif +#ifdef Q_OS_WIN +#include <QtGui/private/qrhid3d11_p.h> +#endif +#if defined(Q_OS_MACOS) || defined(Q_OS_IOS) +#include <QtGui/private/qrhimetal_p.h> +#endif + +class Window : public QWindow +{ +public: + Window(QRhi::Implementation graphicsApi); + + void releaseSwapChain(); + +protected: + virtual void customInit(); + virtual void customRender(); + + // destruction order matters to a certain degree: the fallbackSurface must + // outlive the rhi, the rhi must outlive all other resources. The resources + // need no special order when destroying. +#if QT_CONFIG(opengl) + std::unique_ptr<QOffscreenSurface> m_fallbackSurface; +#endif + std::unique_ptr<QRhi> m_rhi; + std::unique_ptr<QRhiSwapChain> m_sc; + std::unique_ptr<QRhiRenderBuffer> m_ds; + std::unique_ptr<QRhiRenderPassDescriptor> m_rp; + + bool m_hasSwapChain = false; + QMatrix4x4 m_proj; + +private: + void init(); + void resizeSwapChain(); + void render(); + + void exposeEvent(QExposeEvent *) override; + bool event(QEvent *) override; + + QRhi::Implementation m_graphicsApi; + + bool m_running = false; + bool m_notExposed = false; + bool m_newlyExposed = false; +}; + +#endif diff --git a/tests/manual/startsystemmove/main.cpp b/tests/manual/startsystemmove/main.cpp new file mode 100644 index 0000000000..a121d1ed86 --- /dev/null +++ b/tests/manual/startsystemmove/main.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +constexpr qreal border = 20; + +class Window : public QRasterWindow +{ +public: + explicit Window(QWindow *parent = nullptr) : QRasterWindow(parent) + { + resize(300, 200); + setMinimumSize(QSize(border*2, border*2)); + } +protected: + void resizeOrMove(const QPointF &p); + bool event(QEvent *event) override; + void paintEvent(QPaintEvent *event) override; +}; + +void Window::resizeOrMove(const QPointF &p) +{ + Qt::Edges edges; + if (p.x() > width() - border) + edges |= Qt::RightEdge; + if (p.x() < border) + edges |= Qt::LeftEdge; + if (p.y() < border) + edges |= Qt::TopEdge; + if (p.y() > height() - border) + edges |= Qt::BottomEdge; + + if (edges != 0) { + qDebug() << "startSystemResize" << edges; + if (startSystemResize(edges)) + qDebug() << " -> supported"; + else + qDebug() << " -> not supported"; + } else { + qDebug() << "startSystemMove"; + if (startSystemMove()) + qDebug() << " -> supported"; + else + qDebug() << " -> not supported"; + } +} + +bool Window::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::MouseButtonPress: + qDebug() << "Mouse press"; + resizeOrMove(static_cast<QMouseEvent *>(event)->localPos()); + return true; + case QEvent::TouchUpdate: + qDebug() << "Touch update"; + resizeOrMove(static_cast<QTouchEvent *>(event)->touchPoints().first().pos()); + return true; + case QEvent::TouchBegin: + qDebug() << "Touch begin"; + resizeOrMove(static_cast<QTouchEvent *>(event)->touchPoints().first().pos()); + return true; + default: + return QRasterWindow::event(event); + } +} + +void Window::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event); + QPainter painter(this); + QRect fullRect(0, 0, width(), height()); + QRect innerRect = fullRect.marginsRemoved(QMargins(border, border, border, border)); + painter.fillRect(fullRect, QGradient::WarmFlame); + painter.fillRect(innerRect, QGradient::NightFade); + painter.drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, QStringLiteral("Click mouse or touch to move window\nDrag along the sides to resize.")); +} + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + Window window; + window.show(); + return app.exec(); +} diff --git a/tests/manual/startsystemmove/startsystemmove.pro b/tests/manual/startsystemmove/startsystemmove.pro new file mode 100644 index 0000000000..568bda343b --- /dev/null +++ b/tests/manual/startsystemmove/startsystemmove.pro @@ -0,0 +1,4 @@ +TEMPLATE = app +QT = core gui +SOURCES += main.cpp +CONFIG += console diff --git a/tests/shared/emulationdetector.h b/tests/shared/emulationdetector.h index ac584f121b..c8e78c9c54 100644 --- a/tests/shared/emulationdetector.h +++ b/tests/shared/emulationdetector.h @@ -59,7 +59,7 @@ static bool isReportedArchitectureX86(void); * Currently this is only able to check on Linux. If not able to * detect, return false. */ -static bool isRunningArmOnX86() +static Q_DECL_UNUSED bool isRunningArmOnX86() { #ifdef SHOULD_CHECK_ARM_ON_X86 if (isX86SpecificFileAvailable()) |