Files
TheTree_mock/tests/supply/test_supply_auto_purchase.gd

366 lines
32 KiB
GDScript

extends SceneTree
## Real command/ledger boundaries; failure injections are disclosed separately.
class RejectingPaymentEconomy:
extends EconomyService
func transfer(_from: StringName, _to: StringName, _amount: int,
_minute: int = -1, _category: StringName = DEFAULT_CATEGORY,
_source: StringName = &"", _key: StringName = &"", _memo: StringName = &"",
_related: StringName = &"", _notify := true) -> CommandResult:
return CommandResult.failed(CommandResult.Code.VALIDATION_FAILED, 0, "Payment refusal fixture")
class RejectingNotificationEconomy:
extends EconomyService
func commit_transaction_notification(_transaction: StringName) -> bool:
return false
class ProbedInventory:
extends InventoryService
var transaction_boundary: Dictionary = {}
func add_stack(owner: StringName, item: StringName, quantity: int,
quality: int = DEFAULT_QUALITY, expiry: int = -1, created: int = -1,
weight: int = DEFAULT_UNIT_WEIGHT, stack_id: StringName = &"") -> Dictionary:
transaction_boundary = create_snapshot()
return super.add_stack(owner, item, quantity, quality, expiry, created, weight, stack_id)
class PartialFailInventory:
extends ProbedInventory
func add_stack(owner: StringName, item: StringName, quantity: int,
quality: int = DEFAULT_QUALITY, expiry: int = -1, created: int = -1,
weight: int = DEFAULT_UNIT_WEIGHT, stack_id: StringName = &"") -> Dictionary:
super.add_stack(owner, item, quantity, quality, expiry, created, weight, stack_id)
return {&"ok": false, &"code": &"INJECTED_AFTER_STOCK"}
var _runtime: Variant
var _clock: Variant
var _state: Variant
var _warehouse: StringName
var _built: Dictionary
var _checks := 0
var _failures := 0
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
_runtime = root.get_node("SimulationRuntime")
_clock = root.get_node("GameClock")
_state = root.get_node("GameState")
_clock.set_process(false)
_clock.reset(1, 6, 0)
_state.reset()
_expect(_runtime.initialize(_clock, _state, 420_501)[&"valid"], "canonical Runtime initializes")
_clock.set_paused(true)
_runtime.configure_save_policy({&"enabled": false, &"daily_checkpoint_enabled": false})
_expect(_runtime.submit_command(&"build_facility", {&"definition_id": &"warehouse", &"origin": Vector3i(-8, 0, 1)}).is_success(), "ordinary paid warehouse build")
_clock.advance_minutes(180)
for facility: FacilityInstance in _runtime.facility_service.get_instances():
if facility.definition_id == &"warehouse": _warehouse = facility.instance_id
_expect(not _warehouse.is_empty(), "ordinary construction yields a warehouse")
if _warehouse.is_empty(): _finish(); return
_built = _runtime.create_snapshot()
_test_receipt_codec()
_test_default_manual_and_paid_order()
_test_invalid_input_and_corrupt_save()
_test_atomic_failures_and_same_minute_retry()
_test_hold_disable_and_removal()
_test_actual_budget_power_reservation_and_terminal()
_test_multiple_warehouse_order()
_test_legacy13_and_composed_rollback()
_finish()
func _plan(enabled: bool, target: int, key: StringName = &"") -> CommandResult:
return _runtime.submit_command(&"set_supply_auto_purchase", {&"warehouse_id": _warehouse,
&"item_id": SupplyCatalog.RAW_FOOD, &"enabled": enabled, &"target_stock": target}, &"player", _warehouse, 75, -1, key)
func _stock() -> int:
var facility: FacilityInstance = _runtime.facility_service.get_instance(_warehouse)
return _runtime.inventory_service.total_quantity(facility.local_inventory_id, SupplyCatalog.RAW_FOOD)
func _test_receipt_codec() -> void:
var memo := SupplyAutoPurchasePlans.receipt_memo(SupplyCatalog.RAW_FOOD, 6, 3, 18)
var decoded := SupplyAutoPurchasePlans.decode_receipt_memo(memo)
_expect(decoded == {&"item_id": String(SupplyCatalog.RAW_FOOD), &"quantity": 6, &"unit_price": 3, &"total_cost": 18}, "canonical versioned actual quote codec is lossless")
decoded[&"quantity"] = 3
_expect(SupplyAutoPurchasePlans.decode_receipt_memo(memo)[&"quantity"] == 6, "decoded receipt is independently owned")
var punctuation: StringName = &"item:part.日本語"
_expect(SupplyAutoPurchasePlans.decode_receipt_memo(SupplyAutoPurchasePlans.receipt_memo(punctuation, 6, 3, 18))[&"item_id"] == String(punctuation), "length encoding handles punctuation and Unicode without ambiguity")
var prefix: String = SupplyAutoPurchasePlans.RECEIPT_PREFIX + "19:ingredient/raw_food:"
for malformed: String in ["", "supply_purchase", prefix + "3:6:18:extra", prefix + "6:03:18", prefix + "6:+3:18", prefix + "6:3.0:18", prefix + "6:3e0:18", prefix + "6:-3:18", prefix + "6:0:0", prefix + "6:3:019", prefix + "6:3:19", prefix + "10001:3:30003", prefix + "1:9223372036854775808:9223372036854775808", prefix + "2:9223372036854775807:9223372036854775807", "supply_purchase.auto.v2:19:ingredient/raw_food:6:3:18", "supply_purchase.auto.v1:019:ingredient/raw_food:6:3:18", "supply_purchase.auto.v1:18:ingredient/raw_food:6:3:18", "supply_purchase.auto.v1:9223372036854775808:ingredient/raw_food:6:3:18", "supply_purchase.auto.v1:1: :6:3:18"]:
_expect(SupplyAutoPurchasePlans.decode_receipt_memo(StringName(malformed)).is_empty(), "malformed/noncanonical/overflow quote memo is rejected: " + malformed)
var max_memo: StringName = &"supply_purchase.auto.v1:1:x:1:9223372036854775807:9223372036854775807"
_expect(SupplyAutoPurchasePlans.decode_receipt_memo(max_memo).get(&"unit_price", 0) == 9223372036854775807, "signed64 canonical maximum parses without floating conversion or overflow")
func _test_default_manual_and_paid_order() -> void:
_expect(_runtime.auto_purchase_plans.get_plans().is_empty(), "new game has no inferred automatic intent")
var before: Dictionary = _runtime.create_snapshot()
_clock.advance_minutes(1)
_expect(_stock() == 0 and _runtime.economy_service.create_snapshot() == before[&"systems"][&"runtime"][&"economy"], "default disabled tick spends and stocks nothing")
var manual: CommandResult = _runtime.submit_command(&"purchase_supplies", {&"warehouse_id": _warehouse, &"item_id": SupplyCatalog.RAW_FOOD, &"quantity": 4})
_expect(manual.is_success() and int(manual.details.get(&"total_cost", -1)) == 12 and _stock() == 4, "manual contract still charges4 food exactly12G")
var transaction_id := StringName(manual.details.get(&"transaction_id", &""))
var entries: Array = _runtime.economy_service.get_transaction_entries(transaction_id)
_expect(entries.size() == 1 and entries[0].category == &"OPERATING_EXPENSE" and entries[0].memo_key == &"supply_purchase", "manual category/memo remain unchanged")
_expect(_runtime.economy_service.get_transaction_id_for_idempotency_key(StringName("supply.purchase.%d" % manual.command_id)) == transaction_id, "manual ledger key still uses accepted commandID")
var configured: CommandResult = _plan(true, 10, &"auto.test.intent")
_expect(configured.is_success() and _stock() == 4, "player intent does not immediately stock or pay")
var armed: Dictionary = _runtime.create_snapshot()
var cash: int = _runtime.economy_service.get_balance(&"PLAYER_CASH")
var notifications: Array[Dictionary] = []
_runtime.economy_service.transaction_posted.connect(func(id: StringName, ledger_rows: Array) -> void:
var rows: Array[Dictionary] = []
for entry: LedgerEntry in ledger_rows: rows.append(entry.to_dictionary())
notifications.append({&"transaction_id": id, &"entries": rows}))
_clock.advance_minutes(1)
var paid: Dictionary = _runtime.create_snapshot()
var row: Dictionary = _runtime.auto_purchase_plans.get_plan(_warehouse, SupplyCatalog.RAW_FOOD)
_expect(_stock() == 10 and _runtime.economy_service.get_balance(&"PLAYER_CASH") == cash - 18, "ordinary tick buys the exact deficit6 at existing3G")
_expect(_state.get_resource(&"gold") == cash - 18 and row[&"last_result"] == &"PURCHASED" and row[&"last_attempt_minute"] == _clock.absolute_minute, "cash mirror and saved receipt record the real purchase")
var receipt := SupplyAutoPurchasePlans.receipt_from_ledger(_runtime.economy_service, _warehouse, SupplyCatalog.RAW_FOOD, _clock.absolute_minute, StringName(row[&"last_transaction_id"]))
_expect(receipt == {&"item_id": String(SupplyCatalog.RAW_FOOD), &"quantity": 6, &"unit_price": 3, &"total_cost": 18}, "independent actual ledger memo anchors item/quantity/historic price/total")
_expect(notifications.size() == 1 and notifications[0][&"transaction_id"] == StringName(row[&"last_transaction_id"]) and notifications[0][&"entries"].size() == 1 and notifications[0][&"entries"][0][&"memo_key"] == String(SupplyAutoPurchasePlans.receipt_memo(SupplyCatalog.RAW_FOOD, 6, 3, 18)), "normal successful automatic purchase delivers one actual quoted ledger notification")
_expect((_runtime.economy_service.get("_pending_transaction_notifications") as Dictionary).is_empty(), "normal automatic notification is committed without pending residue")
_expect(paid[&"systems"][&"runtime"][&"next_command_id"] == armed[&"systems"][&"runtime"][&"next_command_id"] and var_to_bytes(paid[&"systems"][&"runtime"][&"command_queue"]) == var_to_bytes(armed[&"systems"][&"runtime"][&"command_queue"]), "automatic order allocates no fake player command or queue history")
_expect(var_to_bytes(paid[&"systems"][&"runtime"][&"rng_streams"]) == var_to_bytes(armed[&"systems"][&"runtime"][&"rng_streams"]), "automatic purchase makes no RNG draw")
_expect(_runtime.supply_management.advance_auto_purchases(_runtime, _clock.absolute_minute).is_empty() and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(paid), "same-minute reentry is exact no-op")
_expect(notifications.size() == 1, "same-minute automatic reentry does not duplicate actual notification")
_expect(_runtime.restore_snapshot(armed), "whole pre-order snapshot restores")
_clock.advance_minutes(1)
_expect(var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(paid), "saved pre-order branch replays all typed state/order/events/IDs exactly")
_expect(_runtime.restore_snapshot(paid) and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(paid), "paid order/current14 receipt roundtrip is exact")
var duplicate_before: Dictionary = _runtime.create_snapshot()
var duplicate: CommandResult = _plan(true, 10, &"auto.test.intent")
_expect(not duplicate.is_success() and duplicate.code == CommandResult.Code.DUPLICATE_IDEMPOTENCY_KEY and not duplicate.is_replay and _stock() == 10, "already accepted intent key is rejected by the canonical command queue")
_expect(var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(duplicate_before), "duplicate intent refusal changes no plan, inventory, ledger, IDs, queue or Runtime state")
var owned: Dictionary = _runtime.auto_purchase_plans.get_plan(_warehouse, SupplyCatalog.RAW_FOOD)
owned[&"enabled"] = false
_expect(_runtime.auto_purchase_plans.get_plan(_warehouse, SupplyCatalog.RAW_FOOD)[&"enabled"], "returned plan is owned")
func _test_invalid_input_and_corrupt_save() -> void:
_expect(_runtime.restore_snapshot(_built), "reset to paid real warehouse fixture")
var before: Dictionary = _runtime.create_snapshot()
for value: Variant in [true, -1, 101, 1.5, "4", NAN, INF]:
var result: CommandResult = _runtime.supply_management.set_auto_purchase(_runtime,
SimulationCommand.new(999, _clock.absolute_minute, _clock.absolute_minute, 75,
&"set_supply_auto_purchase", &"player", _warehouse,
{&"warehouse_id": _warehouse, &"item_id": SupplyCatalog.RAW_FOOD, &"enabled": true, &"target_stock": value}))
_expect(not result.is_success() and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(before), "invalidtarget rejects atomically: %s" % value)
for patch: Dictionary in [
{&"warehouse_id": &"missing", &"item_id": SupplyCatalog.RAW_FOOD, &"enabled": true, &"target_stock": 1},
{&"warehouse_id": _warehouse, &"item_id": SupplyCatalog.BASIC_MEAL, &"enabled": true, &"target_stock": 1},
{&"warehouse_id": _warehouse, &"item_id": SupplyCatalog.RAW_FOOD, &"enabled": "true", &"target_stock": 1},
{&"warehouse_id": _warehouse, &"item_id": SupplyCatalog.RAW_FOOD, &"enabled": true, &"target_stock": 0},
{&"warehouse_id": _warehouse, &"item_id": SupplyCatalog.RAW_FOOD, &"enabled": true, &"target_stock": 1, &"unit_price": 0}]:
var result: CommandResult = _runtime.supply_management.set_auto_purchase(_runtime, SimulationCommand.new(999,0,0,75,&"set_supply_auto_purchase",&"player",_warehouse,patch))
_expect(not result.is_success() and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(before), "forged/wrongintent changes no state")
_expect(_plan(true, 6).is_success(), "configure a canonical saved plan")
var canonical: Dictionary = _runtime.create_snapshot()
for mutation: String in ["missing", "version", "duplicate", "unknown", "target", "bool", "clock", "receipt", "price", "extra"]:
var bad: Dictionary = canonical.duplicate(true)
var data: Dictionary = bad[&"systems"][&"runtime"]
var plans: Dictionary = data[&"auto_purchase_plans"]
var row: Dictionary = plans[&"plans"][0]
match mutation:
"missing": data.erase(&"auto_purchase_plans")
"version": plans[&"version"] = 2
"duplicate": (plans[&"plans"] as Array).append(row.duplicate(true))
"unknown": row[&"warehouse_id"] = "missing"
"target": row[&"target_stock"] = 101
"bool": row[&"enabled"] = 1
"clock": row[&"last_attempt_minute"] = _clock.absolute_minute + 1
"receipt": row[&"last_transaction_id"] = "txn.foreign"
"price": row[&"last_unit_price"] = 0.0
"extra": row[&"unit_price"] = 0
_expect(not _runtime.restore_snapshot(bad) and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(canonical), "corrupt14 plan rejected without mutation: " + mutation)
func _test_atomic_failures_and_same_minute_retry() -> void:
for kind: String in ["payment", "notification", "partial_stock"]:
_expect(_runtime.restore_snapshot(_built) and _plan(true, 6).is_success(), "configure independent failure fixture: " + kind)
var economy_before: Dictionary = _runtime.economy_service.create_snapshot()
var inventory_before: Dictionary = _runtime.inventory_service.create_snapshot()
var probe: ProbedInventory = PartialFailInventory.new() if kind == "partial_stock" else ProbedInventory.new()
_expect(probe.restore_snapshot(inventory_before), "Inventory probe starts from full actual snapshot: " + kind)
_runtime.inventory_service = probe
if kind != "partial_stock":
var rejecting: EconomyService = RejectingPaymentEconomy.new() if kind == "payment" else RejectingNotificationEconomy.new()
_expect(rejecting.restore_snapshot(economy_before), "injected Economy starts from actual snapshot")
_runtime.economy_service = rejecting
_runtime.call("_connect_economy_signals")
var notifications: Array[StringName] = []
_runtime.economy_service.transaction_posted.connect(func(id: StringName, _entries: Array) -> void: notifications.append(id))
var pending_before: Dictionary = (_runtime.economy_service.get("_pending_transaction_notifications") as Dictionary).duplicate(true)
_clock.advance_minutes(1)
_expect(_stock() == 0 and var_to_bytes(_runtime.economy_service.create_snapshot()) == var_to_bytes(economy_before), "failed order keeps actual cash and all ledger bytes unchanged: " + kind)
_expect(not probe.transaction_boundary.is_empty() and var_to_bytes(_runtime.inventory_service.create_snapshot()) == var_to_bytes(probe.transaction_boundary), "transaction-boundary rollback restores full Inventory IDs/reservations/history/order, allowing the preceding ordinary clock advancement: " + kind)
_expect(probe.transaction_boundary.get(&"current_minute", -1) == _clock.absolute_minute and _clock.absolute_minute > int(inventory_before[&"current_minute"]), "Inventory probe observes the actual next-minute transaction boundary: " + kind)
_expect(notifications.is_empty() and var_to_bytes(_runtime.economy_service.get("_pending_transaction_notifications")) == var_to_bytes(pending_before), "failed automatic transaction emits no notification and leaves the observed pending set exact: " + kind)
var failed: Dictionary = _runtime.create_snapshot()
var row: Dictionary = _runtime.auto_purchase_plans.get_plan(_warehouse, SupplyCatalog.RAW_FOOD)
_expect(row[&"last_attempt_minute"] == _clock.absolute_minute and row[&"last_result"] != &"PURCHASED", "actual failure stays recorded in same minute: " + kind)
_expect(_runtime.restore_snapshot(failed), "recorded failure restores into regular services: " + kind)
_expect(_runtime.supply_management.advance_auto_purchases(_runtime, _clock.absolute_minute).is_empty() and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(failed), "same-minute regular retry cannot hide the actual failure: " + kind)
_clock.advance_minutes(1)
_expect(_stock() == 6 and _runtime.economy_service.get_balance(&"PLAYER_CASH") == int(_built[&"game_state"][&"resources"][&"gold"]) - 18, "next ordinary tick retries exactly once: " + kind)
func _test_hold_disable_and_removal() -> void:
_expect(_runtime.restore_snapshot(_built), "hold fixture restores")
_expect(_plan(true, 6).is_success(), "enable before normal closure")
_expect(_runtime.submit_command(&"set_facility_policy", {&"facility_id": _warehouse, &"patch": {&"business_open": false}}).is_success(), "normal closure precedes auto tick")
var cash: int = _state.get_resource(&"gold")
_clock.advance_minutes(1)
_expect(_stock() == 0 and _state.get_resource(&"gold") == cash, "closed warehouse does not stock/pay")
_expect(_plan(false, 0).is_success(), "setting disable works despite closed receiver")
_expect(_runtime.submit_command(&"set_facility_policy", {&"facility_id": _warehouse, &"patch": {&"business_open": true}}).is_success(), "normal opening restores logistical eligibility")
_clock.advance_minutes(1)
_expect(_stock() == 0, "disabled plan stays off after reopening")
_expect(_plan(true, 6).is_success(), "enable again")
_clock.advance_minutes(1)
var paid: Dictionary = _runtime.create_snapshot()
var removal: CommandResult = _runtime.submit_command(&"demolish_facility", {&"instance_id": _warehouse})
_expect(not removal.is_success() and _runtime.auto_purchase_plans.create_snapshot() == paid[&"systems"][&"runtime"][&"auto_purchase_plans"], "stock-bearing failed removal preserves plan")
_expect(_runtime.restore_snapshot(_built) and _plan(true, 6).is_success(), "future closure fixture resets")
cash = _state.get_resource(&"gold")
_expect(_runtime.submit_command(&"set_facility_policy", {&"facility_id": _warehouse, &"patch": {&"business_open": false}, &"effective_at": _clock.absolute_minute + 1}).is_success(), "normal future closure is scheduled for next tick")
_clock.advance_minutes(1)
_expect(_stock() == 0 and _state.get_resource(&"gold") == cash and not _runtime.facility_service.get_instance(_warehouse).operator_open, "due closure blocks auto purchase before FacilityCompletion without early policy mutation")
_expect(_runtime.restore_snapshot(_built) and _plan(true, 6).is_success(), "empty warehouse with explicit intent exists")
_expect(_runtime.submit_command(&"demolish_facility", {&"instance_id": _warehouse}).is_success() and _runtime.auto_purchase_plans.get_plans().is_empty(), "successful empty warehouse removal prunes its intent")
_expect(_runtime.restore_snapshot(_runtime.create_snapshot()), "removed warehouse history/ledger remains restorable")
func _test_actual_budget_power_reservation_and_terminal() -> void:
_expect(_runtime.restore_snapshot(_built) and _plan(true, 6).is_success(), "configure a paid budget boundary")
var cash: int = _runtime.economy_service.get_balance(&"PLAYER_CASH")
_expect(_runtime.economy_service.transfer(&"PLAYER_CASH", &"CONSTRUCTION_EXPENSE", cash - 17, _clock.absolute_minute, &"CONSTRUCTION", &"", &"auto.acceptance.budget").is_success(), "disclosed ledger cash fixture leaves17G")
_clock.advance_minutes(1)
var row: Dictionary = _runtime.supply_management.auto_purchase_report(_runtime, _warehouse, SupplyCatalog.RAW_FOOD)
_expect(_stock() == 0 and _state.get_resource(&"gold") == 17 and row[&"reason"] == &"INSUFFICIENT_FUNDS", "full deficit18G never silently becomes partial free or affordable17G order")
_expect(row[&"last_attempt_minute"] == -1, "ineligible quote does not fabricate an executed order")
_expect(_runtime.economy_service.transfer(&"CONSTRUCTION_EXPENSE", &"PLAYER_CASH", 1, _clock.absolute_minute, &"CONSTRUCTION", &"", &"auto.acceptance.budget.refund").is_success(), "same actual ledger can return1G")
_clock.advance_minutes(1)
_expect(_stock() == 6 and _state.get_resource(&"gold") == 0, "eligible full order charges exactly available18G")
var paid: Dictionary = _runtime.create_snapshot()
var manual_key: StringName = &"auto.acceptance.manual.replacement"
var manual: CommandResult = _runtime.submit_command(&"purchase_supplies", {&"warehouse_id": _warehouse, &"item_id": SupplyCatalog.RAW_FOOD, &"quantity": 1}, &"player", _warehouse, 75, -1, manual_key)
_expect(not manual.is_success(), "manual insufficient cash remains rejected")
_expect(_runtime.restore_snapshot(_built) and _plan(true, 6).is_success(), "reserved-stock fixture resets")
_expect(_runtime.submit_command(&"purchase_supplies", {&"warehouse_id": _warehouse, &"item_id": SupplyCatalog.RAW_FOOD, &"quantity": 6}).is_success(), "reserved stock starts from an actual paid order")
var facility: FacilityInstance = _runtime.facility_service.get_instance(_warehouse)
var reservation: Dictionary = _runtime.inventory_service.reserve(facility.local_inventory_id, SupplyCatalog.RAW_FOOD, 6, &"disclosed.reserve.fixture", &"TEST", _clock.absolute_minute)
_expect(reservation.get(&"ok", false), "disclosed Inventory reservation retains physical stock")
cash = _state.get_resource(&"gold")
_clock.advance_minutes(1)
_expect(_stock() == 6 and _runtime.inventory_service.available_quantity(facility.local_inventory_id, SupplyCatalog.RAW_FOOD) == 0 and _state.get_resource(&"gold") == cash, "reserved physical units are not mistaken for missing stock or double-purchased")
_expect(_runtime.restore_snapshot(_built) and _plan(true, 6).is_success(), "power boundary resets")
_state.set_resource(&"mana", 0) # Disclosed resource boundary, not natural Mana generation.
cash = _state.get_resource(&"gold")
_clock.advance_minutes(1)
_expect(_stock() == 0 and _state.get_resource(&"gold") == cash, "Mana0 stops automatic paid order")
_expect(_runtime.restore_snapshot(_built) and _plan(true, 6).is_success(), "paused real-time boundary resets")
var paused: Dictionary = _runtime.create_snapshot()
_expect(_clock.process_real_delta(60.0) == 0 and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(paused), "paused real clock causes no automatic purchase or ID/timer change")
var collision_key: StringName = SupplyAutoPurchasePlans.order_key(_warehouse, SupplyCatalog.RAW_FOOD, _clock.absolute_minute)
_expect(_runtime.economy_service.transfer(&"PLAYER_CASH", &"CONSTRUCTION_EXPENSE", 1, _clock.absolute_minute, &"CONSTRUCTION", _warehouse, collision_key).is_success(), "disclosed foreign ledger-key fixture uses a valid ordinary transfer")
cash = _state.get_resource(&"gold")
var collisions: Array = _runtime.supply_management.advance_auto_purchases(_runtime, _clock.absolute_minute)
_expect(collisions.size() == 1 and _stock() == 0 and _state.get_resource(&"gold") == cash and _runtime.auto_purchase_plans.get_plan(_warehouse, SupplyCatalog.RAW_FOOD)[&"last_result"] == &"REPLAY_MISMATCH", "foreign ledger namespace cannot be treated as a free stocked purchase")
var collision: Dictionary = _runtime.create_snapshot()
_expect(_runtime.restore_snapshot(collision) and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(collision), "foreign-key failure receipt remains restorable without making it purchase income")
_expect(_runtime.restore_snapshot(paid), "restore an actual paid receipt for corruption tests")
var corrupt: Dictionary = paid.duplicate(true)
corrupt[&"systems"][&"runtime"][&"auto_purchase_plans"][&"plans"][0][&"last_transaction_id"] = String(_runtime.economy_service.get_entries()[0].transaction_id)
_expect(not _runtime.restore_snapshot(corrupt) and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(paid), "an existing unrelated actual transaction cannot replace the automatic receipt")
for field: StringName in [&"last_quantity", &"last_unit_price", &"last_total_cost"]:
corrupt = paid.duplicate(true)
corrupt[&"systems"][&"runtime"][&"auto_purchase_plans"][&"plans"][0][field] += 1
_expect(not _runtime.restore_snapshot(corrupt) and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(paid), "saved auto quantity/price/total quote cannot disagree with payment: %s" % field)
for pair: Vector2i in [Vector2i(3, 6), Vector2i(2, 9), Vector2i(1, 18), Vector2i(9, 2)]:
corrupt = paid.duplicate(true)
var changed_row: Dictionary = corrupt[&"systems"][&"runtime"][&"auto_purchase_plans"][&"plans"][0]
changed_row[&"last_quantity"] = pair.x
changed_row[&"last_unit_price"] = pair.y
_expect(not _runtime.restore_snapshot(corrupt) and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(paid), "coordinated factorization retaining actual18G cannot rewrite paid6x3G quote: %s" % pair)
var receipt_id: String = paid[&"systems"][&"runtime"][&"auto_purchase_plans"][&"plans"][0][&"last_transaction_id"]
for malformed: StringName in [&"supply_purchase", SupplyAutoPurchasePlans.receipt_memo(SupplyCatalog.BASIC_MEAL, 6, 3, 18), SupplyAutoPurchasePlans.receipt_memo(SupplyCatalog.RAW_FOOD, 3, 6, 18), &"supply_purchase.auto.v1:19:ingredient/raw_food:6:3:18:extra"]:
corrupt = paid.duplicate(true)
for entry: Dictionary in corrupt[&"systems"][&"runtime"][&"economy"][&"entries"]:
if entry[&"transaction_id"] == receipt_id: entry[&"memo_key"] = String(malformed)
_expect(not _runtime.restore_snapshot(corrupt) and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(paid), "ledger quote missing/wrong item/re-factored/noncanonical is rejected against independent plan atomically: %s" % malformed)
# Operations can only be enabled at fresh Day1 06:00 (360), before building.
# Keep the normal paid construction and intent after that canonical start.
_clock.reset(1, 6, 0)
_state.reset()
_expect(_runtime.initialize(_clock, _state, 420_501)[&"valid"], "fresh canonical bankruptcy fixture initializes")
_clock.set_paused(true)
_runtime.configure_save_policy({&"enabled": false, &"daily_checkpoint_enabled": false})
var started: Dictionary = _runtime.enable_production_operations()
_expect(started[&"ok"] and _clock.absolute_minute == 360, "actual bankruptcy boundary enables ordinary daily operation at fresh Day1 06:00")
_expect(_runtime.submit_command(&"build_facility", {&"definition_id": &"warehouse", &"origin": Vector3i(-8, 0, 1)}).is_success(), "terminal fixture uses ordinary paid warehouse construction")
_clock.advance_minutes(180)
_warehouse = &""
for endpoint: FacilityInstance in _runtime.facility_service.get_instances():
if endpoint.definition_id == &"warehouse": _warehouse = endpoint.instance_id
_expect(not _warehouse.is_empty() and _plan(true, 6).is_success(), "terminal fixture configures explicit player intent after ordinary warehouse completion")
_clock.advance_minutes(4320 - _clock.absolute_minute)
_expect(_runtime.operations_coordinator.get_day_summaries().size() == 3 and _runtime.operations_coordinator.get_terminal_state() == &"BANKRUPT", "warehouse-only actual costs reach existing three-deficit terminal rule")
var terminal: Dictionary = _runtime.create_snapshot()
_expect(_runtime.supply_management.advance_auto_purchases(_runtime, _clock.absolute_minute + 1).is_empty() and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(terminal), "BANKRUPT blocks every further internal purchase without fake commands")
_expect(_runtime.restore_snapshot(terminal), "terminal intent/ledger/current14 save still restores")
func _test_multiple_warehouse_order() -> void:
_expect(_runtime.restore_snapshot(_built), "multiple actual warehouses fixture starts with one paid unit")
_expect(_runtime.submit_command(&"build_facility", {&"definition_id": &"warehouse", &"origin": Vector3i(2,0,1)}).is_success(), "ordinary second warehouse construction is paid")
_clock.advance_minutes(180)
var ids: Array[StringName] = []
for facility: FacilityInstance in _runtime.facility_service.get_instances():
if facility.definition_id == &"warehouse": ids.append(facility.instance_id)
ids.sort_custom(func(a: StringName, b: StringName) -> bool: return String(a) < String(b))
_expect(ids.size() == 2, "two actual warehouse endpoints exist")
if ids.size() != 2: return
for index: int in [1, 0]:
_expect(_runtime.submit_command(&"set_supply_auto_purchase", {&"warehouse_id": ids[index], &"item_id": SupplyCatalog.RAW_FOOD, &"enabled": true, &"target_stock": 1}).is_success(), "reverse player setting order does not define payment priority")
var cash: int = _state.get_resource(&"gold")
_expect(_runtime.economy_service.transfer(&"PLAYER_CASH", &"CONSTRUCTION_EXPENSE", cash - 3, _clock.absolute_minute, &"CONSTRUCTION", &"", &"auto.acceptance.multi_budget").is_success(), "disclosed shared cash fixture funds exactly one existing3G unit")
var before: Dictionary = _runtime.create_snapshot()
_clock.advance_minutes(1)
var after: Dictionary = _runtime.create_snapshot()
_expect(_runtime.inventory_service.total_quantity(_runtime.facility_service.get_instance(ids[0]).local_inventory_id, SupplyCatalog.RAW_FOOD) == 1 and _runtime.inventory_service.total_quantity(_runtime.facility_service.get_instance(ids[1]).local_inventory_id, SupplyCatalog.RAW_FOOD) == 0, "explicit lexicographic warehouse/item ordering deterministically spends shared cash once")
_expect(_runtime.restore_snapshot(before), "multiple-plan pre-order snapshot restores")
_clock.advance_minutes(1)
_expect(var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(after), "restored multiple-plan allocation reproduces every typed field and event in order")
func _test_legacy13_and_composed_rollback() -> void:
_expect(_runtime.restore_snapshot(_built), "legacy fixture resets")
var legacy: Dictionary = _built.duplicate(true)
legacy[&"systems"][&"runtime"][&"runtime_schema_version"] = 13
legacy[&"systems"][&"runtime"].erase(&"auto_purchase_plans")
_expect(_runtime.restore_snapshot(legacy) and _runtime.auto_purchase_plans.get_plans().is_empty(), "valid13 snapshot migrates to disabled14 without purchase inference")
var migrated: Dictionary = _runtime.create_snapshot()
var disguised: Dictionary = legacy.duplicate(true)
disguised[&"systems"][&"runtime"][&"auto_purchase_plans"] = {&"version": 1, &"plans": []}
_expect(not _runtime.restore_snapshot(disguised) and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(migrated), "oldversion cannot covertly retain new aggregate")
_clock.set_paused(false)
_expect(_plan(true, 6).is_success(), "actual current14 pending automatic intent queues")
_clock.set_paused(true)
var pending: Dictionary = _runtime.create_snapshot()
var disguised_pending: Dictionary = pending.duplicate(true)
disguised_pending[&"systems"][&"runtime"][&"runtime_schema_version"] = 13
disguised_pending[&"systems"][&"runtime"].erase(&"auto_purchase_plans")
_expect(not _runtime.restore_snapshot(disguised_pending) and var_to_bytes(_runtime.create_snapshot()) == var_to_bytes(pending), "old13 cannot reinterpret a covert queued automatic order as paid feature intent")
_expect(_runtime.restore_snapshot(_built), "reset after pending downgrade refusal")
_expect(_plan(true, 6).is_success(), "intent exists before composed rollback token")
var token: Dictionary = _runtime.call("_capture_operations_external_state")
_expect(not token.is_empty() and token.has(&"auto_purchase_plans"), "Operations rollback includes owned plan state")
_expect(_runtime.auto_purchase_plans.set_plan(_warehouse, SupplyCatalog.RAW_FOOD, false, 0, _runtime.facility_service)[&"ok"], "disclosed boundary mutation fixture changes only owned intent")
_expect(_runtime.call("_restore_operations_external_state", token) and _runtime.call("_operations_external_state_matches", token), "composed rollback restores exact plan and other participants")
_runtime.call("_discard_operations_domain_events")
func _expect(condition: bool, message: String) -> void:
_checks += 1
if not condition:
_failures += 1
push_error("FAIL: " + message)
func _finish() -> void:
print("SUPPLY_AUTO_PURCHASE checks=%d failures=%d" % [_checks, _failures])
quit(_failures)