diff options
Diffstat (limited to 'tests/auto/qstatemachine/tst_qstatemachine.cpp')
-rw-r--r-- | tests/auto/qstatemachine/tst_qstatemachine.cpp | 4448 |
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" |