Add new tests and implement frame budget management

- Introduced `civilization_benchmark.gd` and `legacy_quantity_math.gd` for benchmarking and legacy quantity calculations.
- Created `test_dynamic_math.gd`, `test_frame_evolution.gd`, and `test_sparse_batches.gd` to validate mathematical operations and frame evolution logic.
- Implemented `frame_budget.gd` to manage cooperative work on the main thread, ensuring no partially calculated state is published.
- Added UID files for all new scripts to maintain unique identifiers.
This commit is contained in:
Kirill
2026-10-01 23:43:34 +03:00
parent f51eea6c0f
commit c4e7302567
53 changed files with 1313 additions and 397 deletions
+48
View File
@@ -2,6 +2,7 @@ extends SceneTree
const E = preload("res://world/owniverse/math/exact.gd")
const Math = preload("res://world/owniverse/quantity_math.gd")
const Legacy = preload("res://tests/fixtures/legacy_quantity_math.gd")
var checks: int = 0
var failures: int = 0
@@ -15,6 +16,24 @@ func check(condition: bool, message: String) -> void:
push_error(message)
func run() -> void:
var rng = RandomNumberGenerator.new()
rng.seed = 65432
var old_remainders: Dictionary = {}
var new_remainders: Dictionary = {}
for sample in 300:
var requests: Dictionary = {}
var weights: Dictionary = {}
for id in ["w", "m", "b", "c", "d", "l"]:
requests[id] = E.of(str(rng.randi_range(-10, 100)) + "." + str(rng.randi_range(0, 9)))
weights[id] = rng.randi_range(0, 100)
if sample % 3 == 0:
for id in requests: requests[id] = E.multiply(requests[id], E.of("1e40"))
var limit: Variant = E.multiply(rng.randi_range(0, 600), E.of("1e40")) if sample % 3 == 0 else rng.randi_range(0, 600)
check(E.eq(Math.allocate_whole(requests, limit), Legacy.allocate_whole(requests, limit)), "Allocation matches legacy with limits, ties and big integers")
var count: Variant = limit
check(E.eq(Math.split(new_remainders, "population", count, weights), Legacy.split(old_remainders, "population", count, weights)), "Split matches legacy rounding")
check(E.eq(new_remainders, old_remainders), "Signed remainder debt matches legacy")
check_ledger_cache()
var Catalog = load("res://world/owniverse/entity_catalog.gd")
check(E.eq(Math.allocate_whole({}, 10), {}), "Empty allocation")
check(E.eq(Math.allocate_whole({"b": 1, "a": 1}, 1), {"a": 1, "b": 0}), "Stable lexical tie")
@@ -62,3 +81,32 @@ func run() -> void:
for entity in catalog.entities.values(): entity.free()
print(("Quantity and catalog: %d checks, %d failures" % [checks, failures]))
quit((1 if failures else 0))
func check_ledger_cache() -> void:
var world = load("res://world/owniverse/owniverse.gd").new()
world.catalog.load_definitions(root.get_node("Global").OwniverseEntities)
world.state.amount.RD = E.of("1e40")
world.state.binds.GEM = {"RD": 7}
check(E.eq(world.ledger.physical_amounts(world.state).RD, E.add(E.of("1e40"), 7)), "Initial cached physical amount")
var returned: Dictionary = world.ledger.physical_amounts(world.state)
returned.RD = 0
check(E.gt(world.ledger.physical_amounts(world.state).RD, 0), "Caller cannot mutate cached physical totals")
world.state.binds.GEM.RD = 11
check(E.eq(world.ledger.physical_amounts(world.state).RD, E.add(E.of("1e40"), 11)), "Nested binding change invalidates physical cache")
world.state.amount.RD = 2
check(E.eq(world.ledger.physical_amounts(world.state).RD, 13), "Direct count change invalidates physical cache")
var other: Dictionary = world.state.duplicate(true)
other.binds.clear()
check(E.eq(world.ledger.physical_amounts(other).RD, 2), "Alternate state has independent physical totals")
check(E.eq(world.ledger.physical_amounts(world.state).RD, 13), "Returning to original state refreshes cache")
var revision: int = world.catalog.index_revision
world.catalog.rebuild_group_index()
check(world.catalog.index_revision > revision, "Catalog rebuild invalidates cached membership")
check(E.eq(world.ledger.physical_amounts(world.state).RD, 13), "Rebuild retains correct physical totals")
var rules: Dictionary = root.get_node("Global").CivilizationRules.duplicate(true)
var original_stages: int = world.catalog.civilization_layout(rules).stages.size()
rules["C2.0"].home = ""
world.catalog.invalidate_civilization_layout()
check(world.catalog.civilization_layout(rules).stages.size() == original_stages - 1, "Explicit rules change rebuilds civilization layout")
for entity in world.catalog.entities.values(): entity.free()
world.free()