summaryrefslogtreecommitdiffstats
path: root/tests/auto/core/nodes/tst_nodes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/core/nodes/tst_nodes.cpp')
-rw-r--r--tests/auto/core/nodes/tst_nodes.cpp147
1 files changed, 147 insertions, 0 deletions
diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp
index 3f7fb4a75..dad66c5d5 100644
--- a/tests/auto/core/nodes/tst_nodes.cpp
+++ b/tests/auto/core/nodes/tst_nodes.cpp
@@ -73,6 +73,7 @@ private slots:
void checkParentChangeToNull();
void checkParentChangeToOtherParent();
void checkParentChangeFromExistingBackendParentToNewlyCreatedParent();
+ void checkBackendNodesCreatedFromTopDown(); //QTBUG-74106
void removingSingleChildNodeFromNode();
void removingMultipleChildNodesFromNode();
@@ -81,6 +82,7 @@ private slots:
void removingChildEntitiesFromNode();
void checkConstructionSetParentMix(); // QTBUG-60612
+ void checkParentingQEntityToQNode(); // QTBUG-73905
void checkConstructionWithParent();
void checkConstructionWithNonRootParent(); // QTBUG-73986
void checkConstructionAsListElement();
@@ -901,6 +903,85 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent()
}
}
+//Test creation changes happen for an entire subtree at once, starting at the top
+// so that parents are always created before their children. Even if the front-end
+// nodes are constructed in a different order.
+void tst_Nodes::checkBackendNodesCreatedFromTopDown()
+{
+ // GIVEN
+ Qt3DCore::QScene scene;
+ ObserverSpy spy;
+ QScopedPointer<MyQNode> root(new MyQNode());
+ root->setArbiterAndScene(&spy, &scene);
+ QScopedPointer<Qt3DCore::QNode> parentWithBackend(new MyQNode(root.data()));
+
+ // create parent backend node
+ QCoreApplication::processEvents();
+ QVERIFY(Qt3DCore::QNodePrivate::get(parentWithBackend.get())->m_hasBackendNode);
+
+ // WHEN -> creating 3 nodes and setting one as a property on the other
+ // child2 is set as property on child1, but is created AFTER child1
+ spy.events.clear();
+ MyQNode *dummyParent(new MyQNode(parentWithBackend.data()));
+ MyQNode *child1(new MyQNode(parentWithBackend.data()));
+ MyQNode *child2(new MyQNode(dummyParent));
+ child2->setNodeProperty(child1);
+
+ // THEN - we should have no events because the new nodes have no backend yet
+ QCOMPARE(spy.events.count(), 0);
+
+ // WHEN - create the backend nodes
+ QCoreApplication::processEvents();
+
+ // THEN
+ QVERIFY(dummyParent->parent() == parentWithBackend.data());
+ QVERIFY(child1->parent() == parentWithBackend.data());
+ QVERIFY(child2->parent() == dummyParent);
+
+ // THEN
+ QCOMPARE(spy.events.size(), 5);
+ // 2 node creation change for dummyParent subtree (dummyParent and child2)
+ // 1 node added to children change (dummyParent to parent)
+ // 1 node created change for child1
+ // 1 node added to children change (child1 to parent)
+
+ {
+ // 1st event: dummyParent creation
+ const auto event1 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
+ QVERIFY(!event1.isNull());
+ QCOMPARE(event1->type(), Qt3DCore::NodeCreated);
+ QCOMPARE(event1->parentId(), parentWithBackend->id());
+ QCOMPARE(event1->subjectId(), dummyParent->id());
+
+ // 2nd event: child2 creation (even though we constructed child1 first)
+ const auto event2 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
+ QVERIFY(!event2.isNull());
+ QCOMPARE(event2->type(), Qt3DCore::NodeCreated);
+ QCOMPARE(event2->parentId(), dummyParent->id());
+ QCOMPARE(event2->subjectId(), child2->id());
+
+ // 3rd event: dummyParent added to parent
+ const auto event3 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
+ QCOMPARE(event3->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(event3->addedNodeId(), dummyParent->id());
+ QCOMPARE(event3->subjectId(), parentWithBackend->id());
+
+ // 4th event: child1 creation
+ const auto event4 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
+ QVERIFY(!event4.isNull());
+ QCOMPARE(event4->type(), Qt3DCore::NodeCreated);
+ QCOMPARE(event4->parentId(), parentWithBackend->id());
+ QCOMPARE(event4->subjectId(), child1->id());
+
+ // 5th event: child 1 added to parent
+ const auto event5 = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
+ QCOMPARE(event5->type(), Qt3DCore::PropertyValueAdded);
+ QCOMPARE(event5->addedNodeId(), child1->id());
+ QCOMPARE(event5->subjectId(), parentWithBackend->id());
+ }
+}
+
+
void tst_Nodes::removingSingleChildNodeFromNode()
{
// GIVEN
@@ -1079,6 +1160,72 @@ void tst_Nodes::checkConstructionSetParentMix()
QCOMPARE(lastEvent->addedNodeId(), subTreeRoot->id());
}
+void tst_Nodes::checkParentingQEntityToQNode()
+{
+ // GIVEN
+ ObserverSpy spy;
+ Qt3DCore::QScene scene;
+ QScopedPointer<MyQNode> root(new MyQNode());
+
+ // WHEN
+ root->setArbiterAndScene(&spy, &scene);
+ root->setSimulateBackendCreated(true);
+
+ // THEN
+ QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->scene() != nullptr);
+
+ // WHEN
+ auto subTreeRoot = new Qt3DCore::QEntity(root.data());
+ auto childEntity = new Qt3DCore::QEntity(subTreeRoot);
+ auto childNode = new Qt3DCore::QNode(subTreeRoot);
+
+ // THEN
+ QCoreApplication::processEvents();
+
+ // Ensure first event is subTreeRoot creation
+ const Qt3DCore::QNodeCreatedChangeBasePtr firstEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
+ QVERIFY(!firstEvent.isNull());
+ QCOMPARE(firstEvent->subjectId(), subTreeRoot->id());
+ QCOMPARE(firstEvent->parentId(), root->id());
+
+ // Ensure 2nd event is childEntity creation
+ const Qt3DCore::QNodeCreatedChangeBasePtr secondEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
+ QVERIFY(!secondEvent.isNull());
+ QCOMPARE(secondEvent->subjectId(), childEntity->id());
+ QCOMPARE(secondEvent->parentId(), subTreeRoot->id());
+
+ // Ensure 3rd event is childNode creation
+ const Qt3DCore::QNodeCreatedChangeBasePtr thirdEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QNodeCreatedChangeBase>();
+ QVERIFY(!thirdEvent.isNull());
+ QCOMPARE(thirdEvent->subjectId(), childNode->id());
+ QCOMPARE(thirdEvent->parentId(), subTreeRoot->id());
+
+
+ // WHEN we reparent the childEntity to the childNode (QNode)
+
+ spy.events.clear();
+ childEntity->setParent(childNode);
+ // THEN we should get
+ // - one child removed change for childEntity->subTreeRoot,
+ // - one child added change for childEntity->childNode,
+ // - and one property updated event specifying the correct QEntity parent (subTreeRoot)
+ QCOMPARE(spy.events.size(), 3);
+
+ const auto removedEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeRemovedChange>();
+ QVERIFY(!removedEvent.isNull());
+ QCOMPARE(removedEvent->subjectId(), subTreeRoot->id());
+
+ const auto addedEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyNodeAddedChange>();
+ QVERIFY(!addedEvent.isNull());
+ QCOMPARE(addedEvent->subjectId(), childNode->id());
+
+ const auto parentChangeEvent = spy.events.takeFirst().change().dynamicCast<Qt3DCore::QPropertyUpdatedChange>();
+ QVERIFY(!parentChangeEvent.isNull());
+ QCOMPARE(parentChangeEvent->subjectId(), childEntity->id());
+ QCOMPARE(parentChangeEvent->propertyName(), "parentEntityUpdated");
+ QCOMPARE(parentChangeEvent->value().value<Qt3DCore::QNodeId>(), subTreeRoot->id());
+}
+
void tst_Nodes::checkConstructionWithParent()
{
// GIVEN