summaryrefslogtreecommitdiffstats
path: root/tests/auto/qstatemachine/tst_qstatemachine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qstatemachine/tst_qstatemachine.cpp')
-rw-r--r--tests/auto/qstatemachine/tst_qstatemachine.cpp4448
1 files changed, 0 insertions, 4448 deletions
diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp
deleted file mode 100644
index 854e81fb81..0000000000
--- a/tests/auto/qstatemachine/tst_qstatemachine.cpp
+++ /dev/null
@@ -1,4448 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QtTest>
-#include <QtCore/QCoreApplication>
-#include <QtGui/QPushButton>
-#include <QtGui/QGraphicsScene>
-#include <QtGui/QGraphicsSceneEvent>
-#include <QtGui/QGraphicsTextItem>
-
-#include "qstatemachine.h"
-#include "qstate.h"
-#include "qhistorystate.h"
-#include "qkeyeventtransition.h"
-#include "qmouseeventtransition.h"
-#include "private/qstate_p.h"
-#include "private/qstatemachine_p.h"
-
-// Will try to wait for the condition while allowing event processing
-#define QTRY_COMPARE(__expr, __expected) \
- do { \
- const int __step = 50; \
- const int __timeout = 5000; \
- if ((__expr) != (__expected)) { \
- QTest::qWait(0); \
- } \
- for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \
- QTest::qWait(__step); \
- } \
- QCOMPARE(__expr, __expected); \
- } while(0)
-
-//TESTED_CLASS=
-//TESTED_FILES=
-
-static int globalTick;
-
-// Run exec for a maximum of TIMEOUT msecs
-#define QCOREAPPLICATION_EXEC(TIMEOUT) \
-{ \
- QTimer timer; \
- timer.setSingleShot(true); \
- timer.setInterval(TIMEOUT); \
- timer.start(); \
- connect(&timer, SIGNAL(timeout()), QCoreApplication::instance(), SLOT(quit())); \
- QCoreApplication::exec(); \
-}
-
-class SignalEmitter : public QObject
-{
-Q_OBJECT
- public:
- SignalEmitter(QObject *parent = 0)
- : QObject(parent) {}
- void emitSignalWithNoArg()
- { emit signalWithNoArg(); }
- void emitSignalWithIntArg(int arg)
- { emit signalWithIntArg(arg); }
- void emitSignalWithStringArg(const QString &arg)
- { emit signalWithStringArg(arg); }
- void emitSignalWithDefaultArg()
- { emit signalWithDefaultArg(); }
-Q_SIGNALS:
- void signalWithNoArg();
- void signalWithIntArg(int);
- void signalWithStringArg(const QString &);
- void signalWithDefaultArg(int i = 42);
-};
-
-class tst_QStateMachine : public QObject
-{
- Q_OBJECT
-public:
- tst_QStateMachine();
- virtual ~tst_QStateMachine();
-
-private slots:
- void init();
- void cleanup();
-
- void rootState();
- void machineWithParent();
- void addAndRemoveState();
- void stateEntryAndExit();
- void assignProperty();
- void assignPropertyWithAnimation();
- void postEvent();
- void cancelDelayedEvent();
- void postDelayedEventAndStop();
- void stopAndPostEvent();
- void stateFinished();
- void parallelStates();
- void parallelRootState();
- void allSourceToTargetConfigurations();
- void signalTransitions();
- void eventTransitions();
- void graphicsSceneEventTransitions();
- void historyStates();
- void startAndStop();
- void targetStateWithNoParent();
- void targetStateDeleted();
- void transitionToRootState();
- void transitionFromRootState();
- void transitionEntersParent();
-
- void defaultErrorState();
- void customGlobalErrorState();
- void customLocalErrorStateInBrokenState();
- void customLocalErrorStateInOtherState();
- void customLocalErrorStateInParentOfBrokenState();
- void customLocalErrorStateOverridesParent();
- void errorStateHasChildren();
- void errorStateHasErrors();
- void errorStateIsRootState();
- void errorStateEntersParentFirst();
- void customErrorStateIsNull();
- void clearError();
- void historyStateHasNowhereToGo();
- void historyStateAsInitialState();
- void historyStateAfterRestart();
- void brokenStateIsNeverEntered();
- void customErrorStateNotInGraph();
- void transitionToStateNotInGraph();
- void restoreProperties();
-
- void defaultGlobalRestorePolicy();
- void globalRestorePolicySetToRestore();
- void globalRestorePolicySetToDontRestore();
-
- void noInitialStateForInitialState();
-
- //void restorePolicyNotInherited();
- //void mixedRestoreProperties();
- //void setRestorePolicyToDoNotRestore();
- //void setGlobalRestorePolicyToGlobalRestore();
- //void restorePolicyOnChildState();
-
- void transitionWithParent();
- void transitionsFromParallelStateWithNoChildren();
- void parallelStateTransition();
- void parallelStateAssignmentsDone();
- void nestedRestoreProperties();
- void nestedRestoreProperties2();
-
- void simpleAnimation();
- void twoAnimations();
- void twoAnimatedTransitions();
- void playAnimationTwice();
- void nestedTargetStateForAnimation();
- void propertiesAssignedSignalTransitionsReuseAnimationGroup();
- void animatedGlobalRestoreProperty();
- void specificTargetValueOfAnimation();
-
- void addDefaultAnimation();
- void addDefaultAnimationWithUnusedAnimation();
- void removeDefaultAnimation();
- void overrideDefaultAnimationWithSpecific();
-
-// void addDefaultAnimationForSource();
-// void addDefaultAnimationForTarget();
-// void removeDefaultAnimationForSource();
-// void removeDefaultAnimationForTarget();
-// void overrideDefaultAnimationWithSource();
-// void overrideDefaultAnimationWithTarget();
-// void overrideDefaultSourceAnimationWithSpecific();
-// void overrideDefaultTargetAnimationWithSpecific();
-// void overrideDefaultTargetAnimationWithSource();
-
- void nestedStateMachines();
- void goToState();
-
- void task260403_clonedSignals();
- void postEventFromOtherThread();
- void eventFilterForApplication();
- void eventClassesExported();
- void stopInTransitionToFinalState();
- void stopInEventTest_data();
- void stopInEventTest();
-};
-
-tst_QStateMachine::tst_QStateMachine()
-{
-}
-
-tst_QStateMachine::~tst_QStateMachine()
-{
-}
-
-class TestState : public QState
-{
-public:
- enum Event {
- Entry,
- Exit
- };
- TestState(QState *parent)
- : QState(parent) {}
- QList<QPair<int, Event> > events;
-protected:
- virtual void onEntry(QEvent *) {
- events.append(qMakePair(globalTick++, Entry));
- }
- virtual void onExit(QEvent *) {
- events.append(qMakePair(globalTick++, Exit));
- }
-};
-
-class TestTransition : public QAbstractTransition
-{
-public:
- TestTransition(QAbstractState *target)
- : QAbstractTransition()
- { setTargetState(target); }
- QList<int> triggers;
-protected:
- virtual bool eventTest(QEvent *) {
- return true;
- }
- virtual void onTransition(QEvent *) {
- triggers.append(globalTick++);
- }
-};
-
-void tst_QStateMachine::init()
-{
-}
-
-void tst_QStateMachine::cleanup()
-{
-}
-
-class EventTransition : public QAbstractTransition
-{
-public:
- EventTransition(QEvent::Type type, QAbstractState *target, QState *parent = 0)
- : QAbstractTransition(parent), m_type(type)
- { setTargetState(target); }
-protected:
- virtual bool eventTest(QEvent *e) {
- return (e->type() == m_type);
- }
- virtual void onTransition(QEvent *) {}
-private:
- QEvent::Type m_type;
-};
-
-void tst_QStateMachine::transitionToRootState()
-{
- QStateMachine machine;
- machine.setObjectName("machine");
-
- QState *initialState = new QState();
- initialState->setObjectName("initial");
- machine.addState(initialState);
- machine.setInitialState(initialState);
-
- QAbstractTransition *trans = new EventTransition(QEvent::User, &machine);
- initialState->addTransition(trans);
- QCOMPARE(trans->sourceState(), initialState);
- QCOMPARE(trans->targetState(), static_cast<QAbstractState *>(&machine));
-
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().count(), 1);
- QVERIFY(machine.configuration().contains(initialState));
-
- machine.postEvent(new QEvent(QEvent::User));
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 'initial'");
- QCoreApplication::processEvents();
- QVERIFY(machine.configuration().isEmpty());
- QVERIFY(!machine.isRunning());
-}
-
-void tst_QStateMachine::transitionFromRootState()
-{
- QStateMachine machine;
- QState *root = &machine;
- QState *s1 = new QState(root);
- EventTransition *trans = new EventTransition(QEvent::User, s1);
- root->addTransition(trans);
- QCOMPARE(trans->sourceState(), root);
- QCOMPARE(trans->targetState(), static_cast<QAbstractState *>(s1));
-}
-
-void tst_QStateMachine::transitionEntersParent()
-{
- QStateMachine machine;
-
- QObject *entryController = new QObject(&machine);
- entryController->setObjectName("entryController");
- entryController->setProperty("greatGrandParentEntered", false);
- entryController->setProperty("grandParentEntered", false);
- entryController->setProperty("parentEntered", false);
- entryController->setProperty("stateEntered", false);
-
- QState *greatGrandParent = new QState();
- greatGrandParent->setObjectName("grandParent");
- greatGrandParent->assignProperty(entryController, "greatGrandParentEntered", true);
- machine.addState(greatGrandParent);
- machine.setInitialState(greatGrandParent);
-
- QState *grandParent = new QState(greatGrandParent);
- grandParent->setObjectName("grandParent");
- grandParent->assignProperty(entryController, "grandParentEntered", true);
-
- QState *parent = new QState(grandParent);
- parent->setObjectName("parent");
- parent->assignProperty(entryController, "parentEntered", true);
-
- QState *state = new QState(parent);
- state->setObjectName("state");
- state->assignProperty(entryController, "stateEntered", true);
-
- QState *initialStateOfGreatGrandParent = new QState(greatGrandParent);
- initialStateOfGreatGrandParent->setObjectName("initialStateOfGreatGrandParent");
- greatGrandParent->setInitialState(initialStateOfGreatGrandParent);
-
- initialStateOfGreatGrandParent->addTransition(new EventTransition(QEvent::User, state));
-
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(entryController->property("greatGrandParentEntered").toBool(), true);
- QCOMPARE(entryController->property("grandParentEntered").toBool(), false);
- QCOMPARE(entryController->property("parentEntered").toBool(), false);
- QCOMPARE(entryController->property("stateEntered").toBool(), false);
- QCOMPARE(machine.configuration().count(), 2);
- QVERIFY(machine.configuration().contains(greatGrandParent));
- QVERIFY(machine.configuration().contains(initialStateOfGreatGrandParent));
-
- entryController->setProperty("greatGrandParentEntered", false);
- entryController->setProperty("grandParentEntered", false);
- entryController->setProperty("parentEntered", false);
- entryController->setProperty("stateEntered", false);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(entryController->property("greatGrandParentEntered").toBool(), false);
- QCOMPARE(entryController->property("grandParentEntered").toBool(), true);
- QCOMPARE(entryController->property("parentEntered").toBool(), true);
- QCOMPARE(entryController->property("stateEntered").toBool(), true);
- QCOMPARE(machine.configuration().count(), 4);
- QVERIFY(machine.configuration().contains(greatGrandParent));
- QVERIFY(machine.configuration().contains(grandParent));
- QVERIFY(machine.configuration().contains(parent));
- QVERIFY(machine.configuration().contains(state));
-}
-
-void tst_QStateMachine::defaultErrorState()
-{
- QStateMachine machine;
- QCOMPARE(machine.errorState(), reinterpret_cast<QAbstractState *>(0));
-
- QState *brokenState = new QState();
- brokenState->setObjectName("MyInitialState");
-
- machine.addState(brokenState);
- machine.setInitialState(brokenState);
-
- QState *childState = new QState(brokenState);
- childState->setObjectName("childState");
-
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: Missing initial state in compound state 'MyInitialState'");
-
- // initialState has no initial state
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.error(), QStateMachine::NoInitialStateError);
- QCOMPARE(machine.errorString(), QString::fromLatin1("Missing initial state in compound state 'MyInitialState'"));
- QCOMPARE(machine.isRunning(), false);
-}
-
-class CustomErrorState: public QState
-{
-public:
- CustomErrorState(QStateMachine *machine, QState *parent = 0)
- : QState(parent), error(QStateMachine::NoError), m_machine(machine)
- {
- }
-
- void onEntry(QEvent *)
- {
- error = m_machine->error();
- errorString = m_machine->errorString();
- }
-
- QStateMachine::Error error;
- QString errorString;
-
-private:
- QStateMachine *m_machine;
-};
-
-void tst_QStateMachine::customGlobalErrorState()
-{
- QStateMachine machine;
-
- CustomErrorState *customErrorState = new CustomErrorState(&machine);
- customErrorState->setObjectName("customErrorState");
- machine.addState(customErrorState);
- machine.setErrorState(customErrorState);
-
- QState *initialState = new QState();
- initialState->setObjectName("initialState");
- machine.addState(initialState);
- machine.setInitialState(initialState);
-
- QState *brokenState = new QState();
- brokenState->setObjectName("brokenState");
- machine.addState(brokenState);
- QState *childState = new QState(brokenState);
- childState->setObjectName("childState");
-
- initialState->addTransition(new EventTransition(QEvent::Type(QEvent::User + 1), brokenState));
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.errorState(), static_cast<QAbstractState*>(customErrorState));
- QCOMPARE(machine.configuration().count(), 1);
- QVERIFY(machine.configuration().contains(initialState));
-
- machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1)));
- QCOMPARE(machine.configuration().count(), 1);
- QVERIFY(machine.configuration().contains(initialState));
-
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.isRunning(), true);
- QCOMPARE(machine.configuration().count(), 1);
- QVERIFY(machine.configuration().contains(customErrorState));
- QCOMPARE(customErrorState->error, QStateMachine::NoInitialStateError);
- QCOMPARE(customErrorState->errorString, QString::fromLatin1("Missing initial state in compound state 'brokenState'"));
- QCOMPARE(machine.error(), QStateMachine::NoInitialStateError);
- QCOMPARE(machine.errorString(), QString::fromLatin1("Missing initial state in compound state 'brokenState'"));
-}
-
-void tst_QStateMachine::customLocalErrorStateInBrokenState()
-{
- QStateMachine machine;
- CustomErrorState *customErrorState = new CustomErrorState(&machine);
- machine.addState(customErrorState);
-
- QState *initialState = new QState();
- initialState->setObjectName("initialState");
- machine.addState(initialState);
- machine.setInitialState(initialState);
-
- QState *brokenState = new QState();
- brokenState->setObjectName("brokenState");
- machine.addState(brokenState);
- brokenState->setErrorState(customErrorState);
-
- QState *childState = new QState(brokenState);
- childState->setObjectName("childState");
-
- initialState->addTransition(new EventTransition(QEvent::Type(QEvent::User + 1), brokenState));
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1)));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.isRunning(), true);
- QCOMPARE(machine.configuration().count(), 1);
- QVERIFY(machine.configuration().contains(customErrorState));
- QCOMPARE(customErrorState->error, QStateMachine::NoInitialStateError);
-}
-
-void tst_QStateMachine::customLocalErrorStateInOtherState()
-{
- QStateMachine machine;
- CustomErrorState *customErrorState = new CustomErrorState(&machine);
- machine.addState(customErrorState);
-
- QState *initialState = new QState();
- initialState->setObjectName("initialState");
- QTest::ignoreMessage(QtWarningMsg, "QState::setErrorState: error state cannot belong to a different state machine");
- initialState->setErrorState(customErrorState);
- machine.addState(initialState);
- machine.setInitialState(initialState);
-
- QState *brokenState = new QState();
- brokenState->setObjectName("brokenState");
-
- machine.addState(brokenState);
-
- QState *childState = new QState(brokenState);
- childState->setObjectName("childState");
-
- initialState->addTransition(new EventTransition(QEvent::Type(QEvent::User + 1), brokenState));
-
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: Missing initial state in compound state 'brokenState'");
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1)));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.isRunning(), false);
-}
-
-void tst_QStateMachine::customLocalErrorStateInParentOfBrokenState()
-{
- QStateMachine machine;
- CustomErrorState *customErrorState = new CustomErrorState(&machine);
- machine.addState(customErrorState);
-
- QState *initialState = new QState();
- initialState->setObjectName("initialState");
- machine.addState(initialState);
- machine.setInitialState(initialState);
-
- QState *parentOfBrokenState = new QState();
- machine.addState(parentOfBrokenState);
- parentOfBrokenState->setObjectName("parentOfBrokenState");
- parentOfBrokenState->setErrorState(customErrorState);
-
- QState *brokenState = new QState(parentOfBrokenState);
- brokenState->setObjectName("brokenState");
- parentOfBrokenState->setInitialState(brokenState);
-
- QState *childState = new QState(brokenState);
- childState->setObjectName("childState");
-
- initialState->addTransition(new EventTransition(QEvent::Type(QEvent::User + 1), brokenState));
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1)));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.isRunning(), true);
- QCOMPARE(machine.configuration().count(), 1);
- QVERIFY(machine.configuration().contains(customErrorState));
-}
-
-void tst_QStateMachine::customLocalErrorStateOverridesParent()
-{
- QStateMachine machine;
- CustomErrorState *customErrorStateForParent = new CustomErrorState(&machine);
- machine.addState(customErrorStateForParent);
-
- CustomErrorState *customErrorStateForBrokenState = new CustomErrorState(&machine);
- machine.addState(customErrorStateForBrokenState);
-
- QState *initialState = new QState();
- initialState->setObjectName("initialState");
- machine.addState(initialState);
- machine.setInitialState(initialState);
-
- QState *parentOfBrokenState = new QState();
- machine.addState(parentOfBrokenState);
- parentOfBrokenState->setObjectName("parentOfBrokenState");
- parentOfBrokenState->setErrorState(customErrorStateForParent);
-
- QState *brokenState = new QState(parentOfBrokenState);
- brokenState->setObjectName("brokenState");
- brokenState->setErrorState(customErrorStateForBrokenState);
- parentOfBrokenState->setInitialState(brokenState);
-
- QState *childState = new QState(brokenState);
- childState->setObjectName("childState");
-
- initialState->addTransition(new EventTransition(QEvent::Type(QEvent::User + 1), brokenState));
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1)));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().count(), 1);
- QVERIFY(machine.configuration().contains(customErrorStateForBrokenState));
- QCOMPARE(customErrorStateForBrokenState->error, QStateMachine::NoInitialStateError);
- QCOMPARE(customErrorStateForParent->error, QStateMachine::NoError);
-}
-
-void tst_QStateMachine::errorStateHasChildren()
-{
- QStateMachine machine;
- CustomErrorState *customErrorState = new CustomErrorState(&machine);
- customErrorState->setObjectName("customErrorState");
- machine.addState(customErrorState);
-
- machine.setErrorState(customErrorState);
-
- QState *childOfErrorState = new QState(customErrorState);
- childOfErrorState->setObjectName("childOfErrorState");
- customErrorState->setInitialState(childOfErrorState);
-
- QState *initialState = new QState();
- initialState->setObjectName("initialState");
- machine.addState(initialState);
- machine.setInitialState(initialState);
-
- QState *brokenState = new QState();
- brokenState->setObjectName("brokenState");
- machine.addState(brokenState);
-
- QState *childState = new QState(brokenState);
- childState->setObjectName("childState");
-
- initialState->addTransition(new EventTransition(QEvent::Type(QEvent::User + 1), brokenState));
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1)));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.isRunning(), true);
- QCOMPARE(machine.configuration().count(), 2);
- QVERIFY(machine.configuration().contains(customErrorState));
- QVERIFY(machine.configuration().contains(childOfErrorState));
-}
-
-
-void tst_QStateMachine::errorStateHasErrors()
-{
- QStateMachine machine;
- CustomErrorState *customErrorState = new CustomErrorState(&machine);
- customErrorState->setObjectName("customErrorState");
- machine.addState(customErrorState);
-
- machine.setErrorState(customErrorState);
-
- QState *childOfErrorState = new QState(customErrorState);
- childOfErrorState->setObjectName("childOfErrorState");
-
- QState *initialState = new QState();
- initialState->setObjectName("initialState");
- machine.addState(initialState);
- machine.setInitialState(initialState);
-
- QState *brokenState = new QState();
- brokenState->setObjectName("brokenState");
- machine.addState(brokenState);
-
- QState *childState = new QState(brokenState);
- childState->setObjectName("childState");
-
- initialState->addTransition(new EventTransition(QEvent::Type(QEvent::User + 1), brokenState));
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1)));
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: Missing initial state in compound state 'customErrorState'");
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.isRunning(), false);
- QCOMPARE(machine.error(), QStateMachine::NoInitialStateError);
- QCOMPARE(machine.errorString(), QString::fromLatin1("Missing initial state in compound state 'customErrorState'"));
-}
-
-void tst_QStateMachine::errorStateIsRootState()
-{
- QStateMachine machine;
- QTest::ignoreMessage(QtWarningMsg, "QStateMachine::setErrorState: root state cannot be error state");
- machine.setErrorState(&machine);
-
- QState *initialState = new QState();
- initialState->setObjectName("initialState");
- machine.addState(initialState);
- machine.setInitialState(initialState);
-
- QState *brokenState = new QState();
- brokenState->setObjectName("brokenState");
- machine.addState(brokenState);
-
- QState *childState = new QState(brokenState);
- childState->setObjectName("childState");
-
- initialState->addTransition(new EventTransition(QEvent::Type(QEvent::User + 1), brokenState));
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 1)));
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: Missing initial state in compound state 'brokenState'");
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.isRunning(), false);
-}
-
-void tst_QStateMachine::errorStateEntersParentFirst()
-{
- QStateMachine machine;
-
- QObject *entryController = new QObject(&machine);
- entryController->setObjectName("entryController");
- entryController->setProperty("greatGrandParentEntered", false);
- entryController->setProperty("grandParentEntered", false);
- entryController->setProperty("parentEntered", false);
- entryController->setProperty("errorStateEntered", false);
-
- QState *greatGrandParent = new QState();
- greatGrandParent->setObjectName("greatGrandParent");
- greatGrandParent->assignProperty(entryController, "greatGrandParentEntered", true);
- machine.addState(greatGrandParent);
- machine.setInitialState(greatGrandParent);
-
- QState *grandParent = new QState(greatGrandParent);
- grandParent->setObjectName("grandParent");
- grandParent->assignProperty(entryController, "grandParentEntered", true);
-
- QState *parent = new QState(grandParent);
- parent->setObjectName("parent");
- parent->assignProperty(entryController, "parentEntered", true);
-
- QState *errorState = new QState(parent);
- errorState->setObjectName("errorState");
- errorState->assignProperty(entryController, "errorStateEntered", true);
- machine.setErrorState(errorState);
-
- QState *initialStateOfGreatGrandParent = new QState(greatGrandParent);
- initialStateOfGreatGrandParent->setObjectName("initialStateOfGreatGrandParent");
- greatGrandParent->setInitialState(initialStateOfGreatGrandParent);
-
- QState *brokenState = new QState(greatGrandParent);
- brokenState->setObjectName("brokenState");
-
- QState *childState = new QState(brokenState);
- childState->setObjectName("childState");
-
- initialStateOfGreatGrandParent->addTransition(new EventTransition(QEvent::User, brokenState));
-
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(entryController->property("greatGrandParentEntered").toBool(), true);
- QCOMPARE(entryController->property("grandParentEntered").toBool(), false);
- QCOMPARE(entryController->property("parentEntered").toBool(), false);
- QCOMPARE(entryController->property("errorStateEntered").toBool(), false);
- QCOMPARE(machine.configuration().count(), 2);
- QVERIFY(machine.configuration().contains(greatGrandParent));
- QVERIFY(machine.configuration().contains(initialStateOfGreatGrandParent));
-
- entryController->setProperty("greatGrandParentEntered", false);
- entryController->setProperty("grandParentEntered", false);
- entryController->setProperty("parentEntered", false);
- entryController->setProperty("errorStateEntered", false);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(entryController->property("greatGrandParentEntered").toBool(), false);
- QCOMPARE(entryController->property("grandParentEntered").toBool(), true);
- QCOMPARE(entryController->property("parentEntered").toBool(), true);
- QCOMPARE(entryController->property("errorStateEntered").toBool(), true);
- QCOMPARE(machine.configuration().count(), 4);
- QVERIFY(machine.configuration().contains(greatGrandParent));
- QVERIFY(machine.configuration().contains(grandParent));
- QVERIFY(machine.configuration().contains(parent));
- QVERIFY(machine.configuration().contains(errorState));
-}
-
-void tst_QStateMachine::customErrorStateIsNull()
-{
- QStateMachine machine;
- machine.setErrorState(0);
-
- QState *initialState = new QState();
- machine.addState(initialState);
- machine.setInitialState(initialState);
-
- QState *brokenState = new QState();
- machine.addState(brokenState);
-
- new QState(brokenState);
- initialState->addTransition(new EventTransition(QEvent::User, brokenState));
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: Missing initial state in compound state ''");
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.errorState(), reinterpret_cast<QAbstractState *>(0));
- QCOMPARE(machine.isRunning(), false);
-}
-
-void tst_QStateMachine::clearError()
-{
- QStateMachine machine;
- machine.setErrorState(new QState(&machine)); // avoid warnings
-
- QState *brokenState = new QState(&machine);
- brokenState->setObjectName("brokenState");
- machine.setInitialState(brokenState);
- new QState(brokenState);
-
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.isRunning(), true);
- QCOMPARE(machine.error(), QStateMachine::NoInitialStateError);
- QCOMPARE(machine.errorString(), QString::fromLatin1("Missing initial state in compound state 'brokenState'"));
-
- machine.clearError();
-
- QCOMPARE(machine.error(), QStateMachine::NoError);
- QVERIFY(machine.errorString().isEmpty());
-}
-
-void tst_QStateMachine::historyStateAsInitialState()
-{
- QStateMachine machine;
-
- QHistoryState *hs = new QHistoryState(&machine);
- machine.setInitialState(hs);
-
- QState *s1 = new QState(&machine);
- hs->setDefaultState(s1);
-
- QState *s2 = new QState(&machine);
-
- QHistoryState *s2h = new QHistoryState(s2);
- s2->setInitialState(s2h);
-
- QState *s21 = new QState(s2);
- s2h->setDefaultState(s21);
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
-
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().size(), 2);
- QVERIFY(machine.configuration().contains(s2));
- QVERIFY(machine.configuration().contains(s21));
-}
-
-void tst_QStateMachine::historyStateHasNowhereToGo()
-{
- QStateMachine machine;
-
- QState *initialState = new QState(&machine);
- machine.setInitialState(initialState);
- machine.setErrorState(new QState(&machine)); // avoid warnings
-
- QState *brokenState = new QState(&machine);
- brokenState->setObjectName("brokenState");
- brokenState->setInitialState(new QState(brokenState));
-
- QHistoryState *historyState = new QHistoryState(brokenState);
- historyState->setObjectName("historyState");
- initialState->addTransition(new EventTransition(QEvent::User, historyState));
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.isRunning(), true);
- QCOMPARE(machine.configuration().count(), 1);
- QVERIFY(machine.configuration().contains(machine.errorState()));
- QCOMPARE(machine.error(), QStateMachine::NoDefaultStateInHistoryStateError);
- 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;
-
- QObject *entryController = new QObject(&machine);
- entryController->setProperty("brokenStateEntered", false);
- entryController->setProperty("childStateEntered", false);
- entryController->setProperty("errorStateEntered", false);
-
- QState *initialState = new QState(&machine);
- machine.setInitialState(initialState);
-
- QState *errorState = new QState(&machine);
- errorState->assignProperty(entryController, "errorStateEntered", true);
- machine.setErrorState(errorState);
-
- QState *brokenState = new QState(&machine);
- brokenState->assignProperty(entryController, "brokenStateEntered", true);
- brokenState->setObjectName("brokenState");
-
- QState *childState = new QState(brokenState);
- childState->assignProperty(entryController, "childStateEntered", true);
-
- initialState->addTransition(new EventTransition(QEvent::User, brokenState));
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(entryController->property("errorStateEntered").toBool(), true);
- QCOMPARE(entryController->property("brokenStateEntered").toBool(), false);
- QCOMPARE(entryController->property("childStateEntered").toBool(), false);
-}
-
-void tst_QStateMachine::transitionToStateNotInGraph()
-{
- QStateMachine machine;
-
- QState *initialState = new QState(&machine);
- initialState->setObjectName("initialState");
- machine.setInitialState(initialState);
-
- QState independentState;
- independentState.setObjectName("independentState");
- initialState->addTransition(&independentState);
-
- machine.start();
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 'initialState'");
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.isRunning(), false);
-}
-
-void tst_QStateMachine::customErrorStateNotInGraph()
-{
- QStateMachine machine;
-
- QState errorState;
- errorState.setObjectName("errorState");
- QTest::ignoreMessage(QtWarningMsg, "QState::setErrorState: error state cannot belong to a different state machine");
- machine.setErrorState(&errorState);
- QCOMPARE(machine.errorState(), reinterpret_cast<QAbstractState *>(0));
-
- QState *initialBrokenState = new QState(&machine);
- initialBrokenState->setObjectName("initialBrokenState");
- machine.setInitialState(initialBrokenState);
- new QState(initialBrokenState);
-
- machine.start();
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: Missing initial state in compound state 'initialBrokenState'");
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.isRunning(), false);
-}
-
-void tst_QStateMachine::restoreProperties()
-{
- QStateMachine machine;
- QCOMPARE(machine.globalRestorePolicy(), QStateMachine::DontRestoreProperties);
- machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
-
- QObject *object = new QObject(&machine);
- object->setProperty("a", 1);
- object->setProperty("b", 2);
-
- QState *S1 = new QState();
- S1->setObjectName("S1");
- S1->assignProperty(object, "a", 3);
- machine.addState(S1);
-
- QState *S2 = new QState();
- S2->setObjectName("S2");
- S2->assignProperty(object, "b", 5);
- machine.addState(S2);
-
- QState *S3 = new QState();
- S3->setObjectName("S3");
- machine.addState(S3);
-
- QFinalState *S4 = new QFinalState();
- machine.addState(S4);
-
- S1->addTransition(new EventTransition(QEvent::User, S2));
- S2->addTransition(new EventTransition(QEvent::User, S3));
- S3->addTransition(S4);
-
- machine.setInitialState(S1);
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(object->property("a").toInt(), 3);
- QCOMPARE(object->property("b").toInt(), 2);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(object->property("a").toInt(), 1);
- QCOMPARE(object->property("b").toInt(), 5);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(object->property("a").toInt(), 1);
- QCOMPARE(object->property("b").toInt(), 2);
-}
-
-void tst_QStateMachine::rootState()
-{
- QStateMachine machine;
- QCOMPARE(qobject_cast<QState*>(machine.parentState()), (QState*)0);
- QCOMPARE(machine.machine(), (QStateMachine*)0);
-
- QState *s1 = new QState(&machine);
- QCOMPARE(s1->parentState(), static_cast<QState*>(&machine));
-
- QState *s2 = new QState();
- s2->setParent(&machine);
- QCOMPARE(s2->parentState(), static_cast<QState*>(&machine));
-}
-
-void tst_QStateMachine::machineWithParent()
-{
- QObject object;
- QStateMachine *machine = new QStateMachine(&object);
- QCOMPARE(machine->parent(), &object);
- QCOMPARE(machine->parentState(), static_cast<QState*>(0));
-}
-
-void tst_QStateMachine::addAndRemoveState()
-{
-#ifdef QT_BUILD_INTERNAL
- QStateMachine machine;
- QStatePrivate *root_d = QStatePrivate::get(&machine);
- QCOMPARE(root_d->childStates().size(), 0);
-
- QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: cannot add null state");
- machine.addState(0);
-
- QState *s1 = new QState();
- QCOMPARE(s1->parentState(), (QState*)0);
- QCOMPARE(s1->machine(), (QStateMachine*)0);
- machine.addState(s1);
- QCOMPARE(s1->machine(), static_cast<QStateMachine*>(&machine));
- QCOMPARE(s1->parentState(), static_cast<QState*>(&machine));
- QCOMPARE(root_d->childStates().size(), 1);
- QCOMPARE(root_d->childStates().at(0), (QAbstractState*)s1);
-
- QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: state has already been added to this machine");
- machine.addState(s1);
-
- QState *s2 = new QState();
- QCOMPARE(s2->parentState(), (QState*)0);
- machine.addState(s2);
- QCOMPARE(s2->parentState(), static_cast<QState*>(&machine));
- QCOMPARE(root_d->childStates().size(), 2);
- QCOMPARE(root_d->childStates().at(0), (QAbstractState*)s1);
- QCOMPARE(root_d->childStates().at(1), (QAbstractState*)s2);
-
- QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: state has already been added to this machine");
- machine.addState(s2);
-
- machine.removeState(s1);
- QCOMPARE(s1->parentState(), (QState*)0);
- QCOMPARE(root_d->childStates().size(), 1);
- QCOMPARE(root_d->childStates().at(0), (QAbstractState*)s2);
-
- machine.removeState(s2);
- QCOMPARE(s2->parentState(), (QState*)0);
- QCOMPARE(root_d->childStates().size(), 0);
-
- QTest::ignoreMessage(QtWarningMsg, "QStateMachine::removeState: cannot remove null state");
- machine.removeState(0);
-
- {
- QStateMachine machine2;
- {
- QString warning;
- warning.sprintf("QStateMachine::removeState: state %p's machine (%p) is different from this machine (%p)",
- &machine2, (void*)0, &machine);
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- machine.removeState(&machine2);
- }
- // ### check this behavior
- machine.addState(&machine2);
- QCOMPARE(machine2.parent(), (QObject*)&machine);
- }
-
- delete s1;
- delete s2;
- // ### how to deal with this?
- // machine.removeState(machine.errorState());
-#endif
-}
-
-void tst_QStateMachine::stateEntryAndExit()
-{
- // Two top-level states
- {
- QStateMachine machine;
-
- TestState *s1 = new TestState(&machine);
- QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: cannot add transition to null state");
- s1->addTransition((QAbstractState*)0);
- QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: cannot add null transition");
- s1->addTransition((QAbstractTransition*)0);
- QTest::ignoreMessage(QtWarningMsg, "QState::removeTransition: cannot remove null transition");
- s1->removeTransition((QAbstractTransition*)0);
-
- TestState *s2 = new TestState(&machine);
- QFinalState *s3 = new QFinalState(&machine);
-
- TestTransition *t = new TestTransition(s2);
- QCOMPARE(t->machine(), (QStateMachine*)0);
- QCOMPARE(t->sourceState(), (QState*)0);
- QCOMPARE(t->targetState(), (QAbstractState*)s2);
- QCOMPARE(t->targetStates().size(), 1);
- QCOMPARE(t->targetStates().at(0), (QAbstractState*)s2);
- t->setTargetState(0);
- QCOMPARE(t->targetState(), (QAbstractState*)0);
- QVERIFY(t->targetStates().isEmpty());
- t->setTargetState(s2);
- QCOMPARE(t->targetState(), (QAbstractState*)s2);
- QTest::ignoreMessage(QtWarningMsg, "QAbstractTransition::setTargetStates: target state(s) cannot be null");
- t->setTargetStates(QList<QAbstractState*>() << 0);
- QCOMPARE(t->targetState(), (QAbstractState*)s2);
- t->setTargetStates(QList<QAbstractState*>() << s2);
- QCOMPARE(t->targetState(), (QAbstractState*)s2);
- QCOMPARE(t->targetStates().size(), 1);
- QCOMPARE(t->targetStates().at(0), (QAbstractState*)s2);
- s1->addTransition(t);
- QCOMPARE(t->sourceState(), (QState*)s1);
- QCOMPARE(t->machine(), &machine);
-
- {
- QAbstractTransition *trans = s2->addTransition(s3);
- QVERIFY(trans != 0);
- QCOMPARE(trans->sourceState(), (QState*)s2);
- QCOMPARE(trans->targetState(), (QAbstractState*)s3);
- {
- QString warning;
- warning.sprintf("QState::removeTransition: transition %p's source state (%p) is different from this state (%p)", trans, s2, s1);
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- s1->removeTransition(trans);
- }
- s2->removeTransition(trans);
- QCOMPARE(trans->sourceState(), (QState*)0);
- QCOMPARE(trans->targetState(), (QAbstractState*)s3);
- s2->addTransition(trans);
- QCOMPARE(trans->sourceState(), (QState*)s2);
- }
-
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- QSignalSpy stoppedSpy(&machine, SIGNAL(stopped()));
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s1);
- QCOMPARE(machine.initialState(), (QAbstractState*)s1);
- {
- QString warning;
- warning.sprintf("QState::setInitialState: state %p is not a child of this state (%p)", &machine, &machine);
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- machine.setInitialState(&machine);
- QCOMPARE(machine.initialState(), (QAbstractState*)s1);
- }
- QVERIFY(machine.configuration().isEmpty());
- globalTick = 0;
- QVERIFY(!machine.isRunning());
- QSignalSpy s1EnteredSpy(s1, SIGNAL(entered()));
- QSignalSpy s1ExitedSpy(s1, SIGNAL(exited()));
- QSignalSpy tTriggeredSpy(t, SIGNAL(triggered()));
- QSignalSpy s2EnteredSpy(s2, SIGNAL(entered()));
- QSignalSpy s2ExitedSpy(s2, SIGNAL(exited()));
- machine.start();
-
- QTRY_COMPARE(startedSpy.count(), 1);
- QTRY_COMPARE(finishedSpy.count(), 1);
- QTRY_COMPARE(stoppedSpy.count(), 0);
- QCOMPARE(machine.configuration().count(), 1);
- QVERIFY(machine.configuration().contains(s3));
-
- // s1 is entered
- QCOMPARE(s1->events.count(), 2);
- QCOMPARE(s1->events.at(0).first, 0);
- QCOMPARE(s1->events.at(0).second, TestState::Entry);
- // s1 is exited
- QCOMPARE(s1->events.at(1).first, 1);
- QCOMPARE(s1->events.at(1).second, TestState::Exit);
- // t is triggered
- QCOMPARE(t->triggers.count(), 1);
- QCOMPARE(t->triggers.at(0), 2);
- // s2 is entered
- QCOMPARE(s2->events.count(), 2);
- QCOMPARE(s2->events.at(0).first, 3);
- QCOMPARE(s2->events.at(0).second, TestState::Entry);
- // s2 is exited
- QCOMPARE(s2->events.at(1).first, 4);
- QCOMPARE(s2->events.at(1).second, TestState::Exit);
-
- QCOMPARE(s1EnteredSpy.count(), 1);
- QCOMPARE(s1ExitedSpy.count(), 1);
- QCOMPARE(tTriggeredSpy.count(), 1);
- QCOMPARE(s2EnteredSpy.count(), 1);
- QCOMPARE(s2ExitedSpy.count(), 1);
- }
- // Two top-level states, one has two child states
- {
- QStateMachine machine;
-
- TestState *s1 = new TestState(&machine);
- TestState *s11 = new TestState(s1);
- TestState *s12 = new TestState(s1);
- TestState *s2 = new TestState(&machine);
- QFinalState *s3 = new QFinalState(&machine);
- s1->setInitialState(s11);
- TestTransition *t1 = new TestTransition(s12);
- s11->addTransition(t1);
- TestTransition *t2 = new TestTransition(s2);
- s12->addTransition(t2);
- s2->addTransition(s3);
-
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s1);
- globalTick = 0;
- machine.start();
-
- QTRY_COMPARE(startedSpy.count(), 1);
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(machine.configuration().count(), 1);
- QVERIFY(machine.configuration().contains(s3));
-
- // s1 is entered
- QCOMPARE(s1->events.count(), 2);
- QCOMPARE(s1->events.at(0).first, 0);
- QCOMPARE(s1->events.at(0).second, TestState::Entry);
- // s11 is entered
- QCOMPARE(s11->events.count(), 2);
- QCOMPARE(s11->events.at(0).first, 1);
- QCOMPARE(s11->events.at(0).second, TestState::Entry);
- // s11 is exited
- QCOMPARE(s11->events.at(1).first, 2);
- QCOMPARE(s11->events.at(1).second, TestState::Exit);
- // t1 is triggered
- QCOMPARE(t1->triggers.count(), 1);
- QCOMPARE(t1->triggers.at(0), 3);
- // s12 is entered
- QCOMPARE(s12->events.count(), 2);
- QCOMPARE(s12->events.at(0).first, 4);
- QCOMPARE(s12->events.at(0).second, TestState::Entry);
- // s12 is exited
- QCOMPARE(s12->events.at(1).first, 5);
- QCOMPARE(s12->events.at(1).second, TestState::Exit);
- // s1 is exited
- QCOMPARE(s1->events.at(1).first, 6);
- QCOMPARE(s1->events.at(1).second, TestState::Exit);
- // t2 is triggered
- QCOMPARE(t2->triggers.count(), 1);
- QCOMPARE(t2->triggers.at(0), 7);
- // s2 is entered
- QCOMPARE(s2->events.count(), 2);
- QCOMPARE(s2->events.at(0).first, 8);
- QCOMPARE(s2->events.at(0).second, TestState::Entry);
- // s2 is exited
- QCOMPARE(s2->events.at(1).first, 9);
- QCOMPARE(s2->events.at(1).second, TestState::Exit);
- }
-}
-
-void tst_QStateMachine::assignProperty()
-{
- QStateMachine machine;
- QState *s1 = new QState(&machine);
-
- QTest::ignoreMessage(QtWarningMsg, "QState::assignProperty: cannot assign property 'foo' of null object");
- s1->assignProperty(0, "foo", QVariant());
-
- s1->assignProperty(s1, "objectName", "s1");
- QFinalState *s2 = new QFinalState(&machine);
- s1->addTransition(s2);
- machine.setInitialState(s1);
- machine.start();
- QTRY_COMPARE(s1->objectName(), QString::fromLatin1("s1"));
-
- s1->assignProperty(s1, "objectName", "foo");
- machine.start();
- QTRY_COMPARE(s1->objectName(), QString::fromLatin1("foo"));
-
- s1->assignProperty(s1, "noSuchProperty", 123);
- machine.start();
- QTRY_COMPARE(s1->dynamicPropertyNames().size(), 1);
- QCOMPARE(s1->dynamicPropertyNames().at(0), QByteArray("noSuchProperty"));
- QCOMPARE(s1->objectName(), QString::fromLatin1("foo"));
-
- {
- QSignalSpy propertiesAssignedSpy(s1, SIGNAL(propertiesAssigned()));
- machine.start();
- QTRY_COMPARE(propertiesAssignedSpy.count(), 1);
- }
-
- // nested states
- {
- QState *s11 = new QState(s1);
- QString str = QString::fromLatin1("set by nested state");
- s11->assignProperty(s11, "objectName", str);
- s1->setInitialState(s11);
- machine.start();
- QTRY_COMPARE(s11->objectName(), str);
- }
-}
-
-void tst_QStateMachine::assignPropertyWithAnimation()
-{
- // Single animation
- {
- QStateMachine machine;
- QVERIFY(machine.isAnimated());
- machine.setAnimated(false);
- QVERIFY(!machine.isAnimated());
- machine.setAnimated(true);
- QVERIFY(machine.isAnimated());
- QObject obj;
- obj.setProperty("foo", 321);
- obj.setProperty("bar", 654);
- QState *s1 = new QState(&machine);
- s1->assignProperty(&obj, "foo", 123);
- QState *s2 = new QState(&machine);
- s2->assignProperty(&obj, "foo", 456);
- s2->assignProperty(&obj, "bar", 789);
- QAbstractTransition *trans = s1->addTransition(s2);
- QVERIFY(trans->animations().isEmpty());
- QTest::ignoreMessage(QtWarningMsg, "QAbstractTransition::addAnimation: cannot add null animation");
- trans->addAnimation(0);
- QPropertyAnimation anim(&obj, "foo");
- anim.setDuration(250);
- trans->addAnimation(&anim);
- QCOMPARE(trans->animations().size(), 1);
- QCOMPARE(trans->animations().at(0), (QAbstractAnimation*)&anim);
- QCOMPARE(anim.parent(), (QObject*)0);
- QTest::ignoreMessage(QtWarningMsg, "QAbstractTransition::removeAnimation: cannot remove null animation");
- trans->removeAnimation(0);
- trans->removeAnimation(&anim);
- QVERIFY(trans->animations().isEmpty());
- trans->addAnimation(&anim);
- QCOMPARE(trans->animations().size(), 1);
- QCOMPARE(trans->animations().at(0), (QAbstractAnimation*)&anim);
- QFinalState *s3 = new QFinalState(&machine);
- s2->addTransition(s2, SIGNAL(propertiesAssigned()), s3);
-
- machine.setInitialState(s1);
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(obj.property("foo").toInt(), 456);
- QCOMPARE(obj.property("bar").toInt(), 789);
- }
- // Two animations
- {
- QStateMachine machine;
- QObject obj;
- obj.setProperty("foo", 321);
- obj.setProperty("bar", 654);
- QState *s1 = new QState(&machine);
- s1->assignProperty(&obj, "foo", 123);
- QState *s2 = new QState(&machine);
- s2->assignProperty(&obj, "foo", 456);
- s2->assignProperty(&obj, "bar", 789);
- QAbstractTransition *trans = s1->addTransition(s2);
- QPropertyAnimation anim(&obj, "foo");
- anim.setDuration(150);
- trans->addAnimation(&anim);
- QPropertyAnimation anim2(&obj, "bar");
- anim2.setDuration(150);
- trans->addAnimation(&anim2);
- QFinalState *s3 = new QFinalState(&machine);
- s2->addTransition(s2, SIGNAL(propertiesAssigned()), s3);
-
- machine.setInitialState(s1);
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(obj.property("foo").toInt(), 456);
- QCOMPARE(obj.property("bar").toInt(), 789);
- }
- // Animation group
- {
- QStateMachine machine;
- QObject obj;
- obj.setProperty("foo", 321);
- obj.setProperty("bar", 654);
- QState *s1 = new QState(&machine);
- s1->assignProperty(&obj, "foo", 123);
- s1->assignProperty(&obj, "bar", 321);
- QState *s2 = new QState(&machine);
- s2->assignProperty(&obj, "foo", 456);
- s2->assignProperty(&obj, "bar", 654);
- s2->assignProperty(&obj, "baz", 789);
- QAbstractTransition *trans = s1->addTransition(s2);
- QSequentialAnimationGroup group;
- group.addAnimation(new QPropertyAnimation(&obj, "foo"));
- group.addAnimation(new QPropertyAnimation(&obj, "bar"));
- trans->addAnimation(&group);
- QFinalState *s3 = new QFinalState(&machine);
- s2->addTransition(s2, SIGNAL(propertiesAssigned()), s3);
-
- machine.setInitialState(s1);
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(obj.property("foo").toInt(), 456);
- QCOMPARE(obj.property("bar").toInt(), 654);
- QCOMPARE(obj.property("baz").toInt(), 789);
- }
- // Nested states
- {
- QStateMachine machine;
- QObject obj;
- obj.setProperty("foo", 321);
- obj.setProperty("bar", 654);
- QState *s1 = new QState(&machine);
- QCOMPARE(s1->childMode(), QState::ExclusiveStates);
- s1->setChildMode(QState::ParallelStates);
- QCOMPARE(s1->childMode(), QState::ParallelStates);
- s1->setChildMode(QState::ExclusiveStates);
- QCOMPARE(s1->childMode(), QState::ExclusiveStates);
- QCOMPARE(s1->initialState(), (QAbstractState*)0);
- s1->setObjectName("s1");
- s1->assignProperty(&obj, "foo", 123);
- s1->assignProperty(&obj, "bar", 456);
- QState *s2 = new QState(&machine);
- s2->setObjectName("s2");
- s2->assignProperty(&obj, "foo", 321);
- QState *s21 = new QState(s2);
- s21->setObjectName("s21");
- s21->assignProperty(&obj, "bar", 654);
- QState *s22 = new QState(s2);
- s22->setObjectName("s22");
- s22->assignProperty(&obj, "bar", 789);
- s2->setInitialState(s21);
- QCOMPARE(s2->initialState(), (QAbstractState*)s21);
-
- QAbstractTransition *trans = s1->addTransition(s2);
- QPropertyAnimation anim(&obj, "foo");
- anim.setDuration(500);
- trans->addAnimation(&anim);
- QPropertyAnimation anim2(&obj, "bar");
- anim2.setDuration(250);
- trans->addAnimation(&anim2);
-
- s21->addTransition(s21, SIGNAL(propertiesAssigned()), s22);
-
- QFinalState *s3 = new QFinalState(&machine);
- s22->addTransition(s2, SIGNAL(propertiesAssigned()), s3);
-
- machine.setInitialState(s1);
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(obj.property("foo").toInt(), 321);
- QCOMPARE(obj.property("bar").toInt(), 789);
- }
- // Aborted animation
- {
- QStateMachine machine;
- SignalEmitter emitter;
- QObject obj;
- obj.setProperty("foo", 321);
- obj.setProperty("bar", 654);
- QState *group = new QState(&machine);
- QState *s1 = new QState(group);
- group->setInitialState(s1);
- s1->assignProperty(&obj, "foo", 123);
- QState *s2 = new QState(group);
- s2->assignProperty(&obj, "foo", 456);
- s2->assignProperty(&obj, "bar", 789);
- QAbstractTransition *trans = s1->addTransition(&emitter, SIGNAL(signalWithNoArg()), s2);
- QPropertyAnimation anim(&obj, "foo");
- anim.setDuration(8000);
- trans->addAnimation(&anim);
- QPropertyAnimation anim2(&obj, "bar");
- anim2.setDuration(8000);
- trans->addAnimation(&anim2);
- QState *s3 = new QState(group);
- s3->assignProperty(&obj, "foo", 911);
- s2->addTransition(&emitter, SIGNAL(signalWithNoArg()), s3);
-
- machine.setInitialState(group);
- machine.start();
- QTRY_COMPARE(machine.configuration().contains(s1), true);
- QSignalSpy propertiesAssignedSpy(s2, SIGNAL(propertiesAssigned()));
- emitter.emitSignalWithNoArg();
- QTRY_COMPARE(machine.configuration().contains(s2), true);
- QVERIFY(propertiesAssignedSpy.isEmpty());
- emitter.emitSignalWithNoArg(); // will cause animations from s1-->s2 to abort
- QTRY_COMPARE(machine.configuration().contains(s3), true);
- QVERIFY(propertiesAssignedSpy.isEmpty());
- QCOMPARE(obj.property("foo").toInt(), 911);
- QCOMPARE(obj.property("bar").toInt(), 789);
- }
-}
-
-struct StringEvent : public QEvent
-{
-public:
- StringEvent(const QString &val)
- : QEvent(QEvent::Type(QEvent::User+2)),
- value(val) {}
-
- QString value;
-};
-
-class StringTransition : public QAbstractTransition
-{
-public:
- StringTransition(const QString &value, QAbstractState *target)
- : QAbstractTransition(), m_value(value)
- { setTargetState(target); }
-
-protected:
- virtual bool eventTest(QEvent *e)
- {
- if (e->type() != QEvent::Type(QEvent::User+2))
- return false;
- StringEvent *se = static_cast<StringEvent*>(e);
- return (m_value == se->value) && (!m_cond.isValid() || (m_cond.indexIn(m_value) != -1));
- }
- virtual void onTransition(QEvent *) {}
-
-private:
- QString m_value;
- QRegExp m_cond;
-};
-
-class StringEventPoster : public QState
-{
-public:
- StringEventPoster(const QString &value, QState *parent = 0)
- : QState(parent), m_value(value), m_delay(-1) {}
-
- void setString(const QString &value)
- { m_value = value; }
- void setDelay(int delay)
- { m_delay = delay; }
-
-protected:
- virtual void onEntry(QEvent *)
- {
- if (m_delay == -1)
- machine()->postEvent(new StringEvent(m_value));
- else
- machine()->postDelayedEvent(new StringEvent(m_value), m_delay);
- }
- virtual void onExit(QEvent *) {}
-
-private:
- QString m_value;
- int m_delay;
-};
-
-void tst_QStateMachine::postEvent()
-{
- for (int x = 0; x < 2; ++x) {
- QStateMachine machine;
- {
- QEvent e(QEvent::None);
- QTest::ignoreMessage(QtWarningMsg, "QStateMachine::postEvent: cannot post event when the state machine is not running");
- machine.postEvent(&e);
- }
- StringEventPoster *s1 = new StringEventPoster("a");
- if (x == 1)
- s1->setDelay(100);
- QFinalState *s2 = new QFinalState;
- s1->addTransition(new StringTransition("a", s2));
- machine.addState(s1);
- machine.addState(s2);
- machine.setInitialState(s1);
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s2));
-
- s1->setString("b");
- QFinalState *s3 = new QFinalState();
- machine.addState(s3);
- s1->addTransition(new StringTransition("b", s3));
- finishedSpy.clear();
- machine.start();
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s3));
- }
-}
-
-void tst_QStateMachine::cancelDelayedEvent()
-{
- QStateMachine machine;
- QTest::ignoreMessage(QtWarningMsg, "QStateMachine::cancelDelayedEvent: the machine is not running");
- QVERIFY(!machine.cancelDelayedEvent(-1));
-
- QState *s1 = new QState(&machine);
- QFinalState *s2 = new QFinalState(&machine);
- s1->addTransition(new StringTransition("a", s2));
- machine.setInitialState(s1);
-
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- int id1 = machine.postDelayedEvent(new StringEvent("c"), 50000);
- QVERIFY(id1 != -1);
- int id2 = machine.postDelayedEvent(new StringEvent("b"), 25000);
- QVERIFY(id2 != -1);
- QVERIFY(id2 != id1);
- int id3 = machine.postDelayedEvent(new StringEvent("a"), 100);
- QVERIFY(id3 != -1);
- QVERIFY(id3 != id2);
- QVERIFY(machine.cancelDelayedEvent(id1));
- QVERIFY(!machine.cancelDelayedEvent(id1));
- QVERIFY(machine.cancelDelayedEvent(id2));
- QVERIFY(!machine.cancelDelayedEvent(id2));
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s2));
-}
-
-void tst_QStateMachine::postDelayedEventAndStop()
-{
- QStateMachine machine;
- QState *s1 = new QState(&machine);
- QFinalState *s2 = new QFinalState(&machine);
- s1->addTransition(new StringTransition("a", s2));
- machine.setInitialState(s1);
-
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- int id1 = machine.postDelayedEvent(new StringEvent("a"), 0);
- QVERIFY(id1 != -1);
- QSignalSpy stoppedSpy(&machine, SIGNAL(stopped()));
- machine.stop();
- QTRY_COMPARE(stoppedSpy.count(), 1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 2);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- int id2 = machine.postDelayedEvent(new StringEvent("a"), 1000);
- QVERIFY(id2 != -1);
- machine.stop();
- QTRY_COMPARE(stoppedSpy.count(), 2);
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 3);
- QTestEventLoop::instance().enterLoop(2);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-}
-
-void tst_QStateMachine::stopAndPostEvent()
-{
- QStateMachine machine;
- QState *s1 = new QState(&machine);
- machine.setInitialState(s1);
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 1);
- QSignalSpy stoppedSpy(&machine, SIGNAL(stopped()));
- machine.stop();
- QCOMPARE(stoppedSpy.count(), 0);
- machine.postEvent(new QEvent(QEvent::User));
- QTRY_COMPARE(stoppedSpy.count(), 1);
- QCoreApplication::processEvents();
-}
-
-void tst_QStateMachine::stateFinished()
-{
- QStateMachine machine;
- QState *s1 = new QState(&machine);
- QState *s1_1 = new QState(s1);
- QFinalState *s1_2 = new QFinalState(s1);
- s1_1->addTransition(s1_2);
- s1->setInitialState(s1_1);
- QFinalState *s2 = new QFinalState(&machine);
- s1->addTransition(s1, SIGNAL(finished()), s2);
- machine.setInitialState(s1);
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s2));
-}
-
-void tst_QStateMachine::parallelStates()
-{
- QStateMachine machine;
-
- QState *s1 = new QState(QState::ParallelStates);
- QCOMPARE(s1->childMode(), QState::ParallelStates);
- QState *s1_1 = new QState(s1);
- QState *s1_1_1 = new QState(s1_1);
- QFinalState *s1_1_f = new QFinalState(s1_1);
- s1_1_1->addTransition(s1_1_f);
- s1_1->setInitialState(s1_1_1);
- QState *s1_2 = new QState(s1);
- QState *s1_2_1 = new QState(s1_2);
- QFinalState *s1_2_f = new QFinalState(s1_2);
- s1_2_1->addTransition(s1_2_f);
- s1_2->setInitialState(s1_2_1);
- {
- QString warning;
- warning.sprintf("QState::setInitialState: ignoring attempt to set initial state of parallel state group %p", s1);
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- s1->setInitialState(0);
- }
- machine.addState(s1);
-
- QFinalState *s2 = new QFinalState();
- machine.addState(s2);
-
- s1->addTransition(s1, SIGNAL(finished()), s2);
-
- machine.setInitialState(s1);
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s2));
-}
-
-void tst_QStateMachine::parallelRootState()
-{
- QStateMachine machine;
- QState *root = &machine;
- QCOMPARE(root->childMode(), QState::ExclusiveStates);
- root->setChildMode(QState::ParallelStates);
- QCOMPARE(root->childMode(), QState::ParallelStates);
-
- QState *s1 = new QState(root);
- QFinalState *s1_f = new QFinalState(s1);
- s1->setInitialState(s1_f);
- QState *s2 = new QState(root);
- QFinalState *s2_f = new QFinalState(s2);
- s2->setInitialState(s2_f);
-
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- QTest::ignoreMessage(QtWarningMsg, "QStateMachine::start: No initial state set for machine. Refusing to start.");
- machine.start();
- QCoreApplication::processEvents();
- QEXPECT_FAIL("", "parallel root state is not supported (task 256587)", Continue);
- QCOMPARE(startedSpy.count(), 1);
-}
-
-void tst_QStateMachine::allSourceToTargetConfigurations()
-{
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- s0->setObjectName("s0");
- QState *s1 = new QState(s0);
- s1->setObjectName("s1");
- QState *s11 = new QState(s1);
- s11->setObjectName("s11");
- QState *s2 = new QState(s0);
- s2->setObjectName("s2");
- QState *s21 = new QState(s2);
- s21->setObjectName("s21");
- QState *s211 = new QState(s21);
- s211->setObjectName("s211");
- QFinalState *f = new QFinalState(&machine);
- f->setObjectName("f");
-
- s0->setInitialState(s1);
- s1->setInitialState(s11);
- s2->setInitialState(s21);
- s21->setInitialState(s211);
-
- s11->addTransition(new StringTransition("g", s211));
- s1->addTransition(new StringTransition("a", s1));
- s1->addTransition(new StringTransition("b", s11));
- s1->addTransition(new StringTransition("c", s2));
- s1->addTransition(new StringTransition("d", s0));
- s1->addTransition(new StringTransition("f", s211));
- s211->addTransition(new StringTransition("d", s21));
- s211->addTransition(new StringTransition("g", s0));
- s211->addTransition(new StringTransition("h", f));
- s21->addTransition(new StringTransition("b", s211));
- s2->addTransition(new StringTransition("c", s1));
- s2->addTransition(new StringTransition("f", s11));
- s0->addTransition(new StringTransition("e", s211));
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new StringEvent("a"));
- QCoreApplication::processEvents();
- machine.postEvent(new StringEvent("b"));
- QCoreApplication::processEvents();
- machine.postEvent(new StringEvent("c"));
- QCoreApplication::processEvents();
- machine.postEvent(new StringEvent("d"));
- QCoreApplication::processEvents();
- machine.postEvent(new StringEvent("e"));
- QCoreApplication::processEvents();
- machine.postEvent(new StringEvent("f"));
- QCoreApplication::processEvents();
- machine.postEvent(new StringEvent("g"));
- QCoreApplication::processEvents();
- machine.postEvent(new StringEvent("h"));
- QCoreApplication::processEvents();
-
- QTRY_COMPARE(finishedSpy.count(), 1);
-}
-
-class TestSignalTransition : public QSignalTransition
-{
-public:
- TestSignalTransition(QState *sourceState = 0)
- : QSignalTransition(sourceState), m_sender(0)
- {}
- TestSignalTransition(QObject *sender, const char *signal,
- QAbstractState *target)
- : QSignalTransition(sender, signal), m_sender(0)
- { setTargetState(target); }
- QObject *senderReceived() const {
- return m_sender;
- }
- int signalIndexReceived() const {
- return m_signalIndex;
- }
- QVariantList argumentsReceived() const {
- return m_args;
- }
-protected:
- bool eventTest(QEvent *e) {
- if (!QSignalTransition::eventTest(e))
- return false;
- QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(e);
- m_sender = se->sender();
- m_signalIndex = se->signalIndex();
- m_args = se->arguments();
- return true;
- }
-private:
- QObject *m_sender;
- int m_signalIndex;
- QVariantList m_args;
-};
-
-void tst_QStateMachine::signalTransitions()
-{
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: sender cannot be null");
- QCOMPARE(s0->addTransition(0, SIGNAL(noSuchSignal()), 0), (QSignalTransition*)0);
-
- SignalEmitter emitter;
- QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: signal cannot be null");
- QCOMPARE(s0->addTransition(&emitter, 0, 0), (QSignalTransition*)0);
-
- QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: cannot add transition to null state");
- QCOMPARE(s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), 0), (QSignalTransition*)0);
-
- QFinalState *s1 = new QFinalState(&machine);
- QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: no such signal SignalEmitter::noSuchSignal()");
- QCOMPARE(s0->addTransition(&emitter, SIGNAL(noSuchSignal()), s1), (QSignalTransition*)0);
-
- QSignalTransition *trans = s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), s1);
- QVERIFY(trans != 0);
- QCOMPARE(trans->sourceState(), s0);
- QCOMPARE(trans->targetState(), (QAbstractState*)s1);
- QCOMPARE(trans->senderObject(), (QObject*)&emitter);
- QCOMPARE(trans->signal(), QByteArray(SIGNAL(signalWithNoArg())));
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
-
- emitter.emitSignalWithNoArg();
-
- QTRY_COMPARE(finishedSpy.count(), 1);
-
- emitter.emitSignalWithNoArg();
-
- trans->setSignal(SIGNAL(signalWithIntArg(int)));
- QCOMPARE(trans->signal(), QByteArray(SIGNAL(signalWithIntArg(int))));
- machine.start();
- QCoreApplication::processEvents();
- emitter.emitSignalWithIntArg(123);
- QTRY_COMPARE(finishedSpy.count(), 2);
-
- machine.start();
- QCoreApplication::processEvents();
- trans->setSignal(SIGNAL(signalWithNoArg()));
- QCOMPARE(trans->signal(), QByteArray(SIGNAL(signalWithNoArg())));
- emitter.emitSignalWithNoArg();
- QTRY_COMPARE(finishedSpy.count(), 3);
-
- SignalEmitter emitter2;
- machine.start();
- QCoreApplication::processEvents();
- trans->setSenderObject(&emitter2);
- emitter2.emitSignalWithNoArg();
- QTRY_COMPARE(finishedSpy.count(), 4);
-
- machine.start();
- QCoreApplication::processEvents();
- QTest::ignoreMessage(QtWarningMsg, "QSignalTransition: no such signal: SignalEmitter::noSuchSignal()");
- trans->setSignal(SIGNAL(noSuchSignal()));
- QCOMPARE(trans->signal(), QByteArray(SIGNAL(noSuchSignal())));
- }
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
- SignalEmitter emitter;
- QSignalTransition *trans = s0->addTransition(&emitter, "signalWithNoArg()", s1);
- QVERIFY(trans != 0);
- QCOMPARE(trans->sourceState(), s0);
- QCOMPARE(trans->targetState(), (QAbstractState*)s1);
- QCOMPARE(trans->senderObject(), (QObject*)&emitter);
- QCOMPARE(trans->signal(), QByteArray("signalWithNoArg()"));
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
-
- emitter.emitSignalWithNoArg();
-
- QTRY_COMPARE(finishedSpy.count(), 1);
-
- trans->setSignal("signalWithIntArg(int)");
- QCOMPARE(trans->signal(), QByteArray("signalWithIntArg(int)"));
- machine.start();
- QCoreApplication::processEvents();
- emitter.emitSignalWithIntArg(123);
- QTRY_COMPARE(finishedSpy.count(), 2);
- }
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
- SignalEmitter emitter;
- TestSignalTransition *trans = new TestSignalTransition(&emitter, SIGNAL(signalWithIntArg(int)), s1);
- s0->addTransition(trans);
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
-
- emitter.emitSignalWithIntArg(123);
-
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(trans->senderReceived(), (QObject*)&emitter);
- QCOMPARE(trans->signalIndexReceived(), emitter.metaObject()->indexOfSignal("signalWithIntArg(int)"));
- QCOMPARE(trans->argumentsReceived().size(), 1);
- QCOMPARE(trans->argumentsReceived().at(0).toInt(), 123);
- }
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
- SignalEmitter emitter;
- TestSignalTransition *trans = new TestSignalTransition(&emitter, SIGNAL(signalWithStringArg(QString)), s1);
- s0->addTransition(trans);
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
-
- QString testString = QString::fromLatin1("hello");
- emitter.emitSignalWithStringArg(testString);
-
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(trans->senderReceived(), (QObject*)&emitter);
- QCOMPARE(trans->signalIndexReceived(), emitter.metaObject()->indexOfSignal("signalWithStringArg(QString)"));
- QCOMPARE(trans->argumentsReceived().size(), 1);
- QCOMPARE(trans->argumentsReceived().at(0).toString(), testString);
- }
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
-
- TestSignalTransition *trans = new TestSignalTransition();
- QCOMPARE(trans->senderObject(), (QObject*)0);
- QCOMPARE(trans->signal(), QByteArray());
-
- SignalEmitter emitter;
- trans->setSenderObject(&emitter);
- QCOMPARE(trans->senderObject(), (QObject*)&emitter);
- trans->setSignal(SIGNAL(signalWithNoArg()));
- QCOMPARE(trans->signal(), QByteArray(SIGNAL(signalWithNoArg())));
- trans->setTargetState(s1);
- s0->addTransition(trans);
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
-
- emitter.emitSignalWithNoArg();
-
- QTRY_COMPARE(finishedSpy.count(), 1);
- }
- // Multiple transitions for same (object,signal)
- {
- QStateMachine machine;
- SignalEmitter emitter;
- QState *s0 = new QState(&machine);
- QState *s1 = new QState(&machine);
- QSignalTransition *t0 = s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), s1);
- QSignalTransition *t1 = s1->addTransition(&emitter, SIGNAL(signalWithNoArg()), s0);
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s0));
-
- emitter.emitSignalWithNoArg();
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- s0->removeTransition(t0);
- emitter.emitSignalWithNoArg();
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s0));
-
- emitter.emitSignalWithNoArg();
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s0));
-
- s1->removeTransition(t1);
- emitter.emitSignalWithNoArg();
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s0));
-
- s0->addTransition(t0);
- s1->addTransition(t1);
- emitter.emitSignalWithNoArg();
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
- }
- // multiple signal transitions from same source
- {
- QStateMachine machine;
- SignalEmitter emitter;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
- s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), s1);
- QFinalState *s2 = new QFinalState(&machine);
- s0->addTransition(&emitter, SIGNAL(signalWithIntArg(int)), s2);
- QFinalState *s3 = new QFinalState(&machine);
- s0->addTransition(&emitter, SIGNAL(signalWithStringArg(QString)), s3);
-
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
-
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 1);
- emitter.emitSignalWithNoArg();
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 2);
- emitter.emitSignalWithIntArg(123);
- QTRY_COMPARE(finishedSpy.count(), 2);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s2));
-
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 3);
- emitter.emitSignalWithStringArg("hello");
- QTRY_COMPARE(finishedSpy.count(), 3);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s3));
- }
- // signature normalization
- {
- QStateMachine machine;
- SignalEmitter emitter;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
- QSignalTransition *t0 = s0->addTransition(&emitter, SIGNAL( signalWithNoArg( ) ), s1);
- QVERIFY(t0 != 0);
- QCOMPARE(t0->signal(), QByteArray(SIGNAL( signalWithNoArg( ) )));
-
- QSignalTransition *t1 = s0->addTransition(&emitter, SIGNAL( signalWithStringArg( const QString & ) ), s1);
- QVERIFY(t1 != 0);
- QCOMPARE(t1->signal(), QByteArray(SIGNAL( signalWithStringArg( const QString & ) )));
-
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 1);
- QCOMPARE(finishedSpy.count(), 0);
-
- emitter.emitSignalWithNoArg();
-
- QTRY_COMPARE(finishedSpy.count(), 1);
- }
-}
-
-class TestEventTransition : public QEventTransition
-{
-public:
- TestEventTransition(QState *sourceState = 0)
- : QEventTransition(sourceState),
- m_eventSource(0), m_eventType(QEvent::None)
- {}
- TestEventTransition(QObject *object, QEvent::Type type,
- QAbstractState *target)
- : QEventTransition(object, type),
- m_eventSource(0), m_eventType(QEvent::None)
- { setTargetState(target); }
- QObject *eventSourceReceived() const {
- return m_eventSource;
- }
- QEvent::Type eventTypeReceived() const {
- return m_eventType;
- }
-protected:
- bool eventTest(QEvent *e) {
- if (!QEventTransition::eventTest(e))
- return false;
- QStateMachine::WrappedEvent *we = static_cast<QStateMachine::WrappedEvent*>(e);
- m_eventSource = we->object();
- m_eventType = we->event()->type();
- return true;
- }
-private:
- QObject *m_eventSource;
- QEvent::Type m_eventType;
-};
-
-void tst_QStateMachine::eventTransitions()
-{
- QPushButton button;
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
-
- QMouseEventTransition *trans;
- trans = new QMouseEventTransition(&button, QEvent::MouseButtonPress, Qt::LeftButton);
- QCOMPARE(trans->targetState(), (QAbstractState*)0);
- trans->setTargetState(s1);
- QCOMPARE(trans->eventType(), QEvent::MouseButtonPress);
- QCOMPARE(trans->button(), Qt::LeftButton);
- QCOMPARE(trans->targetState(), (QAbstractState*)s1);
- s0->addTransition(trans);
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
-
- QTest::mousePress(&button, Qt::LeftButton);
- QTRY_COMPARE(finishedSpy.count(), 1);
-
- QTest::mousePress(&button, Qt::LeftButton);
-
- trans->setEventType(QEvent::MouseButtonRelease);
- QCOMPARE(trans->eventType(), QEvent::MouseButtonRelease);
- machine.start();
- QCoreApplication::processEvents();
- QTest::mouseRelease(&button, Qt::LeftButton);
- QTRY_COMPARE(finishedSpy.count(), 2);
-
- machine.start();
- QCoreApplication::processEvents();
- trans->setEventType(QEvent::MouseButtonPress);
- QTest::mousePress(&button, Qt::LeftButton);
- QTRY_COMPARE(finishedSpy.count(), 3);
-
- QPushButton button2;
- machine.start();
- QCoreApplication::processEvents();
- trans->setEventSource(&button2);
- QTest::mousePress(&button2, Qt::LeftButton);
- QTRY_COMPARE(finishedSpy.count(), 4);
- }
- for (int x = 0; x < 2; ++x) {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
-
- QEventTransition *trans;
- if (x == 0) {
- trans = new QEventTransition();
- QCOMPARE(trans->eventSource(), (QObject*)0);
- QCOMPARE(trans->eventType(), QEvent::None);
- trans->setEventSource(&button);
- trans->setEventType(QEvent::MouseButtonPress);
- trans->setTargetState(s1);
- } else if (x == 1) {
- trans = new QEventTransition(&button, QEvent::MouseButtonPress);
- trans->setTargetState(s1);
- }
- QCOMPARE(trans->eventSource(), (QObject*)&button);
- QCOMPARE(trans->eventType(), QEvent::MouseButtonPress);
- QCOMPARE(trans->targetState(), (QAbstractState*)s1);
- s0->addTransition(trans);
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
-
- QTest::mousePress(&button, Qt::LeftButton);
- QCoreApplication::processEvents();
-
- QTRY_COMPARE(finishedSpy.count(), 1);
- }
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
-
- QMouseEventTransition *trans = new QMouseEventTransition();
- QCOMPARE(trans->eventSource(), (QObject*)0);
- QCOMPARE(trans->eventType(), QEvent::None);
- QCOMPARE(trans->button(), Qt::NoButton);
- trans->setEventSource(&button);
- trans->setEventType(QEvent::MouseButtonPress);
- trans->setButton(Qt::LeftButton);
- trans->setTargetState(s1);
- s0->addTransition(trans);
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
-
- QTest::mousePress(&button, Qt::LeftButton);
- QCoreApplication::processEvents();
-
- QTRY_COMPARE(finishedSpy.count(), 1);
- }
-
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
-
- QKeyEventTransition *trans = new QKeyEventTransition(&button, QEvent::KeyPress, Qt::Key_A);
- QCOMPARE(trans->eventType(), QEvent::KeyPress);
- QCOMPARE(trans->key(), (int)Qt::Key_A);
- trans->setTargetState(s1);
- s0->addTransition(trans);
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
-
- QTest::keyPress(&button, Qt::Key_A);
- QCoreApplication::processEvents();
-
- QTRY_COMPARE(finishedSpy.count(), 1);
- }
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
-
- QKeyEventTransition *trans = new QKeyEventTransition();
- QCOMPARE(trans->eventSource(), (QObject*)0);
- QCOMPARE(trans->eventType(), QEvent::None);
- QCOMPARE(trans->key(), 0);
- trans->setEventSource(&button);
- trans->setEventType(QEvent::KeyPress);
- trans->setKey(Qt::Key_A);
- trans->setTargetState(s1);
- s0->addTransition(trans);
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
-
- QTest::keyPress(&button, Qt::Key_A);
- QCoreApplication::processEvents();
-
- QTRY_COMPARE(finishedSpy.count(), 1);
- }
- // Multiple transitions for same (object,event)
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QState *s1 = new QState(&machine);
- QEventTransition *t0 = new QEventTransition(&button, QEvent::MouseButtonPress);
- t0->setTargetState(s1);
- s0->addTransition(t0);
- QEventTransition *t1 = new QEventTransition(&button, QEvent::MouseButtonPress);
- t1->setTargetState(s0);
- s1->addTransition(t1);
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s0));
-
- QTest::mousePress(&button, Qt::LeftButton);
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- s0->removeTransition(t0);
- QTest::mousePress(&button, Qt::LeftButton);
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s0));
-
- QTest::mousePress(&button, Qt::LeftButton);
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s0));
-
- s1->removeTransition(t1);
- QTest::mousePress(&button, Qt::LeftButton);
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s0));
-
- s0->addTransition(t0);
- s1->addTransition(t1);
- QTest::mousePress(&button, Qt::LeftButton);
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
- }
- // multiple event transitions from same source
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
- QFinalState *s2 = new QFinalState(&machine);
- QEventTransition *t0 = new QEventTransition(&button, QEvent::MouseButtonPress);
- t0->setTargetState(s1);
- s0->addTransition(t0);
- QEventTransition *t1 = new QEventTransition(&button, QEvent::MouseButtonRelease);
- t1->setTargetState(s2);
- s0->addTransition(t1);
-
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
-
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 1);
- QTest::mousePress(&button, Qt::LeftButton);
- QTRY_COMPARE(finishedSpy.count(), 1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 2);
- QTest::mouseRelease(&button, Qt::LeftButton);
- QTRY_COMPARE(finishedSpy.count(), 2);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s2));
- }
- // custom event
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
-
- QEventTransition *trans = new QEventTransition(&button, QEvent::Type(QEvent::User+1));
- trans->setTargetState(s1);
- s0->addTransition(trans);
-
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- machine.setInitialState(s0);
- machine.start();
- QTest::ignoreMessage(QtWarningMsg, "QObject event transitions are not supported for custom types");
- QTRY_COMPARE(startedSpy.count(), 1);
- }
- // custom transition
- {
- QStateMachine machine;
- QState *s0 = new QState(&machine);
- QFinalState *s1 = new QFinalState(&machine);
-
- TestEventTransition *trans = new TestEventTransition(&button, QEvent::MouseButtonPress, s1);
- s0->addTransition(trans);
- QCOMPARE(trans->eventSourceReceived(), (QObject*)0);
- QCOMPARE(trans->eventTypeReceived(), QEvent::None);
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.setInitialState(s0);
- machine.start();
- QCoreApplication::processEvents();
-
- QTest::mousePress(&button, Qt::LeftButton);
- QCoreApplication::processEvents();
-
- QTRY_COMPARE(finishedSpy.count(), 1);
-
- QCOMPARE(trans->eventSourceReceived(), (QObject*)&button);
- QCOMPARE(trans->eventTypeReceived(), QEvent::MouseButtonPress);
- }
-}
-
-void tst_QStateMachine::graphicsSceneEventTransitions()
-{
- QGraphicsScene scene;
- QGraphicsTextItem *textItem = scene.addText("foo");
-
- QStateMachine machine;
- QState *s1 = new QState(&machine);
- QFinalState *s2 = new QFinalState(&machine);
- QEventTransition *t = new QEventTransition(textItem, QEvent::GraphicsSceneMouseMove);
- t->setTargetState(s2);
- s1->addTransition(t);
- machine.setInitialState(s1);
-
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 1);
- QVERIFY(finishedSpy.count() == 0);
- QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
- scene.sendEvent(textItem, &mouseEvent);
- QTRY_COMPARE(finishedSpy.count(), 1);
-}
-
-void tst_QStateMachine::historyStates()
-{
- for (int x = 0; x < 2; ++x) {
- QStateMachine machine;
- QState *root = &machine;
- QState *s0 = new QState(root);
- QState *s00 = new QState(s0);
- QState *s01 = new QState(s0);
- QHistoryState *s0h;
- if (x == 0) {
- s0h = new QHistoryState(s0);
- QCOMPARE(s0h->historyType(), QHistoryState::ShallowHistory);
- s0h->setHistoryType(QHistoryState::DeepHistory);
- } else {
- s0h = new QHistoryState(QHistoryState::DeepHistory, s0);
- }
- QCOMPARE(s0h->historyType(), QHistoryState::DeepHistory);
- s0h->setHistoryType(QHistoryState::ShallowHistory);
- QCOMPARE(s0h->historyType(), QHistoryState::ShallowHistory);
- QCOMPARE(s0h->defaultState(), (QAbstractState*)0);
- s0h->setDefaultState(s00);
- QCOMPARE(s0h->defaultState(), (QAbstractState*)s00);
- QString warning;
- warning.sprintf("QHistoryState::setDefaultState: state %p does not belong to this history state's group (%p)", s0, s0);
- QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- s0h->setDefaultState(s0);
- QState *s1 = new QState(root);
- QFinalState *s2 = new QFinalState(root);
-
- s00->addTransition(new StringTransition("a", s01));
- s0->addTransition(new StringTransition("b", s1));
- s1->addTransition(new StringTransition("c", s0h));
- s0->addTransition(new StringTransition("d", s2));
-
- root->setInitialState(s0);
- s0->setInitialState(s00);
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 2);
- QVERIFY(machine.configuration().contains(s0));
- QVERIFY(machine.configuration().contains(s00));
-
- machine.postEvent(new StringEvent("a"));
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 2);
- QVERIFY(machine.configuration().contains(s0));
- QVERIFY(machine.configuration().contains(s01));
-
- machine.postEvent(new StringEvent("b"));
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- machine.postEvent(new StringEvent("c"));
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 2);
- QVERIFY(machine.configuration().contains(s0));
- QVERIFY(machine.configuration().contains(s01));
-
- machine.postEvent(new StringEvent("d"));
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s2));
-
- QTRY_COMPARE(finishedSpy.count(), 1);
- }
-}
-
-void tst_QStateMachine::startAndStop()
-{
- QStateMachine machine;
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- QSignalSpy stoppedSpy(&machine, SIGNAL(stopped()));
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- QVERIFY(!machine.isRunning());
- QTest::ignoreMessage(QtWarningMsg, "QStateMachine::start: No initial state set for machine. Refusing to start.");
- machine.start();
- QCOMPARE(startedSpy.count(), 0);
- QCOMPARE(stoppedSpy.count(), 0);
- QCOMPARE(finishedSpy.count(), 0);
- QVERIFY(!machine.isRunning());
- machine.stop();
- QCOMPARE(startedSpy.count(), 0);
- QCOMPARE(stoppedSpy.count(), 0);
- QCOMPARE(finishedSpy.count(), 0);
-
- QState *s1 = new QState(&machine);
- machine.setInitialState(s1);
- machine.start();
- QTRY_COMPARE(machine.isRunning(), true);
- QTRY_COMPARE(startedSpy.count(), 1);
- QCOMPARE(stoppedSpy.count(), 0);
- QCOMPARE(finishedSpy.count(), 0);
- QCOMPARE(machine.configuration().count(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- QTest::ignoreMessage(QtWarningMsg, "QStateMachine::start(): already running");
- machine.start();
-
- machine.stop();
- QTRY_COMPARE(machine.isRunning(), false);
- QTRY_COMPARE(stoppedSpy.count(), 1);
- QCOMPARE(startedSpy.count(), 1);
- QCOMPARE(finishedSpy.count(), 0);
-
- QCOMPARE(machine.configuration().count(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- machine.start();
- machine.stop();
- QTRY_COMPARE(startedSpy.count(), 2);
- QCOMPARE(stoppedSpy.count(), 2);
-}
-
-void tst_QStateMachine::targetStateWithNoParent()
-{
- QStateMachine machine;
- QState *s1 = new QState(&machine);
- s1->setObjectName("s1");
- QState s2;
- s1->addTransition(&s2);
- machine.setInitialState(s1);
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- QSignalSpy stoppedSpy(&machine, SIGNAL(stopped()));
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 's1'");
- QTRY_COMPARE(startedSpy.count(), 1);
- QCOMPARE(machine.isRunning(), false);
- QCOMPARE(stoppedSpy.count(), 1);
- QCOMPARE(finishedSpy.count(), 0);
- QCOMPARE(machine.error(), QStateMachine::NoCommonAncestorForTransitionError);
-}
-
-void tst_QStateMachine::targetStateDeleted()
-{
- QStateMachine machine;
- QState *s1 = new QState(&machine);
- s1->setObjectName("s1");
- QState *s2 = new QState(&machine);
- QAbstractTransition *trans = s1->addTransition(s2);
- delete s2;
- QCOMPARE(trans->targetState(), (QAbstractState*)0);
- QVERIFY(trans->targetStates().isEmpty());
-}
-
-void tst_QStateMachine::defaultGlobalRestorePolicy()
-{
- QStateMachine machine;
-
- QObject *propertyHolder = new QObject(&machine);
- propertyHolder->setProperty("a", 1);
- propertyHolder->setProperty("b", 2);
-
- QState *s1 = new QState(&machine);
- s1->assignProperty(propertyHolder, "a", 3);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(propertyHolder, "b", 4);
-
- QState *s3 = new QState(&machine);
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
- s2->addTransition(new EventTransition(QEvent::User, s3));
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 3);
- QCOMPARE(propertyHolder->property("b").toInt(), 2);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 3);
- QCOMPARE(propertyHolder->property("b").toInt(), 4);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 3);
- QCOMPARE(propertyHolder->property("b").toInt(), 4);
-}
-
-void tst_QStateMachine::noInitialStateForInitialState()
-{
- QStateMachine machine;
-
- QState *initialState = new QState(&machine);
- initialState->setObjectName("initialState");
- machine.setInitialState(initialState);
-
- QState *childState = new QState(initialState);
- (void)childState;
-
- QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: "
- "Missing initial state in compound state 'initialState'");
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.isRunning(), false);
- QCOMPARE(int(machine.error()), int(QStateMachine::NoInitialStateError));
-}
-
-/*
-void tst_QStateMachine::restorePolicyNotInherited()
-{
- QStateMachine machine;
-
- QObject *propertyHolder = new QObject();
- propertyHolder->setProperty("a", 1);
- propertyHolder->setProperty("b", 2);
-
- QState *parentState = new QState(&machine);
- parentState->setObjectName("parentState");
- parentState->setRestorePolicy(QState::RestoreProperties);
-
- QState *s1 = new QState(parentState);
- s1->setObjectName("s1");
- s1->assignProperty(propertyHolder, "a", 3);
- parentState->setInitialState(s1);
-
- QState *s2 = new QState(parentState);
- s2->setObjectName("s2");
- s2->assignProperty(propertyHolder, "b", 4);
-
- QState *s3 = new QState(parentState);
- s3->setObjectName("s3");
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
- s2->addTransition(new EventTransition(QEvent::User, s3));
-
- machine.setInitialState(parentState);
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 3);
- QCOMPARE(propertyHolder->property("b").toInt(), 2);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 3);
- QCOMPARE(propertyHolder->property("b").toInt(), 4);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 3);
- QCOMPARE(propertyHolder->property("b").toInt(), 4);
-
-}*/
-
-void tst_QStateMachine::globalRestorePolicySetToDontRestore()
-{
- QStateMachine machine;
- machine.setGlobalRestorePolicy(QStateMachine::DontRestoreProperties);
-
- QObject *propertyHolder = new QObject(&machine);
- propertyHolder->setProperty("a", 1);
- propertyHolder->setProperty("b", 2);
-
- QState *s1 = new QState(&machine);
- s1->assignProperty(propertyHolder, "a", 3);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(propertyHolder, "b", 4);
-
- QState *s3 = new QState(&machine);
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
- s2->addTransition(new EventTransition(QEvent::User, s3));
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 3);
- QCOMPARE(propertyHolder->property("b").toInt(), 2);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 3);
- QCOMPARE(propertyHolder->property("b").toInt(), 4);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 3);
- QCOMPARE(propertyHolder->property("b").toInt(), 4);
-}
-
-/*
-void tst_QStateMachine::setRestorePolicyToDoNotRestore()
-{
- QObject *object = new QObject();
- object->setProperty("a", 1);
- object->setProperty("b", 2);
-
- QStateMachine machine;
-
- QState *S1 = new QState();
- S1->setObjectName("S1");
- S1->assignProperty(object, "a", 3);
- S1->setRestorePolicy(QState::DoNotRestoreProperties);
- machine.addState(S1);
-
- QState *S2 = new QState();
- S2->setObjectName("S2");
- S2->assignProperty(object, "b", 5);
- S2->setRestorePolicy(QState::DoNotRestoreProperties);
- machine.addState(S2);
-
- QState *S3 = new QState();
- S3->setObjectName("S3");
- S3->setRestorePolicy(QState::DoNotRestoreProperties);
- machine.addState(S3);
-
- QFinalState *S4 = new QFinalState();
- machine.addState(S4);
-
- S1->addTransition(new EventTransition(QEvent::User, S2));
- S2->addTransition(new EventTransition(QEvent::User, S3));
- S3->addTransition(S4);
-
- machine.setInitialState(S1);
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(object->property("a").toInt(), 3);
- QCOMPARE(object->property("b").toInt(), 2);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(object->property("a").toInt(), 3);
- QCOMPARE(object->property("b").toInt(), 5);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(object->property("a").toInt(), 3);
- QCOMPARE(object->property("b").toInt(), 5);
-}
-
-void tst_QStateMachine::setGlobalRestorePolicyToGlobalRestore()
-{
- s_countWarnings = false;
- QStateMachine machine;
- machine.setGlobalRestorePolicy(QStateMachine::GlobalRestorePolicy);
-
- QCOMPARE(machine.globalRestorePolicy(), QStateMachine::DoNotRestoreProperties);
- QCOMPARE(s_msgType, QtWarningMsg);
-
- s_msgType = QtDebugMsg;
- machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
- machine.setGlobalRestorePolicy(QStateMachine::GlobalRestorePolicy);
-
- QCOMPARE(machine.globalRestorePolicy(), QStateMachine::RestoreProperties);
- QCOMPARE(s_msgType, QtWarningMsg);
-}
-
-
-void tst_QStateMachine::restorePolicyOnChildState()
-{
- QStateMachine machine;
-
- QObject *propertyHolder = new QObject();
- propertyHolder->setProperty("a", 1);
- propertyHolder->setProperty("b", 2);
-
- QState *parentState = new QState(&machine);
- parentState->setObjectName("parentState");
-
- QState *s1 = new QState(parentState);
- s1->setRestorePolicy(QState::RestoreProperties);
- s1->setObjectName("s1");
- s1->assignProperty(propertyHolder, "a", 3);
- parentState->setInitialState(s1);
-
- QState *s2 = new QState(parentState);
- s2->setRestorePolicy(QState::RestoreProperties);
- s2->setObjectName("s2");
- s2->assignProperty(propertyHolder, "b", 4);
-
- QState *s3 = new QState(parentState);
- s3->setRestorePolicy(QState::RestoreProperties);
- s3->setObjectName("s3");
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
- s2->addTransition(new EventTransition(QEvent::User, s3));
-
- machine.setInitialState(parentState);
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 3);
- QCOMPARE(propertyHolder->property("b").toInt(), 2);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 1);
- QCOMPARE(propertyHolder->property("b").toInt(), 4);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 1);
- QCOMPARE(propertyHolder->property("b").toInt(), 2);
-}
-*/
-
-void tst_QStateMachine::globalRestorePolicySetToRestore()
-{
- QStateMachine machine;
- machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
-
- QObject *propertyHolder = new QObject(&machine);
- propertyHolder->setProperty("a", 1);
- propertyHolder->setProperty("b", 2);
-
- QState *s1 = new QState(&machine);
- s1->assignProperty(propertyHolder, "a", 3);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(propertyHolder, "b", 4);
-
- QState *s3 = new QState(&machine);
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
- s2->addTransition(new EventTransition(QEvent::User, s3));
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 3);
- QCOMPARE(propertyHolder->property("b").toInt(), 2);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 1);
- QCOMPARE(propertyHolder->property("b").toInt(), 4);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("a").toInt(), 1);
- QCOMPARE(propertyHolder->property("b").toInt(), 2);
-}
-
-/*
-void tst_QStateMachine::mixedRestoreProperties()
-{
- QStateMachine machine;
-
- QObject *propertyHolder = new QObject();
- propertyHolder->setProperty("a", 1);
-
- QState *s1 = new QState(&machine);
- s1->setRestorePolicy(QState::RestoreProperties);
- s1->assignProperty(propertyHolder, "a", 3);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(propertyHolder, "a", 4);
-
- QState *s3 = new QState(&machine);
-
- QState *s4 = new QState(&machine);
- s4->assignProperty(propertyHolder, "a", 5);
-
- QState *s5 = new QState(&machine);
- s5->setRestorePolicy(QState::RestoreProperties);
- s5->assignProperty(propertyHolder, "a", 6);
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
- s2->addTransition(new EventTransition(QEvent::User, s3));
- s3->addTransition(new EventTransition(QEvent::User, s4));
- s4->addTransition(new EventTransition(QEvent::User, s5));
- s5->addTransition(new EventTransition(QEvent::User, s3));
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- // Enter s1, save current
- QCOMPARE(propertyHolder->property("a").toInt(), 3);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- // Enter s2, restorePolicy == DoNotRestore, so restore all properties
- QCOMPARE(propertyHolder->property("a").toInt(), 4);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- // Enter s3
- QCOMPARE(propertyHolder->property("a").toInt(), 4);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- // Enter s4
- QCOMPARE(propertyHolder->property("a").toInt(), 5);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- // Enter s5, save current
- QCOMPARE(propertyHolder->property("a").toInt(), 6);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- // Enter s3, restore
- QCOMPARE(propertyHolder->property("a").toInt(), 5);
-}
-*/
-
-void tst_QStateMachine::transitionWithParent()
-{
- QStateMachine machine;
- QState *s1 = new QState(&machine);
- QState *s2 = new QState(&machine);
- EventTransition *trans = new EventTransition(QEvent::User, s2, s1);
- QCOMPARE(trans->sourceState(), s1);
- QCOMPARE(trans->targetState(), (QAbstractState*)s2);
- QCOMPARE(trans->targetStates().size(), 1);
- QCOMPARE(trans->targetStates().at(0), (QAbstractState*)s2);
-}
-
-void tst_QStateMachine::simpleAnimation()
-{
- QStateMachine machine;
-
- QObject *object = new QObject(&machine);
- object->setProperty("fooBar", 1.0);
-
- QState *s1 = new QState(&machine);
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "fooBar", 2.0);
-
- EventTransition *et = new EventTransition(QEvent::User, s2);
- QPropertyAnimation *animation = new QPropertyAnimation(object, "fooBar", s2);
- et->addAnimation(animation);
- s1->addTransition(et);
-
- QState *s3 = new QState(&machine);
- s2->addTransition(animation, SIGNAL(finished()), s3);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(object->property("fooBar").toDouble(), 2.0);
-}
-
-class SlotCalledCounter: public QObject
-{
- Q_OBJECT
-public:
- SlotCalledCounter() : counter(0) {}
-
- int counter;
-
-public slots:
- void slot() { counter++; }
-};
-
-void tst_QStateMachine::twoAnimations()
-{
- QStateMachine machine;
-
- QObject *object = new QObject(&machine);
- object->setProperty("foo", 1.0);
- object->setProperty("bar", 3.0);
-
- QState *s1 = new QState(&machine);
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
- s2->assignProperty(object, "bar", 10.0);
-
- QPropertyAnimation *animationFoo = new QPropertyAnimation(object, "foo", s2);
- QPropertyAnimation *animationBar = new QPropertyAnimation(object, "bar", s2);
- animationBar->setDuration(900);
-
- SlotCalledCounter counter;
- connect(animationFoo, SIGNAL(finished()), &counter, SLOT(slot()));
- connect(animationBar, SIGNAL(finished()), &counter, SLOT(slot()));
-
- EventTransition *et = new EventTransition(QEvent::User, s2);
- et->addAnimation(animationFoo);
- et->addAnimation(animationBar);
- s1->addTransition(et);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
- s2->addTransition(s2, SIGNAL(propertiesAssigned()), s3);
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(object->property("foo").toDouble(), 2.0);
- QCOMPARE(object->property("bar").toDouble(), 10.0);
-
- QCOMPARE(counter.counter, 2);
-}
-
-void tst_QStateMachine::twoAnimatedTransitions()
-{
- QStateMachine machine;
-
- QObject *object = new QObject(&machine);
- object->setProperty("foo", 1.0);
-
- QState *s1 = new QState(&machine);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 5.0);
- QPropertyAnimation *fooAnimation = new QPropertyAnimation(object, "foo", s2);
- EventTransition *trans = new EventTransition(QEvent::User, s2);
- s1->addTransition(trans);
- trans->addAnimation(fooAnimation);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
- s2->addTransition(fooAnimation, SIGNAL(finished()), s3);
-
- QState *s4 = new QState(&machine);
- s4->assignProperty(object, "foo", 2.0);
- QPropertyAnimation *fooAnimation2 = new QPropertyAnimation(object, "foo", s4);
- trans = new EventTransition(QEvent::User, s4);
- s3->addTransition(trans);
- trans->addAnimation(fooAnimation2);
-
- QState *s5 = new QState(&machine);
- QObject::connect(s5, SIGNAL(entered()), QApplication::instance(), SLOT(quit()));
- s4->addTransition(fooAnimation2, SIGNAL(finished()), s5);
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(object->property("foo").toDouble(), 5.0);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s5));
- QCOMPARE(object->property("foo").toDouble(), 2.0);
-}
-
-void tst_QStateMachine::playAnimationTwice()
-{
- QStateMachine machine;
-
- QObject *object = new QObject(&machine);
- object->setProperty("foo", 1.0);
-
- QState *s1 = new QState(&machine);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 5.0);
- QPropertyAnimation *fooAnimation = new QPropertyAnimation(object, "foo", s2);
- EventTransition *trans = new EventTransition(QEvent::User, s2);
- s1->addTransition(trans);
- trans->addAnimation(fooAnimation);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
- s2->addTransition(fooAnimation, SIGNAL(finished()), s3);
-
- QState *s4 = new QState(&machine);
- s4->assignProperty(object, "foo", 2.0);
- trans = new EventTransition(QEvent::User, s4);
- s3->addTransition(trans);
- trans->addAnimation(fooAnimation);
-
- QState *s5 = new QState(&machine);
- QObject::connect(s5, SIGNAL(entered()), QApplication::instance(), SLOT(quit()));
- s4->addTransition(fooAnimation, SIGNAL(finished()), s5);
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(object->property("foo").toDouble(), 5.0);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s5));
- QCOMPARE(object->property("foo").toDouble(), 2.0);
-}
-
-void tst_QStateMachine::nestedTargetStateForAnimation()
-{
- QStateMachine machine;
-
- QObject *object = new QObject(&machine);
- object->setProperty("foo", 1.0);
- object->setProperty("bar", 3.0);
-
- SlotCalledCounter counter;
-
- QState *s1 = new QState(&machine);
- QState *s2 = new QState(&machine);
-
- s2->assignProperty(object, "foo", 2.0);
-
- QState *s2Child = new QState(s2);
- s2Child->assignProperty(object, "bar", 10.0);
- s2->setInitialState(s2Child);
-
- QState *s2Child2 = new QState(s2);
- s2Child2->assignProperty(object, "bar", 11.0);
- QAbstractTransition *at = new EventTransition(QEvent::User, s2Child2);
- s2Child->addTransition(at);
-
- QPropertyAnimation *animation = new QPropertyAnimation(object, "bar", s2);
- animation->setDuration(2000);
- connect(animation, SIGNAL(finished()), &counter, SLOT(slot()));
- at->addAnimation(animation);
-
- at = new EventTransition(QEvent::User, s2);
- s1->addTransition(at);
-
- animation = new QPropertyAnimation(object, "foo", s2);
- connect(animation, SIGNAL(finished()), &counter, SLOT(slot()));
- at->addAnimation(animation);
-
- animation = new QPropertyAnimation(object, "bar", s2);
- connect(animation, SIGNAL(finished()), &counter, SLOT(slot()));
- at->addAnimation(animation);
-
- QState *s3 = new QState(&machine);
- s2->addTransition(s2Child, SIGNAL(propertiesAssigned()), s3);
-
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
- machine.postEvent(new QEvent(QEvent::User));
-
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(object->property("foo").toDouble(), 2.0);
- QCOMPARE(object->property("bar").toDouble(), 10.0);
- QCOMPARE(counter.counter, 2);
-}
-
-void tst_QStateMachine::propertiesAssignedSignalTransitionsReuseAnimationGroup()
-{
- QStateMachine machine;
- QObject *object = new QObject(&machine);
- object->setProperty("foo", 0);
-
- QState *s1 = new QState(&machine);
- s1->assignProperty(object, "foo", 123);
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 456);
- QState *s3 = new QState(&machine);
- s3->assignProperty(object, "foo", 789);
- QFinalState *s4 = new QFinalState(&machine);
-
- QParallelAnimationGroup animationGroup;
- animationGroup.addAnimation(new QPropertyAnimation(object, "foo"));
- QSignalSpy animationFinishedSpy(&animationGroup, SIGNAL(finished()));
- s1->addTransition(s1, SIGNAL(propertiesAssigned()), s2)->addAnimation(&animationGroup);
- s2->addTransition(s2, SIGNAL(propertiesAssigned()), s3)->addAnimation(&animationGroup);
- s3->addTransition(s3, SIGNAL(propertiesAssigned()), s4);
-
- machine.setInitialState(s1);
- QSignalSpy machineFinishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QTRY_COMPARE(machineFinishedSpy.count(), 1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s4));
- QCOMPARE(object->property("foo").toInt(), 789);
-
- QCOMPARE(animationFinishedSpy.count(), 2);
-}
-
-void tst_QStateMachine::animatedGlobalRestoreProperty()
-{
- QStateMachine machine;
- machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
-
- QObject *object = new QObject(&machine);
- object->setProperty("foo", 1.0);
-
- SlotCalledCounter counter;
-
- QState *s1 = new QState(&machine);
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
-
- QState *s3 = new QState(&machine);
-
- QState *s4 = new QState(&machine);
- QObject::connect(s4, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- QAbstractTransition *at = new EventTransition(QEvent::User, s2);
- s1->addTransition(at);
- QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", s2);
- connect(pa, SIGNAL(finished()), &counter, SLOT(slot()));
- at->addAnimation(pa);
-
- at = s2->addTransition(pa, SIGNAL(finished()), s3);
- pa = new QPropertyAnimation(object, "foo", s3);
- connect(pa, SIGNAL(finished()), &counter, SLOT(slot()));
- at->addAnimation(pa);
-
- at = s3->addTransition(pa, SIGNAL(finished()), s4);
- pa = new QPropertyAnimation(object, "foo", s4);
- connect(pa, SIGNAL(finished()), &counter, SLOT(slot()));
- at->addAnimation(pa);
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
-
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s4));
- QCOMPARE(object->property("foo").toDouble(), 1.0);
- QCOMPARE(counter.counter, 2);
-}
-
-void tst_QStateMachine::specificTargetValueOfAnimation()
-{
- QStateMachine machine;
-
- QObject *object = new QObject(&machine);
- object->setProperty("foo", 1.0);
-
- QState *s1 = new QState(&machine);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
-
- QPropertyAnimation *anim = new QPropertyAnimation(object, "foo");
- anim->setEndValue(10.0);
- EventTransition *trans = new EventTransition(QEvent::User, s2);
- s1->addTransition(trans);
- trans->addAnimation(anim);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
- s2->addTransition(anim, SIGNAL(finished()), s3);
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(object->property("foo").toDouble(), 2.0);
- QCOMPARE(anim->endValue().toDouble(), 10.0);
-
- delete anim;
-}
-
-void tst_QStateMachine::addDefaultAnimation()
-{
- QStateMachine machine;
-
- QObject *object = new QObject();
- object->setProperty("foo", 1.0);
-
- QState *s1 = new QState(&machine);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
-
- QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine);
- machine.addDefaultAnimation(pa);
- s2->addTransition(pa, SIGNAL(finished()), s3);
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(object->property("foo").toDouble(), 2.0);
-
- delete object;
-}
-
-void tst_QStateMachine::addDefaultAnimationWithUnusedAnimation()
-{
- QStateMachine machine;
-
- QObject *object = new QObject(&machine);
- object->setProperty("foo", 1.0);
- object->setProperty("bar", 2.0);
-
- SlotCalledCounter counter;
-
- QState *s1 = new QState(&machine);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
-
- QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine);
- connect(pa, SIGNAL(finished()), &counter, SLOT(slot()));
- machine.addDefaultAnimation(pa);
- s2->addTransition(pa, SIGNAL(finished()), s3);
-
- pa = new QPropertyAnimation(object, "bar", &machine);
- connect(pa, SIGNAL(finished()), &counter, SLOT(slot()));
- machine.addDefaultAnimation(pa);
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(object->property("foo").toDouble(), 2.0);
- QCOMPARE(counter.counter, 1);
-}
-
-void tst_QStateMachine::removeDefaultAnimation()
-{
- QStateMachine machine;
-
- QObject propertyHolder;
- propertyHolder.setProperty("foo", 0);
-
- QCOMPARE(machine.defaultAnimations().size(), 0);
-
- QPropertyAnimation *anim = new QPropertyAnimation(&propertyHolder, "foo");
-
- machine.addDefaultAnimation(anim);
-
- QCOMPARE(machine.defaultAnimations().size(), 1);
- QVERIFY(machine.defaultAnimations().contains(anim));
-
- machine.removeDefaultAnimation(anim);
-
- QCOMPARE(machine.defaultAnimations().size(), 0);
-
- machine.addDefaultAnimation(anim);
-
- QPropertyAnimation *anim2 = new QPropertyAnimation(&propertyHolder, "foo");
- machine.addDefaultAnimation(anim2);
-
- QCOMPARE(machine.defaultAnimations().size(), 2);
- QVERIFY(machine.defaultAnimations().contains(anim));
- QVERIFY(machine.defaultAnimations().contains(anim2));
-
- machine.removeDefaultAnimation(anim);
-
- QCOMPARE(machine.defaultAnimations().size(), 1);
- QVERIFY(machine.defaultAnimations().contains(anim2));
-
- machine.removeDefaultAnimation(anim2);
- QCOMPARE(machine.defaultAnimations().size(), 0);
-
- delete anim;
- delete anim2;
-}
-
-void tst_QStateMachine::overrideDefaultAnimationWithSpecific()
-{
- QStateMachine machine;
-
- QObject *object = new QObject(&machine);
- object->setProperty("foo", 1.0);
-
- SlotCalledCounter counter;
-
- QState *s1 = new QState(&machine);
- machine.setInitialState(s1);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- QAbstractTransition *at = new EventTransition(QEvent::User, s2);
- s1->addTransition(at);
-
- QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo");
- connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot()));
-
- QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo");
- s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3);
- connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot()));
-
- machine.addDefaultAnimation(defaultAnimation);
- at->addAnimation(moreSpecificAnimation);
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(counter.counter, 2); // specific animation started and stopped
-
- delete defaultAnimation;
- delete moreSpecificAnimation;
-}
-
-/*
-void tst_QStateMachine::addDefaultAnimationForSource()
-{
- QStateMachine machine;
-
- QObject *object = new QObject();
- object->setProperty("foo", 1.0);
-
- QState *s1 = new QState(&machine);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
-
- QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine);
- machine.addDefaultAnimationForSourceState(s1, pa);
- s2->addTransition(pa, SIGNAL(finished()), s3);
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(object->property("foo").toDouble(), 2.0);
-}
-
-void tst_QStateMachine::addDefaultAnimationForTarget()
-{
- QStateMachine machine;
-
- QObject *object = new QObject();
- object->setProperty("foo", 1.0);
-
- QState *s1 = new QState(&machine);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
-
- QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine);
- machine.addDefaultAnimationForTargetState(s2, pa);
- s2->addTransition(pa, SIGNAL(finished()), s3);
-
- machine.setInitialState(s1);
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(object->property("foo").toDouble(), 2.0);
-}
-
-void tst_QStateMachine::removeDefaultAnimationForSource()
-{
- QStateMachine machine;
-
- QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 0);
-
- QPropertyAnimation *anim = new QPropertyAnimation(this, "foo");
-
- machine.addDefaultAnimationForSourceState(&machine, anim);
-
- QCOMPARE(machine.defaultAnimations().size(), 0);
- QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 0);
- QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 1);
- QVERIFY(machine.defaultAnimationsForSourceState(&machine).contains(anim));
-
- machine.removeDefaultAnimationForTargetState(&machine, anim);
-
- QCOMPARE(machine.defaultAnimations().size(), 0);
- QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 0);
- QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 1);
- QVERIFY(machine.defaultAnimationsForSourceState(&machine).contains(anim));
-
- machine.removeDefaultAnimationForSourceState(&machine, anim);
-
- QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 0);
-
- machine.addDefaultAnimationForSourceState(&machine, anim);
-
- QPropertyAnimation *anim2 = new QPropertyAnimation(this, "foo");
- machine.addDefaultAnimationForSourceState(&machine, anim2);
-
- QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 2);
- QVERIFY(machine.defaultAnimationsForSourceState(&machine).contains(anim));
- QVERIFY(machine.defaultAnimationsForSourceState(&machine).contains(anim2));
-
- machine.removeDefaultAnimationForSourceState(&machine, anim);
-
- QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 1);
- QVERIFY(machine.defaultAnimationsForSourceState(&machine).contains(anim2));
-
- machine.removeDefaultAnimationForSourceState(&machine, anim2);
- QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 0);
-}
-
-void tst_QStateMachine::removeDefaultAnimationForTarget()
-{
- QStateMachine machine;
-
- QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 0);
-
- QPropertyAnimation *anim = new QPropertyAnimation(this, "foo");
-
- machine.addDefaultAnimationForTargetState(&machine, anim);
-
- QCOMPARE(machine.defaultAnimations().size(), 0);
- QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 0);
- QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 1);
- QVERIFY(machine.defaultAnimationsForTargetState(&machine).contains(anim));
-
- machine.removeDefaultAnimationForSourceState(&machine, anim);
-
- QCOMPARE(machine.defaultAnimations().size(), 0);
- QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 0);
- QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 1);
- QVERIFY(machine.defaultAnimationsForTargetState(&machine).contains(anim));
-
- machine.removeDefaultAnimationForTargetState(&machine, anim);
-
- QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 0);
-
- machine.addDefaultAnimationForTargetState(&machine, anim);
-
- QPropertyAnimation *anim2 = new QPropertyAnimation(this, "foo");
- machine.addDefaultAnimationForTargetState(&machine, anim2);
-
- QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 2);
- QVERIFY(machine.defaultAnimationsForTargetState(&machine).contains(anim));
- QVERIFY(machine.defaultAnimationsForTargetState(&machine).contains(anim2));
-
- machine.removeDefaultAnimationForTargetState(&machine, anim);
-
- QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 1);
- QVERIFY(machine.defaultAnimationsForTargetState(&machine).contains(anim2));
-
- machine.removeDefaultAnimationForTargetState(&machine, anim2);
- QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 0);
-}
-
-void tst_QStateMachine::overrideDefaultAnimationWithSource()
-{
- QStateMachine machine;
-
- QObject *object = new QObject();
- object->setProperty("foo", 1.0);
-
- SlotCalledCounter counter;
-
- QState *s1 = new QState(&machine);
- machine.setInitialState(s1);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
-
- QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo");
- connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot()));
-
- QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo");
- s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3);
- connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot()));
-
- machine.addDefaultAnimation(defaultAnimation);
- machine.addDefaultAnimationForSourceState(s1, moreSpecificAnimation);
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(counter.counter, 2); // specific animation started and stopped
-}
-
-void tst_QStateMachine::overrideDefaultAnimationWithTarget()
-{
- QStateMachine machine;
-
- QObject *object = new QObject();
- object->setProperty("foo", 1.0);
-
- SlotCalledCounter counter;
-
- QState *s1 = new QState(&machine);
- machine.setInitialState(s1);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
-
- QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo");
- connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot()));
-
- QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo");
- s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3);
- connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot()));
-
- machine.addDefaultAnimation(defaultAnimation);
- machine.addDefaultAnimationForTargetState(s2, moreSpecificAnimation);
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(counter.counter, 2); // specific animation started and stopped
-
-}
-
-void tst_QStateMachine::overrideDefaultSourceAnimationWithSpecific()
-{
- QStateMachine machine;
-
- QObject *object = new QObject();
- object->setProperty("foo", 1.0);
-
- SlotCalledCounter counter;
-
- QState *s1 = new QState(&machine);
- machine.setInitialState(s1);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2));
-
- QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo");
- connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot()));
-
- QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo");
- s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3);
- connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot()));
-
- machine.addDefaultAnimationForSourceState(s1, defaultAnimation);
- at->addAnimation(moreSpecificAnimation);
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(counter.counter, 2); // specific animation started and stopped
-}
-
-void tst_QStateMachine::overrideDefaultTargetAnimationWithSpecific()
-{
- QStateMachine machine;
-
- QObject *object = new QObject();
- object->setProperty("foo", 1.0);
-
- SlotCalledCounter counter;
-
- QState *s1 = new QState(&machine);
- machine.setInitialState(s1);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2));
-
- QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo");
- connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot()));
-
- QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo");
- s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3);
- connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot()));
-
- machine.addDefaultAnimationForTargetState(s2, defaultAnimation);
- at->addAnimation(moreSpecificAnimation);
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(counter.counter, 2); // specific animation started and stopped
-}
-
-void tst_QStateMachine::overrideDefaultTargetAnimationWithSource()
-{
- QStateMachine machine;
-
- QObject *object = new QObject();
- object->setProperty("foo", 1.0);
-
- SlotCalledCounter counter;
-
- QState *s1 = new QState(&machine);
- machine.setInitialState(s1);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(object, "foo", 2.0);
-
- QState *s3 = new QState(&machine);
- QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit()));
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
-
- QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo");
- connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot()));
-
- QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo");
- s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3);
- connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot()));
-
- machine.addDefaultAnimationForTargetState(s2, defaultAnimation);
- machine.addDefaultAnimationForSourceState(s1, moreSpecificAnimation);
-
- machine.start();
- QCoreApplication::processEvents();
-
- machine.postEvent(new QEvent(QEvent::User));
- QCOREAPPLICATION_EXEC(5000);
-
- QVERIFY(machine.configuration().contains(s3));
- QCOMPARE(counter.counter, 2); // specific animation started and stopped
-}
-
-*/
-
-void tst_QStateMachine::parallelStateAssignmentsDone()
-{
- QStateMachine machine;
-
- QObject *propertyHolder = new QObject(&machine);
- propertyHolder->setProperty("foo", 123);
- propertyHolder->setProperty("bar", 456);
- propertyHolder->setProperty("zoot", 789);
-
- QState *s1 = new QState(&machine);
- machine.setInitialState(s1);
-
- QState *parallelState = new QState(QState::ParallelStates, &machine);
- parallelState->assignProperty(propertyHolder, "foo", 321);
-
- QState *s2 = new QState(parallelState);
- s2->assignProperty(propertyHolder, "bar", 654);
-
- QState *s3 = new QState(parallelState);
- s3->assignProperty(propertyHolder, "zoot", 987);
-
- s1->addTransition(new EventTransition(QEvent::User, parallelState));
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("foo").toInt(), 123);
- QCOMPARE(propertyHolder->property("bar").toInt(), 456);
- QCOMPARE(propertyHolder->property("zoot").toInt(), 789);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(propertyHolder->property("foo").toInt(), 321);
- QCOMPARE(propertyHolder->property("bar").toInt(), 654);
- QCOMPARE(propertyHolder->property("zoot").toInt(), 987);
-}
-
-void tst_QStateMachine::transitionsFromParallelStateWithNoChildren()
-{
- QStateMachine machine;
-
- QState *parallelState = new QState(QState::ParallelStates, &machine);
- machine.setInitialState(parallelState);
-
- QState *s1 = new QState(&machine);
- parallelState->addTransition(new EventTransition(QEvent::User, s1));
-
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(1, machine.configuration().size());
- QVERIFY(machine.configuration().contains(parallelState));
-
- machine.postEvent(new QEvent(QEvent::User));
-
- QCoreApplication::processEvents();
-
- QCOMPARE(1, machine.configuration().size());
- QVERIFY(machine.configuration().contains(s1));
-}
-
-void tst_QStateMachine::parallelStateTransition()
-{
- QStateMachine machine;
-
- QState *parallelState = new QState(QState::ParallelStates, &machine);
- machine.setInitialState(parallelState);
-
- QState *s1 = new QState(parallelState);
- QState *s2 = new QState(parallelState);
-
- QState *s1InitialChild = new QState(s1);
- s1->setInitialState(s1InitialChild);
-
- QState *s2InitialChild = new QState(s2);
- s2->setInitialState(s2InitialChild);
-
- QState *s1OtherChild = new QState(s1);
-
- s1->addTransition(new EventTransition(QEvent::User, s1OtherChild));
-
- machine.start();
- QCoreApplication::processEvents();
-
- QVERIFY(machine.configuration().contains(parallelState));
- QVERIFY(machine.configuration().contains(s1));
- QVERIFY(machine.configuration().contains(s2));
- QVERIFY(machine.configuration().contains(s1InitialChild));
- QVERIFY(machine.configuration().contains(s2InitialChild));
- QCOMPARE(machine.configuration().size(), 5);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- 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()
-{
- QStateMachine machine;
- machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
-
- QObject *propertyHolder = new QObject(&machine);
- propertyHolder->setProperty("foo", 1);
- propertyHolder->setProperty("bar", 2);
-
- QState *s1 = new QState(&machine);
- machine.setInitialState(s1);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(propertyHolder, "foo", 3);
-
- QState *s21 = new QState(s2);
- s21->assignProperty(propertyHolder, "bar", 4);
- s2->setInitialState(s21);
-
- QState *s22 = new QState(s2);
- s22->assignProperty(propertyHolder, "bar", 5);
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
- s21->addTransition(new EventTransition(QEvent::User, s22));
-
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
- QCOMPARE(propertyHolder->property("foo").toInt(), 1);
- QCOMPARE(propertyHolder->property("bar").toInt(), 2);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().size(), 2);
- QVERIFY(machine.configuration().contains(s2));
- QVERIFY(machine.configuration().contains(s21));
- QCOMPARE(propertyHolder->property("foo").toInt(), 3);
- QCOMPARE(propertyHolder->property("bar").toInt(), 4);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().size(), 2);
- QVERIFY(machine.configuration().contains(s2));
- QVERIFY(machine.configuration().contains(s22));
- QCOMPARE(propertyHolder->property("foo").toInt(), 3);
- QCOMPARE(propertyHolder->property("bar").toInt(), 5);
-}
-
-void tst_QStateMachine::nestedRestoreProperties2()
-{
- QStateMachine machine;
- machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties);
-
- QObject *propertyHolder = new QObject(&machine);
- propertyHolder->setProperty("foo", 1);
- propertyHolder->setProperty("bar", 2);
-
- QState *s1 = new QState(&machine);
- machine.setInitialState(s1);
-
- QState *s2 = new QState(&machine);
- s2->assignProperty(propertyHolder, "foo", 3);
-
- QState *s21 = new QState(s2);
- s21->assignProperty(propertyHolder, "bar", 4);
- s2->setInitialState(s21);
-
- QState *s22 = new QState(s2);
- s22->assignProperty(propertyHolder, "foo", 6);
- s22->assignProperty(propertyHolder, "bar", 5);
-
- s1->addTransition(new EventTransition(QEvent::User, s2));
- s21->addTransition(new EventTransition(QEvent::User, s22));
- s22->addTransition(new EventTransition(QEvent::User, s21));
-
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
- QCOMPARE(propertyHolder->property("foo").toInt(), 1);
- QCOMPARE(propertyHolder->property("bar").toInt(), 2);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().size(), 2);
- QVERIFY(machine.configuration().contains(s2));
- QVERIFY(machine.configuration().contains(s21));
- QCOMPARE(propertyHolder->property("foo").toInt(), 3);
- QCOMPARE(propertyHolder->property("bar").toInt(), 4);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().size(), 2);
- QVERIFY(machine.configuration().contains(s2));
- QVERIFY(machine.configuration().contains(s22));
- QCOMPARE(propertyHolder->property("foo").toInt(), 6);
- QCOMPARE(propertyHolder->property("bar").toInt(), 5);
-
- machine.postEvent(new QEvent(QEvent::User));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().size(), 2);
- QVERIFY(machine.configuration().contains(s2));
- QVERIFY(machine.configuration().contains(s21));
- QCOMPARE(propertyHolder->property("foo").toInt(), 3);
- QCOMPARE(propertyHolder->property("bar").toInt(), 4);
-
-}
-
-void tst_QStateMachine::nestedStateMachines()
-{
- QStateMachine machine;
- QState *group = new QState(&machine);
- group->setChildMode(QState::ParallelStates);
- QStateMachine *subMachines[3];
- for (int i = 0; i < 3; ++i) {
- QState *subGroup = new QState(group);
- QStateMachine *subMachine = new QStateMachine(subGroup);
- {
- QState *initial = new QState(subMachine);
- QFinalState *done = new QFinalState(subMachine);
- initial->addTransition(new EventTransition(QEvent::User, done));
- subMachine->setInitialState(initial);
- }
- QFinalState *subMachineDone = new QFinalState(subGroup);
- subMachine->addTransition(subMachine, SIGNAL(finished()), subMachineDone);
- subGroup->setInitialState(subMachine);
- subMachines[i] = subMachine;
- }
- QFinalState *final = new QFinalState(&machine);
- group->addTransition(group, SIGNAL(finished()), final);
- machine.setInitialState(group);
-
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 1);
- QTRY_COMPARE(machine.configuration().count(), 1+2*3);
- QVERIFY(machine.configuration().contains(group));
- for (int i = 0; i < 3; ++i)
- QVERIFY(machine.configuration().contains(subMachines[i]));
-
- QCoreApplication::processEvents(); // starts the submachines
-
- for (int i = 0; i < 3; ++i)
- subMachines[i]->postEvent(new QEvent(QEvent::User));
-
- QTRY_COMPARE(finishedSpy.count(), 1);
-}
-
-void tst_QStateMachine::goToState()
-{
- QStateMachine machine;
- QState *s1 = new QState(&machine);
- QState *s2 = new QState(&machine);
- machine.setInitialState(s1);
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 1);
-
- QStateMachinePrivate::get(&machine)->goToState(s2);
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s2));
-
- QStateMachinePrivate::get(&machine)->goToState(s2);
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s2));
-
- QStateMachinePrivate::get(&machine)->goToState(s1);
- QStateMachinePrivate::get(&machine)->goToState(s2);
- QStateMachinePrivate::get(&machine)->goToState(s1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s2));
-
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- // go to state in group
- QState *s2_1 = new QState(s2);
- s2->setInitialState(s2_1);
- QStateMachinePrivate::get(&machine)->goToState(s2_1);
- QCoreApplication::processEvents();
- QCOMPARE(machine.configuration().size(), 2);
- QVERIFY(machine.configuration().contains(s2));
- QVERIFY(machine.configuration().contains(s2_1));
-}
-
-class CloneSignalTransition : public QSignalTransition
-{
-public:
- CloneSignalTransition(QObject *sender, const char *signal, QAbstractState *target)
- : QSignalTransition(sender, signal)
- {
- setTargetState(target);
- }
-
- void onTransition(QEvent *e)
- {
- QSignalTransition::onTransition(e);
- QStateMachine::SignalEvent *se = static_cast<QStateMachine::SignalEvent*>(e);
- eventSignalIndex = se->signalIndex();
- }
-
- int eventSignalIndex;
-};
-
-void tst_QStateMachine::task260403_clonedSignals()
-{
- SignalEmitter emitter;
- QStateMachine machine;
- QState *s1 = new QState(&machine);
- QState *s2 = new QState(&machine);
- CloneSignalTransition *t1 = new CloneSignalTransition(&emitter, SIGNAL(signalWithDefaultArg()), s2);
- s1->addTransition(t1);
-
- machine.setInitialState(s1);
- machine.start();
- QTest::qWait(1);
-
- emitter.emitSignalWithDefaultArg();
- QTest::qWait(1);
- QCOMPARE(t1->eventSignalIndex, emitter.metaObject()->indexOfSignal("signalWithDefaultArg()"));
-}
-
-class EventPosterThread : public QThread
-{
- Q_OBJECT
-public:
- EventPosterThread(QStateMachine *machine, QObject *parent = 0)
- : QThread(parent), m_machine(machine), m_count(0)
- {
- moveToThread(this);
- QObject::connect(m_machine, SIGNAL(started()),
- this, SLOT(postEvent()));
- }
-protected:
- virtual void run()
- {
- exec();
- }
-private Q_SLOTS:
- void postEvent()
- {
- m_machine->postEvent(new QEvent(QEvent::User));
- if (++m_count < 10000)
- QTimer::singleShot(0, this, SLOT(postEvent()));
- else
- quit();
- }
-private:
- QStateMachine *m_machine;
- int m_count;
-};
-
-void tst_QStateMachine::postEventFromOtherThread()
-{
- QStateMachine machine;
- EventPosterThread poster(&machine);
- StringEventPoster *s1 = new StringEventPoster("foo", &machine);
- s1->addTransition(new EventTransition(QEvent::User, s1));
- QFinalState *f = new QFinalState(&machine);
- s1->addTransition(&poster, SIGNAL(finished()), f);
- machine.setInitialState(s1);
-
- poster.start();
-
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.start();
- QTRY_COMPARE(finishedSpy.count(), 1);
-}
-
-void tst_QStateMachine::eventFilterForApplication()
-{
- QStateMachine machine;
-
- QState *s1 = new QState(&machine);
- {
- machine.setInitialState(s1);
- }
-
- QState *s2 = new QState(&machine);
-
- QEventTransition *transition = new QEventTransition(QCoreApplication::instance(),
- QEvent::ApplicationActivate);
- transition->setTargetState(s2);
- s1->addTransition(transition);
-
- machine.start();
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-
- QCoreApplication::postEvent(QCoreApplication::instance(),
- new QEvent(QEvent::ApplicationActivate));
- QCoreApplication::processEvents();
-
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s2));
-}
-
-void tst_QStateMachine::eventClassesExported()
-{
- // make sure this links
- QStateMachine::WrappedEvent *wrappedEvent = new QStateMachine::WrappedEvent(0, 0);
- Q_UNUSED(wrappedEvent);
- QStateMachine::SignalEvent *signalEvent = new QStateMachine::SignalEvent(0, 0, QList<QVariant>());
- Q_UNUSED(signalEvent);
-}
-
-void tst_QStateMachine::stopInTransitionToFinalState()
-{
- QStateMachine machine;
- QState *s1 = new QState(&machine);
- QFinalState *s2 = new QFinalState(&machine);
- QAbstractTransition *t1 = s1->addTransition(s2);
- machine.setInitialState(s1);
-
- QObject::connect(t1, SIGNAL(triggered()), &machine, SLOT(stop()));
- QSignalSpy stoppedSpy(&machine, SIGNAL(stopped()));
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- QSignalSpy s2EnteredSpy(s2, SIGNAL(entered()));
- machine.start();
-
- // Stopping should take precedence over finished.
- QTRY_COMPARE(stoppedSpy.count(), 1);
- QCOMPARE(finishedSpy.count(), 0);
- QCOMPARE(s2EnteredSpy.count(), 1);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s2));
-}
-
-class StopInEventTestTransition : public QAbstractTransition
-{
-public:
- bool eventTest(QEvent *e)
- {
- if (e->type() == QEvent::User)
- machine()->stop();
- return false;
- }
- void onTransition(QEvent *)
- { }
-};
-
-void tst_QStateMachine::stopInEventTest_data()
-{
- QTest::addColumn<int>("eventPriority");
- QTest::newRow("NormalPriority") << int(QStateMachine::NormalPriority);
- QTest::newRow("HighPriority") << int(QStateMachine::HighPriority);
-}
-
-void tst_QStateMachine::stopInEventTest()
-{
- QFETCH(int, eventPriority);
-
- QStateMachine machine;
- QState *s1 = new QState(&machine);
- s1->addTransition(new StopInEventTestTransition());
- machine.setInitialState(s1);
-
- QSignalSpy startedSpy(&machine, SIGNAL(started()));
- machine.start();
- QTRY_COMPARE(startedSpy.count(), 1);
-
- QSignalSpy stoppedSpy(&machine, SIGNAL(stopped()));
- QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
- machine.postEvent(new QEvent(QEvent::User), QStateMachine::EventPriority(eventPriority));
-
- QTRY_COMPARE(stoppedSpy.count(), 1);
- QCOMPARE(finishedSpy.count(), 0);
- QCOMPARE(machine.configuration().size(), 1);
- QVERIFY(machine.configuration().contains(s1));
-}
-
-QTEST_MAIN(tst_QStateMachine)
-#include "tst_qstatemachine.moc"