diff options
Diffstat (limited to 'tests/auto/qml/qqmlengine/tst_qqmlengine.cpp')
-rw-r--r-- | tests/auto/qml/qqmlengine/tst_qqmlengine.cpp | 146 |
1 files changed, 108 insertions, 38 deletions
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index 895513d822..3c25d29dfb 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// 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 <QQmlEngine> #include <QQmlContext> @@ -36,8 +36,10 @@ public: private slots: void initTestCase() override; void rootContext(); +#if QT_CONFIG(qml_network) void networkAccessManager(); void synchronousNetworkAccessManager(); +#endif void baseUrl(); void contextForObject(); void offlineStoragePath(); @@ -67,6 +69,7 @@ private slots: void cachedGetterLookup_qtbug_75335(); void createComponentOnSingletonDestruction(); void uiLanguage(); + void markCurrentFunctionAsTranslationBinding(); void executeRuntimeFunction(); void captureQProperty(); void listWrapperAsListReference(); @@ -77,6 +80,9 @@ private slots: void qtNamespaceInQtObject(); void nativeModuleImport(); void lockedRootObject(); + void crossReferencingSingletonsDeletion(); + void bindingInstallUseAfterFree(); + void variantListQJsonConversion(); public slots: QObject *createAQObjectForOwnershipTest () @@ -149,6 +155,7 @@ void tst_qqmlengine::rootContext() QVERIFY(!engine.rootContext()->parentContext()); } +#if QT_CONFIG(qml_network) class NetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory { public: @@ -164,21 +171,19 @@ public: void tst_qqmlengine::networkAccessManager() { - QQmlEngine *engine = new QQmlEngine; + std::unique_ptr<QQmlEngine> engine = std::make_unique<QQmlEngine>(); // Test QQmlEngine created manager QPointer<QNetworkAccessManager> manager = engine->networkAccessManager(); QVERIFY(manager != nullptr); - delete engine; // Test factory created manager - engine = new QQmlEngine; + engine.reset(new QQmlEngine); NetworkAccessManagerFactory factory; engine->setNetworkAccessManagerFactory(&factory); QCOMPARE(engine->networkAccessManagerFactory(), &factory); QNetworkAccessManager *engineNam = engine->networkAccessManager(); // calls NetworkAccessManagerFactory::create() QCOMPARE(engineNam, factory.manager); - delete engine; } class ImmediateReply : public QNetworkReply { @@ -226,7 +231,7 @@ void tst_qqmlengine::synchronousNetworkAccessManager() // reply is finished, so should not be in loading state. QVERIFY(!c.isLoading()); } - +#endif void tst_qqmlengine::baseUrl() { @@ -267,7 +272,7 @@ void tst_qqmlengine::baseUrl() void tst_qqmlengine::contextForObject() { - QQmlEngine *engine = new QQmlEngine; + std::unique_ptr<QQmlEngine> engine = std::make_unique<QQmlEngine>(); // Test null-object QVERIFY(!QQmlEngine::contextForObject(nullptr)); @@ -294,7 +299,7 @@ void tst_qqmlengine::contextForObject() QCOMPARE(QQmlEngine::contextForObject(&object), engine->rootContext()); // Delete context - delete engine; engine = nullptr; + engine.reset(); QVERIFY(!QQmlEngine::contextForObject(&object)); } @@ -372,10 +377,9 @@ void tst_qqmlengine::clearComponentCache() // Test "test" property { QQmlComponent component(&engine, fileUrl); - QObject *obj = component.create(); - QVERIFY(obj != nullptr); + std::unique_ptr<QObject> obj { component.create() }; + QVERIFY(obj.get() != nullptr); QCOMPARE(obj->property("test").toInt(), 10); - delete obj; } // Modify qml file @@ -395,10 +399,9 @@ void tst_qqmlengine::clearComponentCache() // Test cache hit { QQmlComponent component(&engine, fileUrl); - QObject *obj = component.create(); - QVERIFY(obj != nullptr); + std::unique_ptr<QObject> obj { component.create() }; + QVERIFY(obj.get() != nullptr); QCOMPARE(obj->property("test").toInt(), 10); - delete obj; } // Clear cache @@ -407,10 +410,9 @@ void tst_qqmlengine::clearComponentCache() // Test cache refresh { QQmlComponent component(&engine, fileUrl); - QObject *obj = component.create(); - QVERIFY(obj != nullptr); + std::unique_ptr<QObject> obj { component.create() }; + QVERIFY(obj.get() != nullptr); QCOMPARE(obj->property("test").toInt(), 11); - delete obj; } // Regular Synchronous loading will leave us with an event posted @@ -437,7 +439,7 @@ public: // There might be JS function objects around that hold a last ref to the compilation unit that's // keeping the type compilation data (CompilationUnit) around. Let's collect them as well so that // trim works well. - engine->collectGarbage(); + gc(*engine); engine->trimComponentCache(); } @@ -496,22 +498,25 @@ void tst_qqmlengine::trimComponentCache_data() // empty apart from their inherited elements, and those that define new properties. // For each there are five types of composition: extension, aggregation, // aggregation via component, property and object-created-via-transient-component. - foreach (const QString &test, (QStringList() << "EmptyComponent" - << "VMEComponent" - << "EmptyExtendEmptyComponent" - << "VMEExtendEmptyComponent" - << "EmptyExtendVMEComponent" - << "VMEExtendVMEComponent" - << "EmptyAggregateEmptyComponent" - << "VMEAggregateEmptyComponent" - << "EmptyAggregateVMEComponent" - << "VMEAggregateVMEComponent" - << "EmptyPropertyEmptyComponent" - << "VMEPropertyEmptyComponent" - << "EmptyPropertyVMEComponent" - << "VMEPropertyVMEComponent" - << "VMETransientEmptyComponent" - << "VMETransientVMEComponent")) { + const QStringList components = { + "EmptyComponent", + "VMEComponent", + "EmptyExtendEmptyComponent", + "VMEExtendEmptyComponent", + "EmptyExtendVMEComponent", + "VMEExtendVMEComponent", + "EmptyAggregateEmptyComponent", + "VMEAggregateEmptyComponent", + "EmptyAggregateVMEComponent", + "VMEAggregateVMEComponent", + "EmptyPropertyEmptyComponent", + "VMEPropertyEmptyComponent", + "EmptyPropertyVMEComponent", + "VMEPropertyVMEComponent", + "VMETransientEmptyComponent", + "VMETransientVMEComponent", + }; + for (const QString &test : components) { // For these cases, we first test that the component instance keeps the components // referenced, and then that the instantiated object keeps the components referenced for (int i = 1; i <= 2; ++i) { @@ -903,7 +908,7 @@ void tst_qqmlengine::qtqmlModule() QFETCH(QString, expectedError); QFETCH(QStringList, expectedWarnings); - foreach (const QString &w, expectedWarnings) + for (const QString &w : std::as_const(expectedWarnings)) QTest::ignoreMessage(QtWarningMsg, qPrintable(w)); QQmlEngine e; @@ -1272,9 +1277,9 @@ void tst_qqmlengine::singletonInstance() { // deleted object - auto dayfly = new Dayfly{}; - auto id = qmlRegisterSingletonInstance("Vanity", 1, 0, "Dayfly", dayfly); - delete dayfly; + auto dayfly = std::make_unique<Dayfly>(); + auto id = qmlRegisterSingletonInstance("Vanity", 1, 0, "Dayfly", dayfly.get()); + dayfly.reset(); 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); @@ -1378,6 +1383,35 @@ void tst_qqmlengine::uiLanguage() } } +class I18nAwareClass : public QObject { + Q_OBJECT + QML_NAMED_ELEMENT(I18nAware) + + Q_PROPERTY(QString text READ text NOTIFY textChanged) +signals: + void textChanged(); +public: + int counter = 0; + + QString text() + { + if (auto engine = qmlEngine(this)) + engine->markCurrentFunctionAsTranslationBinding(); + return QLatin1String("Hello, %1").arg(QString::number(counter++)); + } +}; + +void tst_qqmlengine::markCurrentFunctionAsTranslationBinding() +{ + QQmlEngine engine; + qmlRegisterTypesAndRevisions<I18nAwareClass>("i18ntest", 1); + QQmlComponent comp(&engine, testFileUrl("markCurrentFunctionAsTranslationBinding.qml")); + std::unique_ptr<QObject> root { comp.create() }; + QCOMPARE(root->property("result"), "Hello, 0"); + engine.retranslate(); + QCOMPARE(root->property("result"), "Hello, 1"); +} + void tst_qqmlengine::executeRuntimeFunction() { QQmlEngine engine; @@ -1683,6 +1717,42 @@ void tst_qqmlengine::lockedRootObject() QCOMPARE(o->property("defineProperty2").toBool(), false); } +void tst_qqmlengine::crossReferencingSingletonsDeletion() +{ + QQmlEngine engine; + engine.addImportPath(testFileUrl("crossReferencingSingletonsDeletion").url()); + QQmlComponent c(&engine, testFileUrl("crossReferencingSingletonsDeletion/Module/Main.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + + std::unique_ptr<QObject> o{ c.create() }; + QVERIFY(o); + QCOMPARE(o->property("s").toString(), "SingletonA"); +} + +void tst_qqmlengine::bindingInstallUseAfterFree() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("bindingInstallUseAfterFree.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + std::unique_ptr<QObject> o{ c.create() }; + QVERIFY(o); +} + +void tst_qqmlengine::variantListQJsonConversion() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("variantListQJsonConversion.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + + QTest::ignoreMessage(QtMsgType::QtDebugMsg, R"(["cpp","variant","list"])"); + QTest::ignoreMessage(QtMsgType::QtDebugMsg, R"({"test":["cpp","variant","list"]})"); + QTest::ignoreMessage(QtMsgType::QtDebugMsg, + R"([{"objectName":"o0"},{"objectName":"o1"},{"objectName":"o2"}])"); + + QScopedPointer<QObject> o(c.create()); + QVERIFY(o); +} + QTEST_MAIN(tst_qqmlengine) #include "tst_qqmlengine.moc" |