extends SceneTree const Model = preload("res://scripts/relationship/original_relationship_state.gd") const Service = preload("res://scripts/relationship/relationship_service.gd") var _checks := 0 var _failures := 0 func _initialize() -> void: call_deferred("_run") func _expect(value: bool, message: String) -> void: _checks += 1 if not value: _failures += 1 push_error(message) static func fixture() -> Dictionary: # Validation fixtures, never approved initialization or range limits. return {"subject_id": "heroine_anri", "protagonist_id": "player", "rival_id": "rival_rai", "affection": 142.5, "lust": 23.25, "netorare": 11, "shield_current": 90.5, "shield_max": 142.5} func _service() -> RelationshipService: return Service.new().configure_original_identity_validator( func(p: Dictionary) -> bool: return p["subject_id"] == "heroine_anri" and p["protagonist_id"] == "player" and p["rival_id"] == "rival_rai" ) func _run() -> void: var service := _service() var before := var_to_bytes(service.create_snapshot()) var unset := service.get_original_relationship(&"heroine_anri") _expect(not unset[&"configured"] and unset[&"affection"] == null, "missing record is unset") unset[&"affection"] = 999 _expect(var_to_bytes(service.create_snapshot()) == before, "reads own their dictionaries") var payload := fixture() var payload_bytes := var_to_bytes(payload) _expect(service.register_original_relationship(payload).is_success(), "complete directional fixture registers") payload["affection"] = 0 _expect(service.get_original_relationship(&"heroine_anri")["affection"] == 142.5, "caller cannot mutate stored facts") _expect(not service.register_original_relationship(fixture()).is_success(), "duplicate subject rejected") var saved := service.create_snapshot() var restored := _service() _expect(restored.restore_snapshot(saved), "new-only v2 restores") _expect(var_to_bytes(restored.create_snapshot()) == var_to_bytes(saved), "new-only exact bytes") _expect(var_to_bytes(fixture()) == payload_bytes, "fixture is explicit and stable") for field: String in Model.FIELDS: var missing := fixture() missing.erase(field) _expect(Model.from_snapshot(missing) == null, "missing required field " + field) for value: Variant in [null, true, "12", INF, NAN, {}, []]: var wrong := fixture() wrong["lust"] = value _expect(Model.from_snapshot(wrong) == null, "wrong/nonfinite numeric value rejected") for patch: Dictionary in [{"shield_max": 1}, {"shield_current": -1}, {"shield_current": 143}, {"rival_id": "player"}, {"subject_id": "player"}]: var wrong := fixture() wrong.merge(patch, true) _expect(Model.from_snapshot(wrong) == null, "value/identity invariant rejected") var zero := fixture() for field: String in ["affection", "lust", "netorare", "shield_current", "shield_max"]: zero[field] = 0 _expect(Model.from_snapshot(zero) != null, "explicit zero is configured") var legacy := {"version": 1, "relationships": [{"relationship_id": "old", "actor_a_id": "player", "actor_b_id": "heroine_anri", "metrics": {"affinity": 117, "dependence": 29, "extension": {"opaque": [3, "keep"]}}, "extra": ["raw", 2.5]}], "threshold_candidates": [], "next_candidate_sequence": 1, "extension": {"version": 70}} var legacy_bytes := var_to_bytes(legacy) var migrated := _service() _expect(migrated.restore_snapshot(legacy), "legacy aliases still usable") _expect(migrated.get_relationship(&"old").get_metric(&"affection") == 100, "legacy normalization behavior retained") _expect(not migrated.get_original_relationship(&"heroine_anri")[&"configured"], "legacy never configures original facts") _expect(var_to_bytes(migrated.create_snapshot()[&"legacy"]) == legacy_bytes, "all raw legacy values and extensions preserved") _expect(var_to_bytes(legacy) == legacy_bytes, "legacy input bytes untouched") _expect(migrated.register_original_relationship(fixture()).is_success(), "mixed state registers independently") var mixed := migrated.create_snapshot() _expect(restored.restore_snapshot(mixed), "mixed snapshot restores") _expect(var_to_bytes(restored.create_snapshot()) == var_to_bytes(mixed), "mixed exact bytes") _expect(migrated.apply_value_change(&"old", &"trust", 3, 0).is_success(), "legacy changes still apply") var changed: Dictionary = migrated.create_snapshot()[&"legacy"] _expect(changed["relationships"][0]["metrics"]["affinity"] == 117 and changed["relationships"][0]["metrics"]["trust"] == 3, "changed metric preserves raw alias") for version: Variant in [0, 3, "2", 2.0, true]: var bad := mixed.duplicate(true) bad[&"version"] = version _rejected(restored, bad) var duplicate := mixed.duplicate(true) duplicate[&"original_relationships"].append(fixture()) _rejected(restored, duplicate) for patch: Dictionary in [{"rival_id": "unknown"}, {"protagonist_id": "unknown"}, {"lust": false}, {"shield_max": 10}]: var bad := mixed.duplicate(true) bad[&"original_relationships"][0].merge(patch, true) _rejected(restored, bad) var bad_legacy := legacy.duplicate(true) bad_legacy["relationships"][0]["metrics"]["affinity"] = "117" _rejected(restored, bad_legacy) bad_legacy = legacy.duplicate(true) bad_legacy["relationships"].append(bad_legacy["relationships"][0].duplicate(true)) _rejected(restored, bad_legacy) print("Original relationship model: %d checks, %d failures" % [_checks, _failures]) quit(_failures) func _rejected(service: RelationshipService, payload: Dictionary) -> void: var before := var_to_bytes(service.create_snapshot()) var input := var_to_bytes(payload) _expect(not service.restore_snapshot(payload), "corrupt snapshot rejected") _expect(var_to_bytes(service.create_snapshot()) == before, "rejection preserves prior state") _expect(var_to_bytes(payload) == input, "rejection preserves input bytes")