Files
aetherbound-guild/runtime/tests/fg4/content_registry_test.gd
T

140 lines
7.0 KiB
GDScript

extends SceneTree
const Content = preload("res://fg4/content_registry.gd")
var failures: Array[String] = []
var rejected_cases := 0
func _initialize() -> void:
call_deferred("run_test")
func run_test() -> void:
verify_complete_graph()
verify_bilingual_authority()
verify_route_graph()
verify_negative_boundaries()
if failures.is_empty():
print("ABG_FG4_CONTENT_REGISTRY_OK equipment=80 artifacts=15 enemies=24 bosses=4 contracts=4 markets=48 routes=144 bilingual=true rg03_enemy_usage_min=2 bosses_executable=4 bosses_descriptor_only=0 negative_cases=%d" % rejected_cases)
quit(0)
else:
for failure in failures:
push_error(failure)
quit(1)
func verify_complete_graph() -> void:
var first := Content.snapshot()
var second := Content.snapshot()
var validation := Content.validate(first)
expect(validation.ok, "canonical graph validates: %s" % str(validation.errors))
expect(first == second, "snapshot is byte-identical")
expect(String(first.catalog_hash).length() == 64, "catalog has source-bound hash")
expect(first.equipment.size() == 80, "equipment EQ-081..160 is complete")
expect(first.artifacts.size() == 15, "artifacts AR-016..030 are complete")
expect(first.enemies.size() == 24, "RG-03/RG-04 enemy identities are complete")
expect(first.bosses.size() == 4, "all RG-03/RG-04 Boss descriptors resolve")
expect(first.markets.size() == 12 and first.contract2_markets.size() == 12, "both twelve-Market Contracts resolve")
expect(first.routes.size() == 36 and first.contract2_routes.size() == 36, "both 36-route graphs resolve")
expect(first.rg04_markets.size() == 12 and first.rg04_contract2_markets.size() == 12, "both RG-04 twelve-Market Contracts resolve")
expect(first.rg04_routes.size() == 36 and first.rg04_contract2_routes.size() == 36, "both RG-04 36-route graphs resolve")
expect(first.contract.id == "CTR-R3-01" and first.contract.boss_id == "BO-R3-01", "Contract-1 boundary is exact")
expect(first.contract2.id == "CTR-R3-02" and first.contract2.boss_id == "BO-R3-02", "Contract-2 boundary is exact")
var bosses := Content.rows_by_id(first, "bosses")
expect(bosses["BO-R3-01"].executable and bosses["BO-R3-02"].executable, "both RG-03 Bosses are executable")
expect(bosses["BO-R4-01"].executable and bosses["BO-R4-02"].executable, "both accepted RG-04 Bosses are executable")
func verify_bilingual_authority() -> void:
var content := Content.snapshot()
for family in ["equipment", "artifacts", "enemies", "bosses"]:
for row in content[family]:
expect(has_copy(row.name), "%s has bilingual name" % row.id)
expect(has_copy(row.preview), "%s has bilingual preview" % row.id)
for item in content.equipment:
expect(has_copy(item.effect) and has_copy(item.tradeoff), "%s has bilingual decision copy" % item.id)
for artifact in content.artifacts:
expect(has_copy(artifact.rule) and has_copy(artifact.tradeoff), "%s has bilingual Artifact copy" % artifact.id)
for enemy in content.enemies:
expect(has_copy(enemy.rule) and has_copy(enemy.responses) and has_copy(enemy.escalation), "%s has bilingual enemy copy" % enemy.id)
for market in content.markets:
expect(has_copy(market.name) and has_copy(market.preview), "Market %d has bilingual decision copy" % market.market_index)
expect(has_copy(market.pressure) and has_copy(market.failure) and has_copy(market.milestone), "Market %d has bilingual consequence copy" % market.market_index)
for market in content.contract2_markets:
expect(has_copy(market.name) and has_copy(market.preview), "Contract-2 Market %d has bilingual decision copy" % market.market_index)
expect(has_copy(market.pressure) and has_copy(market.failure) and has_copy(market.milestone), "Contract-2 Market %d has bilingual consequence copy" % market.market_index)
func verify_route_graph() -> void:
var content := Content.snapshot()
var usage := {}
for enemy in content.enemies:
if String(enemy.id).begins_with("EN-R3-"):
usage[String(enemy.id)] = 0
for route in content.routes:
var market_index := int(route.market_index)
var risk := int(route.risk)
expect(route.id == "RO-R3-C01-M%02d-Q%d" % [market_index, risk], "%s identity is exact" % route.id)
expect(route.reward_coin == 22 + 2 * market_index + 7 * risk, "%s reward formula is exact" % route.id)
expect(route.recovery_coin == 12 + market_index + 3 * risk, "%s recovery cost is exact" % route.id)
expect(route.response_tags.size() >= 3, "%s exposes multiple rational responses" % route.id)
expect(route.enemy_ids.size() == route.wave_order.size(), "%s wave count matches composition" % route.id)
for enemy_id in route.enemy_ids:
usage[String(enemy_id)] += 1
for enemy_id in usage:
expect(usage[enemy_id] >= 2, "%s appears in at least two routes" % enemy_id)
for market in content.markets:
var valve: Dictionary = market.pressure_valve
expect(valve.id == "RV-R3-M%02d" % market.market_index, "Market %d valve identity is exact" % market.market_index)
expect(valve.position >= 1 and valve.position <= 10, "Market %d valve position is bounded" % market.market_index)
expect(valve.trigger in ["occupy", "vacate", "cross"], "Market %d valve trigger is disclosed" % market.market_index)
expect(valve.resolve_tick > valve.warning_ticks and valve.fixed_tick_ms == 100, "Market %d countdown is deterministic" % market.market_index)
for route in content.contract2_routes:
var market_index := int(route.market_index)
var risk := int(route.risk)
expect(route.id == "RO-R3-C02-M%02d-Q%d" % [market_index, risk], "%s identity is exact" % route.id)
expect(route.reward_coin == 22 + 2 * market_index + 7 * risk, "%s reward formula is exact" % route.id)
expect(route.spark_disclosure.repeat_threshold == 3, "%s discloses repeat threshold" % route.id)
func verify_negative_boundaries() -> void:
var wrong_source := Content.snapshot()
wrong_source.source.region_catalog_blob = "wrong"
expect_rejected(wrong_source, "source drift")
var missing_copy := Content.snapshot()
missing_copy.equipment[0].effect.zh_CN = ""
expect_rejected(missing_copy, "missing localized copy")
var duplicate_id := Content.snapshot()
duplicate_id.equipment[1].id = duplicate_id.equipment[0].id
expect_rejected(duplicate_id, "duplicate identity")
var bad_reward := Content.snapshot()
bad_reward.routes[0].reward_coin += 1
expect_rejected(bad_reward, "reward drift")
var bad_valve := Content.snapshot()
bad_valve.markets[0].pressure_valve.position = 11
expect_rejected(bad_valve, "valve outside line")
var bad_spark := Content.snapshot()
bad_spark.contract2_markets[0].spark_disclosure.repeat_threshold = 2
expect_rejected(bad_spark, "spark threshold drift")
func expect_rejected(content: Dictionary, label: String) -> void:
var rejected := not bool(Content.validate(content).ok)
expect(rejected, "%s rejects" % label)
if rejected:
rejected_cases += 1
func has_copy(value) -> bool:
return (
value is Dictionary
and not String(value.get("en", "")).is_empty()
and not String(value.get("zh_CN", "")).is_empty()
)
func expect(condition: bool, message: String) -> void:
if not condition:
failures.append("FG-4 content registry: %s" % message)