diff options
Diffstat (limited to 'tests/auto/qml/qqmlengine/tst_qqmlengine.cpp')
-rw-r--r-- | tests/auto/qml/qqmlengine/tst_qqmlengine.cpp | 86 |
1 files changed, 80 insertions, 6 deletions
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index 0cb6753020..64f167b47e 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -43,6 +43,7 @@ #include <QQmlIncubationController> #include <QTemporaryDir> #include <private/qqmlengine_p.h> +#include <private/qqmltypedata_p.h> #include <QQmlAbstractUrlInterceptor> class tst_qqmlengine : public QQmlDataTest @@ -427,7 +428,7 @@ void tst_qqmlengine::trimComponentCache() engine.setIncubationController(&componentCache); QQmlComponent component(&engine, testFileUrl(file)); - QVERIFY(component.isReady()); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); QScopedPointer<QObject> object(component.create()); QVERIFY(object != nullptr); QCOMPARE(object->property("success").toBool(), true); @@ -741,13 +742,17 @@ public: CustomSelector(const QUrl &base):m_base(base){} virtual QUrl intercept(const QUrl &url, QQmlAbstractUrlInterceptor::DataType d) { - if (url.scheme() != QStringLiteral("file")) + if ((url.scheme() != QStringLiteral("file") && url.scheme() != QStringLiteral("qrc")) + || url.path().contains("QtQml")) return url; if (!m_interceptionPoints.contains(d)) return url; - if (url.path().endsWith("Test.2/qmldir"))//Special case - return QUrl::fromLocalFile(m_base.path() + "interception/module/intercepted/qmldir"); + if (url.path().endsWith("Test.2/qmldir")) {//Special case + QUrl url = m_base; + url.setPath(m_base.path() + "interception/module/intercepted/qmldir"); + return url; + } // Special case: with 5.10 we always add the implicit import, so we need to explicitly handle this case now if (url.path().endsWith("intercepted/qmldir")) return url; @@ -835,7 +840,7 @@ void tst_qqmlengine::urlInterceptor() QFETCH(QString, expectedAbsoluteUrl); QQmlEngine e; - e.setImportPathList(QStringList() << testFileUrl("interception/imports").toLocalFile()); + e.addImportPath(testFileUrl("interception/imports").url()); CustomSelector cs(testFileUrl("")); cs.m_interceptionPoints = interceptionPoint; e.setUrlInterceptor(&cs); @@ -935,7 +940,7 @@ void tst_qqmlengine::cppSignalAndEval() { ObjectCaller objectCaller; QQmlEngine engine; - engine.rootContext()->setContextProperty(QLatin1Literal("CallerCpp"), &objectCaller); + engine.rootContext()->setContextProperty(QLatin1String("CallerCpp"), &objectCaller); QQmlComponent c(&engine); c.setData("import QtQuick 2.9\n" "Item {\n" @@ -1015,6 +1020,65 @@ void tst_qqmlengine::singletonInstance() } { + int data = 30; + auto id = qmlRegisterSingletonType<CppSingleton>("Qt.test",1,0,"CapturingLambda",[data](QQmlEngine*, QJSEngine*){ // register qobject singleton with capturing lambda + auto o = new CppSingleton; + o->setProperty("data", data); + return o; + }); + QJSValue value = engine.singletonInstance<QJSValue>(id); + QVERIFY(!value.isUndefined()); + QVERIFY(value.isQObject()); + QObject *instance = value.toQObject(); + QVERIFY(instance); + QCOMPARE(instance->metaObject()->className(), "CppSingleton"); + QCOMPARE(instance->property("data"), data); + } + { + qmlRegisterSingletonType<CppSingleton>("Qt.test",1,0,"NotAmbiguous", [](QQmlEngine* qeng, QJSEngine* jeng) -> QObject* {return CppSingleton::create(qeng, jeng);}); // test that overloads for qmlRegisterSingleton are not ambiguous + } + { + // Register QObject* directly + CppSingleton single; + int id = qmlRegisterSingletonInstance("Qt.test", 1, 0, "CppOwned", + &single); + QQmlEngine engine2; + CppSingleton *singlePtr = engine2.singletonInstance<CppSingleton *>(id); + QVERIFY(singlePtr); + QCOMPARE(&single, singlePtr); + QVERIFY(engine2.objectOwnership(singlePtr) == QQmlEngine::CppOwnership); + } + + { + CppSingleton single; + QQmlEngine engineA; + QQmlEngine engineB; + int id = qmlRegisterSingletonInstance("Qt.test", 1, 0, "CppOwned", &single); + auto singlePtr = engineA.singletonInstance<CppSingleton *>(id); + QVERIFY(singlePtr); + singlePtr = engineA.singletonInstance<CppSingleton *>(id); // accessing the singleton multiple times from the same engine is fine + QVERIFY(singlePtr); + QTest::ignoreMessage(QtMsgType::QtCriticalMsg, "<Unknown File>: qmlRegisterSingletonType(): \"CppOwned\" is not available because the callback function returns a null pointer."); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: Singleton registered by registerSingletonInstance must only be accessed from one engine"); + QCOMPARE(&single, singlePtr); + auto noSinglePtr = engineB.singletonInstance<CppSingleton *>(id); + QVERIFY(!noSinglePtr); + } + + { + CppSingleton single; + QThread newThread {}; + single.moveToThread(&newThread); + QCOMPARE(single.thread(), &newThread); + QQmlEngine engineB; + int id = qmlRegisterSingletonInstance("Qt.test", 1, 0, "CppOwned", &single); + QTest::ignoreMessage(QtMsgType::QtCriticalMsg, "<Unknown File>: qmlRegisterSingletonType(): \"CppOwned\" is not available because the callback function returns a null pointer."); + QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: Registered object must live in the same thread as the engine it was registered with"); + auto noSinglePtr = engineB.singletonInstance<CppSingleton *>(id); + QVERIFY(!noSinglePtr); + } + + { // Invalid types QJSValue value; value = engine.singletonInstance<QJSValue>(-4711); @@ -1043,6 +1107,16 @@ void tst_qqmlengine::singletonInstance() SomeQObjectClass * instance = engine.singletonInstance<SomeQObjectClass*>(cppSingletonTypeId); QVERIFY(!instance); } + + { + // deleted object + auto dayfly = new QObject{}; + auto id = qmlRegisterSingletonInstance("Vanity", 1, 0, "Dayfly", dayfly); + delete dayfly; + QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: The registered singleton has already been deleted. Ensure that it outlives the engine."); + QObject *instance = engine.singletonInstance<QObject*>(id); + QVERIFY(!instance); + } } void tst_qqmlengine::aggressiveGc() |