P18-01-CODE: 原本関係モデル・旧値保全・Runtime保存と読取経路
This commit is contained in:
@@ -1457,6 +1457,7 @@ func _run() -> void:
|
||||
_expect(runtime.restore_snapshot(retained), "refused departures survive save and readback")
|
||||
_expect(runtime.relationship_service.get_original_relationship(&"heroine_anri")[&"configured"], "departure never deletes original record")
|
||||
_extra_coverage(runtime)
|
||||
_review6_coverage(runtime)
|
||||
_representative_saves(runtime)
|
||||
runtime.free()
|
||||
clock.free()
|
||||
@@ -1465,6 +1466,93 @@ func _run() -> void:
|
||||
quit(_failures)
|
||||
|
||||
|
||||
func _review6_recovery(runtime: Variant, snapshot: Dictionary, accepted: bool) -> void:
|
||||
var path := "user://p18_review6"
|
||||
SaveService.delete_save(path)
|
||||
var input := var_to_bytes(snapshot)
|
||||
_expect(SaveService.save_snapshot(path, snapshot)[&"ok"], "review6 checksum-valid package written")
|
||||
var before := var_to_bytes(runtime.create_snapshot())
|
||||
var service: Variant = runtime.relationship_service
|
||||
var service_bytes := var_to_bytes(service.create_snapshot())
|
||||
var result: Dictionary = runtime.load_with_recovery(path)
|
||||
_expect(result[&"ok"] == accepted, "review6 actual recovery outcome")
|
||||
if not accepted:
|
||||
_expect(result[&"code"] == &"RESTORE_FAILED" and not result[&"recovery_report"][&"restore_committed"] and not result[&"recovery_report"][&"forbidden_repairs_applied"], "review6 no forbidden repair")
|
||||
_expect(runtime.relationship_service == service and var_to_bytes(service.create_snapshot()) == service_bytes, "recovery retains service identity and bytes")
|
||||
_expect(var_to_bytes(runtime.create_snapshot()) == before, "recovery retains complete authority and clock")
|
||||
_expect(var_to_bytes(snapshot) == input, "recovery preserves caller bytes")
|
||||
SaveService.delete_save(path)
|
||||
|
||||
|
||||
func _review6_coverage(runtime: Variant) -> void:
|
||||
var snapshot: Dictionary = runtime.create_snapshot()
|
||||
var container: Dictionary = snapshot[&"systems"][&"runtime"][&"relationships"]
|
||||
container[&"legacy"]["relationships"][0]["route_lock"] = "EXCLUSIVE_LOCKED"
|
||||
container[&"legacy"]["relationships"][0]["route_id"] = "review6_explicit_route"
|
||||
container[&"relationships"] = container[&"legacy"]["relationships"].duplicate(true)
|
||||
_expect(runtime.restore_snapshot(snapshot), "valid exclusive route normal positive control")
|
||||
_review6_recovery(runtime, snapshot, true)
|
||||
var bad := snapshot.duplicate(true)
|
||||
var payload: Dictionary = bad[&"systems"][&"runtime"][&"relationships"]
|
||||
payload[&"legacy"]["relationships"][0]["route_id"] = ""
|
||||
payload[&"relationships"] = payload[&"legacy"]["relationships"].duplicate(true)
|
||||
_reject_runtime(runtime, bad)
|
||||
_review6_recovery(runtime, bad, false)
|
||||
var service: Variant = runtime.relationship_service
|
||||
service._register_threshold_candidate(service.get_relationship(&"aliases"), &"affection", 60, 360, false)
|
||||
snapshot = runtime.create_snapshot()
|
||||
var legacy: Dictionary = snapshot[&"systems"][&"runtime"][&"relationships"][&"legacy"]
|
||||
legacy["threshold_candidates"][-1]["review6_extension"] = {"raw": [7, "keep"]}
|
||||
var v1 := snapshot.duplicate(true)
|
||||
v1[&"systems"][&"runtime"][&"relationships"] = legacy.duplicate(true)
|
||||
_expect(runtime.restore_snapshot(v1), "real producer candidate v1 positive")
|
||||
var roundtrip: Dictionary = runtime.create_snapshot()
|
||||
_expect(roundtrip[&"systems"][&"runtime"][&"relationships"][&"legacy"] == legacy, "producer raw types and unknown facts preserved")
|
||||
_expect(runtime.restore_snapshot(roundtrip), "producer v2 readback positive")
|
||||
_review6_recovery(runtime, roundtrip, true)
|
||||
var strings := roundtrip.duplicate(true)
|
||||
var string_candidate: Dictionary = strings[&"systems"][&"runtime"][&"relationships"][&"legacy"]["threshold_candidates"][-1]
|
||||
for identity: String in ["candidate_id", "relationship_id", "metric_id"]:
|
||||
string_candidate[identity] = String(string_candidate[identity])
|
||||
string_candidate["actor_ids"] = ["heroine_anri", "player"]
|
||||
_expect(runtime.restore_snapshot(strings), "legacy String identifiers remain valid")
|
||||
_expect(runtime.create_snapshot() == strings, "String identifiers retained without normalization")
|
||||
_review6_recovery(runtime, strings, true)
|
||||
_expect(runtime.restore_snapshot(roundtrip), "return to typed producer positive control")
|
||||
# Restored raw order is intentional; new monotonic producer ids append in order.
|
||||
service = runtime.relationship_service
|
||||
var prior_candidates: Array = service.create_snapshot()[&"legacy"]["threshold_candidates"]
|
||||
service._register_threshold_candidate(service.get_relationship(&"aliases"), &"affection", 61, 361, false)
|
||||
var appended: Array = service.create_snapshot()[&"legacy"]["threshold_candidates"]
|
||||
_expect(appended.slice(0, prior_candidates.size()) == prior_candidates and appended.size() == prior_candidates.size() + 1, "mutation preserves restored raw candidate order and appends producer id")
|
||||
_expect(runtime.restore_snapshot(roundtrip), "candidate mutation control reset")
|
||||
var wrong := {
|
||||
"candidate_id": [null, 9, []], "relationship_id": [null, 9, []],
|
||||
"metric_id": [null, 9, {}], "deduplication_key": [null, 9, {}],
|
||||
"threshold": ["60", true, 60.0, null], "created_at": ["360", true, 360.0, null],
|
||||
"requires_unlock_event": [1, "false", null],
|
||||
"actor_ids": ["actors", {}, [9, &"player"], []]}
|
||||
for key: String in wrong:
|
||||
for value: Variant in wrong[key]:
|
||||
bad = roundtrip.duplicate(true)
|
||||
payload = bad[&"systems"][&"runtime"][&"relationships"]
|
||||
payload[&"legacy"]["threshold_candidates"][-1][key] = value
|
||||
service = runtime.relationship_service
|
||||
var before := var_to_bytes(service.create_snapshot())
|
||||
var input := var_to_bytes(payload)
|
||||
_expect(not service.restore_snapshot(payload), "candidate wrong type rejected by service")
|
||||
_expect(var_to_bytes(service.create_snapshot()) == before and var_to_bytes(payload) == input, "candidate service rejection atomic")
|
||||
_reject_runtime(runtime, bad)
|
||||
_review6_recovery(runtime, bad, false)
|
||||
var bad_v1 := bad.duplicate(true)
|
||||
bad_v1[&"systems"][&"runtime"][&"relationships"] = payload[&"legacy"].duplicate(true)
|
||||
var legacy_input := var_to_bytes(payload[&"legacy"])
|
||||
_expect(not service.restore_snapshot(payload[&"legacy"]), "v1 candidate wrong type rejected by service")
|
||||
_expect(var_to_bytes(service.create_snapshot()) == before and var_to_bytes(payload[&"legacy"]) == legacy_input, "v1 candidate rejection preserves service and input")
|
||||
_reject_runtime(runtime, bad_v1)
|
||||
_review6_recovery(runtime, bad_v1, false)
|
||||
|
||||
|
||||
func _reject_runtime(runtime: Variant, candidate: Dictionary) -> void:
|
||||
var before := var_to_bytes(runtime.create_snapshot())
|
||||
var service: Variant = runtime.relationship_service
|
||||
|
||||
Reference in New Issue
Block a user