Co-authored-by: Antoine <33425718+anth2o@users.noreply.github.com>
Co-authored-by: Bastien <bastien.baret@gmail.com>
Co-authored-by: Clément Sirieix <clement.sirieix@mistral.ai>
Co-authored-by: Kim-Adeline Miguel <51720070+kimadeline@users.noreply.github.com>
Co-authored-by: Mathias Gesbert <mathias.gesbert@mistral.ai>
Co-authored-by: Maxime Dolores <maxime.dolores@ext.mistral.ai>
Co-authored-by: Michel Thomazo <51709227+michelTho@users.noreply.github.com>
Co-authored-by: Nelson PROIA <144663685+Nelson-PROIA@users.noreply.github.com>
Co-authored-by: Pierre Rossinès <pierre.rossines@mistral.ai>
Co-authored-by: Quentin <quentin.torroba@mistral.ai>
Co-authored-by: Robin Gullo <robin.gullo@mistral.ai>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
Clément Drouin 2026-04-28 17:44:07 +02:00 committed by GitHub
parent a83c81ecf5
commit 632ea8c032
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
253 changed files with 13965 additions and 2525 deletions

155
tests/acp/test_session.py Normal file
View file

@ -0,0 +1,155 @@
from __future__ import annotations
import asyncio
from unittest.mock import MagicMock
import pytest
from vibe.acp.session import AcpSessionLoop
def _make_session() -> AcpSessionLoop:
return AcpSessionLoop(
id="test-session", agent_loop=MagicMock(), command_registry=MagicMock()
)
class TestSpawn:
@pytest.mark.asyncio
async def test_spawn_creates_task(self) -> None:
session = _make_session()
ran = asyncio.Event()
async def work() -> None:
ran.set()
task = session.spawn(work())
assert task is not None
await task
assert ran.is_set()
@pytest.mark.asyncio
async def test_spawn_returns_none_after_close(self) -> None:
session = _make_session()
await session.close()
async def noop() -> None:
pass
assert session.spawn(noop()) is None
@pytest.mark.asyncio
async def test_spawn_tracks_multiple_tasks(self) -> None:
session = _make_session()
gate = asyncio.Event()
async def wait_for_gate() -> None:
await gate.wait()
t1 = session.spawn(wait_for_gate())
t2 = session.spawn(wait_for_gate())
assert t1 is not None
assert t2 is not None
assert not t1.done()
assert not t2.done()
gate.set()
await asyncio.gather(t1, t2)
class TestPromptTask:
@pytest.mark.asyncio
async def test_set_prompt_task_tracks_task(self) -> None:
session = _make_session()
async def work() -> None:
pass
task = session.set_prompt_task(work())
assert session.prompt_task is task
await task
assert session.prompt_task is None
@pytest.mark.asyncio
async def test_cancel_prompt_cancels_active_task(self) -> None:
session = _make_session()
async def hang() -> None:
await asyncio.Event().wait()
task = session.set_prompt_task(hang())
await session.cancel_prompt()
assert task.cancelled()
assert session.prompt_task is None
@pytest.mark.asyncio
async def test_cancel_prompt_is_noop_without_task(self) -> None:
session = _make_session()
await session.cancel_prompt()
@pytest.mark.asyncio
async def test_cancel_prompt_does_not_cancel_background_tasks(self) -> None:
session = _make_session()
gate = asyncio.Event()
async def bg() -> None:
await gate.wait()
bg_task = session.spawn(bg())
assert bg_task is not None
async def hang() -> None:
await asyncio.Event().wait()
session.set_prompt_task(hang())
await session.cancel_prompt()
assert not bg_task.cancelled()
gate.set()
await bg_task
class TestClose:
@pytest.mark.asyncio
async def test_close_cancels_all_tasks(self) -> None:
session = _make_session()
async def hang() -> None:
await asyncio.Event().wait()
bg = session.spawn(hang())
prompt = session.set_prompt_task(hang())
assert bg is not None
await session.close()
assert bg.cancelled()
assert prompt.cancelled()
assert session.prompt_task is None
@pytest.mark.asyncio
async def test_close_is_idempotent(self) -> None:
session = _make_session()
await session.close()
await session.close()
@pytest.mark.asyncio
async def test_close_waits_for_task_cleanup(self) -> None:
session = _make_session()
cleanup_ran = asyncio.Event()
async def task_with_cleanup() -> None:
try:
await asyncio.Event().wait()
except asyncio.CancelledError:
cleanup_ran.set()
raise
session.spawn(task_with_cleanup())
await asyncio.sleep(0) # let the task start
await session.close()
assert cleanup_ran.is_set()