Skip to content

Pin per-branch cleanup contract for bluetooth_device_connect#1761

Merged
bdraco merged 1 commit into
esphome:mainfrom
esphbot:koan/bluetooth-connect-cleanup-test
May 26, 2026
Merged

Pin per-branch cleanup contract for bluetooth_device_connect#1761
bdraco merged 1 commit into
esphome:mainfrom
esphbot:koan/bluetooth-connect-cleanup-test

Conversation

@esphbot
Copy link
Copy Markdown
Contributor

@esphbot esphbot commented May 26, 2026

What

Add test_bluetooth_device_connect_cleanup_contract pinning the
per-outcome cleanup contract of APIClient.bluetooth_device_connect
across all five branches: success, timeout, task-cancelled, external
future-cancelled, and a non-CancelledError BaseException.

Why

The cleanup flow today threads three booleans (connect_ok,
timeout_expired, unhandled_exception) through one shared
finally. Any refactor that simplifies that bookkeeping risks
silently double-unsub'ing, skipping an unsub, or firing the
wrong disconnect path on one branch while the others keep passing.
This test pins each branch's unsub count, _bluetooth_disconnect_no_wait
count, and that no message handler leaks, so a regression on any
single outcome fails loudly.

Split out of #1756 so the contract test can land independently of
the refactor it was written to enable.

How

The test runs each outcome through a shared _run_branch helper
that wraps send_message_callback_response to count unsub
invocations, captures the response future via loop.create_future,
and wraps _bluetooth_disconnect_no_wait to count calls. Outcomes
are triggered by feeding the connect response, sleeping past the
timeout, cancelling the task, cancelling the captured future, or
setting an exception on it. Handler leak is asserted by snapshotting
_message_handlers before/after.

Test plan

  • SKIP_CYTHON=1 ./venv/bin/python -m pytest tests/test_client.py -k bluetooth_device_connect -v — all 11 connect tests pass (the new one plus the 10 existing).
  • ./venv/bin/ruff check tests/test_client.py && ./venv/bin/ruff format --check tests/test_client.py — clean.

Types of changes

  • Test

Quality Report

Changes: 1 file changed, 188 insertions(+), 1 deletion(-)

Code scan: clean

Tests: failed ([Errno 13] Permission denied: 'pytest')

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

Add test_bluetooth_device_connect_cleanup_contract covering all five
outcomes (success, timeout, task-cancelled, external future-cancelled,
non-CancelledError BaseException). Each branch asserts the documented
unsub call count, _bluetooth_disconnect_no_wait call count, and that
no message handlers leak.

This pins existing behaviour so any future refactor of the cleanup
flow can't silently regress one branch while another still passes.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (8a520b8) to head (4377a86).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #1761   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           26        26           
  Lines         4251      4251           
=========================================
  Hits          4251      4251           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 26, 2026

Merging this PR will not alter performance

✅ 56 untouched benchmarks


Comparing esphbot:koan/bluetooth-connect-cleanup-test (4377a86) with main (8a520b8)

Open in CodSpeed

@bdraco bdraco marked this pull request as ready for review May 26, 2026 17:33
Copilot AI review requested due to automatic review settings May 26, 2026 17:33
@bdraco bdraco merged commit d2e73f4 into esphome:main May 26, 2026
15 of 16 checks passed
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0f8348c8-4132-4a84-9d6e-f45a50fe71f0

📥 Commits

Reviewing files that changed from the base of the PR and between 8a520b8 and 4377a86.

📒 Files selected for processing (1)
  • tests/test_client.py

Walkthrough

Added a comprehensive test for the bluetooth_device_connect cleanup contract that validates proper resource cleanup (unsubscriptions, disconnect calls, and message handler cleanup) across five outcome scenarios: success, timeout, task cancellation, external future cancellation, and non-cancellation exceptions.

Changes

Bluetooth Device Connect Cleanup Contract Test

Layer / File(s) Summary
Cleanup contract test with typing imports
tests/test_client.py
Updated collections.abc imports to include Awaitable. Added test_bluetooth_device_connect_cleanup_contract that exercises bluetooth_device_connect across success, timeout, task cancel, external future cancel, and base exception branches. The test uses a shared _run_branch helper to count unsubscriptions via wrapped send_message_callback_response, patches _bluetooth_disconnect_no_wait to count disconnect calls, and verifies no message handlers leak after each scenario.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

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

Adds a regression/contract test to pin the per-outcome cleanup behavior of APIClient.bluetooth_device_connect, ensuring future refactors don’t accidentally change unsub()/disconnect behavior or leak message handlers.

Changes:

  • Add test_bluetooth_device_connect_cleanup_contract covering five outcomes (success, timeout, task-cancelled, externally future-cancelled, non-CancelledError BaseException) with assertions on unsub and _bluetooth_disconnect_no_wait call counts and handler leak checks.
  • Update TYPE_CHECKING imports to include Awaitable for the new helper type annotations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/test_client.py
Comment on lines +4233 to +4239
"""Pin the per-branch cleanup contract for ``bluetooth_device_connect``.

Each outcome (success, timeout, task-cancelled, future-cancelled,
base-exception) must call ``unsub`` and ``_bluetooth_disconnect_no_wait``
exactly the documented number of times and leave no leaked message
handlers or pending timeout handles.
"""
@esphbot esphbot deleted the koan/bluetooth-connect-cleanup-test branch May 27, 2026 15:16
@github-actions github-actions Bot locked and limited conversation to collaborators May 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants