blob: 1c50531d57bd3f185d1c9ca88095871e06575c2d (
plain)
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"
|