Skip to content
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

Add missed dialogs to qtbot in test_qt_notifications to prevent segfaults #5171

Merged
merged 7 commits into from
Oct 17, 2022

Conversation

Czaki
Copy link
Collaborator

@Czaki Czaki commented Oct 4, 2022

Description

update of test_qt_notifications.py to better guard Qt object.

Type of change

  • Bug-fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

References

How has this been tested?

  • example: the test suite for my feature covers cases x, y, and z
  • example: all tests pass with my change
  • example: I check if my changes works with both PySide and PyQt backends
    as there are small differences between the two Qt bindings.

Final checklist:

  • My PR is the minimum possible work for the desired functionality
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • If I included new strings, I have used trans. to make them localizable.
    For more information see our translations guide.

@github-actions github-actions bot added qt Relates to qt tests Something related to our tests labels Oct 4, 2022
@codecov
Copy link

codecov bot commented Oct 4, 2022

Codecov Report

Merging #5171 (7c07fad) into main (d64b351) will increase coverage by 0.00%.
The diff coverage is 95.91%.

@@           Coverage Diff           @@
##             main    #5171   +/-   ##
=======================================
  Coverage   88.78%   88.78%           
=======================================
  Files         572      573    +1     
  Lines       48810    48892   +82     
=======================================
+ Hits        43336    43410   +74     
- Misses       5474     5482    +8     
Impacted Files Coverage Δ
napari/_qt/_tests/test_qt_notifications.py 96.00% <95.91%> (+0.27%) ⬆️
napari/_qt/dialogs/qt_notification.py 89.30% <0.00%> (-3.30%) ⬇️
napari/layers/utils/layer_utils.py 93.12% <0.00%> (-0.19%) ⬇️
napari/layers/shapes/shapes.py 91.15% <0.00%> (-0.07%) ⬇️
napari/components/dims.py 97.68% <0.00%> (-0.03%) ⬇️
napari/layers/points/points.py 99.07% <0.00%> (-0.02%) ⬇️
napari/layers/base/base.py 91.70% <0.00%> (ø)
napari/_qt/qt_main_window.py 75.41% <0.00%> (ø)
napari/utils/colormaps/colormap.py 98.07% <0.00%> (ø)
napari/components/_tests/test_dims.py 100.00% <0.00%> (ø)
... and 8 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@Czaki Czaki changed the title Another approach to prevent leak of Qt objects. Add more dialogs to qtbot in test_qt_notifications to prevent segfaults Oct 4, 2022
@Czaki Czaki requested a review from andy-sweet October 4, 2022 10:52
Copy link
Member

@andy-sweet andy-sweet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I almost want to rewrite these tests from scratch, but there's nothing from with this changes as far as I can see, so I'm approving.

Which dialog was not being added to qtbot?

qtbot.add_widget(widget)
show_count = 0

