from dataclasses import replace import pytest from synthgen import dictionary from synthgen.config import Config from synthgen.counterparties import WEIGHTS, plan from synthgen.group import build_group @pytest.fixture(scope="module") def orgs(): return dictionary.load() def _mean_len(p): return sum(len(v) for v in p.by_file.values()) / len(p.by_file) def test_mean_matches(orgs): cfg = Config(group_size=10, periods=4, osv_counterparties_mean=60) p = plan(cfg, build_group(cfg, orgs)) assert not p.capped assert len(p.by_file) == 10 * len(WEIGHTS) assert abs(_mean_len(p) - 60) <= 0.15 * 60 def test_cap_and_flag(orgs): cfg = Config(group_size=40, periods=4, osv_counterparties_mean=150) g = build_group(cfg, orgs) p = plan(cfg, g) assert p.capped bank_inns = {b.inn for b in g.banks} for (code, acct), lst in p.by_file.items(): assert len(lst) == len({o.inn for o in lst}) if acct in ("66", "67"): assert len(lst) <= len(g.banks) and all(o.inn in bank_inns for o in lst) else: assert len(lst) <= len(g.externals) def test_sets_disjoint_from_group(orgs): cfg = Config(group_size=8, osv_counterparties_mean=100) g = build_group(cfg, orgs) p = plan(cfg, g) forbidden = {m.org.inn for m in g.members} | {b.inn for b in g.banks} for (code, acct), lst in p.by_file.items(): if acct in ("58", "60", "62", "76"): assert not forbidden & {o.inn for o in lst} def test_zero_mean(orgs): cfg = Config(group_size=4, osv_counterparties_mean=0) p = plan(cfg, build_group(cfg, orgs)) assert all(v == [] for v in p.by_file.values()) and not p.capped def test_plan_deterministic(orgs): cfg = Config(group_size=6) g = build_group(cfg, orgs) assert plan(cfg, g) == plan(cfg, g) other = plan(replace(cfg, seed=2), build_group(replace(cfg, seed=2), orgs)) assert other != plan(cfg, g)