Files
TheTree_mock/tests/s2/test_ledger_backed_resources.gd

76 lines
3.3 KiB
GDScript

extends SceneTree
const StateScript = preload("res://autoload/game_state.gd")
const EconomyScript = preload("res://scripts/economy/economy_service.gd")
const AdapterScript = preload("res://scripts/economy/ledger_backed_resource_state.gd")
var _checks := 0
var _failures := 0
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
print("S2: ledger-backed resource adapter")
var state = StateScript.new()
state.reset()
var economy = EconomyScript.new({
&"PLAYER_CASH": false,
&"CONSTRUCTION_EXPENSE": false,
})
economy.initialize_account(&"PLAYER_CASH", state.get_resource(&"gold"), 360, &"initial-player")
var minute := 400
var adapter = AdapterScript.new(
state,
economy,
&"CONSTRUCTION_EXPENSE",
&"CONSTRUCTION",
&"CONSTRUCTION_REFUND",
&"construction_service",
func() -> int: return minute
)
_expect(adapter.can_afford({&"gold": 500, &"materials": 8}), "combined ledger and material balances validate together")
_expect(adapter.spend({&"gold": 500, &"materials": 8}), "construction cost commits through one resource contract")
_expect(economy.get_balance(&"PLAYER_CASH") == 4500, "Gold spending changes the authoritative ledger balance")
_expect(state.get_resource(&"gold") == 4500, "GameState Gold remains a read-compatible UI mirror")
_expect(state.get_resource(&"materials") == 42, "non-Gold resources commit with the same spend")
_expect(economy.get_balance(&"CONSTRUCTION_EXPENSE") == 500, "construction uses an explicit counter-account")
var expense_entries: Array = economy.get_entries()
_expect(expense_entries[-1].absolute_minute == 400 and expense_entries[-1].category == &"CONSTRUCTION", "ledger entry captures minute and construction category")
minute = 410
_expect(adapter.apply_resource_deltas({&"gold": 125, &"materials": 2}), "demolition refund restores Gold and material atomically")
_expect(economy.get_balance(&"PLAYER_CASH") == 4625 and state.get_resource(&"gold") == 4625, "refund keeps ledger and UI mirror equal")
_expect(economy.get_balance(&"CONSTRUCTION_EXPENSE") == 375, "refund reduces its original expense counter-account")
_expect(state.get_resource(&"materials") == 44, "material refund is applied once")
var before: Dictionary = adapter.create_snapshot()
_expect(not adapter.spend({&"gold": 10_000, &"materials": 1}), "insufficient Gold rejects a mixed spend")
_expect(adapter.create_snapshot() == before, "rejected mixed spend changes neither ledger nor resources")
_expect(not adapter.apply_resource_deltas({&"gold": 1000}), "refund cannot exceed the recorded expense balance")
_expect(adapter.create_snapshot() == before, "failed refund rolls back every resource and ledger field")
adapter.spend({&"gold": 100, &"materials": 1})
_expect(adapter.restore_snapshot(before), "adapter restores resource and economy snapshots together")
_expect(adapter.create_snapshot() == before, "adapter snapshot round trip is exact")
_expect(economy.validate_ledger()[&"ok"], "restored authoritative ledger still reconciles")
state.free()
if _failures == 0:
print("PASS: %d checks" % _checks)
else:
push_error("FAIL: %d of %d checks failed" % [_failures, _checks])
quit(_failures)
func _expect(condition: bool, label: String) -> void:
_checks += 1
if condition:
print(" ✓ %s" % label)
return
_failures += 1
push_error(" ✗ %s" % label)