summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp')
-rw-r--r--tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp132
1 files changed, 122 insertions, 10 deletions
diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
index 8ddca93cb7..8f8ab33e64 100644
--- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
+++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
@@ -1,6 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2016 Intel Corporation.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qcoreapplication.h"
@@ -9,6 +9,7 @@
#include <private/qabstracteventdispatcher_p.h> // for qGlobalPostedEventsCount()
#include <private/qcoreapplication_p.h>
+#include <private/qcoreevent_p.h>
#include <private/qeventloop_p.h>
#include <private/qthread_p.h>
@@ -24,9 +25,12 @@ class EventSpy : public QObject
public:
QList<int> recordedEvents;
- bool eventFilter(QObject *, QEvent *event) override
+ std::function<void(QObject *, QEvent *)> eventCallback;
+ bool eventFilter(QObject *target, QEvent *event) override
{
recordedEvents.append(event->type());
+ if (eventCallback)
+ eventCallback(target, event);
return false;
}
};
@@ -175,7 +179,7 @@ void tst_QCoreApplication::argc()
char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
TestApplication app(argc, argv);
QCOMPARE(argc, 1);
- QCOMPARE(app.arguments().count(), 1);
+ QCOMPARE(app.arguments().size(), 1);
}
{
@@ -186,7 +190,7 @@ void tst_QCoreApplication::argc()
const_cast<char*>("arg3") };
TestApplication app(argc, argv);
QCOMPARE(argc, 4);
- QCOMPARE(app.arguments().count(), 4);
+ QCOMPARE(app.arguments().size(), 4);
}
{
@@ -194,7 +198,7 @@ void tst_QCoreApplication::argc()
char **argv = 0;
TestApplication app(argc, argv);
QCOMPARE(argc, 0);
- QCOMPARE(app.arguments().count(), 0);
+ QCOMPARE(app.arguments().size(), 0);
}
{
@@ -203,7 +207,7 @@ void tst_QCoreApplication::argc()
const_cast<char*>("-qmljsdebugger=port:3768,block") };
TestApplication app(argc, argv);
QCOMPARE(argc, 1);
- QCOMPARE(app.arguments().count(), 1);
+ QCOMPARE(app.arguments().size(), 1);
}
}
@@ -1021,7 +1025,7 @@ void tst_QCoreApplication::addRemoveLibPaths()
TestApplication app(argc, argv);
// If libraryPaths only contains currentDir, neither will be in libraryPaths now.
- if (paths.length() != 1 && currentDir != paths[0]) {
+ if (paths.size() != 1 && currentDir != paths[0]) {
// Check that modifications stay alive across the creation of an application.
QVERIFY(QCoreApplication::libraryPaths().contains(currentDir));
QVERIFY(!QCoreApplication::libraryPaths().contains(paths[0]));
@@ -1034,19 +1038,127 @@ void tst_QCoreApplication::addRemoveLibPaths()
}
#endif
+static bool theMainThreadIsSet()
+{
+ // QCoreApplicationPrivate::mainThread() has a Q_ASSERT we'd trigger
+ return QCoreApplicationPrivate::theMainThreadId.loadRelaxed() != nullptr;
+}
+
+static bool theMainThreadWasUnset = !theMainThreadIsSet(); // global static
+void tst_QCoreApplication::theMainThread()
+{
+ QVERIFY2(theMainThreadWasUnset, "Something set the theMainThread before main()");
+ QVERIFY(theMainThreadIsSet()); // we have at LEAST one QObject alive: tst_QCoreApplication
+
+ int argc = 1;
+ char *argv[] = { const_cast<char*>(QTest::currentAppName()) };
+ TestApplication app(argc, argv);
+ QVERIFY(QCoreApplicationPrivate::theMainThreadId.loadRelaxed());
+ QVERIFY(QThread::isMainThread());
+ QCOMPARE(app.thread(), thread());
+ QCOMPARE(app.thread(), QThread::currentThread());
+}
+
static void createQObjectOnDestruction()
{
- // Make sure that we can create a QObject after the last QObject has been
- // destroyed (especially after QCoreApplication has).
- //
+ // Make sure that we can create a QObject (and thus have an associated
+ // QThread) after the last QObject has been destroyed (especially after
+ // QCoreApplication has).
+
+#if !defined(QT_QGUIAPPLICATIONTEST) && !defined(Q_OS_WIN)
+ // QCoreApplicationData's global static destructor has run and cleaned up
+ // the QAdoptedThread.
+ if (theMainThreadIsSet())
+ qFatal("theMainThreadIsSet() returned true; some QObject must have leaked");
+#endif
+
// Before the fixes, this would cause a dangling pointer dereference. If
// the problem comes back, it's possible that the following causes no
// effect.
QObject obj;
obj.thread()->setProperty("testing", 1);
+ if (!theMainThreadIsSet())
+ qFatal("theMainThreadIsSet() returned false");
+
+ // because we created a QObject after QCoreApplicationData was destroyed,
+ // the QAdoptedThread won't get cleaned up
}
Q_DESTRUCTOR_FUNCTION(createQObjectOnDestruction)
+void tst_QCoreApplication::testDeleteLaterFromBeforeOutermostEventLoop()
+{
+ int argc = 0;
+ QCoreApplication app(argc, nullptr);
+
+ EventSpy *spy = new EventSpy();
+ QPointer<QObject> spyPointer = spy;
+
+ app.installEventFilter(spy);
+ spy->eventCallback = [spy](QObject *, QEvent *event) {
+ if (event->type() == QEvent::User + 1)
+ spy->deleteLater();
+ };
+
+ QCoreApplication::postEvent(&app, new QEvent(QEvent::Type(QEvent::User + 1)));
+ QCoreApplication::processEvents();
+
+ QEventLoop loop;
+ QTimer::singleShot(0, &loop, &QEventLoop::quit);
+ loop.exec();
+ QVERIFY(!spyPointer);
+}
+
+void tst_QCoreApplication::setIndividualAttributes_data()
+{
+ QTest::addColumn<Qt::ApplicationAttribute>("attribute");
+
+ const QMetaEnum &metaEnum = Qt::staticMetaObject.enumerator(Qt::staticMetaObject.indexOfEnumerator("ApplicationAttribute"));
+ // - 1 to avoid AA_AttributeCount.
+ for (int i = 0; i < metaEnum.keyCount(); ++i) {
+ const auto attribute = static_cast<Qt::ApplicationAttribute>(metaEnum.value(i));
+ if (attribute == Qt::AA_AttributeCount)
+ continue;
+
+ QTest::addRow("%s", metaEnum.key(i)) << attribute;
+ }
+}
+
+void tst_QCoreApplication::setIndividualAttributes()
+{
+ QFETCH(Qt::ApplicationAttribute, attribute);
+
+ const auto originalValue = QCoreApplication::testAttribute(attribute);
+ auto cleanup = qScopeGuard([=]() {
+ QCoreApplication::setAttribute(attribute, originalValue);
+ });
+
+ QCoreApplication::setAttribute(attribute, true);
+ QVERIFY(QCoreApplication::testAttribute(attribute));
+
+ QCoreApplication::setAttribute(attribute, false);
+ QVERIFY(!QCoreApplication::testAttribute(attribute));
+}
+
+void tst_QCoreApplication::setMultipleAttributes()
+{
+ const auto originalDontUseNativeMenuWindowsValue = QCoreApplication::testAttribute(Qt::AA_DontUseNativeMenuWindows);
+ const auto originalDisableSessionManagerValue = QCoreApplication::testAttribute(Qt::AA_DisableSessionManager);
+ auto cleanup = qScopeGuard([=]() {
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, originalDontUseNativeMenuWindowsValue);
+ QCoreApplication::setAttribute(Qt::AA_DisableSessionManager, originalDisableSessionManagerValue);
+ });
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, true);
+ QCoreApplication::setAttribute(Qt::AA_DisableSessionManager, true);
+ QVERIFY(QCoreApplication::testAttribute(Qt::AA_DontUseNativeMenuWindows));
+ QVERIFY(QCoreApplication::testAttribute(Qt::AA_DisableSessionManager));
+
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows, false);
+ QCoreApplication::setAttribute(Qt::AA_DisableSessionManager, false);
+ QVERIFY(!QCoreApplication::testAttribute(Qt::AA_DontUseNativeMenuWindows));
+ QVERIFY(!QCoreApplication::testAttribute(Qt::AA_DisableSessionManager));
+}
+
#ifndef QT_QGUIAPPLICATIONTEST
QTEST_APPLESS_MAIN(tst_QCoreApplication)
#endif