summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp11
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h2
-rw-r--r--tests/auto/qstatemachine/tst_qstatemachine.cpp59
3 files changed, 72 insertions, 0 deletions
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index bd7e626..9d5c49f 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -1175,6 +1175,16 @@ void QStateMachinePrivate::removeStartState()
_startState = 0;
}
+void QStateMachinePrivate::clearHistory()
+{
+ Q_Q(QStateMachine);
+ QList<QHistoryState*> historyStates = qFindChildren<QHistoryState*>(q);
+ for (int i = 0; i < historyStates.size(); ++i) {
+ QHistoryState *h = historyStates.at(i);
+ QHistoryStatePrivate::get(h)->configuration.clear();
+ }
+}
+
void QStateMachinePrivate::_q_start()
{
Q_Q(QStateMachine);
@@ -1186,6 +1196,7 @@ void QStateMachinePrivate::_q_start()
internalEventQueue.clear();
qDeleteAll(externalEventQueue);
externalEventQueue.clear();
+ clearHistory();
#ifdef QSTATEMACHINE_DEBUG
qDebug() << q << ": starting";
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
index 0fead5d..5e1015f 100644
--- a/src/corelib/statemachine/qstatemachine_p.h
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -126,6 +126,8 @@ public:
QState *startState();
void removeStartState();
+ void clearHistory();
+
void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList);
bool isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const;
QSet<QAbstractTransition*> selectTransitions(QEvent *event) const;
diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp
index 90b5a22..2bf76e7 100644
--- a/tests/auto/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp
@@ -155,6 +155,7 @@ private slots:
void clearError();
void historyStateHasNowhereToGo();
void historyStateAsInitialState();
+ void historyStateAfterRestart();
void brokenStateIsNeverEntered();
void customErrorStateNotInGraph();
void transitionToStateNotInGraph();
@@ -906,6 +907,64 @@ void tst_QStateMachine::historyStateHasNowhereToGo()
QCOMPARE(machine.errorString(), QString::fromLatin1("Missing default state in history state 'historyState'"));
}
+void tst_QStateMachine::historyStateAfterRestart()
+{
+ // QTBUG-8842
+ QStateMachine machine;
+
+ QState *s1 = new QState(&machine);
+ machine.setInitialState(s1);
+ QState *s2 = new QState(&machine);
+ QState *s21 = new QState(s2);
+ QState *s22 = new QState(s2);
+ QHistoryState *s2h = new QHistoryState(s2);
+ s2h->setDefaultState(s21);
+ s1->addTransition(new EventTransition(QEvent::User, s2h));
+ s21->addTransition(new EventTransition(QEvent::User, s22));
+ s2->addTransition(new EventTransition(QEvent::User, s1));
+
+ for (int x = 0; x < 2; ++x) {
+ QSignalSpy startedSpy(&machine, SIGNAL(started()));
+ machine.start();
+ QTRY_COMPARE(startedSpy.count(), 1);
+ QCOMPARE(machine.configuration().count(), 1);
+ QVERIFY(machine.configuration().contains(s1));
+
+ // s1 -> s2h -> s21 (default state)
+ machine.postEvent(new QEvent(QEvent::User));
+ QCoreApplication::processEvents();
+ QCOMPARE(machine.configuration().count(), 2);
+ QVERIFY(machine.configuration().contains(s2));
+ // This used to fail on the 2nd run because the
+ // history had not been cleared.
+ QVERIFY(machine.configuration().contains(s21));
+
+ // s21 -> s22
+ machine.postEvent(new QEvent(QEvent::User));
+ QCoreApplication::processEvents();
+ QCOMPARE(machine.configuration().count(), 2);
+ QVERIFY(machine.configuration().contains(s2));
+ QVERIFY(machine.configuration().contains(s22));
+
+ // s2 -> s1 (s22 saved in s2h)
+ machine.postEvent(new QEvent(QEvent::User));
+ QCoreApplication::processEvents();
+ QCOMPARE(machine.configuration().count(), 1);
+ QVERIFY(machine.configuration().contains(s1));
+
+ // s1 -> s2h -> s22 (saved state)
+ machine.postEvent(new QEvent(QEvent::User));
+ QCoreApplication::processEvents();
+ QCOMPARE(machine.configuration().count(), 2);
+ QVERIFY(machine.configuration().contains(s2));
+ QVERIFY(machine.configuration().contains(s22));
+
+ QSignalSpy stoppedSpy(&machine, SIGNAL(stopped()));
+ machine.stop();
+ QTRY_COMPARE(stoppedSpy.count(), 1);
+ }
+}
+
void tst_QStateMachine::brokenStateIsNeverEntered()
{
QStateMachine machine;