summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/auto.pro3
-rw-r--r--tests/auto/statemachineinfo/statemachine.scxml45
-rw-r--r--tests/auto/statemachineinfo/statemachineinfo.pro13
-rw-r--r--tests/auto/statemachineinfo/tst_statemachineinfo.cpp205
-rw-r--r--tests/auto/statemachineinfo/tst_statemachineinfo.qrc5
5 files changed, 270 insertions, 1 deletions
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 776a54a..60576d5 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -4,4 +4,5 @@ SUBDIRS = cmake\
dynamicmetaobject\
parser\
scion\
- statemachine
+ statemachine \
+ statemachineinfo
diff --git a/tests/auto/statemachineinfo/statemachine.scxml b/tests/auto/statemachineinfo/statemachine.scxml
new file mode 100644
index 0000000..94f06b1
--- /dev/null
+++ b/tests/auto/statemachineinfo/statemachine.scxml
@@ -0,0 +1,45 @@
+<?xml version="1.0" ?>
+<!--
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtScxml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+-->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0" name="InfoTest">
+ <transition/>
+ <state>
+ <transition target="next" event="step"/>
+ </state>
+ <parallel id="next">
+ <state id="a">
+ <transition target="theEnd" event="step"/>
+ </state>
+ <state id="b">
+ <transition target="theEnd" event="step" type="internal"/>
+ </state>
+ </parallel>
+ <final id="theEnd"/>
+</scxml>
diff --git a/tests/auto/statemachineinfo/statemachineinfo.pro b/tests/auto/statemachineinfo/statemachineinfo.pro
new file mode 100644
index 0000000..f8d5b5d
--- /dev/null
+++ b/tests/auto/statemachineinfo/statemachineinfo.pro
@@ -0,0 +1,13 @@
+QT = core gui qml testlib scxml-private
+CONFIG += testcase
+
+TARGET = tst_statemachineinfo
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+RESOURCES += tst_statemachineinfo.qrc
+
+SOURCES += \
+ tst_statemachineinfo.cpp
diff --git a/tests/auto/statemachineinfo/tst_statemachineinfo.cpp b/tests/auto/statemachineinfo/tst_statemachineinfo.cpp
new file mode 100644
index 0000000..1c33847
--- /dev/null
+++ b/tests/auto/statemachineinfo/tst_statemachineinfo.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtScxml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest>
+#include <QtScxml/qscxmlstatemachine.h>
+#include <QtScxml/private/qscxmlstatemachineinfo_p.h>
+
+Q_DECLARE_METATYPE(QScxmlError);
+
+class tst_StateMachineInfo: public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void checkInfo();
+};
+
+class Recorder: public QObject
+{
+ Q_OBJECT
+
+public:
+ void clear()
+ {
+ enterCount = 0;
+ entered.clear();
+ exitCount = 0;
+ exited.clear();
+ transitionTriggerCount = 0;
+ transitions.clear();
+ macroStepDone = false;
+ }
+
+public slots:
+ void statesEntered(const QVector<QScxmlStateMachineInfo::StateId> &states)
+ { entered = states; ++enterCount; }
+
+ void statesExited(const QVector<QScxmlStateMachineInfo::StateId> &states)
+ { exited = states; ++exitCount; }
+
+ void transitionsTriggered(const QVector<QScxmlStateMachineInfo::TransitionId> &transitions)
+ { this->transitions = transitions; ++transitionTriggerCount; }
+
+ void reachedStableState()
+ { macroStepDone = true; }
+
+ bool finishMacroStep() const
+ {
+ for (int i = 0; i < 100; ++i) {
+ if (!macroStepDone)
+ QCoreApplication::processEvents();
+ }
+
+ return macroStepDone;
+ }
+
+public:
+ int enterCount = 0;
+ QVector<QScxmlStateMachineInfo::StateId> entered;
+ int exitCount = 0;
+ QVector<QScxmlStateMachineInfo::StateId> exited;
+ int transitionTriggerCount = 0;
+ QVector<QScxmlStateMachineInfo::TransitionId> transitions;
+ bool macroStepDone = false;
+};
+
+void tst_StateMachineInfo::checkInfo()
+{
+ QScopedPointer<QScxmlStateMachine> stateMachine(
+ QScxmlStateMachine::fromFile(QString(":/tst_statemachineinfo/statemachine.scxml")));
+ QVERIFY(!stateMachine.isNull());
+ QVERIFY(stateMachine->parseErrors().isEmpty());
+ auto info = new QScxmlStateMachineInfo(stateMachine.data());
+
+ const QString machineName = QLatin1String("InfoTest");
+ QCOMPARE(info->stateName(QScxmlStateMachineInfo::StateMachineRootState), machineName);
+
+ auto states = info->allStates();
+ QCOMPARE(states.size(), 5);
+ QCOMPARE(info->stateName(states.at(0)), QLatin1String(""));
+ QCOMPARE(info->stateName(states.at(1)), QLatin1String("next"));
+ QCOMPARE(info->stateName(states.at(2)), QLatin1String("a"));
+ QCOMPARE(info->stateName(states.at(3)), QLatin1String("b"));
+ QCOMPARE(info->stateName(states.at(4)), QLatin1String("theEnd"));
+
+ QCOMPARE(info->stateType(states.at(0)), QScxmlStateMachineInfo::NormalState);
+ QCOMPARE(info->stateType(states.at(1)), QScxmlStateMachineInfo::ParallelState);
+ QCOMPARE(info->stateType(states.at(2)), QScxmlStateMachineInfo::NormalState);
+ QCOMPARE(info->stateType(states.at(3)), QScxmlStateMachineInfo::NormalState);
+ QCOMPARE(info->stateType(states.at(4)), QScxmlStateMachineInfo::FinalState);
+
+ auto transitions = info->allTransitions();
+ QCOMPARE(transitions.size(), 6);
+
+ // targetless transition on top level
+ QCOMPARE(info->transitionType(transitions.at(0)), QScxmlStateMachineInfo::ExternalTransition);
+ QCOMPARE(info->stateType(info->transitionSource(transitions.at(0))),
+ QScxmlStateMachineInfo::StateMachineRootState);
+ QCOMPARE(info->transitionTargets(transitions.at(0)).size(), 0);
+
+ // <anon>->next
+ QCOMPARE(info->transitionType(transitions.at(1)), QScxmlStateMachineInfo::ExternalTransition);
+ QCOMPARE(info->transitionSource(transitions.at(1)), states.at(0));
+ QCOMPARE(info->transitionTargets(transitions.at(1)).size(), 1);
+ QCOMPARE(info->transitionTargets(transitions.at(1)).at(0), states.at(1));
+
+ // a->theEnd
+ QCOMPARE(info->transitionType(transitions.at(2)), QScxmlStateMachineInfo::ExternalTransition);
+ QCOMPARE(info->transitionSource(transitions.at(2)), states.at(2));
+ QCOMPARE(info->transitionTargets(transitions.at(2)).size(), 1);
+ QCOMPARE(info->transitionTargets(transitions.at(2)).at(0), states.at(4));
+
+ // b->theEnd
+ QCOMPARE(info->transitionType(transitions.at(3)), QScxmlStateMachineInfo::InternalTransition);
+ QCOMPARE(info->transitionSource(transitions.at(3)), states.at(3));
+ QCOMPARE(info->transitionTargets(transitions.at(3)).size(), 1);
+ QCOMPARE(info->transitionTargets(transitions.at(3)).at(0), states.at(4));
+
+ // initial transition that activates the first (anonymous) state
+ QCOMPARE(info->transitionType(transitions.at(4)), QScxmlStateMachineInfo::SyntheticTransition);
+ QCOMPARE(info->stateType(info->transitionSource(transitions.at(4))),
+ QScxmlStateMachineInfo::StateMachineRootState);
+ QCOMPARE(info->transitionTargets(transitions.at(4)).size(), 1);
+ QCOMPARE(info->transitionTargets(transitions.at(4)).at(0), states.at(0));
+
+ // "initial" transition in the next state that activates all sub-states
+ QCOMPARE(info->transitionType(transitions.at(5)), QScxmlStateMachineInfo::SyntheticTransition);
+ QCOMPARE(info->transitionSource(transitions.at(5)), states.at(1));
+ QCOMPARE(info->transitionTargets(transitions.at(5)).size(), 2);
+ QCOMPARE(info->transitionTargets(transitions.at(5)).at(0), states.at(2));
+ QCOMPARE(info->transitionTargets(transitions.at(5)).at(1), states.at(3));
+
+ Recorder recorder;
+ QObject::connect(info, &QScxmlStateMachineInfo::statesEntered,
+ &recorder, &Recorder::statesEntered);
+ QObject::connect(info, &QScxmlStateMachineInfo::statesExited,
+ &recorder, &Recorder::statesExited);
+ QObject::connect(info, &QScxmlStateMachineInfo::transitionsTriggered,
+ &recorder, &Recorder::transitionsTriggered);
+ QObject::connect(stateMachine.data(), &QScxmlStateMachine::reachedStableState,
+ &recorder, &Recorder::reachedStableState);
+
+ // initial step into first anonymous state
+ stateMachine->start();
+ QVERIFY(recorder.finishMacroStep());
+ QCOMPARE(recorder.enterCount, 1);
+ QCOMPARE(recorder.entered, QVector<QScxmlStateMachineInfo::StateId>() << 0);
+ QVERIFY(recorder.exited.isEmpty());
+
+ recorder.clear();
+
+ // step from anonymous state into the parallel state, which activates "a" and "b" (in THAT
+ // order!)
+ stateMachine->submitEvent("step");
+ QVERIFY(recorder.finishMacroStep());
+ QCOMPARE(recorder.enterCount, 1);
+ QCOMPARE(recorder.entered, QVector<QScxmlStateMachineInfo::StateId>() << 1 << 2 << 3);
+ QCOMPARE(recorder.exited, QVector<QScxmlStateMachineInfo::StateId>() << 0);
+ QCOMPARE(recorder.transitionTriggerCount, 1);
+ QCOMPARE(recorder.transitions, QVector<QScxmlStateMachineInfo::TransitionId>() << 1);
+
+ recorder.clear();
+
+ // step from the state "b" into "theEnd", which exits "b", "a", and "next" in exactly that
+ // order
+ stateMachine->submitEvent("step");
+ QVERIFY(recorder.finishMacroStep());
+ QCOMPARE(recorder.enterCount, 1);
+ QCOMPARE(recorder.entered, QVector<QScxmlStateMachineInfo::StateId>() << 4);
+ QCOMPARE(recorder.exited, QVector<QScxmlStateMachineInfo::StateId>() << 3 << 2 << 1);
+ QCOMPARE(recorder.transitionTriggerCount, 1);
+ QCOMPARE(recorder.transitions, QVector<QScxmlStateMachineInfo::TransitionId>() << 2);
+}
+
+
+QTEST_MAIN(tst_StateMachineInfo)
+
+#include "tst_statemachineinfo.moc"
+
+
diff --git a/tests/auto/statemachineinfo/tst_statemachineinfo.qrc b/tests/auto/statemachineinfo/tst_statemachineinfo.qrc
new file mode 100644
index 0000000..0e464d4
--- /dev/null
+++ b/tests/auto/statemachineinfo/tst_statemachineinfo.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/tst_statemachineinfo">
+ <file>statemachine.scxml</file>
+ </qresource>
+</RCC>