"""CharacterGenerateRequest.role_mix 校验单测(⑦ 群像按定位配比)。 纯 pydantic 校验,无 DB/网关。契约:role_mix 在场时 count 取各值之和, 每项数量须 ≥ 1、总和须 ≤ MAX_GENERATE_COUNT。 """ from __future__ import annotations import pytest from pydantic import ValidationError from ww_api.schemas.generation import MAX_GENERATE_COUNT, CharacterGenerateRequest def test_role_mix_absent_keeps_explicit_count() -> None: req = CharacterGenerateRequest(brief="剑修", count=3) assert req.role_mix is None assert req.count == 3 def test_role_mix_sets_count_to_sum() -> None: req = CharacterGenerateRequest(brief="群像", role_mix={"主角": 1, "对手": 2, "配角": 3}) assert req.count == 6 def test_role_mix_overrides_provided_count() -> None: # role_mix 在场时 count 取各值之和,忽略客户端显式传入的 count req = CharacterGenerateRequest(brief="群像", count=1, role_mix={"主角": 2, "对手": 2}) assert req.count == 4 def test_role_mix_total_at_max_allowed() -> None: req = CharacterGenerateRequest(brief="群像", role_mix={"主角": MAX_GENERATE_COUNT}) assert req.count == MAX_GENERATE_COUNT def test_role_mix_sum_over_max_rejected() -> None: with pytest.raises(ValidationError): # 6 + 7 = 13 > 12 CharacterGenerateRequest(brief="群像", role_mix={"主角": 6, "对手": 7}) def test_role_mix_empty_dict_rejected() -> None: with pytest.raises(ValidationError): CharacterGenerateRequest(brief="群像", role_mix={}) def test_role_mix_nonpositive_value_rejected() -> None: with pytest.raises(ValidationError): CharacterGenerateRequest(brief="群像", role_mix={"主角": 0}) with pytest.raises(ValidationError): CharacterGenerateRequest(brief="群像", role_mix={"主角": -1})