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.
87 lines
3.7 KiB
Python
87 lines
3.7 KiB
Python
# #region TestTranslateAsyncConcurrency [C:3] [TYPE Module] [SEMANTICS test, translate, async, concurrency]
|
|
# @BRIEF Tests for concurrent execution of preview and schema check.
|
|
# @RELATION BINDS_TO -> [TranslationPreview]
|
|
# @TEST_CONTRACT: preview + schema_check -> concurrent execution
|
|
# @TEST_EDGE: polling_uses_asyncio_sleep -> VERIFIED_BY: test_polling_uses_asyncio_sleep_not_time_sleep
|
|
import asyncio
|
|
import os
|
|
import re
|
|
|
|
import pytest
|
|
|
|
|
|
# #region test_preview_and_schema_check_concurrent [C:2] [TYPE Function]
|
|
# @BRIEF Verify preview and schema check runs concurrently using asyncio.gather.
|
|
@pytest.mark.asyncio
|
|
async def test_preview_and_schema_check_concurrent():
|
|
"""Verify preview + schema_check execute concurrently, not sequentially."""
|
|
t0 = asyncio.get_event_loop().time()
|
|
|
|
async def mock_preview():
|
|
await asyncio.sleep(0.1)
|
|
return {"rows": 10}
|
|
|
|
async def mock_schema_check():
|
|
await asyncio.sleep(0.05)
|
|
return {"table_exists": True}
|
|
|
|
results = await asyncio.gather(mock_preview(), mock_schema_check())
|
|
elapsed = asyncio.get_event_loop().time() - t0
|
|
|
|
assert elapsed < 0.15, f"Not concurrent: {elapsed:.3f}s (max task was 0.1s)"
|
|
assert results[0]["rows"] == 10
|
|
assert results[1]["table_exists"] is True
|
|
# #endregion test_preview_and_schema_check_concurrent
|
|
|
|
|
|
# #region test_polling_uses_asyncio_sleep_not_time_sleep [C:2] [TYPE Function]
|
|
# @BRIEF Static check: grep superset_executor.py for time.sleep in active code.
|
|
# @TEST_EDGE: polling_uses_asyncio_sleep
|
|
def test_polling_uses_asyncio_sleep_not_time_sleep():
|
|
"""Verify superset_executor uses asyncio.sleep, not time.sleep, in active code."""
|
|
filepath = os.path.join(
|
|
os.path.dirname(__file__), "..", "..", "..", "src", "plugins", "translate", "superset_executor.py"
|
|
)
|
|
filepath = os.path.normpath(filepath)
|
|
with open(filepath) as f:
|
|
content = f.read()
|
|
# time.sleep in comments and REJECTED docs is OK — only flag active code
|
|
matches = re.findall(r"^(?!\s*#).*time\.sleep", content, re.MULTILINE)
|
|
assert len(matches) == 0, f"Found time.sleep in active code: {matches}"
|
|
# #endregion test_polling_uses_asyncio_sleep_not_time_sleep
|
|
|
|
|
|
# #region test_llm_async_uses_asyncio_sleep_not_time_sleep [C:2] [TYPE Function]
|
|
# @BRIEF Static check: grep _llm_async_http.py for time.sleep in active code.
|
|
# @TEST_EDGE: llm_async_uses_asyncio_sleep
|
|
def test_llm_async_uses_asyncio_sleep_not_time_sleep():
|
|
"""Verify _llm_async_http uses asyncio.sleep for 429 backoff, not time.sleep."""
|
|
filepath = os.path.join(
|
|
os.path.dirname(__file__), "..", "..", "..", "src", "plugins", "translate", "_llm_async_http.py"
|
|
)
|
|
filepath = os.path.normpath(filepath)
|
|
with open(filepath) as f:
|
|
content = f.read()
|
|
matches = re.findall(r"^(?!\s*#).*time\.sleep", content, re.MULTILINE)
|
|
assert len(matches) == 0, f"Found time.sleep in active code: {matches}"
|
|
# #endregion test_llm_async_uses_asyncio_sleep_not_time_sleep
|
|
|
|
|
|
# #region test_concurrent_tasks_share_event_loop [C:2] [TYPE Function]
|
|
# @BRIEF Verify multiple async tasks scheduled via asyncio.gather share the same event loop.
|
|
@pytest.mark.asyncio
|
|
async def test_concurrent_tasks_share_event_loop():
|
|
"""Verify gather'd tasks run on the same loop — no thread isolation."""
|
|
loop = asyncio.get_event_loop()
|
|
loop_ids = []
|
|
|
|
async def capture_loop():
|
|
loop_ids.append(id(asyncio.get_event_loop()))
|
|
await asyncio.sleep(0.01)
|
|
|
|
await asyncio.gather(capture_loop(), capture_loop(), capture_loop())
|
|
assert len(set(loop_ids)) == 1, "Tasks ran on different event loops"
|
|
# #endregion test_concurrent_tasks_share_event_loop
|
|
|
|
# #endregion TestTranslateAsyncConcurrency
|