238 lines
8.7 KiB
GDScript
238 lines
8.7 KiB
GDScript
extends GutTest
|
|
|
|
|
|
func test_core_catalog_enumerates_new_authoring_domains_deterministically() -> void:
|
|
var catalog := ContentCatalog.create_core()
|
|
assert_true(catalog.is_valid(), "%s" % [catalog.get_errors()])
|
|
assert_eq(
|
|
_tag_ids(catalog.get_capability_tags()),
|
|
[&"item.food", &"item.medicine", &"item.wood", &"resource.harvestable", &"storage.village"]
|
|
)
|
|
assert_eq(
|
|
_resource_ids(catalog.get_resources()),
|
|
[&"resource_berry_patch", &"resource_herb_patch", &"resource_tree"]
|
|
)
|
|
assert_eq(
|
|
_storage_ids(catalog.get_storages()),
|
|
[&"village_apothecary", &"village_pantry", &"village_woodpile"]
|
|
)
|
|
var report := catalog.get_authoring_report()
|
|
assert_true(report["valid"])
|
|
assert_eq(report["resources"], _resource_ids(catalog.get_resources()))
|
|
assert_eq(report["storages"], _storage_ids(catalog.get_storages()))
|
|
assert_false(report.has("presentation_assets"))
|
|
var returned_resources := catalog.get_resources()
|
|
returned_resources.clear()
|
|
assert_eq(catalog.get_resources().size(), 3)
|
|
|
|
|
|
func test_herb_route_is_data_only_and_legacy_routes_remain_stable() -> void:
|
|
var catalog := ContentCatalog.create_core()
|
|
var routing := StorageRoutingPolicy.new(catalog)
|
|
var herb_source := catalog.get_resource(&"resource_herb_patch")
|
|
assert_not_null(herb_source)
|
|
assert_eq(herb_source.item_id, &"herb")
|
|
assert_eq(herb_source.extraction_action_id, SimulationIds.ACTION_GATHER_FOOD)
|
|
assert_eq(routing.resolve_definition(herb_source.item_id).storage_id, &"village_apothecary")
|
|
assert_eq(
|
|
routing.resolve_definition(SimulationIds.RESOURCE_FOOD).storage_id,
|
|
SimulationIds.STORAGE_VILLAGE_PANTRY
|
|
)
|
|
assert_eq(
|
|
routing.resolve_definition(SimulationIds.RESOURCE_WOOD).storage_id,
|
|
SimulationIds.STORAGE_VILLAGE_WOODPILE
|
|
)
|
|
assert_null(routing.resolve_definition(&"unknown_item"))
|
|
|
|
var apothecary := catalog.get_storage(&"village_apothecary")
|
|
var nearly_full := apothecary.create_state({"herb": 39.0})
|
|
var states: Array[StorageStateRecord] = [nearly_full]
|
|
assert_same(routing.resolve_state(&"herb", 1.0, states), nearly_full)
|
|
assert_null(routing.resolve_state(&"herb", 2.0, states))
|
|
|
|
|
|
func test_routes_rank_priority_then_stable_storage_id() -> void:
|
|
var core := load(ContentCatalog.CORE_PACK_PATH) as SimulationContentPack
|
|
var addon := _pack(&"routing_addon")
|
|
addon.required_pack_ids = [&"core"]
|
|
var early := _storage(&"a_medicine_store", &"item.medicine", 100)
|
|
var low_priority := _storage(&"field_medicine_store", &"item.medicine", 10)
|
|
addon.storages = [low_priority, early]
|
|
var packs: Array[SimulationContentPack] = [addon, core]
|
|
var catalog := ContentCatalog.new()
|
|
assert_true(catalog.rebuild(packs).is_empty(), "%s" % [catalog.get_errors()])
|
|
|
|
var candidates := StorageRoutingPolicy.new(catalog).get_candidates(&"herb")
|
|
assert_eq(
|
|
_storage_ids(candidates),
|
|
[&"a_medicine_store", &"village_apothecary", &"field_medicine_store"]
|
|
)
|
|
|
|
|
|
func test_catalog_rejects_duplicate_content_ids_without_publishing_overrides() -> void:
|
|
var first := _complete_minimal_pack(&"first")
|
|
var second := _complete_minimal_pack(&"second")
|
|
var packs: Array[SimulationContentPack] = [second, first]
|
|
var catalog := ContentCatalog.new()
|
|
var duplicated_cues: Array[StringName] = [&"known.cue", &"known.cue"]
|
|
var errors := catalog.rebuild(packs, [], duplicated_cues)
|
|
|
|
for expected in [
|
|
"Duplicate action_id 'shared_action'",
|
|
"Duplicate item_id 'shared_item'",
|
|
"Duplicate tag_id 'shared_tag'",
|
|
"Duplicate resource_id 'shared_resource'",
|
|
"Duplicate storage_id 'shared_storage'",
|
|
"Duplicate supported presentation cue 'known.cue'",
|
|
]:
|
|
assert_true(_has_error(errors, expected), "%s missing from %s" % [expected, errors])
|
|
assert_false(catalog.is_valid())
|
|
assert_true(catalog.get_items().is_empty())
|
|
assert_null(catalog.get_storage(&"shared_storage"))
|
|
|
|
|
|
func test_catalog_rejects_unknown_action_item_tag_handler_and_cue_references() -> void:
|
|
var pack := _pack(&"broken")
|
|
var item := _item(&"broken_item", &"unknown_item_tag")
|
|
item.presentation_cue_id = &"unknown.item.cue"
|
|
var action := _action(&"broken_action")
|
|
action.actor_capability_tags = [&"unknown_actor_tag"]
|
|
action.target_capability_tags = [&"unknown_target_tag"]
|
|
action.completion_handler_id = &"unknown_handler"
|
|
action.presentation_cue_id = &"unknown.action.cue"
|
|
var effect := ActionEffect.new()
|
|
effect.effect_id = &"broken_effect"
|
|
effect.effect_kind = ActionEffect.KIND_SCHEDULE_ACTION
|
|
effect.scheduled_action_id = &"unknown_scheduled_action"
|
|
effect.item_id = &"unknown_effect_item"
|
|
action.effects = [effect]
|
|
var resource := _resource(&"broken_resource", &"unknown_resource_item", &"unknown_action")
|
|
resource.capability_tag_ids = [&"unknown_resource_tag"]
|
|
resource.presentation_cue_id = &"unknown.resource.cue"
|
|
var storage := _storage(&"broken_storage", &"unknown_storage_item_tag", 1)
|
|
storage.accepted_item_ids = [&"unknown_storage_item"]
|
|
storage.capability_tag_ids = [&"unknown_storage_tag"]
|
|
storage.deposit_action_id = &"unknown_deposit_action"
|
|
storage.presentation_cue_id = &"unknown.storage.cue"
|
|
pack.items = [item]
|
|
pack.actions = [action]
|
|
pack.resources = [resource]
|
|
pack.storages = [storage]
|
|
var packs: Array[SimulationContentPack] = [pack]
|
|
var handlers: Array[StringName] = [&"known_handler"]
|
|
var cues: Array[StringName] = [&"known.cue"]
|
|
var errors := ContentCatalog.new().rebuild(packs, handlers, cues)
|
|
|
|
for expected in [
|
|
"unknown tag 'unknown_item_tag'",
|
|
"unknown presentation cue 'unknown.item.cue'",
|
|
"unknown tag 'unknown_actor_tag'",
|
|
"unknown tag 'unknown_target_tag'",
|
|
"unknown completion handler 'unknown_handler'",
|
|
"unknown action 'unknown_scheduled_action'",
|
|
"unknown item 'unknown_effect_item'",
|
|
"unknown item 'unknown_resource_item'",
|
|
"unknown action 'unknown_action'",
|
|
"unknown tag 'unknown_resource_tag'",
|
|
"unknown item 'unknown_storage_item'",
|
|
"unknown tag 'unknown_storage_item_tag'",
|
|
"unknown tag 'unknown_storage_tag'",
|
|
"unknown action 'unknown_deposit_action'",
|
|
"unknown presentation cue 'unknown.storage.cue'",
|
|
]:
|
|
assert_true(_has_error(errors, expected), "%s missing from %s" % [expected, errors])
|
|
|
|
|
|
func _complete_minimal_pack(pack_id: StringName) -> SimulationContentPack:
|
|
var pack := _pack(pack_id)
|
|
var tag := CapabilityTagDefinition.new()
|
|
tag.tag_id = &"shared_tag"
|
|
tag.display_name = "Shared tag"
|
|
tag.domain = CapabilityTagDefinition.DOMAIN_ITEM
|
|
var item := _item(&"shared_item", tag.tag_id)
|
|
var action := _action(&"shared_action")
|
|
action.target_type = SimulationIds.TARGET_RESOURCE
|
|
action.resource_action_id = action.action_id
|
|
var resource := _resource(&"shared_resource", item.item_id, action.action_id)
|
|
var storage := _storage(&"shared_storage", tag.tag_id, 1)
|
|
pack.capability_tags = [tag]
|
|
pack.items = [item]
|
|
pack.actions = [action]
|
|
pack.resources = [resource]
|
|
pack.storages = [storage]
|
|
return pack
|
|
|
|
|
|
func _pack(pack_id: StringName) -> SimulationContentPack:
|
|
var pack := SimulationContentPack.new()
|
|
pack.pack_id = pack_id
|
|
pack.display_name = String(pack_id).capitalize()
|
|
return pack
|
|
|
|
|
|
func _item(item_id: StringName, tag_id: StringName) -> ItemDefinition:
|
|
var item := ItemDefinition.new()
|
|
item.item_id = item_id
|
|
item.display_name = String(item_id).capitalize()
|
|
item.category = ItemDefinition.CATEGORY_RESOURCE
|
|
item.capability_tag_ids = [tag_id]
|
|
return item
|
|
|
|
|
|
func _action(action_id: StringName) -> ActionDefinition:
|
|
var action := ActionDefinition.new()
|
|
action.action_id = action_id
|
|
action.display_name = String(action_id).capitalize()
|
|
action.target_type = SimulationIds.TARGET_ACTIVITY
|
|
return action
|
|
|
|
|
|
func _resource(
|
|
resource_id: StringName, item_id: StringName, action_id: StringName
|
|
) -> ResourceDefinition:
|
|
var resource := ResourceDefinition.new()
|
|
resource.resource_id = resource_id
|
|
resource.display_name = String(resource_id).capitalize()
|
|
resource.item_id = item_id
|
|
resource.extraction_action_id = action_id
|
|
return resource
|
|
|
|
|
|
func _storage(
|
|
storage_id: StringName, accepted_item_tag_id: StringName, priority: int
|
|
) -> StorageDefinition:
|
|
var storage := StorageDefinition.new()
|
|
storage.storage_id = storage_id
|
|
storage.display_name = String(storage_id).capitalize()
|
|
storage.accepted_item_tag_ids = [accepted_item_tag_id]
|
|
storage.routing_priority = priority
|
|
return storage
|
|
|
|
|
|
func _tag_ids(definitions: Array[CapabilityTagDefinition]) -> Array[StringName]:
|
|
var ids: Array[StringName] = []
|
|
for definition in definitions:
|
|
ids.append(definition.tag_id)
|
|
return ids
|
|
|
|
|
|
func _resource_ids(definitions: Array[ResourceDefinition]) -> Array[StringName]:
|
|
var ids: Array[StringName] = []
|
|
for definition in definitions:
|
|
ids.append(definition.resource_id)
|
|
return ids
|
|
|
|
|
|
func _storage_ids(definitions: Array[StorageDefinition]) -> Array[StringName]:
|
|
var ids: Array[StringName] = []
|
|
for definition in definitions:
|
|
ids.append(definition.storage_id)
|
|
return ids
|
|
|
|
|
|
func _has_error(errors: Array[String], fragment: String) -> bool:
|
|
for error in errors:
|
|
if fragment in error:
|
|
return true
|
|
return false
|