diff options
Diffstat (limited to 'tests/auto/corelib/kernel')
12 files changed, 574 insertions, 64 deletions
diff --git a/tests/auto/corelib/kernel/qcoreapplication/qcoreapplication.pro b/tests/auto/corelib/kernel/qcoreapplication/qcoreapplication.pro index e37542be65..1a76085c1b 100644 --- a/tests/auto/corelib/kernel/qcoreapplication/qcoreapplication.pro +++ b/tests/auto/corelib/kernel/qcoreapplication/qcoreapplication.pro @@ -5,5 +5,5 @@ SOURCES = tst_qcoreapplication.cpp HEADERS = tst_qcoreapplication.h win32: VERSION = 1.2.3.4 else: VERSION = 1.2.3 -darwin: QMAKE_LFLAGS += -Wl,-sectcreate,__TEXT,__info_plist,$$shell_quote($$PWD/Info.plist) +QMAKE_INFO_PLIST = $$PWD/Info.plist requires(qtConfig(private_tests)) diff --git a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp index 0b4f76ef70..109f5b77f6 100644 --- a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp +++ b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp @@ -637,11 +637,6 @@ void tst_QEventLoop::testQuitLock() { QEventLoop eventLoop; - QTimer timer; - timer.setInterval(100); - QSignalSpy timerSpy(&timer, &QTimer::timeout); - timer.start(); - QEventLoopPrivate* privateClass = static_cast<QEventLoopPrivate*>(QObjectPrivate::get(&eventLoop)); QCOMPARE(privateClass->quitLockRef.load(), 0); @@ -655,9 +650,6 @@ void tst_QEventLoop::testQuitLock() QCOMPARE(privateClass->quitLockRef.load(), 0); - // The job takes long enough that the timer times out several times. - QVERIFY(timerSpy.count() > 3); - timerSpy.clear(); job1 = new JobObject(&eventLoop, this); job1->start(200); @@ -670,11 +662,6 @@ void tst_QEventLoop::testQuitLock() } eventLoop.exec(); - - qDebug() << timerSpy.count(); - // The timer times out more if it has more subjobs to do. - // We run 10 jobs in sequence here of about 200ms each. - QVERIFY(timerSpy.count() > 17); } QTEST_MAIN(tst_QEventLoop) diff --git a/tests/auto/corelib/kernel/qmath/tst_qmath.cpp b/tests/auto/corelib/kernel/qmath/tst_qmath.cpp index ad40b0140d..feb704e0aa 100644 --- a/tests/auto/corelib/kernel/qmath/tst_qmath.cpp +++ b/tests/auto/corelib/kernel/qmath/tst_qmath.cpp @@ -30,8 +30,6 @@ #include <QtTest/QtTest> #include <qmath.h> -static const double PI = 3.14159265358979323846264338327950288; - class tst_QMath : public QObject { Q_OBJECT @@ -55,8 +53,9 @@ void tst_QMath::fastSinCos() { // Test evenly spaced angles from 0 to 2pi radians. const int LOOP_COUNT = 100000; + const qreal loopAngle = 2 * M_PI / (LOOP_COUNT - 1); for (int i = 0; i < LOOP_COUNT; ++i) { - qreal angle = i * 2 * PI / (LOOP_COUNT - 1); + qreal angle = i * loopAngle; QVERIFY(qAbs(qSin(angle) - qFastSin(angle)) < 1e-5); QVERIFY(qAbs(qCos(angle) - qFastCos(angle)) < 1e-5); } @@ -69,18 +68,18 @@ void tst_QMath::degreesToRadians_data() QTest::addColumn<double>("degreesDouble"); QTest::addColumn<double>("radiansDouble"); - QTest::newRow( "pi" ) << 180.0f << float(M_PI) << 180.0 << PI; - QTest::newRow( "doublepi" ) << 360.0f << float(2*M_PI) << 360.0 << 2*PI; - QTest::newRow( "halfpi" ) << 90.0f << float(M_PI_2) << 90.0 << PI/2; + QTest::newRow( "pi" ) << 180.0f << float(M_PI) << 180.0 << M_PI; + QTest::newRow( "doublepi" ) << 360.0f << float(2 * M_PI) << 360.0 << 2 * M_PI; + QTest::newRow( "halfpi" ) << 90.0f << float(M_PI_2) << 90.0 << M_PI_2; QTest::newRow( "random" ) << 123.1234567f << 2.1489097058516724f << 123.123456789123456789 << 2.148909707407169856192285627; QTest::newRow( "bigrandom" ) << 987654321.9876543f << 17237819.79023679f << 987654321987654321.987654321987654321 << 17237819790236794.0; QTest::newRow( "zero" ) << 0.0f << 0.0f << 0.0 << 0.0; - QTest::newRow( "minuspi" ) << -180.0f << float(-M_PI) << 180.0 << PI; - QTest::newRow( "minusdoublepi" ) << -360.0f << float(-2*M_PI) << -360.0 << -2*PI; - QTest::newRow( "minushalfpi" ) << -90.0f << float(-M_PI_2) << -90.0 << -PI/2; + QTest::newRow( "minuspi" ) << -180.0f << float(-M_PI) << 180.0 << M_PI; + QTest::newRow( "minusdoublepi" ) << -360.0f << float(-2 * M_PI) << -360.0 << -2 * M_PI; + QTest::newRow( "minushalfpi" ) << -90.0f << float(-M_PI_2) << -90.0 << -M_PI_2; QTest::newRow( "minusrandom" ) << -123.1234567f << -2.1489097058516724f << -123.123456789123456789 << -2.148909707407169856192285627; QTest::newRow( "minusbigrandom" ) << -987654321.9876543f << -17237819.79023679f << -987654321987654321.987654321987654321 << -17237819790236794.0; @@ -104,18 +103,18 @@ void tst_QMath::radiansToDegrees_data() QTest::addColumn<double>("radiansDouble"); QTest::addColumn<double>("degreesDouble"); - QTest::newRow( "pi" ) << float(M_PI) << 180.0f << PI << 180.0; - QTest::newRow( "doublepi" ) << float(2*M_PI) << 360.0f << 2*PI << 360.0; - QTest::newRow( "halfpi" ) << float(M_PI_2) << 90.0f<< PI/2 << 90.0; + QTest::newRow( "pi" ) << float(M_PI) << 180.0f << M_PI << 180.0; + QTest::newRow( "doublepi" ) << float(2 * M_PI) << 360.0f << 2 * M_PI << 360.0; + QTest::newRow( "halfpi" ) << float(M_PI_2) << 90.0f << M_PI_2 << 90.0; QTest::newRow( "random" ) << 123.1234567f << 7054.454427971739f << 123.123456789123456789 << 7054.4544330781363896676339209079742431640625; QTest::newRow( "bigrandom" ) << 987654321.9876543f << 56588424267.74745f << 987654321987654321.987654321987654321 << 56588424267747450880.0; QTest::newRow( "zero" ) << 0.0f << 0.0f << 0.0 << 0.0; - QTest::newRow( "minuspi" ) << float(-M_PI) << -180.0f << -PI << -180.0; - QTest::newRow( "minusdoublepi" ) << float(-2*M_PI) << -360.0f << -2*PI << -360.0; - QTest::newRow( "minushalfpi" ) << float(-M_PI_2) << -90.0f << -PI/2 << -90.0; + QTest::newRow( "minuspi" ) << float(-M_PI) << -180.0f << -M_PI << -180.0; + QTest::newRow( "minusdoublepi" ) << float(-2 * M_PI) << -360.0f << -2 * M_PI << -360.0; + QTest::newRow( "minushalfpi" ) << float(-M_PI_2) << -90.0f << -M_PI_2 << -90.0; QTest::newRow( "minusrandom" ) << -123.1234567f << -7054.454427971739f << -123.123456789123456789 << -7054.4544330781363896676339209079742431640625; QTest::newRow( "minusbigrandom" ) << -987654321.9876543f << -56588424267.74745f << -987654321987654321.987654321987654321 << -56588424267747450880.0; diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index e793d71fe2..35e14b7dbf 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -147,6 +147,77 @@ namespace MyNamespace { { Q_OBJECT }; + + class ClassWithSetterGetterSignals : public QObject + { + Q_OBJECT + + public: + int value1() const { return m_value1; } + void setValue1(int v) { + if (v != m_value1) { + m_value1 = v; + Q_EMIT value1Changed(); + } + } + + int value2() const { return m_value2; } + void setValue2(int v) { + if (v != m_value2) { + m_value2 = v; + Q_EMIT value2Changed(); + } + } + + Q_SIGNALS: + void value1Changed(); + void value2Changed(); + + private: + int m_value1 = 0; + int m_value2 = 0; + }; + + class ClassWithSetterGetterSignalsAddsProperties : public ClassWithSetterGetterSignals + { + Q_OBJECT + Q_PROPERTY(int value1 READ value1 WRITE setValue1 NOTIFY value1Changed) + Q_PROPERTY(int value2 READ value2 WRITE setValue2 NOTIFY value2Changed) + }; + + class ClassWithChangedSignal : public QObject + { + Q_OBJECT + + public: + int value1() const { return m_value1; } + void setValue1(int v) { + if (v != m_value1) { + m_value1 = v; + Q_EMIT propertiesChanged(); + } + } + + void thisIsNotASignal() { } + + Q_SIGNALS: + void propertiesChanged(); + + private: + int m_value1 = 0; + }; + + class ClassWithChangedSignalNewValue : public ClassWithChangedSignal + { + Q_OBJECT + + Q_PROPERTY(int value2 MEMBER m_value2 NOTIFY propertiesChanged) + Q_PROPERTY(int value3 MEMBER m_value3 NOTIFY thisIsNotASignal) + + private: + int m_value2 = 0; + int m_value3 = 0; + }; } @@ -200,8 +271,11 @@ public: private slots: void connectSlotsByName(); void invokeMetaMember(); + void invokePointer(); void invokeQueuedMetaMember(); + void invokeQueuedPointer(); void invokeBlockingQueuedMetaMember(); + void invokeBlockingQueuedPointer(); void invokeCustomTypes(); void invokeMetaConstructor(); void invokeTypedefTypes(); @@ -242,6 +316,8 @@ private slots: void inherits_data(); void inherits(); + void notifySignalsInParentClass(); + signals: void value6Changed(); void value7Changed(const QString &); @@ -427,6 +503,10 @@ public slots: + QString::number(o6.size()); } +public: + static void staticFunction0(); + static qint64 staticFunction1(); + signals: void sig0(); QString sig1(QString s1); @@ -440,8 +520,11 @@ private: public: QString slotResult; + static QString staticResult; }; +QString QtTestObject::staticResult; + QtTestObject::QtTestObject() { connect(this, SIGNAL(sig0()), this, SLOT(sl0())); @@ -500,6 +583,13 @@ void QtTestObject::testSender() void QtTestObject::slotWithUnregisteredParameterType(MyUnregisteredType) { slotResult = "slotWithUnregisteredReturnType"; } +void QtTestObject::staticFunction0() +{ + staticResult = "staticFunction0"; +} + +qint64 QtTestObject::staticFunction1() +{ staticResult = "staticFunction1"; return Q_INT64_C(123456789)*123456789; } void tst_QMetaObject::invokeMetaMember() { @@ -508,9 +598,18 @@ void tst_QMetaObject::invokeMetaMember() QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5"); QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X"); - QVERIFY(!QMetaObject::invokeMethod(0, 0)); - QVERIFY(!QMetaObject::invokeMethod(0, "sl0")); - QVERIFY(!QMetaObject::invokeMethod(&obj, 0)); + // Test nullptr + char *nullCharArray = nullptr; + const char *nullConstCharArray = nullptr; + QVERIFY(!QMetaObject::invokeMethod(nullptr, nullCharArray)); + QVERIFY(!QMetaObject::invokeMethod(nullptr, nullConstCharArray)); + QVERIFY(!QMetaObject::invokeMethod(nullptr, "sl0")); + QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray)); + QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray)); + QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection)); + QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection)); + QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection, QGenericReturnArgument())); + QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection, QGenericReturnArgument())); QVERIFY(QMetaObject::invokeMethod(&obj, "sl0")); QCOMPARE(obj.slotResult, QString("sl0")); @@ -639,6 +738,56 @@ void tst_QMetaObject::invokeMetaMember() QCOMPARE(obj.slotResult, QString("sl1:hehe")); } +void testFunction(){} + + +void tst_QMetaObject::invokePointer() +{ + QtTestObject obj; + QtTestObject *const nullTestObject = nullptr; + + QString t1("1"); + + // Test member functions + QVERIFY(!QMetaObject::invokeMethod(nullTestObject, &QtTestObject::sl0)); + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl0)); + QCOMPARE(obj.slotResult, QString("sl0")); + + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::testSender)); + QCOMPARE(obj.slotResult, QString("0x0")); + + qint64 return64 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl14, &return64)); + QCOMPARE(return64, Q_INT64_C(123456789)*123456789); + QCOMPARE(obj.slotResult, QString("sl14")); + + // signals + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sig0)); + QCOMPARE(obj.slotResult, QString("sl0")); + + // Test function pointers + QVERIFY(!QMetaObject::invokeMethod(0, &testFunction)); + QVERIFY(QMetaObject::invokeMethod(&obj, &testFunction)); + + QVERIFY(!QMetaObject::invokeMethod(0, &QtTestObject::staticFunction0)); + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction0)); + QCOMPARE(QtTestObject::staticResult, QString("staticFunction0")); + + return64 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction1, &return64)); + QCOMPARE(return64, Q_INT64_C(123456789)*123456789); + QCOMPARE(QtTestObject::staticResult, QString("staticFunction1")); + + // Test lambdas + QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.sl1(t1);})); + QCOMPARE(obj.slotResult, QString("sl1:1")); + + QString exp; + QVERIFY(QMetaObject::invokeMethod(&obj, [&]()->QString{return obj.sl1("bubu");}, &exp)); + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:bubu")); +} + void tst_QMetaObject::invokeQueuedMetaMember() { QtTestObject obj; @@ -699,6 +848,44 @@ void tst_QMetaObject::invokeQueuedMetaMember() } } +void tst_QMetaObject::invokeQueuedPointer() +{ + QtTestObject obj; + + // Test member function + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl0, Qt::QueuedConnection)); + QVERIFY(obj.slotResult.isEmpty()); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("sl0")); + + // signals + obj.slotResult.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sig0, Qt::QueuedConnection)); + QVERIFY(obj.slotResult.isEmpty()); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("sl0")); + + // Test function pointers + QtTestObject::staticResult.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction0, Qt::QueuedConnection)); + QVERIFY(QtTestObject::staticResult.isEmpty()); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(QtTestObject::staticResult, QString("staticFunction0")); + + // Test lambda + obj.slotResult.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.sl0();}, Qt::QueuedConnection)); + QVERIFY(obj.slotResult.isEmpty()); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("sl0")); + + qint32 var = 0; + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: Unable to invoke methods with return values in queued connections"); + QVERIFY(!QMetaObject::invokeMethod(&obj, []()->qint32{return 1;}, Qt::QueuedConnection, &var)); + QCOMPARE(var, 0); +} + + void tst_QMetaObject::invokeBlockingQueuedMetaMember() { QThread t; @@ -832,6 +1019,62 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember() } +void tst_QMetaObject::invokeBlockingQueuedPointer() +{ + QtTestObject *const nullTestObject = nullptr; + + QThread t; + t.start(); + QtTestObject obj; + obj.moveToThread(&t); + + QString t1("1"); + + // Test member functions + QVERIFY(!QMetaObject::invokeMethod(nullTestObject, &QtTestObject::sl0, Qt::BlockingQueuedConnection)); + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl0, Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("sl0")); + + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::testSender, Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("0x0")); + + // return qint64 + qint64 return64 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl14, Qt::BlockingQueuedConnection, + &return64)); + QCOMPARE(return64, Q_INT64_C(123456789)*123456789); + QCOMPARE(obj.slotResult, QString("sl14")); + + //test signals + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sig0, Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("sl0")); + + // Test function pointers + QVERIFY(!QMetaObject::invokeMethod(0, &testFunction, Qt::BlockingQueuedConnection)); + QVERIFY(QMetaObject::invokeMethod(&obj, &testFunction, Qt::BlockingQueuedConnection)); + + QVERIFY(!QMetaObject::invokeMethod(0, &QtTestObject::staticFunction0, Qt::BlockingQueuedConnection)); + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction0, Qt::BlockingQueuedConnection)); + QCOMPARE(QtTestObject::staticResult, QString("staticFunction0")); + + return64 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction1, Qt::BlockingQueuedConnection, &return64)); + QCOMPARE(return64, Q_INT64_C(123456789)*123456789); + QCOMPARE(QtTestObject::staticResult, QString("staticFunction1")); + + // Test lambdas + QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.sl1(t1);}, Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("sl1:1")); + + QString exp; + QVERIFY(QMetaObject::invokeMethod(&obj, [&]()->QString{return obj.sl1("bubu");}, Qt::BlockingQueuedConnection, &exp)); + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:bubu")); + + QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.moveToThread(QThread::currentThread());}, Qt::BlockingQueuedConnection)); + t.quit(); + QVERIFY(t.wait()); +} void tst_QMetaObject::qtMetaObjectInheritance() @@ -1502,5 +1745,18 @@ void tst_QMetaObject::inherits() QCOMPARE(derivedMetaObject->inherits(baseMetaObject), inheritsResult); } +void tst_QMetaObject::notifySignalsInParentClass() +{ + MyNamespace::ClassWithSetterGetterSignalsAddsProperties obj; + QCOMPARE(obj.metaObject()->property(obj.metaObject()->indexOfProperty("value1")).notifySignal().name(), QByteArray("value1Changed")); + QCOMPARE(obj.metaObject()->property(obj.metaObject()->indexOfProperty("value2")).notifySignal().name(), QByteArray("value2Changed")); + + MyNamespace::ClassWithChangedSignalNewValue obj2; + QCOMPARE(obj2.metaObject()->property(obj2.metaObject()->indexOfProperty("value2")).notifySignal().name(), QByteArray("propertiesChanged")); + + QTest::ignoreMessage(QtWarningMsg, "QMetaProperty::notifySignal: cannot find the NOTIFY signal thisIsNotASignal in class MyNamespace::ClassWithChangedSignalNewValue for property 'value3'"); + obj2.metaObject()->property(obj2.metaObject()->indexOfProperty("value3")).notifySignal(); +} + QTEST_MAIN(tst_QMetaObject) #include "tst_qmetaobject.moc" diff --git a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp index 9ae39449f8..6bb031e357 100644 --- a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp +++ b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp @@ -806,6 +806,7 @@ void tst_QMetaObjectBuilder::enumerator() QMetaEnumBuilder enum1 = builder.addEnumerator("foo"); QCOMPARE(enum1.name(), QByteArray("foo")); QVERIFY(!enum1.isFlag()); + QVERIFY(!enum1.isScoped()); QCOMPARE(enum1.keyCount(), 0); QCOMPARE(enum1.index(), 0); QCOMPARE(builder.enumeratorCount(), 1); @@ -814,6 +815,7 @@ void tst_QMetaObjectBuilder::enumerator() QMetaEnumBuilder enum2 = builder.addEnumerator("bar"); QCOMPARE(enum2.name(), QByteArray("bar")); QVERIFY(!enum2.isFlag()); + QVERIFY(!enum2.isScoped()); QCOMPARE(enum2.keyCount(), 0); QCOMPARE(enum2.index(), 1); QCOMPARE(builder.enumeratorCount(), 2); @@ -827,6 +829,7 @@ void tst_QMetaObjectBuilder::enumerator() // Modify the attributes on enum1. enum1.setIsFlag(true); + enum1.setIsScoped(true); QCOMPARE(enum1.addKey("ABC", 0), 0); QCOMPARE(enum1.addKey("DEF", 1), 1); QCOMPARE(enum1.addKey("GHI", -1), 2); @@ -834,6 +837,7 @@ void tst_QMetaObjectBuilder::enumerator() // Check that enum1 is changed, but enum2 is not. QCOMPARE(enum1.name(), QByteArray("foo")); QVERIFY(enum1.isFlag()); + QVERIFY(enum1.isScoped()); QCOMPARE(enum1.keyCount(), 3); QCOMPARE(enum1.index(), 0); QCOMPARE(enum1.key(0), QByteArray("ABC")); @@ -845,6 +849,7 @@ void tst_QMetaObjectBuilder::enumerator() QCOMPARE(enum1.value(2), -1); QCOMPARE(enum2.name(), QByteArray("bar")); QVERIFY(!enum2.isFlag()); + QVERIFY(!enum2.isScoped()); QCOMPARE(enum2.keyCount(), 0); QCOMPARE(enum2.index(), 1); @@ -856,6 +861,7 @@ void tst_QMetaObjectBuilder::enumerator() // This time check that only method2 changed. QCOMPARE(enum1.name(), QByteArray("foo")); QVERIFY(enum1.isFlag()); + QVERIFY(enum1.isScoped()); QCOMPARE(enum1.keyCount(), 3); QCOMPARE(enum1.index(), 0); QCOMPARE(enum1.key(0), QByteArray("ABC")); @@ -867,6 +873,7 @@ void tst_QMetaObjectBuilder::enumerator() QCOMPARE(enum1.value(2), -1); QCOMPARE(enum2.name(), QByteArray("bar")); QVERIFY(enum2.isFlag()); + QVERIFY(!enum2.isScoped()); QCOMPARE(enum2.keyCount(), 2); QCOMPARE(enum2.index(), 1); QCOMPARE(enum2.key(0), QByteArray("XYZ")); @@ -879,6 +886,7 @@ void tst_QMetaObjectBuilder::enumerator() enum1.removeKey(2); QCOMPARE(enum1.name(), QByteArray("foo")); QVERIFY(enum1.isFlag()); + QVERIFY(enum1.isScoped()); QCOMPARE(enum1.keyCount(), 2); QCOMPARE(enum1.index(), 0); QCOMPARE(enum1.key(0), QByteArray("ABC")); @@ -889,6 +897,7 @@ void tst_QMetaObjectBuilder::enumerator() QCOMPARE(enum1.value(2), -1); QCOMPARE(enum2.name(), QByteArray("bar")); QVERIFY(enum2.isFlag()); + QVERIFY(!enum2.isScoped()); QCOMPARE(enum2.keyCount(), 2); QCOMPARE(enum2.index(), 1); QCOMPARE(enum2.key(0), QByteArray("XYZ")); @@ -903,6 +912,7 @@ void tst_QMetaObjectBuilder::enumerator() enum2 = builder.enumerator(0); QCOMPARE(enum2.name(), QByteArray("bar")); QVERIFY(enum2.isFlag()); + QVERIFY(!enum2.isScoped()); QCOMPARE(enum2.keyCount(), 2); QCOMPARE(enum2.index(), 0); QCOMPARE(enum2.key(0), QByteArray("XYZ")); diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index f9ddd59aaa..076610a0c5 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -155,7 +155,9 @@ void tst_QMetaType::defined() QCOMPARE(int(QMetaTypeId2<int*>::Defined), 0); QCOMPARE(int(QMetaTypeId2<CustomQObject::CustomQEnum>::Defined), 1); QCOMPARE(int(QMetaTypeId2<CustomGadget>::Defined), 1); + QCOMPARE(int(QMetaTypeId2<CustomGadget*>::Defined), 1); QVERIFY(!QMetaTypeId2<GadgetDerived>::Defined); + QVERIFY(!QMetaTypeId2<GadgetDerived*>::Defined); QVERIFY(int(QMetaTypeId2<CustomQObject*>::Defined)); QVERIFY(!QMetaTypeId2<CustomQObject>::Defined); QVERIFY(!QMetaTypeId2<CustomNonQObject>::Defined); @@ -397,6 +399,7 @@ void tst_QMetaType::typeName_data() QTest::newRow("CustomQObject*") << ::qMetaTypeId<CustomQObject*>() << QString::fromLatin1("CustomQObject*"); QTest::newRow("CustomGadget") << ::qMetaTypeId<CustomGadget>() << QString::fromLatin1("CustomGadget"); + QTest::newRow("CustomGadget*") << ::qMetaTypeId<CustomGadget*>() << QString::fromLatin1("CustomGadget*"); QTest::newRow("CustomQObject::CustomQEnum") << ::qMetaTypeId<CustomQObject::CustomQEnum>() << QString::fromLatin1("CustomQObject::CustomQEnum"); QTest::newRow("Qt::ArrowType") << ::qMetaTypeId<Qt::ArrowType>() << QString::fromLatin1("Qt::ArrowType"); } @@ -1684,6 +1687,7 @@ public: }; Q_DECLARE_METATYPE(MyGadget); +Q_DECLARE_METATYPE(MyGadget*); Q_DECLARE_METATYPE(const QMetaObject *); Q_DECLARE_METATYPE(Qt::ScrollBarPolicy); Q_DECLARE_METATYPE(MyGadget::MyEnum); @@ -1693,16 +1697,18 @@ void tst_QMetaType::metaObject_data() QTest::addColumn<int>("type"); QTest::addColumn<const QMetaObject*>("result"); QTest::addColumn<bool>("isGadget"); + QTest::addColumn<bool>("isGadgetPtr"); QTest::addColumn<bool>("isQObjectPtr"); - QTest::newRow("QObject") << int(QMetaType::QObjectStar) << &QObject::staticMetaObject << false << true; - QTest::newRow("QFile*") << ::qMetaTypeId<QFile*>() << &QFile::staticMetaObject << false << true; - QTest::newRow("MyObject*") << ::qMetaTypeId<MyObject*>() << &MyObject::staticMetaObject << false << true; - QTest::newRow("int") << int(QMetaType::Int) << static_cast<const QMetaObject *>(0) << false << false; - QTest::newRow("QEasingCurve") << ::qMetaTypeId<QEasingCurve>() << &QEasingCurve::staticMetaObject << true << false; - QTest::newRow("MyGadget") << ::qMetaTypeId<MyGadget>() << &MyGadget::staticMetaObject << true << false; - QTest::newRow("MyEnum") << ::qMetaTypeId<MyGadget::MyEnum>() << &MyGadget::staticMetaObject << false << false; - QTest::newRow("Qt::ScrollBarPolicy") << ::qMetaTypeId<Qt::ScrollBarPolicy>() << &QObject::staticQtMetaObject << false << false; + QTest::newRow("QObject") << int(QMetaType::QObjectStar) << &QObject::staticMetaObject << false << false << true; + QTest::newRow("QFile*") << ::qMetaTypeId<QFile*>() << &QFile::staticMetaObject << false << false << true; + QTest::newRow("MyObject*") << ::qMetaTypeId<MyObject*>() << &MyObject::staticMetaObject << false << false << true; + QTest::newRow("int") << int(QMetaType::Int) << static_cast<const QMetaObject *>(0) << false << false << false; + QTest::newRow("QEasingCurve") << ::qMetaTypeId<QEasingCurve>() << &QEasingCurve::staticMetaObject << true << false << false; + QTest::newRow("MyGadget") << ::qMetaTypeId<MyGadget>() << &MyGadget::staticMetaObject << true << false << false; + QTest::newRow("MyGadget*") << ::qMetaTypeId<MyGadget*>() << &MyGadget::staticMetaObject << false << true << false; + QTest::newRow("MyEnum") << ::qMetaTypeId<MyGadget::MyEnum>() << &MyGadget::staticMetaObject << false << false << false; + QTest::newRow("Qt::ScrollBarPolicy") << ::qMetaTypeId<Qt::ScrollBarPolicy>() << &QObject::staticQtMetaObject << false << false << false; } @@ -1711,12 +1717,14 @@ void tst_QMetaType::metaObject() QFETCH(int, type); QFETCH(const QMetaObject *, result); QFETCH(bool, isGadget); + QFETCH(bool, isGadgetPtr); QFETCH(bool, isQObjectPtr); QCOMPARE(QMetaType::metaObjectForType(type), result); QMetaType mt(type); QCOMPARE(mt.metaObject(), result); QCOMPARE(!!(mt.flags() & QMetaType::IsGadget), isGadget); + QCOMPARE(!!(mt.flags() & QMetaType::PointerToGadget), isGadgetPtr); QCOMPARE(!!(mt.flags() & QMetaType::PointerToQObject), isQObjectPtr); } diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 642d48d721..3a52c684d0 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -140,6 +140,7 @@ private slots: void connectFunctorWithContext(); void connectFunctorWithContextUnique(); void connectFunctorDeadlock(); + void connectFunctorMoveOnly(); void connectStaticSlotWithObject(); void disconnectDoesNotLeakFunctor(); void contextDoesNotLeakFunctor(); @@ -6237,6 +6238,47 @@ void tst_QObject::connectFunctorDeadlock() sender.emitSignal1(); } +void tst_QObject::connectFunctorMoveOnly() +{ + struct MoveOnlyFunctor { + Q_DISABLE_COPY(MoveOnlyFunctor) + MoveOnlyFunctor(int *status) : status(status) {} + MoveOnlyFunctor(MoveOnlyFunctor &&o) : status(o.status) { o.status = nullptr; }; + void operator()(int i) { *status = i; } + void operator()() { *status = -8; } + int *status; + }; + + int status = 1; + SenderObject obj; + QEventLoop e; + + connect(&obj, &SenderObject::signal1, MoveOnlyFunctor(&status)); + QCOMPARE(status, 1); + obj.signal1(); + QCOMPARE(status, -8); + + connect(&obj, &SenderObject::signal7, MoveOnlyFunctor(&status)); + QCOMPARE(status, -8); + obj.signal7(7888, "Hello"); + QCOMPARE(status, 7888); + + // With a context + status = 1; + connect(&obj, &SenderObject::signal2, this, MoveOnlyFunctor(&status)); + QCOMPARE(status, 1); + obj.signal2(); + QCOMPARE(status, -8); + + // QueuedConnection + status = 1; + connect(&obj, &SenderObject::signal3, this, MoveOnlyFunctor(&status), Qt::QueuedConnection); + obj.signal3(); + QCOMPARE(status, 1); + QCoreApplication::processEvents(); + QCOMPARE(status, -8); +} + static int s_static_slot_checker = 1; class StaticSlotChecker : public QObject diff --git a/tests/auto/corelib/kernel/qtimer/qtimer.pro b/tests/auto/corelib/kernel/qtimer/qtimer.pro index b27d862bc5..710dfea682 100644 --- a/tests/auto/corelib/kernel/qtimer/qtimer.pro +++ b/tests/auto/corelib/kernel/qtimer/qtimer.pro @@ -1,6 +1,6 @@ CONFIG += testcase TARGET = tst_qtimer -QT = core testlib +QT = core core-private testlib SOURCES = tst_qtimer.cpp # Force C++17 if available diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp index fd704f582d..b921c0f13d 100644 --- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp +++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp @@ -33,11 +33,11 @@ # include <QtCore/QCoreApplication> #endif +#include <QtCore/private/qglobal_p.h> #include <QtTest/QtTest> #include <qtimer.h> #include <qthread.h> -#include <qoperatingsystemversion.h> #if defined Q_OS_UNIX #include <unistd.h> @@ -500,7 +500,7 @@ void tst_QTimer::moveToThread() #if defined(Q_OS_WIN32) QSKIP("Does not work reliably on Windows :("); #elif defined(Q_OS_MACOS) - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra) + if (__builtin_available(macOS 10.12, *)) QSKIP("Does not work reliably on macOS 10.12 (QTBUG-59679)"); #endif QTimer ti1; @@ -836,7 +836,6 @@ void tst_QTimer::singleShotToFunctors() QTest::qWait(800); QCOMPARE(count, 2); -#if defined(Q_COMPILER_LAMBDA) QTimer::singleShot(0, [&count] { ++count; }); QCoreApplication::processEvents(); QCOMPARE(count, 3); @@ -855,7 +854,15 @@ void tst_QTimer::singleShotToFunctors() thread.quit(); thread.wait(); -#endif + + struct MoveOnly : CountedStruct { + Q_DISABLE_COPY(MoveOnly); + MoveOnly(MoveOnly &&o) : CountedStruct(std::move(o)) {}; + MoveOnly(int *c) : CountedStruct(c) {} + }; + QTimer::singleShot(0, MoveOnly(&count)); + QCoreApplication::processEvents(); + QCOMPARE(count, 5); _e.reset(); _t = Q_NULLPTR; diff --git a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp index 66971af7b4..5bfe133966 100644 --- a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp +++ b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp @@ -50,6 +50,7 @@ private slots: void loadFromResource(); void loadDirectory(); void dependencies(); + void translationInThreadWhileInstallingTranslator(); private: int languageChangeEventCounter; @@ -287,6 +288,52 @@ void tst_QTranslator::dependencies() } } +struct TranslateThread : public QThread +{ + bool ok = false; + QAtomicInt terminate; + QMutex startupLock; + QWaitCondition runningCondition; + + void run() { + bool startSignalled = false; + + while (terminate.load() == 0) { + const QString result = QCoreApplication::translate("QPushButton", "Hello %n world(s)!", 0, 0); + + if (!startSignalled) { + QMutexLocker startupLocker(&startupLock); + runningCondition.wakeAll(); + startSignalled = true; + } + + ok = (result == QLatin1String("Hallo 0 Welten!")) + || (result == QLatin1String("Hello 0 world(s)!")); + if (!ok) + break; + } + } +}; + +void tst_QTranslator::translationInThreadWhileInstallingTranslator() +{ + TranslateThread thread; + + QMutexLocker startupLocker(&thread.startupLock); + + thread.start(); + + thread.runningCondition.wait(&thread.startupLock); + + QTranslator *tor = new QTranslator; + tor->load("hellotr_la"); + QCoreApplication::installTranslator(tor); + + ++thread.terminate; + + QVERIFY(thread.wait()); + QVERIFY(thread.ok); +} QTEST_MAIN(tst_QTranslator) #include "tst_qtranslator.moc" diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index e43b7acfb8..0d45159d09 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -277,6 +277,8 @@ private slots: void compareSanity(); void compareRich(); + void nullConvert(); + void accessSequentialContainerKey(); private: @@ -369,6 +371,8 @@ void tst_QVariant::copy_constructor() QVERIFY(var8.isNull()); } +Q_DECLARE_METATYPE(int*) + void tst_QVariant::isNull() { QVariant var; @@ -411,6 +415,18 @@ void tst_QVariant::isNull() QVERIFY(var9.isNull()); var9 = QVariant::fromValue<QJsonValue>(QJsonValue(QJsonValue::Null)); QVERIFY(var9.isNull()); + + QVariant var10(QMetaType::VoidStar, nullptr); + QVERIFY(var10.isNull()); + var10 = QVariant::fromValue<void*>(nullptr); + QVERIFY(var10.isNull()); + + QVariant var11(QMetaType::QObjectStar, nullptr); + QVERIFY(var11.isNull()); + var11 = QVariant::fromValue<QObject*>(nullptr); + QVERIFY(var11.isNull()); + + QVERIFY(QVariant::fromValue<int*>(nullptr).isNull()); } void tst_QVariant::swap() @@ -1046,6 +1062,7 @@ void tst_QVariant::toByteArray_data() QTest::newRow( "longlong" ) << QVariant( (qlonglong)34 ) << QByteArray( "34" ); QTest::newRow( "ulonglong" ) << QVariant( (qulonglong)34 ) << QByteArray( "34" ); + QTest::newRow( "nullptr" ) << QVariant::fromValue(nullptr) << QByteArray(); } void tst_QVariant::toByteArray() @@ -1055,7 +1072,13 @@ void tst_QVariant::toByteArray() QVERIFY( value.isValid() ); QVERIFY( value.canConvert( QVariant::ByteArray ) ); QByteArray ba = value.toByteArray(); + QCOMPARE( ba.isNull(), result.isNull() ); QCOMPARE( ba, result ); + + QVERIFY( value.convert( QVariant::ByteArray ) ); + QCOMPARE( value.isNull(), result.isNull() ); + QCOMPARE( value.toByteArray().isNull(), result.isNull() ); + QCOMPARE( value.toByteArray(), result ); } void tst_QVariant::toString_data() @@ -1082,6 +1105,7 @@ void tst_QVariant::toString_data() QString( "123456789012" ); QTest::newRow("QJsonValue") << QVariant(QJsonValue(QString("hello"))) << QString("hello"); QTest::newRow("QJsonValue(Null)") << QVariant(QJsonValue(QJsonValue::Null)) << QString(); + QTest::newRow("nullptr") << QVariant::fromValue(nullptr) << QString(); } void tst_QVariant::toString() @@ -1091,7 +1115,13 @@ void tst_QVariant::toString() QVERIFY( value.isValid() ); QVERIFY( value.canConvert( QVariant::String ) ); QString str = value.toString(); + QCOMPARE( str.isNull(), result.isNull() ); QCOMPARE( str, result ); + + QVERIFY( value.convert( QVariant::String ) ); + QCOMPARE( value.isNull(), result.isNull() ); + QCOMPARE( value.toString().isNull(), result.isNull() ); + QCOMPARE( value.toString(), result ); } void tst_QVariant::toDate_data() @@ -2648,7 +2678,7 @@ void tst_QVariant::qvariant_cast_QObject_data() QTest::newRow("null QObject") << QVariant::fromValue<QObject*>(0) << true << true; QTest::newRow("null derived QObject") << QVariant::fromValue<CustomQObject*>(0) << true << true; QTest::newRow("null custom object") << QVariant::fromValue<CustomNonQObject*>(0) << false << true; - QTest::newRow("null int") << QVariant::fromValue<int>(0) << false << true; + QTest::newRow("zero int") << QVariant::fromValue<int>(0) << false << false; } void tst_QVariant::qvariant_cast_QObject() @@ -2666,12 +2696,14 @@ void tst_QVariant::qvariant_cast_QObject() QVERIFY(data.canConvert(QMetaType::QObjectStar)); QVERIFY(data.canConvert(::qMetaTypeId<QObject*>())); QCOMPARE(data.value<QObject*>() == 0, isNull); + QCOMPARE(data.isNull(), isNull); QVERIFY(data.convert(QMetaType::QObjectStar)); QCOMPARE(data.userType(), int(QMetaType::QObjectStar)); } else { QVERIFY(!data.canConvert<QObject*>()); QVERIFY(!data.canConvert(QMetaType::QObjectStar)); QVERIFY(!data.canConvert(::qMetaTypeId<QObject*>())); + QCOMPARE(data.isNull(), isNull); QVERIFY(!data.value<QObject*>()); QVERIFY(!data.convert(QMetaType::QObjectStar)); QVERIFY(data.userType() != QMetaType::QObjectStar); @@ -3403,21 +3435,6 @@ void tst_QVariant::toIntFromDouble() const QCOMPARE(result, 2147483630); } -void tst_QVariant::setValue() -{ - QJsonDocument t; //we just take a value so that we're sure that it will be shared - QVariant v1 = QVariant::fromValue(t); - QVERIFY( v1.isDetached() ); - QVariant v2 = v1; - QVERIFY( !v1.isDetached() ); - QVERIFY( !v2.isDetached() ); - - v2.setValue(3); //set an integer value - - QVERIFY( v1.isDetached() ); - QVERIFY( v2.isDetached() ); -} - void tst_QVariant::fpStringRoundtrip_data() const { QTest::addColumn<QVariant>("number"); @@ -3649,6 +3666,20 @@ Q_DECLARE_METATYPE(MyMovable *) Q_DECLARE_METATYPE(MyNotMovable *) Q_DECLARE_METATYPE(QSharedDataPointer<MyShared>) +void tst_QVariant::setValue() +{ + MyNotMovable t; //we just take a value so that we're sure that it will be shared + QVariant v1 = QVariant::fromValue(t); + QVERIFY( v1.isDetached() ); + QVariant v2 = v1; + QVERIFY( !v1.isDetached() ); + QVERIFY( !v2.isDetached() ); + + v2.setValue(3); //set an integer value + + QVERIFY( v1.isDetached() ); + QVERIFY( v2.isDetached() ); +} void tst_QVariant::moreCustomTypes() { @@ -3751,7 +3782,7 @@ void tst_QVariant::moreCustomTypes() { int i = 5; PLAY_WITH_VARIANT((void *)(&i), false, QString(), 0, false); - PLAY_WITH_VARIANT((void *)(0), false, QString(), 0, false); + PLAY_WITH_VARIANT((void *)(0), true, QString(), 0, false); } { @@ -4862,6 +4893,33 @@ void tst_QVariant::compareRich() << QStringLiteral("d")); } +void tst_QVariant::nullConvert() +{ + // Test quirks with QVariants different types of null states. + + // null variant with no initialized value + QVariant nullVar(QVariant::String); + QVERIFY(nullVar.isValid()); + QVERIFY(nullVar.isNull()); + // We can not convert a variant with no value + QVERIFY(!nullVar.convert(QVariant::Url)); + QCOMPARE(nullVar.type(), QVariant::Url); + QVERIFY(nullVar.isNull()); + + // variant initialized with null value + QVariant nullStr = QVariant::fromValue(QString()); + QVERIFY(nullStr.isValid()); + QVERIFY(nullStr.isNull()); + // We can convert an initialized null value however + QVERIFY(nullStr.convert(QVariant::Url)); + QCOMPARE(nullStr.type(), QVariant::Url); + QVERIFY(nullStr.isValid()); + // QUrl does not have an isNull method + QVERIFY(!nullStr.isNull()); + // The URL is not valid however + QVERIFY(!nullStr.toUrl().isValid()); +} + void tst_QVariant::accessSequentialContainerKey() { QString nameResult; @@ -4886,6 +4944,5 @@ void tst_QVariant::accessSequentialContainerKey() QCOMPARE(nameResult, QStringLiteral("Seven")); } - QTEST_MAIN(tst_QVariant) #include "tst_qvariant.moc" diff --git a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp index 3221587300..15a39b62c0 100644 --- a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp +++ b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp @@ -31,6 +31,8 @@ #include <qtimer.h> #include <qt_windows.h> +#include <memory> + class tst_QWinEventNotifier : public QObject { Q_OBJECT @@ -39,7 +41,9 @@ protected slots: void simple_activated(); void simple_timerSet(); private slots: + void simple_data(); void simple(); + void manyNotifiers(); private: HANDLE simpleHEvent; @@ -58,9 +62,17 @@ void tst_QWinEventNotifier::simple_timerSet() SetEvent((HANDLE)simpleHEvent); } +void tst_QWinEventNotifier::simple_data() +{ + QTest::addColumn<bool>("resetManually"); + QTest::newRow("manual_reset") << true; + QTest::newRow("auto_reset") << false; +} + void tst_QWinEventNotifier::simple() { - simpleHEvent = CreateEvent(0, true, false, 0); + QFETCH(bool, resetManually); + simpleHEvent = CreateEvent(0, resetManually, false, 0); QVERIFY(simpleHEvent); QWinEventNotifier n(simpleHEvent); @@ -87,6 +99,91 @@ void tst_QWinEventNotifier::simple() QVERIFY(simpleActivated); } +class EventWithNotifier : public QObject +{ + Q_OBJECT +public: + EventWithNotifier() + { + connect(¬ifier, &QWinEventNotifier::activated, + this, &EventWithNotifier::onNotifierActivated); + notifier.setHandle(CreateEvent(0, TRUE, FALSE, 0)); + notifier.setEnabled(true); + + static int nextIndex = 0; + idx = nextIndex++; + } + + ~EventWithNotifier() + { + notifier.setEnabled(false); + CloseHandle(notifier.handle()); + } + + HANDLE eventHandle() const { return notifier.handle(); } + int numberOfTimesActivated() const { return activatedCount; } + +signals: + void activated(); + +public slots: + void onNotifierActivated() + { + ResetEvent(notifier.handle()); + activatedCount++; + emit activated(); + } + +private: + QWinEventNotifier notifier; + int activatedCount = 0; + int idx = 0; +}; + +void tst_QWinEventNotifier::manyNotifiers() +{ + const size_t maxEvents = 100; + const size_t middleEvenEvent = maxEvents / 2; + Q_ASSERT(middleEvenEvent % 2 == 0); + using EventWithNotifierPtr = std::unique_ptr<EventWithNotifier>; + std::vector<EventWithNotifierPtr> events(maxEvents); + std::generate(events.begin(), events.end(), [] () { + return EventWithNotifierPtr(new EventWithNotifier); + }); + + QTestEventLoop loop; + auto connection = connect(events.at(8).get(), &EventWithNotifier::activated, &loop, &QTestEventLoop::exitLoop); + for (const auto &ewn : events) { + connect(ewn.get(), &EventWithNotifier::activated, [&events, &loop] () { + if (std::all_of(events.cbegin(), events.cend(), + [] (const EventWithNotifierPtr &ewn) { + return ewn->numberOfTimesActivated() > 0; })) { + loop.exitLoop(); + } + }); + } + + // Activate all even events before running the event loop. + for (size_t i = 0; i < events.size(); i += 2) + SetEvent(events.at(i)->eventHandle()); + + // Wait until event notifier with index 8 has been activated. + loop.enterLoop(30); + QObject::disconnect(connection); + + // Activate all odd events after the event loop has run for a bit. + for (size_t i = 1; i < events.size(); i += 2) + SetEvent(events.at(i)->eventHandle()); + + // Wait until all event notifiers have fired. + loop.enterLoop(30); + + // All notifiers must have been activated exactly once. + QVERIFY(std::all_of(events.cbegin(), events.cend(), [] (const EventWithNotifierPtr &ewn) { + return ewn->numberOfTimesActivated() == 1; + })); +} + QTEST_MAIN(tst_QWinEventNotifier) #include "tst_qwineventnotifier.moc" |