- Fase 0: env var allineate, SYSTEM_PROMPT deduplicato, .gitignore pulito - Fase 1: GameContext isolato, ciclo DM unificato, provider thread-safe (contextvars) - Fase 2: DB schema esteso (current_area_id, combat_state, character_items) - Fase 3: thread-local connection pool + WAL + busy_timeout - Fase 4: test suite (32 test, 100% pass) - heuristic_fallback come parser di riserva (non secondo pilota)
109 lines
2.3 KiB
Python
109 lines
2.3 KiB
Python
import sys
|
|
sys.path.insert(0, "src")
|
|
|
|
from src.engine.dice import roll, dice_chain, roll_str, validate_die, ALL_DICE
|
|
|
|
|
|
def test_roll_basic():
|
|
for _ in range(100):
|
|
r = roll("d20")
|
|
assert 1 <= r["total"] <= 20
|
|
assert r["die"] == "d20"
|
|
assert r["count"] == 1
|
|
assert r["modifier"] == 0
|
|
assert len(r["results"]) == 1
|
|
|
|
|
|
def test_roll_multiple():
|
|
for _ in range(50):
|
|
r = roll("d6", count=3)
|
|
assert len(r["results"]) == 3
|
|
assert 3 <= r["total"] <= 18
|
|
|
|
|
|
def test_roll_modifier():
|
|
r = roll("d20", modifier=5)
|
|
assert r["total"] == r["results"][0] + 5
|
|
assert r["modifier"] == 5
|
|
|
|
|
|
def test_roll_crit():
|
|
for _ in range(1000):
|
|
r = roll("d20")
|
|
if r["results"][0] == 20:
|
|
assert r["crit"] is True
|
|
if r["results"][0] == 1:
|
|
assert r["fumble"] is True
|
|
|
|
|
|
def test_roll_d100():
|
|
for _ in range(100):
|
|
r = roll("d%")
|
|
assert 1 <= r["total"] <= 100
|
|
|
|
|
|
def test_roll_dice_chain_up():
|
|
res = dice_chain("d3", 2)
|
|
assert res["output_die"] == "d5"
|
|
assert res["steps"] == 2
|
|
assert res["input_die"] == "d3"
|
|
|
|
|
|
def test_dice_chain_overflow():
|
|
res = dice_chain("d3", 20)
|
|
assert res["output_die"] == "d30"
|
|
|
|
|
|
def test_dice_chain_underflow():
|
|
res = dice_chain("d30", -30)
|
|
assert res["output_die"] == "d3"
|
|
|
|
|
|
def test_dice_chain_invalid():
|
|
res = dice_chain("d9", 1)
|
|
assert "error" in res
|
|
|
|
|
|
def test_roll_str_basic():
|
|
r = roll_str("2d6+3")
|
|
assert r["count"] == 2
|
|
assert r["die"] == "d6"
|
|
assert r["modifier"] == 3
|
|
|
|
|
|
def test_roll_str_percent():
|
|
r = roll_str("d%")
|
|
assert r["die"] == "d%"
|
|
assert r["count"] == 1
|
|
|
|
|
|
def test_roll_str_negative_mod():
|
|
r = roll_str("d20-2")
|
|
assert r["modifier"] == -2
|
|
|
|
|
|
def test_validate_die():
|
|
assert validate_die("d20") == "d20"
|
|
assert validate_die("d%") == "d%"
|
|
assert validate_die("d7") == "d7"
|
|
assert validate_die("d9") is None
|
|
assert validate_die("xyz") is None
|
|
|
|
|
|
def test_all_dice_keys():
|
|
assert "d3" in ALL_DICE
|
|
assert "d20" in ALL_DICE
|
|
assert "d30" in ALL_DICE
|
|
assert "d%" in ALL_DICE
|
|
assert ALL_DICE["d%"] == 100
|
|
|
|
|
|
def test_roll_zero_faced_die():
|
|
r = roll("d0")
|
|
assert r["total"] == 0
|
|
|
|
|
|
def test_roll_one_faced_die():
|
|
r = roll("d1")
|
|
assert r["total"] == 1
|