summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp')
-rw-r--r--tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp443
1 files changed, 443 insertions, 0 deletions
diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
index 6598a74e31..b048f9c2f0 100644
--- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
@@ -193,6 +193,15 @@ private slots:
void setPropertyAfterRestore();
void transitionWithNoTarget_data();
void transitionWithNoTarget();
+
+ void restorePropertiesSimple();
+ void restoreProperties2();
+ void restoreProperties3();
+ void restoreProperties4();
+ void restorePropertiesSelfTransition();
+ void changeStateWhileAnimatingProperty();
+ void propertiesAreAssignedBeforeEntryCallbacks_data();
+ void propertiesAreAssignedBeforeEntryCallbacks();
};
class TestState : public QState
@@ -4187,5 +4196,439 @@ void tst_QStateMachine::transitionWithNoTarget()
delete object;
}
+class PropertyObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int prop READ prop WRITE setProp)
+public:
+ PropertyObject(QObject *parent = 0)
+ : QObject(parent), m_propValue(0), m_propWriteCount(0)
+ {}
+ int prop() const { return m_propValue; }
+ void setProp(int value) { m_propValue = value; ++m_propWriteCount; }
+ int propWriteCount() const { return m_propWriteCount; }
+private:
+ int m_propValue;
+ int m_propWriteCount;
+};
+
+void tst_QStateMachine::restorePropertiesSimple()
+{
+ QStateMachine machine;
+ machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
+
+ PropertyObject *po = new PropertyObject;
+ po->setProp(2);
+ QCOMPARE(po->propWriteCount(), 1);
+
+ QState *s1 = new QState(&machine);
+ s1->assignProperty(po, "prop", 4);
+ machine.setInitialState(s1);
+
+ QState *s2 = new QState(&machine);
+ s1->addTransition(new EventTransition(QEvent::User, s2));
+
+ QState *s3 = new QState(&machine);
+ s3->assignProperty(po, "prop", 6);
+ s2->addTransition(new EventTransition(QEvent::User, s3));
+
+ QState *s4 = new QState(&machine);
+ s4->assignProperty(po, "prop", 8);
+ s3->addTransition(new EventTransition(QEvent::User, s4));
+
+ QState *s5 = new QState(&machine);
+ s4->addTransition(new EventTransition(QEvent::User, s5));
+
+ QState *s6 = new QState(&machine);
+ s5->addTransition(new EventTransition(QEvent::User, s6));
+
+ machine.start();
+
+ QTRY_VERIFY(machine.configuration().contains(s1));
+ QCOMPARE(po->propWriteCount(), 2);
+ QCOMPARE(po->prop(), 4);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s2));
+ QCOMPARE(po->propWriteCount(), 3);
+ QCOMPARE(po->prop(), 2); // restored
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s3));
+ QCOMPARE(po->propWriteCount(), 4);
+ QCOMPARE(po->prop(), 6);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s4));
+ QCOMPARE(po->propWriteCount(), 5);
+ QCOMPARE(po->prop(), 8);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s5));
+ QCOMPARE(po->propWriteCount(), 6);
+ QCOMPARE(po->prop(), 2); // restored
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s6));
+ QCOMPARE(po->propWriteCount(), 6);
+
+ delete po;
+}
+
+void tst_QStateMachine::restoreProperties2()
+{
+ QStateMachine machine;
+ machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
+
+ PropertyObject *po = new PropertyObject;
+ po->setProp(2);
+ QCOMPARE(po->propWriteCount(), 1);
+
+ QState *s1 = new QState(&machine);
+ s1->assignProperty(po, "prop", 4);
+ machine.setInitialState(s1);
+
+ QState *s11 = new QState(s1);
+ s1->setInitialState(s11);
+
+ QState *s12 = new QState(s1);
+ s11->addTransition(new EventTransition(QEvent::User, s12));
+
+ QState *s13 = new QState(s1);
+ s13->assignProperty(po, "prop", 6);
+ s12->addTransition(new EventTransition(QEvent::User, s13));
+
+ QState *s14 = new QState(s1);
+ s14->assignProperty(po, "prop", 8);
+ s13->addTransition(new EventTransition(QEvent::User, s14));
+
+ QState *s15 = new QState(s1);
+ s14->addTransition(new EventTransition(QEvent::User, s15));
+
+ QState *s16 = new QState(s1);
+ s15->addTransition(new EventTransition(QEvent::User, s16));
+
+ QState *s2 = new QState(&machine);
+ s2->assignProperty(po, "prop", 10);
+ s16->addTransition(new EventTransition(QEvent::User, s2));
+
+ QState *s3 = new QState(&machine);
+ s2->addTransition(new EventTransition(QEvent::User, s3));
+
+ machine.start();
+
+ QTRY_VERIFY(machine.configuration().contains(s11));
+ QCOMPARE(po->propWriteCount(), 2);
+ QCOMPARE(po->prop(), 4);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s12));
+ QCOMPARE(po->propWriteCount(), 2);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s13));
+ QCOMPARE(po->propWriteCount(), 3);
+ QCOMPARE(po->prop(), 6);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s14));
+ QCOMPARE(po->propWriteCount(), 4);
+ QCOMPARE(po->prop(), 8);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s15));
+ QCOMPARE(po->propWriteCount(), 5);
+ QCOMPARE(po->prop(), 4); // restored s1
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s16));
+ QCOMPARE(po->propWriteCount(), 5);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s2));
+ QCOMPARE(po->propWriteCount(), 6);
+ QCOMPARE(po->prop(), 10);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s3));
+ QCOMPARE(po->propWriteCount(), 7);
+ QCOMPARE(po->prop(), 2); // restored original
+
+ delete po;
+}
+
+void tst_QStateMachine::restoreProperties3()
+{
+ QStateMachine machine;
+ machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
+
+ PropertyObject *po = new PropertyObject;
+ po->setProp(2);
+ QCOMPARE(po->propWriteCount(), 1);
+
+ QState *s1 = new QState(&machine);
+ s1->assignProperty(po, "prop", 4);
+ machine.setInitialState(s1);
+
+ QState *s11 = new QState(s1);
+ s11->assignProperty(po, "prop", 6);
+ s1->setInitialState(s11);
+
+ QState *s12 = new QState(s1);
+ s11->addTransition(new EventTransition(QEvent::User, s12));
+
+ QState *s13 = new QState(s1);
+ s13->assignProperty(po, "prop", 8);
+ s12->addTransition(new EventTransition(QEvent::User, s13));
+
+ QState *s2 = new QState(&machine);
+ s13->addTransition(new EventTransition(QEvent::User, s2));
+
+ machine.start();
+
+ QTRY_VERIFY(machine.configuration().contains(s11));
+ QCOMPARE(po->propWriteCount(), 3);
+ QCOMPARE(po->prop(), 6); // s11
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s12));
+ QCOMPARE(po->propWriteCount(), 4);
+ QCOMPARE(po->prop(), 4); // restored s1
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s13));
+ QCOMPARE(po->propWriteCount(), 5);
+ QCOMPARE(po->prop(), 8);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s2));
+ QCOMPARE(po->propWriteCount(), 6);
+ QCOMPARE(po->prop(), 2); // restored original
+
+ delete po;
+}
+
+// QTBUG-20362
+void tst_QStateMachine::restoreProperties4()
+{
+ QStateMachine machine;
+ machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
+
+ PropertyObject *po1 = new PropertyObject;
+ po1->setProp(2);
+ QCOMPARE(po1->propWriteCount(), 1);
+ PropertyObject *po2 = new PropertyObject;
+ po2->setProp(4);
+ QCOMPARE(po2->propWriteCount(), 1);
+
+ QState *s1 = new QState(&machine);
+ s1->setChildMode(QState::ParallelStates);
+ machine.setInitialState(s1);
+
+ QState *s11 = new QState(s1);
+ QState *s111 = new QState(s11);
+ s111->assignProperty(po1, "prop", 6);
+ s11->setInitialState(s111);
+
+ QState *s112 = new QState(s11);
+ s112->assignProperty(po1, "prop", 8);
+ s111->addTransition(new EventTransition(QEvent::User, s112));
+
+ QState *s12 = new QState(s1);
+ QState *s121 = new QState(s12);
+ s121->assignProperty(po2, "prop", 10);
+ s12->setInitialState(s121);
+
+ QState *s122 = new QState(s12);
+ s122->assignProperty(po2, "prop", 12);
+ s121->addTransition(new EventTransition(static_cast<QEvent::Type>(QEvent::User+1), s122));
+
+ QState *s2 = new QState(&machine);
+ s112->addTransition(new EventTransition(QEvent::User, s2));
+
+ machine.start();
+
+ QTRY_VERIFY(machine.configuration().contains(s1));
+ QVERIFY(machine.configuration().contains(s11));
+ QVERIFY(machine.configuration().contains(s111));
+ QVERIFY(machine.configuration().contains(s12));
+ QVERIFY(machine.configuration().contains(s121));
+ QCOMPARE(po1->propWriteCount(), 2);
+ QCOMPARE(po1->prop(), 6);
+ QCOMPARE(po2->propWriteCount(), 2);
+ QCOMPARE(po2->prop(), 10);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s112));
+ QCOMPARE(po1->propWriteCount(), 3);
+ QCOMPARE(po1->prop(), 8);
+ QCOMPARE(po2->propWriteCount(), 2);
+
+ machine.postEvent(new QEvent(static_cast<QEvent::Type>(QEvent::User+1)));
+ QTRY_VERIFY(machine.configuration().contains(s122));
+ QCOMPARE(po1->propWriteCount(), 3);
+ QCOMPARE(po2->propWriteCount(), 3);
+ QCOMPARE(po2->prop(), 12);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s2));
+ QCOMPARE(po1->propWriteCount(), 4);
+ QCOMPARE(po1->prop(), 2); // restored original
+ QCOMPARE(po2->propWriteCount(), 4);
+ QCOMPARE(po2->prop(), 4); // restored original
+
+ delete po1;
+ delete po2;
+}
+
+void tst_QStateMachine::restorePropertiesSelfTransition()
+{
+ QStateMachine machine;
+ machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
+
+ PropertyObject *po = new PropertyObject;
+ po->setProp(2);
+ QCOMPARE(po->propWriteCount(), 1);
+
+ QState *s1 = new QState(&machine);
+ s1->assignProperty(po, "prop", 4);
+ s1->addTransition(new EventTransition(QEvent::User, s1));
+ machine.setInitialState(s1);
+
+ QState *s2 = new QState(&machine);
+ s1->addTransition(new EventTransition(static_cast<QEvent::Type>(QEvent::User+1), s2));
+
+ machine.start();
+ QTRY_VERIFY(machine.configuration().contains(s1));
+ QCOMPARE(po->propWriteCount(), 2);
+ QCOMPARE(po->prop(), 4);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_COMPARE(po->propWriteCount(), 3);
+ QCOMPARE(po->prop(), 4);
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_COMPARE(po->propWriteCount(), 4);
+ QCOMPARE(po->prop(), 4);
+
+ machine.postEvent(new QEvent(static_cast<QEvent::Type>(QEvent::User+1)));
+ QTRY_VERIFY(machine.configuration().contains(s2));
+ QCOMPARE(po->propWriteCount(), 5);
+ QCOMPARE(po->prop(), 2); // restored
+
+ delete po;
+}
+
+void tst_QStateMachine::changeStateWhileAnimatingProperty()
+{
+ QStateMachine machine;
+ machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
+
+ QObject *o1 = new QObject;
+ o1->setProperty("x", 10.);
+ QObject *o2 = new QObject;
+ o2->setProperty("y", 20.);
+
+ QState *group = new QState(&machine);
+ machine.setInitialState(group);
+
+ QState *s0 = new QState(group);
+ group->setInitialState(s0);
+
+ QState *s1 = new QState(group);
+ s1->assignProperty(o1, "x", 15.);
+ QPropertyAnimation *a1 = new QPropertyAnimation(o1, "x", s1);
+ a1->setDuration(800);
+ machine.addDefaultAnimation(a1);
+ group->addTransition(new EventTransition(QEvent::User, s1));
+
+ QState *s2 = new QState(group);
+ s2->assignProperty(o2, "y", 25.);
+ QPropertyAnimation *a2 = new QPropertyAnimation(o2, "y", s2);
+ a2->setDuration(800);
+ machine.addDefaultAnimation(a2);
+ group->addTransition(new EventTransition(static_cast<QEvent::Type>(QEvent::User+1), s2));
+
+ machine.start();
+ QTRY_VERIFY(machine.configuration().contains(s0));
+
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s1));
+ QCOREAPPLICATION_EXEC(400);
+ machine.postEvent(new QEvent(static_cast<QEvent::Type>(QEvent::User+1)));
+ QTRY_VERIFY(machine.configuration().contains(s2));
+ QCOREAPPLICATION_EXEC(300);
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s1));
+ QCOREAPPLICATION_EXEC(200);
+ machine.postEvent(new QEvent(static_cast<QEvent::Type>(QEvent::User+1)));
+ QTRY_VERIFY(machine.configuration().contains(s2));
+ QCOREAPPLICATION_EXEC(100);
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s1));
+
+ QTRY_COMPARE(o1->property("x").toDouble(), 15.);
+ QTRY_COMPARE(o2->property("y").toDouble(), 20.);
+
+ delete o1;
+ delete o2;
+}
+
+class AssignPropertyTestState : public QState
+{
+ Q_OBJECT
+public:
+ AssignPropertyTestState(QState *parent = 0)
+ : QState(parent), onEntryPassed(false), enteredPassed(false)
+ { QObject::connect(this, SIGNAL(entered()), this, SLOT(onEntered())); }
+
+ virtual void onEntry(QEvent *)
+ { onEntryPassed = property("wasAssigned").toBool(); }
+
+ bool onEntryPassed;
+ bool enteredPassed;
+
+private Q_SLOTS:
+ void onEntered()
+ { enteredPassed = property("wasAssigned").toBool(); }
+};
+
+void tst_QStateMachine::propertiesAreAssignedBeforeEntryCallbacks_data()
+{
+ QTest::addColumn<int>("restorePolicy");
+ QTest::newRow("DontRestoreProperties") << int(QStateMachine::DontRestoreProperties);
+ QTest::newRow("RestoreProperties") << int(QStateMachine::RestoreProperties);
+}
+
+void tst_QStateMachine::propertiesAreAssignedBeforeEntryCallbacks()
+{
+ QFETCH(int, restorePolicy);
+
+ QStateMachine machine;
+ machine.setGlobalRestorePolicy(static_cast<QStateMachine::RestorePolicy>(restorePolicy));
+
+ AssignPropertyTestState *s1 = new AssignPropertyTestState(&machine);
+ s1->assignProperty(s1, "wasAssigned", true);
+ machine.setInitialState(s1);
+
+ AssignPropertyTestState *s2 = new AssignPropertyTestState(&machine);
+ s2->assignProperty(s2, "wasAssigned", true);
+ s1->addTransition(new EventTransition(QEvent::User, s2));
+
+ QVERIFY(!s1->property("wasAssigned").toBool());
+ machine.start();
+ QTRY_VERIFY(machine.configuration().contains(s1));
+
+ QVERIFY(s1->onEntryPassed);
+ QVERIFY(s1->enteredPassed);
+
+ QVERIFY(!s2->property("wasAssigned").toBool());
+ machine.postEvent(new QEvent(QEvent::User));
+ QTRY_VERIFY(machine.configuration().contains(s2));
+
+ QVERIFY(s2->onEntryPassed);
+ QVERIFY(s2->enteredPassed);
+}
+
QTEST_MAIN(tst_QStateMachine)
#include "tst_qstatemachine.moc"