Prevent XMPP racing condition causing test failures at random times#1526
Prevent XMPP racing condition causing test failures at random times#1526
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1526 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 194 194
Lines 25372 25372
Branches 4118 4118
=========================================
Hits 25372 25372 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR fixes a race condition in XMPP test coverage that caused random test failures. The issue occurred because background runner threads created by SlixmppAdapter.process() could still be running during pytest's teardown phase, causing intermittent conflicts with log capture cleanup.
Changes:
- Added thread capture mechanism to ensure background runner threads are properly joined before test completion
- Implemented
_CapturingThreadclass to track thread creation in the test - Added explicit thread join with appropriate timeout in the test cleanup phase
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
tests/test_plugin_xmpp.py
Outdated
| # Optional gate the test can set to make `wait()` pause until a checkpoint | ||
| # is reached. This must be class-level because `threading.Event()` is | ||
| # constructed with no arguments in the code under test. | ||
| signal_evt: Optional[threading.Event] = None |
There was a problem hiding this comment.
The class-level signal_evt attribute creates a potential race condition if multiple tests using _FakeDoneEvent run in parallel. Since this is shared state across all instances, concurrent tests could interfere with each other by overwriting the signal_evt value. Consider using instance-level state or a thread-safe mechanism to avoid test interference.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
tests/test_plugin_xmpp.py
Outdated
| def _patch_threading( | ||
| monkeypatch: pytest.MonkeyPatch, *, | ||
| done_event_cls: type, | ||
| created_thread: dict[str, Any]) -> None: |
There was a problem hiding this comment.
The created_thread parameter is populated but never used anywhere in the codebase. If thread tracking is not needed for these tests, consider removing this parameter to simplify the code. If it was intended for future use or debugging, consider adding a comment explaining its purpose.
tests/test_plugin_xmpp.py
Outdated
| created_thread: dict[str, Any] = {"thread": None} | ||
| _FakeDoneEvent.signal_evt = client_created | ||
|
|
||
| def __getattr__(self, name: str) -> Any: | ||
| return getattr(_real_threading, name) | ||
|
|
||
| monkeypatch.setattr( | ||
| xmpp_adapter, "threading", _ThreadingProxy(), raising=True) | ||
| _patch_threading( | ||
| monkeypatch, | ||
| done_event_cls=_FakeDoneEvent, | ||
| created_thread=created_thread, | ||
| ) |
There was a problem hiding this comment.
After setting _FakeDoneEvent.signal_evt to a specific event or None for a test, this class-level state should be restored to its original value to avoid affecting subsequent tests. Consider adding a try-finally block or pytest fixture to ensure cleanup, or document that tests must explicitly set this value before use.
tests/test_plugin_xmpp.py
Outdated
| created_thread: dict[str, Any] = {"thread": None} | ||
| _FakeDoneEvent.signal_evt = loop_created | ||
|
|
||
| monkeypatch.setattr( | ||
| xmpp_adapter, "threading", _ThreadingProxy(), raising=True) | ||
| _patch_threading( | ||
| monkeypatch, | ||
| done_event_cls=_FakeDoneEvent, | ||
| created_thread=created_thread, | ||
| ) |
There was a problem hiding this comment.
After setting _FakeDoneEvent.signal_evt to a specific event or None for a test, this class-level state should be restored to its original value to avoid affecting subsequent tests. Consider adding a try-finally block or pytest fixture to ensure cleanup, or document that tests must explicitly set this value before use.
tests/test_plugin_xmpp.py
Outdated
| created_thread: dict[str, Any] = {"thread": None} | ||
| _FakeDoneEvent.signal_evt = None | ||
|
|
||
| monkeypatch.setattr( | ||
| xmpp_adapter, "threading", _ThreadingProxy(), raising=True) | ||
| _patch_threading( | ||
| monkeypatch, | ||
| done_event_cls=_FakeDoneEvent, | ||
| created_thread=created_thread, | ||
| ) |
There was a problem hiding this comment.
After setting _FakeDoneEvent.signal_evt to a specific event or None for a test, this class-level state should be restored to its original value to avoid affecting subsequent tests. Consider adding a try-finally block or pytest fixture to ensure cleanup, or document that tests must explicitly set this value before use.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
|
@copilot open a new pull request to apply changes based on the comments in this thread |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot open a new pull request to apply changes based on the comments in this thread |
Description
Related issue (if applicable): #497
XMPP test coverage would randomly fail due to a race condition that is hopefully handled in this PR
Checklist
tox -e lintand optionallytox -e format).tox -e minimal).Testing
Anyone can help test as follows: