iOSBuildServer/tests/test_build_queue.py
shen 6f4f625c56 Initial commit: iOS Build Server
- FastAPI backend with build queue, WebSocket logs, task management
- Vue 3 frontend with build/config/history views
- Xcode project build automation with IPA export
- Fix: initialize build_dir before try block to ensure cleanup on early failure
2026-06-06 17:42:27 +08:00

119 lines
2.9 KiB
Python

"""打包队列测试"""
import asyncio
import pytest
from backend.services.build_queue import BuildQueue
@pytest.fixture
def queue():
return BuildQueue(max_concurrent=2)
def test_initial_state(queue):
"""初始状态"""
assert queue.queue_size == 0
assert queue.running_count == 0
def test_submit_starts_workers(queue):
"""提交任务后自动启动 worker"""
async def dummy_build(task_id):
pass
async def run():
await queue.submit("t1", dummy_build)
# 等待任务完成
await asyncio.sleep(0.1)
assert queue._started
assert len(queue._workers) == 2
asyncio.get_event_loop().run_until_complete(run())
def test_task_executes(queue):
"""任务被执行"""
executed = []
async def mock_build(task_id):
executed.append(task_id)
async def run():
await queue.submit("t1", mock_build)
await asyncio.sleep(0.2)
return executed
result = asyncio.get_event_loop().run_until_complete(run())
assert "t1" in result
def test_concurrent_limit(queue):
"""并发数不超过限制"""
running = []
max_concurrent = 0
async def slow_build(task_id):
nonlocal max_concurrent
running.append(task_id)
max_concurrent = max(max_concurrent, len(running))
await asyncio.sleep(0.3)
running.remove(task_id)
async def run():
tasks = []
for i in range(5):
tasks.append(queue.submit(f"t{i}", slow_build))
await asyncio.gather(*tasks)
await asyncio.sleep(1) # 等所有任务完成
return max_concurrent
result = asyncio.get_event_loop().run_until_complete(run())
assert result <= 2 # max_concurrent = 2
def test_cancel_running_task(queue):
"""取消运行中的任务"""
cancelled = False
async def long_build(task_id):
nonlocal cancelled
try:
await asyncio.sleep(10)
except asyncio.CancelledError:
cancelled = True
raise
async def run():
await queue.submit("t1", long_build)
await asyncio.sleep(0.1) # 等任务开始
queue.cancel("t1")
await asyncio.sleep(0.2) # 等取消生效
return cancelled
result = asyncio.get_event_loop().run_until_complete(run())
assert result is True
def test_cancel_nonexistent_task(queue):
"""取消不存在的任务(不应报错)"""
queue.cancel("nonexistent")
def test_multiple_tasks(queue):
"""多个任务顺序执行"""
completed = []
async def mock_build(task_id):
await asyncio.sleep(0.05)
completed.append(task_id)
async def run():
for i in range(4):
await queue.submit(f"t{i}", mock_build)
await asyncio.sleep(1)
return completed
result = asyncio.get_event_loop().run_until_complete(run())
assert len(result) == 4
assert set(result) == {"t0", "t1", "t2", "t3"}