-
Notifications
You must be signed in to change notification settings - Fork 451
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Tribler startup/shutdown and GUI tests stability #6828
Fix Tribler startup/shutdown and GUI tests stability #6828
Conversation
retest this please |
3 similar comments
retest this please |
retest this please |
retest this please |
4bf095f
to
0ca3212
Compare
retest this please |
4 similar comments
retest this please |
retest this please |
retest this please |
retest this please |
e7be306
to
315439a
Compare
315439a
to
b5349c6
Compare
GUI tests are passing, but core tests are still sometimes aborted on timeout. For example, right now Core tests was timed out on def test_add_content_dir(tdef):
"""
Test whether adding a single content directory with two files is working correctly.
"""
torrent_dir = TESTS_DATA_DIR / "contentdir"
tdef.add_content(torrent_dir / "file.txt")
tdef.add_content(torrent_dir / "otherfile.txt")
tdef.save()
metainfo = tdef.get_metainfo()
assert len(metainfo[b'info'][b'files']) == 2 It seems that for core tests, the deadlocks are caused not by tests themselves but by something in the pytests setup. Anyway, GUI tests stability seems to be fixed. |
retest this please |
retest this please |
1 similar comment
retest this please |
b5349c6
to
da025dc
Compare
Kudos, SonarCloud Quality Gate passed! 0 Bugs No Coverage information |
retest this please |
GitHub web hooks and actions status is degraded today: https://www.githubstatus.com/ |
retest this please |
1 similar comment
retest this please |
Fixes #6583.
It seems I was able to fix unstable GUI tests. I tested this PR 15 times in a row without a single failure, while without this PR, almost every run of GUI tests ends with a failure.
The PR consists of several mostly independent commits; it is easier to review them on a per-commit basis.
The first commit changes the logic of the
QApplication
shutdown to preventRuntimeError
exceptions "wrapped C/C++ object of type ... has been deleted". The reason for the error is that we should not touch any Qt object after theQApplication.quit()
invocation, as Qt objectы can already be partially destroyed at this stage. It is not easy to satisfy this requirement, as some Qt signals are emitted afterQApplication.quit()
was already called, for exampleQProcess.readyReadStandardOutput
andQProcess.readyReadStandardError
. Also, if an exception hook catches some exception during the application shutdown, it should not openFeedbackDialog
as it can already be destroyed as well.QCoreApplication
has a specialclosingDown
property that was apparently added for this type of check. Unfortunately, it is not working correctly for some reason - it returnsFalse
inside a signal during the application closing down, and any attempt to access a Qt object immediately after that leads to the same RuntimeError "wrapped C/C++ object ... has been deleted".To solve this, I added a special
AppManager
class that handles the application shutdown. Now, instead of directly callingQApplication.quit()
, you should always callapp_manager.quit_application()
. A code can check theapp_manager.quitting_app
flag before accessing a Qt object to ensure that the application is not shutting down. This way, all runtime errors "wrapped C/C++ object ... has been deleted" were eliminated.The reason for implementing a separate
AppManager
class instead of adding the functionality into an existing class (likeTriblerWindow
) is to avoid circular imports and to simplify dependency injections.The second commit renames a signal
EventRequestManager.tribler_started
tocore_connected
to better reflect the actual purpose of the signal - it is emitted at the moment GUI starts receiving events from Core.Then I rewrote the
wait_for_signal
function used in GUI tests. It turns out the previous implementation was completely broken - it used a global variablesignal_received
that was not reset after the usage. In GUI tests, thewait_for_signal
function was called multiple times, first inside thewindow
fixture to wait for the application to start and then in specific tests to wait for a particular GUI state. As a result,wait_for_signal
never worked properly inside tests, as thesignal_received
flag was already set in thewindow
fixture and newer reset.The main fix for the
wait_for_signal
function is in passing to the function a dynamically calculated condition that is re-evaluated on each iteration instead of passing just a static value of a boolean flag.After I fixed the
wait_for_signal
function, I discovered a brokentest_tags_dialog
test and fixed it as well.