SessionZero-Client/sessionzero-client/scripts/datapacks/datapack_tests.gd

375 lines
14 KiB
GDScript

# ------------------------------- WARNING --------------------------------
# These tests were auto generated by an LLM according to a design document
# to simply test the workflow. These tests should not be completely relied
# on for tesing full functionality of the datapack system.
# ------------------------------------------------------------------------
class_name DatapackTestNode
extends Node
# --- PRIMARY PACK CONSTANTS ---
const PACK_NAME = "core_data_test_pack"
const ENTRY_ID = "test_item_sword"
const WEAPONS_DATASET_ID = "weapons_dataset"
const SKILLS_DATASET_ID = "skills_dataset"
const CHAR_TEMPLATE_ID = "base_char_template"
const SESSION_TEMPLATE_ID = "basic_session_template"
# --- NEW CROSS-PACK CONSTANTS ---
const DEPENDENCY_PACK_NAME = "stat_core_pack"
const DEPENDENCY_DATASET_ID = "core_stats_dataset"
const DEPENDENCY_ENTRY_ID = "base_strength"
const DEPENDER_PACK_NAME = "class_pack"
const DEPENDER_DATASET_ID = "warrior_class"
func _ready() -> void:
print("--- Starting Datapack Test ---")
# --- Primary Test (Pack 1) ---
var creation_success = _create_and_save_datapack()
if not creation_success:
push_error("TEST FAILED: Datapack creation failed.")
return
_load_and_verify_datapack()
_test_formula_resolution()
# --- New Cross-Pack Dependency Test (Pack 2 & 3) ---
_test_cross_datapack_dependency()
print("--- Datapack Test Complete ---")
#----------------------------------------------------------------------
## --- STEP 2: CREATION AND SAVING ---
#----------------------------------------------------------------------
func _create_and_save_datapack() -> bool:
print("\n--- 2. Creating and Saving Datapack ---")
# --- 0. Setup Core Data ---
var stats_group := DatasetGroup.new()
stats_group.id = "base_stats"
stats_group.name = "Base Stats"
# Simple Numeric Field
var damage_field := DataFieldValue.new()
damage_field.field_type = DataFieldValue.DataFieldType.NUMBER
damage_field.value = 12
stats_group.fields["damage"] = damage_field
# --- FORMULA Field ---
var formula_res := FormulaValue.new()
formula_res.expression = "Base_Damage * Critical_Multiplier"
var crit_damage_field := DataFieldValue.new()
crit_damage_field.field_type = DataFieldValue.DataFieldType.FORMULA
crit_damage_field.value = formula_res
stats_group.fields["critical_damage"] = crit_damage_field
# --- LIST Field ---
var list_res := ListValue.new()
# Add nested DataFieldValue items to the ListValue resource
var list_item_1 := DataFieldValue.new()
list_item_1.field_type = DataFieldValue.DataFieldType.NUMBER
list_item_1.value = 5
var list_item_2 := DataFieldValue.new()
list_item_2.field_type = DataFieldValue.DataFieldType.TEXT
list_item_2.value = "Stun"
list_res.items.append(list_item_1)
list_res.items.append(list_item_2)
var effect_list_field := DataFieldValue.new()
effect_list_field.field_type = DataFieldValue.DataFieldType.LIST
effect_list_field.value = list_res
stats_group.fields["on_hit_effects"] = effect_list_field
# Create Dataset Entry
var sword_entry := DatasetEntry.new()
sword_entry.id = ENTRY_ID
sword_entry.name = "Longsword of Testing"
sword_entry.description = "A sword for unit testing."
sword_entry.groups.append(stats_group)
# Create Dataset Model (Weapons)
var weapons_dataset := DatasetModel.new()
weapons_dataset.id = WEAPONS_DATASET_ID
weapons_dataset.name = "Weapons"
weapons_dataset.entries[sword_entry.id] = sword_entry
weapons_dataset.sz_type = "Weapon"
# --- Dependency Setup: Skills Dataset ---
var skills_dataset := DatasetModel.new()
skills_dataset.id = SKILLS_DATASET_ID
skills_dataset.name = "Skills"
skills_dataset.sz_type = "Skill"
# --- Dependency Setup: CharacterTemplate ---
var char_template := CharacterTemplate.new()
char_template.id = CHAR_TEMPLATE_ID
char_template.name = "Standard Character"
var skills_dependency := DependencySource.new()
skills_dependency.mode = DependencySource.DependencyMode.SPECIFIC_DATASET
skills_dependency.target_sz_object_id = SKILLS_DATASET_ID
char_template.data_dependencies["Skills_Source"] = skills_dependency
# --- Dependency Setup: SessionTemplate ---
var session_template := SessionTemplate.new()
session_template.id = SESSION_TEMPLATE_ID
session_template.name = "Basic Campaign Session"
var char_dep_source := DependencySource.new()
char_dep_source.mode = DependencySource.DependencyMode.SPECIFIC_DATASET
char_dep_source.target_sz_object_id = CHAR_TEMPLATE_ID
session_template.character_template_ref = char_dep_source
# --- Create and Save Datapack Model ---
var datapack := DatapackModel.new()
datapack.name = "Test Pack"
datapack.version = "1.0.0"
datapack.sz_objects.append(weapons_dataset)
datapack.sz_objects.append(skills_dataset)
datapack.sz_objects.append(char_template)
datapack.sz_objects.append(session_template)
var creator = DatapackCreator.new()
var success = creator.save_datapack(datapack, PACK_NAME)
return success
#----------------------------------------------------------------------
## --- STEP 3: LOADING AND VERIFICATION (Omitted for brevity, assumed stable) ---
#----------------------------------------------------------------------
func _load_and_verify_datapack() -> void:
print("\n--- 3. Loading and Verification ---")
var loader = DatapackLoader.new()
var loaded_pack: DatapackModel = loader.load_datapack(PACK_NAME)
if not loaded_pack:
push_error("TEST FAILED: DatapackLoader returned null.")
return
DatapackManager.register_pack(loaded_pack)
print("Verification: Datapack registered with DatapackManager.")
var loaded_weapons_dataset: DatasetModel = loaded_pack.get_object_by_id(WEAPONS_DATASET_ID)
var loaded_entry: DatasetEntry = loaded_weapons_dataset.entries.get(ENTRY_ID)
var loaded_group: DatasetGroup = loaded_entry.groups.filter(func(g): return g.id == "base_stats").front()
var loaded_char_template: CharacterTemplate = loaded_pack.get_object_by_id(CHAR_TEMPLATE_ID)
var loaded_session_template: SessionTemplate = loaded_pack.get_object_by_id(SESSION_TEMPLATE_ID)
# 1. SessionTemplate Character Reference
var char_ref_dep_source: DependencySource = loaded_session_template.character_template_ref
var resolved_char_template_array = DatapackManager.resolve_dependency_source(char_ref_dep_source)
if resolved_char_template_array.size() == 1 and resolved_char_template_array.front() == loaded_char_template:
print("✅ SUCCESS: SessionTemplate dependency link resolved.")
else:
push_error("TEST FAILED: SessionTemplate character_template_ref resolution failed.")
# 2. CharacterTemplate Skills Dependency
var skills_dep_source: DependencySource = loaded_char_template.data_dependencies.get("Skills_Source")
var resolved_skills_array = DatapackManager.resolve_dependency_source(skills_dep_source)
var loaded_skills_dataset = loaded_pack.get_object_by_id(SKILLS_DATASET_ID)
if resolved_skills_array.size() == 1 and resolved_skills_array.front() == loaded_skills_dataset:
print("✅ SUCCESS: CharacterTemplate data dependency link resolved.")
else:
push_error("TEST FAILED: CharacterTemplate data dependency resolution failed.")
# 3. Verify FORMULA field
var loaded_crit_field: DataFieldValue = loaded_group.fields.get("critical_damage")
if loaded_crit_field and loaded_crit_field.field_type == DataFieldValue.DataFieldType.FORMULA:
var formula: FormulaValue = loaded_crit_field.value
if formula is FormulaValue and formula.expression == "Base_Damage * Critical_Multiplier":
print("✅ SUCCESS: Found and verified FormulaValue resource.")
else:
push_error("TEST FAILED: FormulaValue verification failed (wrong type or expression).")
else:
push_error("TEST FAILED: Critical damage field not found or wrong type.")
# 4. Verify LIST field
var loaded_list_field: DataFieldValue = loaded_group.fields.get("on_hit_effects")
if loaded_list_field and loaded_list_field.field_type == DataFieldValue.DataFieldType.LIST:
var list_val: ListValue = loaded_list_field.value
if list_val is ListValue and list_val.items.size() == 2:
if list_val.items[1] is DataFieldValue and list_val.items[1].value == "Stun":
print("✅ SUCCESS: Found and verified ListValue and its nested contents.")
else:
push_error("TEST FAILED: ListValue contents verification failed.")
else:
push_error("TEST FAILED: ListValue resource failed to load correctly.")
else:
push_error("TEST FAILED: On hit effects field not found or wrong type.")
print("\nVerification: All checks completed.")
#----------------------------------------------------------------------
## --- STEP 4: FORMULA RESOLUTION TEST (Omitted for brevity, assumed stable) ---
#----------------------------------------------------------------------
func _test_formula_resolution():
print("\n--- 4. Testing Formula Resolver with Variable Substitution ---")
var resolver := FormulaResolver.new()
var raw_expression := "Base_Damage * Critical_Multiplier + floor(Skill_Level / 2)"
var context: Dictionary = {
"Base_Damage": 15,
"Critical_Multiplier": 2.5,
"Skill_Level": 7
}
var expected_result = 40.5
var result = resolver.resolve_formula(raw_expression, context)
if abs(result - expected_result) < 0.001:
print("✅ SUCCESS: FormulaResolver calculated the correct result: %f" % result)
else:
push_error("TEST FAILED: FormulaResolver result incorrect. Expected %f, Got %f" % [expected_result, result])
#----------------------------------------------------------------------
## --- STEP 5: CROSS-PACK DEPENDENCY RESOLUTION ---
#----------------------------------------------------------------------
func _test_cross_datapack_dependency():
print("\n--- 5. Testing Cross-Pack Dependency Resolution ---")
DatapackManager.clear_loaded_packs()
print("DatapackManager cleared for cross-pack test.")
# --- 5a. Create and Save DEPENDENCY PACK (Pack A: Stat Core) ---
# FIX: Capture the DatapackModel to get its GUID
var pack_a_model: DatapackModel = _create_dependency_pack_a()
if not pack_a_model:
push_error("TEST FAILED: Failed to create Dependency Pack A.")
return
var dependency_pack_guid: Guid = pack_a_model.guid # <--- This is the Guid object needed
print("Pack A GUID captured: %s" % dependency_pack_guid.to_string())
# --- 5b. Create and Save DEPENDER PACK (Pack B: Class Pack) ---
# FIX: Pass the GUID object to the creator function
var success_b = _create_depender_pack_b(dependency_pack_guid)
if not success_b:
push_error("TEST FAILED: Failed to create Depender Pack B.")
return
# --- 5c. Load and Register Both Packs ---
var loader = DatapackLoader.new()
var pack_a: DatapackModel = loader.load_datapack(DEPENDENCY_PACK_NAME)
var pack_b: DatapackModel = loader.load_datapack(DEPENDER_PACK_NAME)
if not pack_a or not pack_b:
push_error("TEST FAILED: Failed to load one or both dependency test packs.")
return
DatapackManager.register_pack(pack_a)
DatapackManager.register_pack(pack_b)
print("Registered both Dependency (A) and Depender (B) packs.")
# --- 5d. Resolve Dependency in Pack B ---
var depender_dataset: DatasetModel = pack_b.get_object_by_id(DEPENDER_DATASET_ID)
if not depender_dataset:
push_error("TEST FAILED: Could not find Depender Dataset in Pack B.")
return
var dependency_source: DependencySource = depender_dataset.get_meta("core_stats_source")
if not dependency_source:
push_error("TEST FAILED: Could not find the DependencySource object in Pack B.")
return
var resolved_objects: Array = DatapackManager.resolve_dependency_source(dependency_source)
# --- 5e. Verification ---
if resolved_objects.size() != 1:
push_error("TEST FAILED: Dependency resolution returned incorrect count: %d" % resolved_objects.size())
return
var resolved_dataset: DatasetModel = resolved_objects.front()
var expected_dataset: DatasetModel = pack_a.get_object_by_id(DEPENDENCY_DATASET_ID)
if resolved_dataset == expected_dataset:
print("✅ SUCCESS: Cross-pack dependency successfully resolved.")
if resolved_dataset.entries.has(DEPENDENCY_ENTRY_ID):
print("✅ SUCCESS: Resolved dataset contains the expected entry '%s'." % DEPENDENCY_ENTRY_ID)
else:
push_error("TEST FAILED: Dependency resolved to the wrong object.")
# --- Helper Functions for Cross-Pack Test ---
# UPDATED: Returns the DatapackModel for GUID retrieval
func _create_dependency_pack_a() -> DatapackModel:
# Create entry
var str_field := DataFieldValue.new()
str_field.field_type = DataFieldValue.DataFieldType.NUMBER
str_field.value = 10
var strength_entry := DatasetEntry.new()
strength_entry.id = DEPENDENCY_ENTRY_ID
strength_entry.name = "Strength"
strength_entry.top_level_fields["value"] = str_field
# Create dataset
var core_stats_dataset := DatasetModel.new()
core_stats_dataset.id = DEPENDENCY_DATASET_ID
core_stats_dataset.name = "Core Stats"
core_stats_dataset.sz_type = "StatDefinition"
core_stats_dataset.entries[strength_entry.id] = strength_entry
# Create datapack
var datapack := DatapackModel.new()
datapack.name = "Stat Core Pack"
datapack.version = "1.0.0"
datapack.sz_objects.append(core_stats_dataset)
var creator = DatapackCreator.new()
var success = creator.save_datapack(datapack, DEPENDENCY_PACK_NAME)
if success:
return datapack
else:
return null # Return null on failure
# UPDATED: Accepts the GUID to correctly create the DatapackDependency
func _create_depender_pack_b(dependency_pack_guid: Guid) -> bool:
# Create DependencySource (internal reference by string ID)
var dependency_source := DependencySource.new()
dependency_source.mode = DependencySource.DependencyMode.SPECIFIC_DATASET
dependency_source.target_sz_object_id = DEPENDENCY_DATASET_ID
# Create Depender Dataset
var warrior_class_dataset := DatasetModel.new()
warrior_class_dataset.id = DEPENDER_DATASET_ID
warrior_class_dataset.name = "Warrior Class"
warrior_class_dataset.sz_type = "ClassDefinition"
warrior_class_dataset.set_meta("core_stats_source", dependency_source)
# Create Datapack
var datapack := DatapackModel.new()
datapack.name = "Warrior Class Pack"
datapack.version = "1.0.0"
datapack.sz_objects.append(warrior_class_dataset)
# Add the explicit pack dependency
var pack_dep := DatapackDependency.new()
# FIX: Assign the Guid object to the 'id' property
pack_dep.id = dependency_pack_guid
pack_dep.name = "Stat Core Pack"
pack_dep.version = "1.0.0"
datapack.dependencies.append(pack_dep)
var creator = DatapackCreator.new()
var success = creator.save_datapack(datapack, DEPENDER_PACK_NAME)
return success