From 881955c52ce5ccd3bd10e92bf9aa25c9ba083ee8 Mon Sep 17 00:00:00 2001 From: Didier Durand Date: Tue, 20 May 2025 09:02:37 +0200 Subject: [PATCH 1/3] adding 12 tests for InMemoryQueueManager --- .../events/test_inmemory_queue_manager.py | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 tests/server/events/test_inmemory_queue_manager.py diff --git a/tests/server/events/test_inmemory_queue_manager.py b/tests/server/events/test_inmemory_queue_manager.py new file mode 100644 index 00000000..e35660d6 --- /dev/null +++ b/tests/server/events/test_inmemory_queue_manager.py @@ -0,0 +1,150 @@ +from contextlib import asynccontextmanager + +import pytest +import asyncio +from unittest.mock import MagicMock, patch + +from a2a.server.events import InMemoryQueueManager +from a2a.server.events.event_queue import EventQueue +from a2a.server.events.queue_manager import ( + NoTaskQueue, + TaskQueueExists, +) + + + +class TestInMemoryQueueManager: + @pytest.fixture + def queue_manager(self): + """Fixture to create a fresh InMemoryQueueManager for each test.""" + manager = InMemoryQueueManager() + return manager + + @pytest.fixture + def event_queue(self): + """Fixture to create a mock EventQueue.""" + queue = MagicMock(spec=EventQueue) + # Mock the tap method to return itself + queue.tap.return_value = queue + return queue + + @pytest.mark.asyncio + async def test_init(self, queue_manager): + """Test that the InMemoryQueueManager initializes with empty task queue and a lock.""" + assert queue_manager._task_queue == {} + assert isinstance(queue_manager._lock, asyncio.Lock) + + @pytest.mark.asyncio + async def test_add_new_queue(self, queue_manager, event_queue): + """Test adding a new queue to the manager.""" + task_id = "test_task_id" + await queue_manager.add(task_id, event_queue) + assert queue_manager._task_queue[task_id] == event_queue + + @pytest.mark.asyncio + async def test_add_existing_queue(self, queue_manager, event_queue): + """Test adding a queue with an existing task_id raises TaskQueueExists.""" + task_id = "test_task_id" + await queue_manager.add(task_id, event_queue) + + with pytest.raises(TaskQueueExists): + await queue_manager.add(task_id, event_queue) + + @pytest.mark.asyncio + async def test_get_existing_queue(self, queue_manager, event_queue): + """Test getting an existing queue returns the queue.""" + task_id = "test_task_id" + await queue_manager.add(task_id, event_queue) + + result = await queue_manager.get(task_id) + assert result == event_queue + + @pytest.mark.asyncio + async def test_get_nonexistent_queue(self, queue_manager): + """Test getting a non-existent queue returns None.""" + result = await queue_manager.get("nonexistent_task_id") + assert result is None + + @pytest.mark.asyncio + async def test_tap_existing_queue(self, queue_manager, event_queue): + """Test tapping an existing queue returns the tapped queue.""" + task_id = "test_task_id" + await queue_manager.add(task_id, event_queue) + + result = await queue_manager.tap(task_id) + assert result == event_queue + event_queue.tap.assert_called_once() + + @pytest.mark.asyncio + async def test_tap_nonexistent_queue(self, queue_manager): + """Test tapping a non-existent queue returns None.""" + result = await queue_manager.tap("nonexistent_task_id") + assert result is None + + @pytest.mark.asyncio + async def test_close_existing_queue(self, queue_manager, event_queue): + """Test closing an existing queue removes it from the manager.""" + task_id = "test_task_id" + await queue_manager.add(task_id, event_queue) + + await queue_manager.close(task_id) + assert task_id not in queue_manager._task_queue + + @pytest.mark.asyncio + async def test_close_nonexistent_queue(self, queue_manager): + """Test closing a non-existent queue raises NoTaskQueue.""" + with pytest.raises(NoTaskQueue): + await queue_manager.close("nonexistent_task_id") + + @pytest.mark.asyncio + async def test_create_or_tap_new_queue(self, queue_manager): + """Test create_or_tap with a new task_id creates and returns a new queue.""" + task_id = "test_task_id" + + result = await queue_manager.create_or_tap(task_id) + assert isinstance(result, EventQueue) + assert queue_manager._task_queue[task_id] == result + + @pytest.mark.asyncio + async def test_create_or_tap_existing_queue(self, queue_manager, event_queue): + """Test create_or_tap with an existing task_id taps and returns the existing queue.""" + task_id = "test_task_id" + await queue_manager.add(task_id, event_queue) + + result = await queue_manager.create_or_tap(task_id) + + assert result == event_queue + event_queue.tap.assert_called_once() + + @pytest.mark.asyncio + async def test_concurrency(self, queue_manager): + """Test concurrent access to the queue manager.""" + + async def add_task(task_id): + queue = EventQueue() + await queue_manager.add(task_id, queue) + return task_id + + async def get_task(task_id): + return await queue_manager.get(task_id) + + # Create 10 different task IDs + task_ids = [f"task_{i}" for i in range(10)] + + # Add tasks concurrently + add_tasks = [add_task(task_id) for task_id in task_ids] + added_task_ids = await asyncio.gather(*add_tasks) + + # Verify all tasks were added + assert set(added_task_ids) == set(task_ids) + + # Get tasks concurrently + get_tasks = [get_task(task_id) for task_id in task_ids] + queues = await asyncio.gather(*get_tasks) + + # Verify all queues are not None + assert all(queue is not None for queue in queues) + + # Verify all tasks are in the manager + for task_id in task_ids: + assert task_id in queue_manager._task_queue \ No newline at end of file From b1ba04516ef3dde15256b47f2d9a9f693c93436f Mon Sep 17 00:00:00 2001 From: Didier Durand Date: Tue, 20 May 2025 09:09:28 +0200 Subject: [PATCH 2/3] fixing lint issues --- tests/server/events/test_inmemory_queue_manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/server/events/test_inmemory_queue_manager.py b/tests/server/events/test_inmemory_queue_manager.py index e35660d6..5e8115ea 100644 --- a/tests/server/events/test_inmemory_queue_manager.py +++ b/tests/server/events/test_inmemory_queue_manager.py @@ -1,8 +1,8 @@ -from contextlib import asynccontextmanager + import pytest import asyncio -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock from a2a.server.events import InMemoryQueueManager from a2a.server.events.event_queue import EventQueue From 2231b649efcf1ef730a951846d2701f0ca74f967 Mon Sep 17 00:00:00 2001 From: Holt Skinner Date: Tue, 20 May 2025 07:11:18 -0700 Subject: [PATCH 3/3] Spelling/formatting --- .../events/test_inmemory_queue_manager.py | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/tests/server/events/test_inmemory_queue_manager.py b/tests/server/events/test_inmemory_queue_manager.py index 5e8115ea..8371903c 100644 --- a/tests/server/events/test_inmemory_queue_manager.py +++ b/tests/server/events/test_inmemory_queue_manager.py @@ -1,8 +1,8 @@ +import asyncio +from unittest.mock import MagicMock import pytest -import asyncio -from unittest.mock import MagicMock from a2a.server.events import InMemoryQueueManager from a2a.server.events.event_queue import EventQueue @@ -12,7 +12,6 @@ ) - class TestInMemoryQueueManager: @pytest.fixture def queue_manager(self): @@ -30,21 +29,21 @@ def event_queue(self): @pytest.mark.asyncio async def test_init(self, queue_manager): - """Test that the InMemoryQueueManager initializes with empty task queue and a lock.""" - assert queue_manager._task_queue == {} - assert isinstance(queue_manager._lock, asyncio.Lock) + """Test that the InMemoryQueueManager initializes with empty task queue and a lock.""" + assert queue_manager._task_queue == {} + assert isinstance(queue_manager._lock, asyncio.Lock) @pytest.mark.asyncio async def test_add_new_queue(self, queue_manager, event_queue): """Test adding a new queue to the manager.""" - task_id = "test_task_id" + task_id = 'test_task_id' await queue_manager.add(task_id, event_queue) assert queue_manager._task_queue[task_id] == event_queue @pytest.mark.asyncio async def test_add_existing_queue(self, queue_manager, event_queue): """Test adding a queue with an existing task_id raises TaskQueueExists.""" - task_id = "test_task_id" + task_id = 'test_task_id' await queue_manager.add(task_id, event_queue) with pytest.raises(TaskQueueExists): @@ -53,7 +52,7 @@ async def test_add_existing_queue(self, queue_manager, event_queue): @pytest.mark.asyncio async def test_get_existing_queue(self, queue_manager, event_queue): """Test getting an existing queue returns the queue.""" - task_id = "test_task_id" + task_id = 'test_task_id' await queue_manager.add(task_id, event_queue) result = await queue_manager.get(task_id) @@ -61,14 +60,14 @@ async def test_get_existing_queue(self, queue_manager, event_queue): @pytest.mark.asyncio async def test_get_nonexistent_queue(self, queue_manager): - """Test getting a non-existent queue returns None.""" - result = await queue_manager.get("nonexistent_task_id") + """Test getting a nonexistent queue returns None.""" + result = await queue_manager.get('nonexistent_task_id') assert result is None @pytest.mark.asyncio async def test_tap_existing_queue(self, queue_manager, event_queue): """Test tapping an existing queue returns the tapped queue.""" - task_id = "test_task_id" + task_id = 'test_task_id' await queue_manager.add(task_id, event_queue) result = await queue_manager.tap(task_id) @@ -77,14 +76,14 @@ async def test_tap_existing_queue(self, queue_manager, event_queue): @pytest.mark.asyncio async def test_tap_nonexistent_queue(self, queue_manager): - """Test tapping a non-existent queue returns None.""" - result = await queue_manager.tap("nonexistent_task_id") + """Test tapping a nonexistent queue returns None.""" + result = await queue_manager.tap('nonexistent_task_id') assert result is None @pytest.mark.asyncio async def test_close_existing_queue(self, queue_manager, event_queue): """Test closing an existing queue removes it from the manager.""" - task_id = "test_task_id" + task_id = 'test_task_id' await queue_manager.add(task_id, event_queue) await queue_manager.close(task_id) @@ -92,23 +91,25 @@ async def test_close_existing_queue(self, queue_manager, event_queue): @pytest.mark.asyncio async def test_close_nonexistent_queue(self, queue_manager): - """Test closing a non-existent queue raises NoTaskQueue.""" + """Test closing a nonexistent queue raises NoTaskQueue.""" with pytest.raises(NoTaskQueue): - await queue_manager.close("nonexistent_task_id") + await queue_manager.close('nonexistent_task_id') @pytest.mark.asyncio async def test_create_or_tap_new_queue(self, queue_manager): """Test create_or_tap with a new task_id creates and returns a new queue.""" - task_id = "test_task_id" + task_id = 'test_task_id' result = await queue_manager.create_or_tap(task_id) assert isinstance(result, EventQueue) assert queue_manager._task_queue[task_id] == result @pytest.mark.asyncio - async def test_create_or_tap_existing_queue(self, queue_manager, event_queue): + async def test_create_or_tap_existing_queue( + self, queue_manager, event_queue + ): """Test create_or_tap with an existing task_id taps and returns the existing queue.""" - task_id = "test_task_id" + task_id = 'test_task_id' await queue_manager.add(task_id, event_queue) result = await queue_manager.create_or_tap(task_id) @@ -129,7 +130,7 @@ async def get_task(task_id): return await queue_manager.get(task_id) # Create 10 different task IDs - task_ids = [f"task_{i}" for i in range(10)] + task_ids = [f'task_{i}' for i in range(10)] # Add tasks concurrently add_tasks = [add_task(task_id) for task_id in task_ids] @@ -147,4 +148,4 @@ async def get_task(task_id): # Verify all tasks are in the manager for task_id in task_ids: - assert task_id in queue_manager._task_queue \ No newline at end of file + assert task_id in queue_manager._task_queue