Files
browser-use--browser-use/tests/ci/test_event_bus_resilience.py
wehub-resource-sync 4cd2d4af2b
Test Browser Use CLI Install / uv pip install (ubuntu-latest) (push) Failing after 1s
Test Browser Use CLI Install / uvx browser-use from local wheel (push) Failing after 1s
Test Browser Use CLI Install / uvx browser-use[cli] from PyPI (push) Failing after 1s
package / pip-install-on-macos-latest-py-3.11 (push) Has been skipped
package / pip-install-on-macos-latest-py-3.13 (push) Has been skipped
package / pip-install-on-ubuntu-latest-py-3.11 (push) Has been skipped
package / pip-install-on-windows-latest-py-3.13 (push) Has been skipped
cloud_evals / trigger_cloud_eval_image_build (push) Failing after 1s
docker / build_publish_image (push) Failing after 1s
Test Browser Use CLI Install / browser-use skill sync (push) Failing after 1s
lint / code-style (push) Failing after 0s
lint / type-checker (push) Failing after 1s
package / pip-build (push) Failing after 1s
lint / syntax-errors (push) Failing after 3s
package / pip-install-on-ubuntu-latest-py-3.13 (push) Has been skipped
package / pip-install-on-windows-latest-py-3.11 (push) Has been skipped
test / ${{ matrix.test_filename }} (push) Has been skipped
test / evaluate-tasks (push) Has been skipped
test / setup-chromium (push) Failing after 2s
test / find_tests (push) Failing after 2s
Test Browser Use CLI Install / uv pip install (windows-latest) (push) Has been cancelled
Test Browser Use CLI Install / uv pip install (macos-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:02:32 +08:00

86 lines
3.0 KiB
Python

"""Regression tests for ENG-5280: V2 worker crash on warm-Lambda resume.
A reused keep_alive session bus is stopped and nulled by Agent.close(); on resume the worker
can step() it before a dispatch() restarts it, which makes stock bubus assert. ResilientEventBus
no-ops step()/wait_until_idle() in that state while still restarting on the next dispatch().
"""
import asyncio
from bubus import BaseEvent, EventBus
from browser_use.browser import BrowserProfile, BrowserSession
from browser_use.browser.session import ResilientEventBus
class ResiliencePingEvent(BaseEvent):
pass
def _tear_down_like_agent_close(bus: EventBus) -> None:
"""Mimic the keep_alive teardown in Agent.close() that triggers ENG-5280."""
bus.event_queue = None
bus._on_idle = None
def test_browser_session_uses_resilient_event_bus():
"""The session's default event bus must be the resilient subclass."""
session = BrowserSession(browser_profile=BrowserProfile(keep_alive=True))
assert isinstance(session.event_bus, ResilientEventBus)
def test_resilient_event_bus_keeps_event_bus_name_prefix():
"""The subclass must keep the ``EventBus_`` default name (not ``ResilientEventBus_``)."""
assert ResilientEventBus().name.startswith('EventBus_')
# Explicit names are still honored.
assert ResilientEventBus(name='EventBus_custom').name == 'EventBus_custom'
async def test_step_on_torn_down_bus_is_noop_not_assertion():
"""Stepping a stopped+nulled bus returns None instead of raising AssertionError."""
bus = ResilientEventBus(name='ResilientWarmResumeStep')
bus.dispatch(ResiliencePingEvent())
await asyncio.sleep(0.1)
await bus.stop(clear=False, timeout=1.0)
_tear_down_like_agent_close(bus)
# Warm-Lambda resume: worker steps the torn-down bus. Must not raise.
assert await bus.step() is None
assert await bus.wait_until_idle(timeout=0.1) is None
async def test_torn_down_bus_still_restarts_on_dispatch():
"""A later dispatch() must recreate the queue and process events normally."""
processed: list[BaseEvent] = []
bus = ResilientEventBus(name='ResilientWarmResumeRestart')
bus.on('ResiliencePingEvent', lambda event: processed.append(event))
bus.dispatch(ResiliencePingEvent())
await asyncio.sleep(0.1)
await bus.stop(clear=False, timeout=1.0)
_tear_down_like_agent_close(bus)
# No-op step on the torn-down bus, then dispatch again -> bus restarts.
assert await bus.step() is None
processed.clear()
event = bus.dispatch(ResiliencePingEvent())
await asyncio.wait_for(event, timeout=2.0)
assert len(processed) == 1
await bus.stop(timeout=0.5)
async def test_stock_event_bus_reproduces_the_crash():
"""Document the upstream bug the subclass guards against (stock bus still asserts)."""
bus = EventBus(name='StockWarmResume')
bus.dispatch(ResiliencePingEvent())
await asyncio.sleep(0.1)
await bus.stop(clear=False, timeout=1.0)
_tear_down_like_agent_close(bus)
try:
await bus.step()
raised = False
except AssertionError:
raised = True
assert raised, 'stock EventBus.step() should assert on a torn-down bus'