summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorSvenn-Arne Dragly <s@dragly.com>2019-02-21 15:54:02 +0100
committerJani Heikkinen <jani.heikkinen@qt.io>2019-02-22 15:00:03 +0000
commite5b256effa320fb7806205f5a37a4dc1943175f0 (patch)
tree0a52d77a881588881bfd03f08414ac8c013c624c /tests
parenta48635f21fa68c5033ebe0d6832d405acfcca937 (diff)
Fix broken creation order for nodes used as properties
Otherwise, child nodes may be constructed before their parents and their node creation changes will arrive at the backend out-of-order. This could result in a child node referencing a parent that we have not yet received a creation change for. Also add a unit test to take this case into account. Change-Id: I26b29e63863d1686e7b9239c63297c7e6c341f4e Task-number: QTBUG-73986 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/core/nodes/tst_nodes.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp
index 75d7a7799..accd20ceb 100644
--- a/tests/auto/core/nodes/tst_nodes.cpp
+++ b/tests/auto/core/nodes/tst_nodes.cpp
@@ -82,6 +82,7 @@ private slots:
void checkConstructionSetParentMix(); // QTBUG-60612
void checkConstructionWithParent();
+ void checkConstructionWithNonRootParent(); // QTBUG-73986
void checkConstructionAsListElement();
void checkSceneIsSetOnConstructionWithParent(); // QTBUG-69352
@@ -1119,6 +1120,61 @@ void tst_Nodes::checkConstructionWithParent()
QCOMPARE(propertyEvent->value().value<Qt3DCore::QNodeId>(), node->id());
}
+void tst_Nodes::checkConstructionWithNonRootParent()
+{
+ // GIVEN
+ ObserverSpy spy;
+ Qt3DCore::QScene scene;
+ QScopedPointer<MyQNode> root(new MyQNode());
+
+ // WHEN
+ root->setArbiterAndScene(&spy, &scene);
+ root->setSimulateBackendCreated(true);
+ QScopedPointer<MyQNode> parent(new MyQNode(root.data()));
+
+ // THEN
+ QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->scene() != nullptr);
+ QVERIFY(Qt3DCore::QNodePrivate::get(parent.data())->scene() != nullptr);
+
+ // WHEN we create a child and then set it as a Node* property
+ auto *child = new MyQNode(parent.data());
+ root->setNodeProperty(child);
+
+ // THEN we should get
+ // - one creation change for parent,
+ // - one creation change for child,
+ // - one child added change for root->parent,
+ // - and one property change event,
+ // in that order.
+ QCoreApplication::processEvents();
+ QCOMPARE(root->children().count(), 1);
+ QCOMPARE(parent->children().count(), 1);
+
+ QCOMPARE(spy.events.size(), 4); // 2 creation changes, 1 child added changes, 1 property change
+
+ // Ensure first event is parent node's creation change
+ const auto parentCreationEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
+ QVERIFY(!parentCreationEvent.isNull());
+ QCOMPARE(parentCreationEvent->subjectId(), parent->id());
+
+ const auto childCreationEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
+ QVERIFY(!childCreationEvent.isNull());
+ QCOMPARE(childCreationEvent->subjectId(), child->id());
+
+ const auto parentNewChildEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
+ QVERIFY(!parentNewChildEvent.isNull());
+ QCOMPARE(parentNewChildEvent->subjectId(), root->id());
+ QCOMPARE(parentNewChildEvent->propertyName(), "children");
+ QCOMPARE(parentNewChildEvent->addedNodeId(), parent->id());
+
+ // Ensure second and last event is property set change
+ const auto propertyEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyUpdatedChange>();
+ QVERIFY(!propertyEvent.isNull());
+ QCOMPARE(propertyEvent->subjectId(), root->id());
+ QCOMPARE(propertyEvent->propertyName(), "nodeProperty");
+ QCOMPARE(propertyEvent->value().value<Qt3DCore::QNodeId>(), child->id());
+}
+
void tst_Nodes::checkConstructionAsListElement()
{
// GIVEN