105 lines
3.5 KiB
Python
105 lines
3.5 KiB
Python
from __future__ import annotations
|
|
|
|
import sqlite3
|
|
|
|
from idea134_matchops_federated_verifiable import (
|
|
AggregatedSignal,
|
|
CloudApiAdapter,
|
|
FederatedOptimizer,
|
|
GameServerRouterAdapter,
|
|
GoCRegistry,
|
|
MatchOpsSpec,
|
|
Region,
|
|
Server,
|
|
SessionDemand,
|
|
SessionType,
|
|
SQLiteGovernanceLedger,
|
|
CapacityBudget,
|
|
LatencyBudget,
|
|
compile_spec,
|
|
)
|
|
from idea134_matchops_federated_verifiable.optimizer import reconcile_plan_deltas
|
|
|
|
|
|
def sample_spec() -> MatchOpsSpec:
|
|
return MatchOpsSpec(
|
|
regions=[
|
|
Region(name="us-east", provider="aws", fairness_weight=1.0),
|
|
Region(name="eu-west", provider="gcp", fairness_weight=2.0),
|
|
],
|
|
servers=[
|
|
Server(name="se-1", region="us-east", capacity=200),
|
|
Server(name="se-2", region="eu-west", capacity=150),
|
|
],
|
|
session_types=[SessionType(name="ranked", max_players=10, latency_budget_ms=80)],
|
|
capacity_budgets=[
|
|
CapacityBudget(region="us-east", max_sessions=10, max_players=100),
|
|
CapacityBudget(region="eu-west", max_sessions=8, max_players=80),
|
|
],
|
|
latency_budgets=[LatencyBudget(session_type="ranked", p95_ms=80)],
|
|
)
|
|
|
|
|
|
def test_compile_spec_builds_verifiable_execution_graph():
|
|
plan = compile_spec(sample_spec())
|
|
|
|
assert plan.execution_graph.verify()
|
|
assert plan.ir.ir_hash
|
|
assert len(plan.ir.local_regions) == 2
|
|
assert plan.ir.constraint_graph.nodes
|
|
|
|
|
|
def test_registry_and_adapters_translate_ir():
|
|
plan = compile_spec(sample_spec())
|
|
registry = GoCRegistry()
|
|
registry.register(CloudApiAdapter())
|
|
registry.register(GameServerRouterAdapter())
|
|
|
|
translations = registry.translate_all(plan.ir)
|
|
|
|
assert {translation.adapter_name for translation in translations} == {"cloud-api", "game-server-router"}
|
|
assert all(translation.translation_hash for translation in translations)
|
|
assert any(action.action == "ensure_region_capacity" for action in translations[0].actions + translations[1].actions)
|
|
|
|
|
|
def test_optimizer_prefers_lower_latency_region_and_is_deterministic():
|
|
spec = sample_spec()
|
|
optimizer = FederatedOptimizer(iterations=3)
|
|
signals = [
|
|
AggregatedSignal(region="us-east", queue_depth=12, load_factor=0.8, avg_latency_ms=95, available_capacity=20, version=7),
|
|
AggregatedSignal(region="eu-west", queue_depth=5, load_factor=0.3, avg_latency_ms=40, available_capacity=20, version=8),
|
|
]
|
|
demand = [SessionDemand(session_type="ranked", players=10, max_latency_ms=80)]
|
|
|
|
result = optimizer.optimize(spec, signals, demand)
|
|
repeat = optimizer.optimize(spec, signals, demand)
|
|
|
|
assert result == repeat
|
|
assert result.allocations[0].region == "eu-west"
|
|
assert result.delta.region == "federated"
|
|
|
|
|
|
def test_plan_delta_reconciliation_and_ledger_integrity(tmp_path):
|
|
ledger = SQLiteGovernanceLedger(tmp_path / "ledger.sqlite")
|
|
ledger.append("compiler", "compile-spec", {"spec": "matchops"})
|
|
ledger.append("optimizer", "allocate-sessions", {"allocations": 2})
|
|
|
|
verification = ledger.verify()
|
|
assert verification.ok
|
|
assert verification.entries == 2
|
|
|
|
entries, sync_hash = reconcile_plan_deltas(
|
|
[
|
|
compile_spec(sample_spec()).ir.plan_deltas[1],
|
|
compile_spec(sample_spec()).ir.plan_deltas[0],
|
|
]
|
|
)
|
|
assert len(entries) == 2
|
|
assert sync_hash
|
|
|
|
with sqlite3.connect(tmp_path / "ledger.sqlite") as conn:
|
|
conn.execute("UPDATE governance_ledger SET action = 'tampered' WHERE sequence = 0")
|
|
conn.commit()
|
|
|
|
assert not ledger.verify().ok
|