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.cpp99
1 files changed, 89 insertions, 10 deletions
diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
index 605d1e7393..96d0a62f6b 100644
--- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
@@ -246,6 +246,7 @@ private slots:
void childModeConstructor();
void qtbug_44963();
+ void qtbug_44783();
};
class TestState : public QState
@@ -910,8 +911,11 @@ void tst_QStateMachine::historyStateHasNowhereToGo()
QStateMachine machine;
QState *initialState = new QState(&machine);
+ initialState->setObjectName("initialState");
machine.setInitialState(initialState);
- machine.setErrorState(new QState(&machine)); // avoid warnings
+ QState *errorState = new QState(&machine);
+ errorState->setObjectName("errorState");
+ machine.setErrorState(errorState); // avoid warnings
QState *brokenState = new QState(&machine);
brokenState->setObjectName("brokenState");
@@ -919,7 +923,9 @@ void tst_QStateMachine::historyStateHasNowhereToGo()
QHistoryState *historyState = new QHistoryState(brokenState);
historyState->setObjectName("historyState");
- initialState->addTransition(new EventTransition(QEvent::User, historyState));
+ EventTransition *t = new EventTransition(QEvent::User, historyState);
+ t->setObjectName("initialState->historyState");
+ initialState->addTransition(t);
machine.start();
QCoreApplication::processEvents();
@@ -4274,6 +4280,11 @@ void tst_QStateMachine::transitionsFromParallelStateWithNoChildren()
void tst_QStateMachine::parallelStateTransition()
{
+ // This test checks if the parallel state is exited and re-entered if one compound state
+ // is exited and subsequently re-entered. When the parallel state is exited, the other compound
+ // state in the parallel state has to be exited too. When the parallel state is re-entered, the
+ // other state also needs to be re-entered.
+
QStateMachine machine;
QState *parallelState = new QState(QState::ParallelStates, &machine);
@@ -4302,12 +4313,16 @@ void tst_QStateMachine::parallelStateTransition()
s1OtherChild->setObjectName("s1OtherChild");
DEFINE_ACTIVE_SPY(s1OtherChild);
+ // The following transition will exit s1 (which means that parallelState is also exited), and
+ // subsequently re-entered (which means that parallelState is also re-entered).
EventTransition *et = new EventTransition(QEvent::User, s1OtherChild);
et->setObjectName("s1->s1OtherChild");
s1->addTransition(et);
machine.start();
QCoreApplication::processEvents();
+
+ // Initial entrance of the parallel state and its sub-states:
TEST_ACTIVE_CHANGED(parallelState, 1);
TEST_ACTIVE_CHANGED(s1, 1);
TEST_ACTIVE_CHANGED(s1InitialChild, 1);
@@ -4325,22 +4340,22 @@ void tst_QStateMachine::parallelStateTransition()
machine.postEvent(new QEvent(QEvent::User));
QCoreApplication::processEvents();
- TEST_ACTIVE_CHANGED(parallelState, 1);
- TEST_ACTIVE_CHANGED(s1, 3);
- TEST_ACTIVE_CHANGED(s1InitialChild, 2);
- TEST_ACTIVE_CHANGED(s2, 3);
- TEST_ACTIVE_CHANGED(s2InitialChild, 3);
- TEST_ACTIVE_CHANGED(s1OtherChild, 1);
+ TEST_ACTIVE_CHANGED(parallelState, 3); // initial + exit + entry
+ TEST_ACTIVE_CHANGED(s1, 3); // initial + exit + entry
+ TEST_ACTIVE_CHANGED(s1InitialChild, 2); // initial + exit
+ TEST_ACTIVE_CHANGED(s2, 3); // initial + exit due to parent exit + entry due to parent re-entry
+ TEST_ACTIVE_CHANGED(s2InitialChild, 3); // initial + exit due to parent exit + re-entry due to parent re-entry
+ TEST_ACTIVE_CHANGED(s1OtherChild, 1); // entry due to transition
QVERIFY(machine.isRunning());
+ // Check that s1InitialChild is not in the configuration, because although s1 is re-entered,
+ // another child state (s1OtherChild) is active, so the initial child should not be activated.
QVERIFY(machine.configuration().contains(parallelState));
-
QVERIFY(machine.configuration().contains(s1));
QVERIFY(machine.configuration().contains(s2));
QVERIFY(machine.configuration().contains(s1OtherChild));
QVERIFY(machine.configuration().contains(s2InitialChild));
QCOMPARE(machine.configuration().size(), 5);
-
}
void tst_QStateMachine::nestedRestoreProperties()
@@ -6256,5 +6271,69 @@ void tst_QStateMachine::qtbug_44963()
QVERIFY(machine.isRunning());
}
+void tst_QStateMachine::qtbug_44783()
+{
+ SignalEmitter emitter;
+
+ QStateMachine machine;
+ QState s(&machine);
+ QState p(QState::ParallelStates, &s);
+ QState p1(&p);
+ QState p1_1(&p1);
+ QState p1_2(&p1);
+ QState p2(&p);
+ QState s1(&machine);
+
+ machine.setInitialState(&s);
+ s.setInitialState(&p);
+ p1.setInitialState(&p1_1);
+ p1_1.addTransition(&emitter, SIGNAL(signalWithNoArg()), &p1_2)->setObjectName("p1_1->p1_2");
+ p2.addTransition(&emitter, SIGNAL(signalWithNoArg()), &s1)->setObjectName("p2->s1");
+
+ s.setObjectName("s");
+ p.setObjectName("p");
+ p1.setObjectName("p1");
+ p1_1.setObjectName("p1_1");
+ p1_2.setObjectName("p1_2");
+ p2.setObjectName("p2");
+ s1.setObjectName("s1");
+
+ machine.start();
+
+ QTRY_COMPARE(machine.configuration().contains(&s), true);
+ QTRY_COMPARE(machine.configuration().contains(&p), true);
+ QTRY_COMPARE(machine.configuration().contains(&p1), true);
+ QTRY_COMPARE(machine.configuration().contains(&p1_1), true);
+ QTRY_COMPARE(machine.configuration().contains(&p1_2), false);
+ QTRY_COMPARE(machine.configuration().contains(&p2), true);
+ QTRY_COMPARE(machine.configuration().contains(&s1), false);
+
+ emitter.emitSignalWithNoArg();
+
+ // Only one of the following two can be true, because the two possible transitions conflict.
+ if (machine.configuration().contains(&s1)) {
+ // the transition p2 -> s1 was taken, not p1_1 -> p1_2, so:
+ // the parallel state exited, so none of the states inside it are active
+ QTRY_COMPARE(machine.configuration().contains(&s), false);
+ QTRY_COMPARE(machine.configuration().contains(&p), false);
+ QTRY_COMPARE(machine.configuration().contains(&p1), false);
+ QTRY_COMPARE(machine.configuration().contains(&p1_1), false);
+ QTRY_COMPARE(machine.configuration().contains(&p1_2), false);
+ QTRY_COMPARE(machine.configuration().contains(&p2), false);
+ } else {
+ // the transition p1_1 -> p1_2 was taken, not p2 -> s1, so:
+ // the parallel state was not exited and the state is the same as the start state with one
+ // difference: p1_1 inactive and p1_2 active:
+ QTRY_COMPARE(machine.configuration().contains(&s), true);
+ QTRY_COMPARE(machine.configuration().contains(&p), true);
+ QTRY_COMPARE(machine.configuration().contains(&p1), true);
+ QTRY_COMPARE(machine.configuration().contains(&p1_1), false);
+ QTRY_COMPARE(machine.configuration().contains(&p1_2), true);
+ QTRY_COMPARE(machine.configuration().contains(&p2), true);
+ }
+
+ QVERIFY(machine.isRunning());
+}
+
QTEST_MAIN(tst_QStateMachine)
#include "tst_qstatemachine.moc"