aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp')
-rw-r--r--tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp106
1 files changed, 85 insertions, 21 deletions
diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
index 5f57b9ebb0..5999bc42e9 100644
--- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
+++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
@@ -33,6 +33,8 @@
#include <QQmlComponent>
#include <QQmlExpression>
#include <private/qqmlcontext_p.h>
+#include <private/qv4qmlcontext_p.h>
+#include <private/qv4object_p.h>
#include "../../shared/util.h"
class tst_qqmlcontext : public QQmlDataTest
@@ -47,6 +49,7 @@ private slots:
void engineMethod();
void parentContext();
void setContextProperty();
+ void setContextProperties();
void setContextObject();
void destruction();
void idAsContextProperty();
@@ -63,6 +66,7 @@ private slots:
void qobjectDerived();
void qtbug_49232();
void contextViaClosureAfterDestruction();
+ void contextLeak();
private:
QQmlEngine engine;
@@ -112,7 +116,7 @@ void tst_qqmlcontext::resolvedUrl()
QQmlContext ctxt2(ctxt);
QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl("http://www.qt-project.org/main2.qml"));
- delete ctxt; ctxt = 0;
+ delete ctxt; ctxt = nullptr;
QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl());
}
@@ -140,7 +144,7 @@ void tst_qqmlcontext::engineMethod()
QCOMPARE(ctxt3.engine(), engine);
QCOMPARE(ctxt4.engine(), engine);
- delete engine; engine = 0;
+ delete engine; engine = nullptr;
QCOMPARE(ctxt.engine(), engine);
QCOMPARE(ctxt2.engine(), engine);
@@ -152,7 +156,7 @@ void tst_qqmlcontext::parentContext()
{
QQmlEngine *engine = new QQmlEngine;
- QCOMPARE(engine->rootContext()->parentContext(), (QQmlContext *)0);
+ QCOMPARE(engine->rootContext()->parentContext(), (QQmlContext *)nullptr);
QQmlContext *ctxt = new QQmlContext(engine);
QQmlContext *ctxt2 = new QQmlContext(ctxt);
@@ -170,23 +174,23 @@ void tst_qqmlcontext::parentContext()
QCOMPARE(ctxt6->parentContext(), engine->rootContext());
QCOMPARE(ctxt7->parentContext(), engine->rootContext());
- delete ctxt2; ctxt2 = 0;
+ delete ctxt2; ctxt2 = nullptr;
QCOMPARE(ctxt->parentContext(), engine->rootContext());
- QCOMPARE(ctxt3->parentContext(), (QQmlContext *)0);
- QCOMPARE(ctxt4->parentContext(), (QQmlContext *)0);
+ QCOMPARE(ctxt3->parentContext(), (QQmlContext *)nullptr);
+ QCOMPARE(ctxt4->parentContext(), (QQmlContext *)nullptr);
QCOMPARE(ctxt5->parentContext(), ctxt);
QCOMPARE(ctxt6->parentContext(), engine->rootContext());
QCOMPARE(ctxt7->parentContext(), engine->rootContext());
- delete engine; engine = 0;
+ delete engine; engine = nullptr;
- QCOMPARE(ctxt->parentContext(), (QQmlContext *)0);
- QCOMPARE(ctxt3->parentContext(), (QQmlContext *)0);
- QCOMPARE(ctxt4->parentContext(), (QQmlContext *)0);
- QCOMPARE(ctxt5->parentContext(), (QQmlContext *)0);
- QCOMPARE(ctxt6->parentContext(), (QQmlContext *)0);
- QCOMPARE(ctxt7->parentContext(), (QQmlContext *)0);
+ QCOMPARE(ctxt->parentContext(), (QQmlContext *)nullptr);
+ QCOMPARE(ctxt3->parentContext(), (QQmlContext *)nullptr);
+ QCOMPARE(ctxt4->parentContext(), (QQmlContext *)nullptr);
+ QCOMPARE(ctxt5->parentContext(), (QQmlContext *)nullptr);
+ QCOMPARE(ctxt6->parentContext(), (QQmlContext *)nullptr);
+ QCOMPARE(ctxt7->parentContext(), (QQmlContext *)nullptr);
delete ctxt7;
delete ctxt6;
@@ -363,6 +367,32 @@ void tst_qqmlcontext::setContextProperty()
}
}
+void tst_qqmlcontext::setContextProperties()
+{
+ QQmlContext ctxt(&engine);
+
+ TestObject obj1;
+ obj1.setA(3345);
+ TestObject obj2;
+ obj2.setA(-19);
+
+ QVector<QQmlContext::PropertyPair> properties;
+
+ properties.append({QString("a"), QVariant(10)});
+ properties.append({QString("b"), QVariant(19)});
+ properties.append({QString("d"), QVariant::fromValue<TestObject*>(&obj2)});
+ properties.append({QString("c"), QVariant(QString("Hello World!"))});
+ properties.append({QString("e"), QVariant::fromValue<TestObject*>(&obj1)});
+
+ ctxt.setContextProperties(properties);
+
+ TEST_CONTEXT_PROPERTY(&ctxt, a, QVariant(10));
+ TEST_CONTEXT_PROPERTY(&ctxt, b, QVariant(19));
+ TEST_CONTEXT_PROPERTY(&ctxt, c, QVariant(QString("Hello World!")));
+ TEST_CONTEXT_PROPERTY(&ctxt, d.a, QVariant(-19));
+ TEST_CONTEXT_PROPERTY(&ctxt, e.a, QVariant(3345));
+}
+
void tst_qqmlcontext::setContextObject()
{
QQmlContext ctxt(&engine);
@@ -423,12 +453,12 @@ void tst_qqmlcontext::destruction()
QObject obj;
QQmlEngine::setContextForObject(&obj, ctxt);
- QQmlExpression expr(ctxt, 0, "a");
+ QQmlExpression expr(ctxt, nullptr, "a");
QCOMPARE(ctxt, QQmlEngine::contextForObject(&obj));
QCOMPARE(ctxt, expr.context());
- delete ctxt; ctxt = 0;
+ delete ctxt; ctxt = nullptr;
QCOMPARE(ctxt, QQmlEngine::contextForObject(&obj));
QCOMPARE(ctxt, expr.context());
@@ -477,7 +507,7 @@ void tst_qqmlcontext::readOnlyContexts()
QCOMPARE(context->contextProperty("hello"), QVariant());
QTest::ignoreMessage(QtWarningMsg, "QQmlContext: Cannot set context object for internal context.");
- context->setContextObject(0);
+ context->setContextObject(nullptr);
QCOMPARE(context->contextObject(), obj);
delete obj;
@@ -505,7 +535,7 @@ void tst_qqmlcontext::nameForObject()
component.setData("import QtQuick 2.0; QtObject { id: root; property QtObject o: QtObject { id: nested } }", QUrl());
QObject *o = component.create();
- QVERIFY(o != 0);
+ QVERIFY(o != nullptr);
QCOMPARE(qmlContext(o)->nameForObject(o), QString("root"));
QCOMPARE(qmlContext(o)->nameForObject(qvariant_cast<QObject*>(o->property("o"))), QString("nested"));
@@ -518,12 +548,12 @@ class DeleteCommand : public QObject
{
Q_OBJECT
public:
- DeleteCommand() : object(0) {}
+ DeleteCommand() : object(nullptr) {}
QObject *object;
public slots:
- void doCommand() { if (object) delete object; object = 0; }
+ void doCommand() { if (object) delete object; object = nullptr; }
};
// Calling refresh expressions would crash if an expression or context was deleted during
@@ -656,7 +686,7 @@ void tst_qqmlcontext::skipExpressionRefresh_qtbug_53431()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("qtbug_53431.qml"));
- QScopedPointer<QObject> object(component.create(0));
+ QScopedPointer<QObject> object(component.create(nullptr));
QVERIFY(!object.isNull());
QCOMPARE(object->property("value").toInt(), 1);
object->setProperty("value", 10);
@@ -683,7 +713,7 @@ void tst_qqmlcontext::evalAfterInvalidate()
QQmlComponent component(&engine, testFileUrl("evalAfterInvalidate.qml"));
QScopedPointer<QObject> o(component.create());
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QCoreApplication::processEvents();
}
@@ -751,6 +781,40 @@ void tst_qqmlcontext::contextViaClosureAfterDestruction()
QCOMPARE(subObject.toString(), QLatin1String("Error: Qt.createQmlObject(): Cannot create a component in an invalid context"));
}
+void tst_qqmlcontext::contextLeak()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("contextLeak.qml"));
+
+ QQmlGuardedContextData scriptContext;
+
+ {
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QCOMPARE(obj->property("value").toInt(), 42);
+
+ QQmlData *ddata = QQmlData::get(obj.data());
+ QVERIFY(ddata);
+ QQmlContextData *context = ddata->context;
+ QVERIFY(context);
+ QVERIFY(!context->importedScripts.isNullOrUndefined());
+ QCOMPARE(int(context->importedScripts.valueRef()->as<QV4::Object>()->getLength()), 1);
+
+ {
+ QV4::Scope scope(ddata->jsWrapper.engine());
+ QV4::ScopedValue scriptContextWrapper(scope);
+ scriptContextWrapper = context->importedScripts.valueRef()->as<QV4::Object>()->getIndexed(0);
+ scriptContext = scriptContextWrapper->as<QV4::QQmlContextWrapper>()->getContext();
+ }
+ }
+
+ engine.collectGarbage();
+
+ // Each time a JS file (non-pragma-shared) is imported, we create a QQmlContext(Data) for it.
+ // Make sure that context does not leak.
+ QVERIFY(scriptContext.isNull());
+}
+
QTEST_MAIN(tst_qqmlcontext)
#include "tst_qqmlcontext.moc"