"""#1743 worker 批量重渲判定 + 封面哈希选帧纯函数测试。 - should_rerender_for_batch_dedup:批次首版查重率 >20% 才重渲(非批次/重渲版/无查重率不重渲) - pick_batch_cover_index:task_id md5 稳定哈希分散候选帧(同任务稳定、跨任务分散) """ from __future__ import annotations import hashlib import sys from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[2] for sub in ("apps/worker", "apps/api", "packages", ""): p = str(REPO_ROOT / sub) if sub else str(REPO_ROOT) if p not in sys.path: sys.path.insert(0, p) from worker_app.tasks.generation import ( # noqa: E402 BATCH_RENDER_SIMILARITY_LIMIT, pick_batch_cover_index, should_rerender_for_batch_dedup, ) class TestShouldRerenderForBatchDedup: def test_non_batch_never_rerenders(self): """非批次任务(batch_id 为空)任何查重率都不重渲。""" assert should_rerender_for_batch_dedup(batch_id="", render_attempt=0, batch_similarity=0.99) is False assert should_rerender_for_batch_dedup(batch_id="", render_attempt=0, batch_similarity=None) is False def test_batch_first_version_over_threshold_rerenders(self): """批次首版(attempt=0)查重率 >20% → 重渲。""" assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.601) is True assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.21) is True def test_batch_first_version_under_threshold_no_rerender(self): """批次首版查重率 ≤20% → 不重渲。""" assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.20) is False assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.0) is False assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=0.05) is False def test_rerendered_version_never_rerenders_again(self): """重渲版(attempt=1)即使仍超阈值也不再重渲(最多重渲一次)。""" assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=1, batch_similarity=0.99) is False def test_missing_similarity_no_rerender(self): """查重率缺失(None,非批次查重路径)→ 不重渲。""" assert should_rerender_for_batch_dedup(batch_id="batch-1", render_attempt=0, batch_similarity=None) is False def test_threshold_constant_is_20_percent(self): assert BATCH_RENDER_SIMILARITY_LIMIT == 0.20 class TestPickBatchCoverIndex: def test_stable_for_same_task(self): """同一 task_id 多次调用结果稳定(重试封面不变)。""" first = pick_batch_cover_index("task-abc", 3) for _ in range(5): assert pick_batch_cover_index("task-abc", 3) == first def test_zero_or_one_candidate_returns_zero(self): assert pick_batch_cover_index("task-x", 0) == 0 assert pick_batch_cover_index("task-x", 1) == 0 def test_index_within_range(self): for i in range(20): idx = pick_batch_cover_index(f"task-{i}", 3) assert 0 <= idx < 3 def test_matches_md5_formula(self): """与主流程公式一致:md5(task_id) % 候选数。""" task_id = "task-formula-check" expected = int(hashlib.md5(task_id.encode()).hexdigest(), 16) % 3 assert pick_batch_cover_index(task_id, 3) == expected def test_batch_tasks_spread_across_frames(self): """30 个批次任务在 3 个候选帧上分散(不能全部落在 frame_0——旧 bug 回归守卫)。""" indexes = {pick_batch_cover_index(f"batch-task-{i}", 3) for i in range(30)} assert len(indexes) >= 2, f"封面帧应分散到多个帧位,实际全部落在: {indexes}"