diff options
author | Jarek Kobus <jaroslaw.kobus@qt.io> | 2020-08-06 11:19:30 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2020-08-10 11:30:24 +0000 |
commit | 0c7536902901a882fd3e58f5314d03a37a386033 (patch) | |
tree | ec22a507b9df698bac9efe3c731802a819d9a4de | |
parent | 53b71057390a31532517fead1eda1be2c503f6ef (diff) |
Fix flaky autotest with a delayed event in scion
Before the historical fix for the issue
(commit 3da30ee8928ab27249a74966ed4981766d62ff25)
the playEvent() method submitted directly the
delayed event and it tried to verify the configuration
just after. It couldn't work, since
the event was delayed, so the demanded configuration
couldn't be reached yet - it was checked too early.
After the mentioned fix, we didn't submit an event
immediately, but waited demanded time (in hope,
that statemachine reaches the configuration expected
after a delay) to mimic the delay, and after that,
we submitted a non-delayed event directly.
This could also cause issues like
these mentioned in task description. The reason could
be a race between the point in time when statemachine
issues the delayed "s" event and the point in time
when we submit the "t2" event. It could happen, that
we submit "t2" while still being in "b" state (so before
the statemachine issues the "s" event), and in this
case the "t2" event doesn't trigger any change in
the statemachine, thus the configuration stay unchanged.
In the current fix we go back to the original idea of
submitting the delayed event directly, but we are
delaying the point in time when we do check the configuration
expected after the event is dispatched. So is case of delayed
event we connect to the statemachine's signal emitted
when the event is being dispatched.
After the connection is established, we submit a delayed event
and start awaiting for the right moment when we should
expect the stabilized configuration. This will be signalled
with a timeout of trigger timer object.
When the submitted event has been dispatched (after the
desired delay), we connect synchronously to state machine's
reachedStableState() signal. When reachedStableState() is
received, we trigger the timer to unwind from synchronously
called slot and to get back to the place where we were
awaiting for timer to be triggered. Now we should expect
the right configuration.
The above approach works nicely also in case of playing
non-delayed events.
Fixes: QTBUG-83420
Change-Id: Ia6ddbc6ac9282a2dd41e0c99dd1bb59610690c95
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit 2427b675711119c6aac68b662434eb8a0910c3a3)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | tests/auto/scion/tst_scion.cpp | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/tests/auto/scion/tst_scion.cpp b/tests/auto/scion/tst_scion.cpp index 5473e9d..d1e4873 100644 --- a/tests/auto/scion/tst_scion.cpp +++ b/tests/auto/scion/tst_scion.cpp @@ -329,18 +329,33 @@ static bool playEvent(QScxmlStateMachine *stateMachine, const QJsonObject &event e->setOrigin(origin); e->setOriginType(origintype); e->setInvokeId(invokeid); - if (eventDescription.contains(QLatin1String("after"))) - QTest::qWait(eventDescription.value(QLatin1String("after")).toInt()); + int delay = 0; + if (eventDescription.contains(QLatin1String("after"))) { + delay = eventDescription.value(QLatin1String("after")).toInt(); + Q_ASSERT(delay > 0); + e->setDelay(delay); + } + + QTimer trigger; + trigger.setSingleShot(true); + stateMachine->connectToEvent(eventName, &trigger, [&stateMachine, &trigger](const QScxmlEvent &) { + QObject::connect(stateMachine, &QScxmlStateMachine::reachedStableState, + &trigger, QOverload<>::of(&QTimer::start)); + }); + MySignalSpy triggerSpy(&trigger, SIGNAL(timeout())); stateMachine->submitEvent(e); - if (!MySignalSpy(stateMachine, SIGNAL(reachedStableState())).fastWait()) { - qWarning() << "State machine did not reach a stable state!"; + if (!triggerSpy.fastWait()) { + qWarning() << "State machine did not reach a stable state."; } else if (verifyStates(stateMachine, eventDescription, QLatin1String("nextConfiguration"), counter)) { return true; } - qWarning() << "... after sending event" << event; + if (delay > 0) + qWarning("... after sending delayed event %s with a delay of %dms.", qPrintable(eventName), delay); + else + qWarning("... after sending event %s.", qPrintable(eventName)); return false; } |