1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
|
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtTest/qtest.h>
#include <QQmlEngine>
#include <QtQuick/qquickitem.h>
#include <QtQuickTemplates2/private/qquickdeferredexecute_p_p.h>
#include <QQmlIncubator>
class DeferredPropertyTester : public QObject
{
Q_OBJECT
Q_PROPERTY(QQuickItem *objectProperty READ objectProperty WRITE setObjectProperty NOTIFY objectChanged)
Q_CLASSINFO("DeferredPropertyNames", "objectProperty")
public:
DeferredPropertyTester() {}
QQuickItem *objectProperty() {
if (!m_object.wasExecuted()) {
quickBeginDeferred(this, "objectProperty", m_object);
quickCompleteDeferred(this, "objectProperty", m_object);
}
return m_object;
}
void setObjectProperty(QQuickItem *obj) {
if (m_object == obj)
return;
m_object = obj;
if (!m_object.isExecuting()) // first read
emit objectChanged();
}
signals:
void objectChanged();
private:
QQuickDeferredPointer<QQuickItem> m_object = nullptr;
};
class tst_qquickdeferred : public QQmlDataTest
{
Q_OBJECT
public:
tst_qquickdeferred() : QQmlDataTest(QT_QMLTEST_DATADIR) {}
private slots:
void noSpuriousBinding();
void abortedIncubation();
};
void tst_qquickdeferred::noSpuriousBinding() {
QTest::failOnWarning(QRegularExpression(QLatin1StringView(".*Binding loop detected.*")));
qmlRegisterType<DeferredPropertyTester>("test", 1, 0, "DeferredPropertyTester");
QQmlEngine engine;
QQmlComponent comp(&engine, testFileUrl("noSpuriousBinding.qml"));
std::unique_ptr<QObject> root(comp.create());
QVERIFY2(root, qPrintable(comp.errorString()));
root->setProperty("toggle", false);
}
// QTBUG-116828
// This test checks the case where we cancel incubation of a componet with a deferred property
// Components that have deferred properties should also provide an itemDestoryed method that
// that resets the deferred property to null to prevent issues with dangling pointers.
void tst_qquickdeferred::abortedIncubation()
{
QQmlEngine engine;
QQmlIncubationController controller;
engine.setIncubationController(&controller);
{
QQmlIncubator incubator;
QQmlComponent componet(&engine, testFileUrl("abortedIncubation.qml"));
componet.create(incubator);
controller.incubateFor(1);
incubator.clear(); // abort incubation (and dont crash)
}
}
QTEST_MAIN(tst_qquickdeferred)
#include "tst_qquickdeferred.moc"
|