summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTarja Sundqvist <tarja.sundqvist@qt.io>2023-10-11 16:01:45 +0300
committerTarja Sundqvist <tarja.sundqvist@qt.io>2023-10-11 16:01:45 +0300
commit3f56c6b4bd1e3883581340243b4a7289807fffc9 (patch)
treebd3c65b5950d0931ba1a826e5f64f250584e2deb
parente8727aabe55526956295407d27317ec15e12b283 (diff)
parent29c25449e72ac918b5500f9b9e4cd0b189630498 (diff)
Merge remote-tracking branch 'origin/tqtc/lts-5.15.12' into tqtc/lts-5.15-opensourcev5.15.12-lts-lgpl
-rw-r--r--.qmake.conf2
-rw-r--r--src/scxml/qscxmlstatemachine.cpp9
-rw-r--r--tests/auto/scion/tst_scion.cpp54
3 files changed, 57 insertions, 8 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 098b456..9b73845 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -4,4 +4,4 @@ CONFIG += warning_clean
DEFINES += QT_NO_FOREACH QT_NO_JAVA_STYLE_ITERATORS QT_NO_LINKED_LIST
-MODULE_VERSION = 5.15.11
+MODULE_VERSION = 5.15.12
diff --git a/src/scxml/qscxmlstatemachine.cpp b/src/scxml/qscxmlstatemachine.cpp
index 58832b8..b22c618 100644
--- a/src/scxml/qscxmlstatemachine.cpp
+++ b/src/scxml/qscxmlstatemachine.cpp
@@ -767,6 +767,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();
@@ -2366,7 +2369,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 d1e4873..eaa8e4d 100644
--- a/tests/auto/scion/tst_scion.cpp
+++ b/tests/auto/scion/tst_scion.cpp
@@ -269,16 +269,37 @@ 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;
+ };
+
+ // 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, QLatin1String("activeStateNames()"));
+ 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, QLatin1String("isActive()"));
+ 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, QLatin1String("metaobject read"));
+ return false;
+ }
+ }
+ return true;
}
static bool playEvent(QScxmlStateMachine *stateMachine, const QJsonObject &eventDescription, int counter)
@@ -344,11 +365,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.
+ 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 + QLatin1String("Changed(bool)");
+ auto signalIndex = mo->indexOfSignal(changedSignal.toUtf8().constData());
+ stateSpies.push_back(std::unique_ptr<QSignalSpy>(
+ new 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;
}