101 lines
4.1 KiB
GDScript
101 lines
4.1 KiB
GDScript
extends SceneTree
|
||
## Suite: Prüfsummen-Fremdformat-Dialog (t_9814f18f).
|
||
## Ausführen: godot4 --headless --path . --script res://tests/test_svmap_resign_dialog.gd
|
||
## Exit 0 = alles grün. Läuft OHNE UI (nur SvmapIO/SvmapDocument).
|
||
##
|
||
## Deckt den Sly-Fall ab: Datei von fremdem Writer (V13 schlägt fehl,
|
||
## Kern V3–V16 grün) → checksum_only_failure → load_from_file_resign
|
||
## akzeptiert + signiert v2 + Roundtrip bleibt stabil.
|
||
|
||
var failures := 0
|
||
var checks := 0
|
||
|
||
|
||
func _init() -> void:
|
||
_cleanup()
|
||
_run_tests()
|
||
_cleanup()
|
||
if failures == 0:
|
||
print("ALL OK: %d checks" % checks)
|
||
quit(0)
|
||
else:
|
||
print("FAILED: %d/%d checks" % [failures, checks])
|
||
quit(1)
|
||
|
||
|
||
func _cleanup() -> void:
|
||
for path in ["user://test_resign.svmap", "user://test_resign2.svmap"]:
|
||
if FileAccess.file_exists(path):
|
||
DirAccess.remove_absolute(ProjectSettings.globalize_path(path))
|
||
|
||
|
||
func _check(cond: bool, label: String) -> void:
|
||
checks += 1
|
||
if cond:
|
||
print(" ok: %s" % label)
|
||
else:
|
||
failures += 1
|
||
print(" FAIL: %s" % label)
|
||
|
||
|
||
func _errors_contain(errors: Array, needle: String) -> bool:
|
||
for e in errors:
|
||
if str(e).contains(needle):
|
||
return true
|
||
return false
|
||
|
||
|
||
func _run_tests() -> void:
|
||
print("== Fremdformat-Dialog: Erkennung + Resign-Weg (t_9814f18f) ==")
|
||
var doc := SvmapDocument.create_new("Resign-Test", 512.0, "mittag")
|
||
_check(doc.has("format_version"), "Test-Dokument erzeugt")
|
||
|
||
# 1) Normaler Save + Load.
|
||
var save := SvmapIO.save_to_file("user://test_resign.svmap", doc)
|
||
_check(save["ok"], "Baseline-Map gespeichert (v2)")
|
||
|
||
# 2) Prüfsumme manipulieren (64 Nullen) → V13-only-Fehler.
|
||
var text := FileAccess.get_file_as_string("user://test_resign.svmap")
|
||
var parsed: Variant = JSON.parse_string(text)
|
||
var bad: Dictionary = parsed
|
||
bad["checksum"]["value"] = "0".repeat(64)
|
||
var fa := FileAccess.open("user://test_resign.svmap", FileAccess.WRITE)
|
||
fa.store_string(JSON.stringify(bad, " "))
|
||
fa.close()
|
||
var broken := SvmapIO.load_from_file("user://test_resign.svmap")
|
||
_check(not broken["ok"], "manipulierte Prüfsumme → Load schlägt fehl")
|
||
_check(_errors_contain(broken["errors"], "V13"), "Fehler ist V13 (Prüfsumme)")
|
||
_check(SvmapIO.checksum_only_failure(broken["errors"]), "checksum_only_failure erkennt V13-only-Fall")
|
||
|
||
# 3) Kern-defekte Map (Name leer) → NICHT als V13-only erkennbar.
|
||
var core_bad: Dictionary = JSON.parse_string(text)
|
||
core_bad["info"]["name"] = ""
|
||
var fa2 := FileAccess.open("user://test_resign2.svmap", FileAccess.WRITE)
|
||
fa2.store_string(JSON.stringify(core_bad, " "))
|
||
fa2.close()
|
||
var core := SvmapIO.load_from_file("user://test_resign2.svmap")
|
||
_check(not core["ok"], "Kern-defekte Map (Name leer) schlägt fehl")
|
||
_check(not SvmapIO.checksum_only_failure(core["errors"]), "Kern-Fehler ist KEIN V13-only-Fall (harter Abbruch bleibt)")
|
||
|
||
# 4) Resign-Weg: Datei trotz manipulierter Prüfsumme laden.
|
||
var resign := SvmapIO.load_from_file_resign("user://test_resign.svmap")
|
||
_check(resign["ok"], "load_from_file_resign akzeptiert V13-only-Datei")
|
||
_check(str(resign["data"]["checksum"]["schema"]) == "v2", "Resign trägt schema v2")
|
||
|
||
# 5) Resign-Dokument speichern + laden → stabiler v2-Roundtrip.
|
||
var resave := SvmapIO.save_to_file("user://test_resign.svmap", resign["data"])
|
||
_check(resave["ok"], "Resign-Dokument gespeichert")
|
||
var reload := SvmapIO.load_from_file("user://test_resign.svmap")
|
||
_check(reload["ok"], "Resign-Map lädt normal (Roundtrip)")
|
||
_check(str(reload["data"]["checksum"]["schema"]) == "v2", "Datei trägt v2 nach Resave")
|
||
|
||
# 6) Adversarial-Float im Sly-Fall: 15-stelliger Wert überlebt Resign+Save+Load.
|
||
var adv: Dictionary = JSON.parse_string(FileAccess.get_file_as_string("user://test_resign.svmap"))
|
||
if (adv["objects"] as Array).size() > 0:
|
||
adv["objects"][0]["pos"][1] = 0.000457770656900891
|
||
var adv_save := SvmapIO.save_to_file("user://test_resign.svmap", adv)
|
||
_check(adv_save["ok"], "Map mit adversarial Float gespeichert (Quantisierung)")
|
||
var adv_load := SvmapIO.load_from_file("user://test_resign.svmap")
|
||
_check(adv_load["ok"], "Map mit adversarial Float lädt (v2-Hash formatunabhängig)")
|
||
else:
|
||
_check(true, "kein Objekt im Default-Dokument — Float-Check entfällt (v2-Suite deckt adversarial ab)")
|