def mock_show_dialog(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: might be nice to either define a fixture for this to be consistent with NapariQtNotification, or just use a plain function instead of a callable and pass the class for which you want to mock show (i.e. NapariQtNotification or TracebackDialog).

Copy link
Collaborator Author

@Czaki Czaki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I put comments where NapariQtNotification are created without using qtbot.

@@ -125,17 +147,16 @@ def run(self):
res = NapariQtNotification.show_notification(notif)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This created here.

@@ -162,9 +183,9 @@ def test_notification_display(
notif = Notification('hi', severity, actions=[('click', lambda x: None)])
NapariQtNotification.show_notification(notif)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This created here


def mock_show_dialog(self):
stat.show_count += 1
qtbot.add_widget(self)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only adds the widget on each call of show. If there are no calls that means it won't be added, which I guess is why we also have the other calls to add_widget in the tests. Could we patch __init__ so that we add it exactly once instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you check now?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I recall correctly, all the tests were passing before this change, but now the flaky windows 3.8 pyside2 test is failing again due to test_qt_notifications. We might have just got lucky before this change and I don't see any reason why the new changes are worse than the previous ones, but just wondered if you had any thoughts?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found 2 places..
But they are failing only if run all tests, not when running individual tests.

@andy-sweet
Copy link
Member

Thanks for clarifying. Added an optional question/suggestion, but still looks fine to me.

@Czaki Czaki force-pushed the bugfix/anothe_guard_for_dialog branch from 1b928a3 to 869f969 Compare October 7, 2022 23:50
@Czaki Czaki changed the title Add more dialogs to qtbot in test_qt_notifications to prevent segfaults Add missed dialogs to qtbot in test_qt_notifications to prevent segfaults Oct 8, 2022
old_traceback_init(self, *args, **kwargs)
qtbot.add_widget(self)

monkeypatch.setattr(NapariQtNotification, "__init__", mock_notif_init)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will the class definition (e.g. NapariQtNotification) be imported fresh for each test function? Or is there a risk that old_notif_init may be the definition from the last test function run?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pytest monkeypatch, restore previous value on test end

Copy link
Collaborator Author

@Czaki Czaki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found 2 calls of show functions that also start animations, that may be reason of faliture.

Comment on lines 77 to 83
@pytest.fixture(autouse=True)
def raise_on_show(monkeypatch, qtbot):
def _raise_on_show(self, *args, **kwargs):
raise RuntimeError('error!')

monkeypatch.setattr(NapariQtNotification, 'show', _raise_on_show)
monkeypatch.setattr(TracebackDialog, 'show', _raise_on_show)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixture raises an exception on the show call if another fixture does not mock it.

old_traceback_init(self, *args, **kwargs)
qtbot.add_widget(self)

monkeypatch.setattr(NapariQtNotification, "__init__", mock_notif_init)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pytest monkeypatch, restore previous value on test end

Comment on lines +262 to +264
monkeypatch.setattr(
NapariQtNotification, "show_notification", lambda x: None
)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me, it is only a workaround, but I do not have any idea how to do this better.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏼

Comment on lines +144 to +146
monkeypatch.setattr(
NapariQtNotification, "show_notification", lambda x: None
)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me, it is only a workaround, but I do not have any idea how to do this better.

@Czaki
Copy link
Collaborator Author

Czaki commented Oct 11, 2022

Still fails...


bttn = dialog.row2_widget.findChild(QPushButton)
assert bttn.text() == 'View Traceback'
mock_show.assert_not_called()
assert count_show.show_traceback_count == 0
bttn.click()
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks like I found a source of the problem. The click of this button is called close_with_fade which starts a timer.
And just after this test, there is a segfault.

Copy link
Contributor

@goanpeca goanpeca left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good @Czaki ! thanks for working on this

@andy-sweet
Copy link
Member

I'll merge this after 24 hours unless there are any objections.

@andy-sweet andy-sweet merged commit fb81ff6 into napari:main Oct 17, 2022
@Czaki Czaki deleted the bugfix/anothe_guard_for_dialog branch June 7, 2023 11:16
@Czaki Czaki mentioned this pull request Jun 7, 2023
@Czaki Czaki added the bugfix PR with bugfix label Jun 7, 2023
@Czaki Czaki added this to the 0.4.18 milestone Jun 7, 2023
@Czaki Czaki added the triaged-0.4.18 To mark PR that is triaged in 0.4.18 release process label Jun 7, 2023
Czaki added a commit that referenced this pull request Jun 16, 2023
…egfaults (#5171)

* check another approach to collect items

* guard other dialogs

* mock __init__ for add to qtbot

* test to find show calls

* disable show_notifications

* put monkeypatch in better place

* close with fade
Czaki added a commit that referenced this pull request Jun 17, 2023
…egfaults (#5171)

* check another approach to collect items

* guard other dialogs

* mock __init__ for add to qtbot

* test to find show calls

* disable show_notifications

* put monkeypatch in better place

* close with fade
Czaki added a commit that referenced this pull request Jun 18, 2023
…egfaults (#5171)

* check another approach to collect items

* guard other dialogs

* mock __init__ for add to qtbot

* test to find show calls

* disable show_notifications

* put monkeypatch in better place

* close with fade
Czaki added a commit that referenced this pull request Jun 19, 2023
…egfaults (#5171)

* check another approach to collect items

* guard other dialogs

* mock __init__ for add to qtbot

* test to find show calls

* disable show_notifications

* put monkeypatch in better place

* close with fade
Czaki added a commit that referenced this pull request Jun 21, 2023
…egfaults (#5171)

* check another approach to collect items

* guard other dialogs

* mock __init__ for add to qtbot

* test to find show calls

* disable show_notifications

* put monkeypatch in better place

* close with fade
Czaki added a commit that referenced this pull request Jun 21, 2023
…egfaults (#5171)

* check another approach to collect items

* guard other dialogs

* mock __init__ for add to qtbot

* test to find show calls

* disable show_notifications

* put monkeypatch in better place

* close with fade
Czaki added a commit that referenced this pull request Jun 21, 2023
…egfaults (#5171)

* check another approach to collect items

* guard other dialogs

* mock __init__ for add to qtbot

* test to find show calls

* disable show_notifications

* put monkeypatch in better place

* close with fade
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugfix PR with bugfix qt Relates to qt tests Something related to our tests triaged-0.4.18 To mark PR that is triaged in 0.4.18 release process
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants