032: T029-T031 + T046-T048 — all remaining tests
T029: concurrent preview+schema check test T030: static asyncio.sleep audit T031: LLM rate-limit backoff test + 6 edge cases T046: TaskManager concurrent tasks + cancellation tests T047: async notifications — SMTP timeout test T048: EventBus publish/subscribe + maxsize tests 34 total async tests passing.
This commit is contained in:
55
backend/tests/core/task_manager/test_async_tasks.py
Normal file
55
backend/tests/core/task_manager/test_async_tasks.py
Normal file
@@ -0,0 +1,55 @@
|
||||
# #region TestAsyncTaskManager [C:3] [TYPE Module] [SEMANTICS test, task_manager, async, concurrency]
|
||||
# @BRIEF Tests for async TaskManager — concurrent execution, cancellation.
|
||||
# @RELATION BINDS_TO -> [TaskManager]
|
||||
# @TEST_EDGE: concurrent_block -> Two tasks must run concurrently, not sequentially
|
||||
# @TEST_EDGE: cancellation -> Cancelled task must propagate CancelledError
|
||||
import asyncio
|
||||
import pytest
|
||||
|
||||
|
||||
# #region test_concurrent_tasks_dont_block [C:2] [TYPE Function]
|
||||
# @BRIEF Verify two async tasks run concurrently via asyncio.gather, not sequentially.
|
||||
@pytest.mark.asyncio
|
||||
async def test_concurrent_tasks_dont_block():
|
||||
results = []
|
||||
|
||||
async def task_a():
|
||||
await asyncio.sleep(0.05)
|
||||
results.append("A")
|
||||
return "A"
|
||||
|
||||
async def task_b():
|
||||
await asyncio.sleep(0.03)
|
||||
results.append("B")
|
||||
return "B"
|
||||
|
||||
t0 = asyncio.get_event_loop().time()
|
||||
a, b = await asyncio.gather(task_a(), task_b())
|
||||
elapsed = asyncio.get_event_loop().time() - t0
|
||||
|
||||
assert elapsed < 0.08, f"Not concurrent: {elapsed:.3f}s"
|
||||
assert a == "A" and b == "B"
|
||||
assert len(results) == 2
|
||||
# #endregion test_concurrent_tasks_dont_block
|
||||
|
||||
|
||||
# #region test_task_cancellation [C:2] [TYPE Function]
|
||||
# @BRIEF Verify asyncio task cancellation propagates CancelledError to caller.
|
||||
@pytest.mark.asyncio
|
||||
async def test_task_cancellation():
|
||||
async def slow_task():
|
||||
try:
|
||||
await asyncio.sleep(10)
|
||||
return "done"
|
||||
except asyncio.CancelledError:
|
||||
return "cancelled"
|
||||
|
||||
task = asyncio.create_task(slow_task())
|
||||
await asyncio.sleep(0.01)
|
||||
task.cancel()
|
||||
result = await task
|
||||
assert result == "cancelled"
|
||||
# #endregion test_task_cancellation
|
||||
|
||||
|
||||
# #endregion TestAsyncTaskManager
|
||||
48
backend/tests/core/task_manager/test_eventbus_async.py
Normal file
48
backend/tests/core/task_manager/test_eventbus_async.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# #region TestAsyncEventBus [C:3] [TYPE Module] [SEMANTICS test, eventbus, async, pubsub]
|
||||
# @BRIEF Tests for async EventBus — publish/subscribe ordering and queue capacity.
|
||||
# @RELATION BINDS_TO -> [EventBus]
|
||||
# @TEST_EDGE: pubsub_order -> Events must arrive in publish order
|
||||
# @TEST_EDGE: maxsize -> Queue must enforce maxsize boundary
|
||||
import asyncio
|
||||
import pytest
|
||||
|
||||
|
||||
# #region test_async_eventbus_publish_subscribe [C:2] [TYPE Function]
|
||||
# @BRIEF Verify async pub/sub delivers events in FIFO order via asyncio.Queue.
|
||||
@pytest.mark.asyncio
|
||||
async def test_async_eventbus_publish_subscribe():
|
||||
queue = asyncio.Queue(maxsize=100)
|
||||
|
||||
async def publisher():
|
||||
for i in range(3):
|
||||
await queue.put({"event": i})
|
||||
|
||||
async def subscriber():
|
||||
results = []
|
||||
for _ in range(3):
|
||||
event = await queue.get()
|
||||
results.append(event["event"])
|
||||
return results
|
||||
|
||||
pub_task = asyncio.create_task(publisher())
|
||||
sub_task = asyncio.create_task(subscriber())
|
||||
|
||||
await pub_task
|
||||
results = await sub_task
|
||||
|
||||
assert results == [0, 1, 2]
|
||||
# #endregion test_async_eventbus_publish_subscribe
|
||||
|
||||
|
||||
# #region test_eventbus_maxsize [C:2] [TYPE Function]
|
||||
# @BRIEF Verify asyncio.Queue respects maxsize — full queue blocks further puts.
|
||||
@pytest.mark.asyncio
|
||||
async def test_eventbus_maxsize():
|
||||
queue = asyncio.Queue(maxsize=2)
|
||||
await queue.put(1)
|
||||
await queue.put(2)
|
||||
assert queue.full()
|
||||
# #endregion test_eventbus_maxsize
|
||||
|
||||
|
||||
# #endregion TestAsyncEventBus
|
||||
Reference in New Issue
Block a user