Bug 330665 - BackendTest::createSession() may fail to catch the ready() signal by m_session
Summary: BackendTest::createSession() may fail to catch the ready() signal by m_session
Status: RESOLVED FIXED
Alias: None
Product: cantor
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: unspecified Linux
: NOR normal
Target Milestone: ---
Assignee: Alexander Rieder
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-02-02 12:35 UTC by Tuukka Verho
Modified: 2014-02-06 21:38 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments
Fix the bug using QSignalSpy (2.36 KB, patch)
2014-02-02 12:40 UTC, Tuukka Verho
Details
A fix that keeps the event loop approach (1.46 KB, patch)
2014-02-03 23:39 UTC, Tuukka Verho
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tuukka Verho 2014-02-02 12:35:36 UTC
The method BackendTest::createSession() creates an event loop to block until m_session emits the ready() signal. However, if m_session->login() emits the signal immediately, it won't be caught (python2 and qalculate backends do this). See the fix below.

Reproducible: Always
Comment 1 Tuukka Verho 2014-02-02 12:40:24 UTC
Created attachment 84947 [details]
Fix the bug using QSignalSpy

Use QSignalSpy instead of a temporary event loop. For consistency, also use QSignalSpy in BackendTest::waitForSignal(). Furthermore, use the waitForSignal() method in evalExp() to avoid code duplication.

As an added feature, a timeout prevents hanging if the session fails to emit the ready() signal.
Comment 2 Alexander Rieder 2014-02-03 22:14:51 UTC
Hi,
the idea of using QSignalspy is good, but I think the use of processEvent in a loop is bad, as it seems to waste a lot of cpu cycles waiting (my laptop goes to 100% usage and a short test with cachegrind reveals there a lot more commands being executed with your patch applied). If you look at the implementation of QSignalSpy::wait() in Qt5 you see that they also use an event loop for doing this. So I think this should be the way waitForSignal should be implemented. Also maybe you can share the code between the init and the waitForEvent by taking a QSignalSpy as parameter and doing the event-loop thing for that?
Comment 3 Tuukka Verho 2014-02-03 23:38:34 UTC
Ok, in that case the simplest solution seems to be to stick with the old approach but use a signal spy in createSession() to catch the ready() signal if it is emitted immediately. Another approach would be to have a slot to call m_session->login() and invoke it with QTimer::singleShot(), but I don't think it would be any tidier...

Somehow I don't like the idea of creating a new event loop just to wait for a signal, but it indeed seems to be the Qt way to do it...
Comment 4 Tuukka Verho 2014-02-03 23:39:46 UTC
Created attachment 84979 [details]
A fix that keeps the event loop approach
Comment 5 Alexander Rieder 2014-02-04 20:23:19 UTC
the new patch seems to work well. Do you have commit access or should I do it for you?
Comment 6 Tuukka Verho 2014-02-05 06:26:10 UTC
No, I don't have a dev account.
Comment 7 Alexander Rieder 2014-02-06 21:38:56 UTC
Git commit ab7c8302fe7c20e9b7956a4c886d706f14033ffe by Alexander Rieder.
Committed on 06/02/2014 at 21:36.
Pushed by arieder into branch 'master'.

use QSignalSpy to detect if a signal was emited in the unit tests.

this way we won't miss signals when they are emitted immediately, i.e. before we
create the temporary event loop.

patch by Tuukka Verho, thanks!

M  +8    -12   src/lib/test/backendtest.cpp

http://commits.kde.org/cantor/ab7c8302fe7c20e9b7956a4c886d706f14033ffe