Skip to content

Prevent XMPP racing condition causing test failures at random times#1526

Merged
caronc merged 10 commits intomasterfrom
xmpp-test-race-condition-fix
Feb 20, 2026
Merged

Prevent XMPP racing condition causing test failures at random times#1526
caronc merged 10 commits intomasterfrom
xmpp-test-race-condition-fix

Conversation

@caronc
Copy link
Owner

@caronc caronc commented Feb 19, 2026

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

  • Documentation ticket created (if applicable): n/a
  • The change is tested and works locally.
  • No commented-out code in this PR.
  • No lint errors (use tox -e lint and optionally tox -e format).
  • Test coverage added or updated (use tox -e minimal).

Testing

Anyone can help test as follows:

# Create a virtual environment
python3 -m venv apprise

# Change into our new directory
cd apprise

# Activate our virtual environment
source bin/activate

# Install the branch
pip install git+https://github.com/caronc/apprise.git@xmpp-test-race-condition-fix

# Run tests and do not get an xmpp error:
tox -e qa

@caronc caronc changed the title prevent racing condition during some test coverage Pevent XMPP racing condition causing test failures in random cases Feb 19, 2026
@caronc caronc changed the title Pevent XMPP racing condition causing test failures in random cases Pevent XMPP racing condition causing test failures at random times Feb 19, 2026
@codecov
Copy link

codecov bot commented Feb 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (9d9931a) to head (0214835).
⚠️ Report is 1 commits behind head on master.

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:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@caronc caronc changed the title Pevent XMPP racing condition causing test failures at random times Prevent XMPP racing condition causing test failures at random times Feb 19, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 _CapturingThread class 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.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.

# 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
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

def _patch_threading(
monkeypatch: pytest.MonkeyPatch, *,
done_event_cls: type,
created_thread: dict[str, Any]) -> None:
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines 948 to 955
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,
)
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines 1039 to 1046
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,
)
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines 1133 to 1140
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,
)
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

Copy link

Copilot AI commented Feb 20, 2026

@caronc I've opened a new pull request, #1527, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link

Copilot AI commented Feb 20, 2026

@caronc I've opened a new pull request, #1528, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link

Copilot AI commented Feb 20, 2026

@caronc I've opened a new pull request, #1529, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link

Copilot AI commented Feb 20, 2026

@caronc I've opened a new pull request, #1530, to work on those changes. Once the pull request is ready, I'll request review from you.

@caronc
Copy link
Owner Author

caronc commented Feb 20, 2026

@copilot open a new pull request to apply changes based on the comments in this thread

Copy link

Copilot AI commented Feb 20, 2026

@caronc I've opened a new pull request, #1531, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.

@caronc
Copy link
Owner Author

caronc commented Feb 20, 2026

@copilot open a new pull request to apply changes based on the comments in this thread

Copy link

Copilot AI commented Feb 20, 2026

@caronc I've opened a new pull request, #1533, to work on those changes. Once the pull request is ready, I'll request review from you.

@caronc caronc merged commit 1401205 into master Feb 20, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants