summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/scxml/qscxmlstatemachine.cpp9
-rw-r--r--tests/auto/scion/tst_scion.cpp55
2 files changed, 57 insertions, 7 deletions
diff --git a/src/scxml/qscxmlstatemachine.cpp b/src/scxml/qscxmlstatemachine.cpp
index 931e9c6..ba7eece 100644
--- a/src/scxml/qscxmlstatemachine.cpp
+++ b/src/scxml/qscxmlstatemachine.cpp
@@ -729,6 +729,9 @@ void QScxmlStateMachinePrivate::attach(QScxmlStateMachineInfo *info)
void QScxmlStateMachinePrivate::updateMetaCache()
{
+ // This function creates a mapping from state index/name to their signal indexes.
+ // The state index may differ from its signal index as we don't generate history
+ // and invalid states, effectively skipping them
m_stateIndexToSignalIndex.clear();
m_stateNameToSignalIndex.clear();
@@ -2361,7 +2364,11 @@ void QScxmlStateMachine::stop()
bool QScxmlStateMachine::isActive(int stateIndex) const
{
Q_D(const QScxmlStateMachine);
- return d->m_configuration.contains(stateIndex);
+ // Here we need to find the actual internal state index that corresponds with the
+ // index of the compiled metaobject (which is same as its mapped signal index).
+ // See updateMetaCache()
+ const int mappedStateIndex = d->m_stateIndexToSignalIndex.key(stateIndex, -1);
+ return d->m_configuration.contains(mappedStateIndex);
}
QT_END_NAMESPACE
diff --git a/tests/auto/scion/tst_scion.cpp b/tests/auto/scion/tst_scion.cpp
index e98df03..37cc42f 100644
--- a/tests/auto/scion/tst_scion.cpp
+++ b/tests/auto/scion/tst_scion.cpp
@@ -244,16 +244,38 @@ void TestScion::compiled()
static bool verifyStates(QScxmlStateMachine *stateMachine, const QJsonObject &stateDescription, const QString &key, int counter)
{
+ const auto errorMessage = [&key, &counter](const QStringList& current,
+ const QStringList& expected, const QLatin1String& details) {
+ qWarning("Incorrect %s (%d)!", qPrintable(key), counter);
+ qWarning() << "Current configuration:" << current;
+ qWarning() << "Expected configuration:" << expected;
+ qWarning() << "Failed state read was done with:" << details;
+ };
+ using namespace Qt::StringLiterals;
+
+ // Verify that activeStateNames() matches the expectation
auto current = stateMachine->activeStateNames();
std::sort(current.begin(), current.end());
auto expected = getStates(stateDescription, key);
- if (current == expected)
- return true;
+ if (current != expected) {
+ errorMessage(current, expected, "activeStateNames()"_L1);
+ return false;
+ }
- qWarning("Incorrect %s (%d)!", qPrintable(key), counter);
- qWarning() << "Current configuration:" << current;
- qWarning() << "Expected configuration:" << expected;
- return false;
+ for (const auto& s : expected) {
+ // Verify that isActive(stateName) matches the expectation
+ if (!stateMachine->isActive(s)) {
+ errorMessage(current, expected, "isActive()"_L1);
+ return false;
+ }
+ // Verify that the metaobject matches the expectation
+ const auto mo = stateMachine->metaObject();
+ if (!mo->property(mo->indexOfProperty(s.toLocal8Bit())).read(stateMachine).toBool()) {
+ errorMessage(current, expected, "metaobject read"_L1);
+ return false;
+ }
+ }
+ return true;
}
static bool playEvent(QScxmlStateMachine *stateMachine, const QJsonObject &eventDescription, int counter)
@@ -319,11 +341,32 @@ static bool playEvent(QScxmlStateMachine *stateMachine, const QJsonObject &event
});
MySignalSpy triggerSpy(&trigger, SIGNAL(timeout()));
+ // Create a signal spy for each state we expect to be (de)activated in next transition.
+ using namespace Qt::StringLiterals;
+ const auto expectedActive = getStates(eventDescription, QLatin1String("nextConfiguration"));
+ std::list<std::unique_ptr<QSignalSpy>> stateSpies;
+ const auto mo = stateMachine->metaObject();
+
+ for (const auto& s : stateMachine->stateNames()) {
+ if (expectedActive.contains(s) == stateMachine->isActive(s))
+ continue;
+ // The state is expected to undergo an activation change, create a signal spy
+ const auto changedSignal = s + "Changed(bool)"_L1;
+ auto signalIndex = mo->indexOfSignal(changedSignal.toUtf8().constData());
+ stateSpies.push_back(std::make_unique<QSignalSpy>(stateMachine, mo->method(signalIndex)));
+ }
+
stateMachine->submitEvent(e);
if (!triggerSpy.fastWait()) {
qWarning() << "State machine did not reach a stable state.";
} else if (verifyStates(stateMachine, eventDescription, QLatin1String("nextConfiguration"), counter)) {
+ for (const auto& spy : stateSpies) {
+ if (spy->size() != 1) {
+ qWarning() << "Signal error for:" << spy->signal() << ", size:" << spy->size();
+ return false;
+ }
+ }
return true;
}