aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qml/qqmlengine/tst_qqmlengine.cpp')
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp146
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"