extends SceneTree ## Suite: Migration veralteter Objekt-IDs beim Laden (test.svmap-Fall, Pilze). ## Ausführen: godot4 --headless --path . --script res://tests/test_migration.gd var failures := 0 var checks := 0 const PFAD := "user://test_migration.svmap" func _init() -> void: _run_tests() if FileAccess.file_exists(PFAD): DirAccess.remove_absolute(ProjectSettings.globalize_path(PFAD)) if failures == 0: print("ALL OK: %d checks" % checks) quit(0) else: print("FAILED: %d/%d checks" % [failures, checks]) quit(1) func _check(cond: bool, label: String) -> void: checks += 1 if cond: print(" ok: %s" % label) else: failures += 1 print(" FAIL: %s" % label) func _run_tests() -> void: var lib: Dictionary = SvmapIO._manifest_or({}) _check(lib.get("objects", {}).has("grass_003"), "Ersatz-Objekt grass_003 steht in der Bibliothek") _check(not lib["objects"].has("pilz_austernseitling"), "Pilze sind aus der Bibliothek verschwunden") # Map mit Pilz (ersetzbar), unbekanntem Objekt (kein Ersatz) und gültigem Objekt var doc := SvmapDocument.create_new("Migration", 256.0, "mittag") doc["objects"] = [ {"id": "barrier_001", "pos": [1.0, 0.0, 1.0], "scale": 1.0, "rot_y_deg": 0.0}, {"id": "pilz_austernseitling", "pos": [5.0, 0.0, 6.0], "scale": 2.0, "rot_y_deg": 33.0, "group": "g1"}, {"id": "pilz_steinpilz", "pos": [7.0, 0.0, 8.0], "scale": 1.0, "rot_y_deg": 0.0}, {"id": "gibt_es_nicht", "pos": [9.0, 0.0, 9.0], "scale": 1.0, "rot_y_deg": 0.0}, ] SvmapIO.sign_map(doc) var f := FileAccess.open(PFAD, FileAccess.WRITE) f.store_string(JSON.stringify(doc)) f.close() var normal := SvmapIO.load_from_file(PFAD) _check(not normal["ok"], "normales Laden scheitert an V7") _check(SvmapIO.migrierbar(normal["errors"]), "Fehler gelten als migrierbar (nur V7)") var r := SvmapIO.load_from_file_migriert(PFAD) _check(r["ok"], "Laden mit Migration klappt: %s" % str(r["errors"])) var objs: Array = r["data"]["objects"] _check(objs.size() == 3, "3 Objekte (1 gültig + 2 Pilze ersetzt, 1 unbekanntes übersprungen) – ist %d" % objs.size()) _check(objs[0]["id"] == "barrier_001", "gültiges Objekt unverändert, Reihenfolge bleibt") _check(objs[1]["id"] == "grass_003" and objs[2]["id"] == "grass_003", "Pilze → grass_003") _check(objs[1]["pos"] == [5.0, 0.0, 6.0] and float(objs[1]["scale"]) == 2.0 and float(objs[1]["rot_y_deg"]) == 33.0 and objs[1]["group"] == "g1", "Position, Skalierung, Drehung und Gruppe bleiben erhalten") var m: Dictionary = r["migration"] _check(int(m["gesamt"]) == 3 and m["entfernt"].get("gibt_es_nicht", 0) == 1 and m["ersetzt"]["pilz_steinpilz"]["anzahl"] == 1, "Bericht zählt Ersetzte und Übersprungene") _check(SvmapMigration.zusammenfassung(m, lib["objects"]).contains("übersprungen"), "Zusammenfassung nennt Übersprungene") _check(SvmapIO.validate_map(r["data"]).is_empty(), "migrierte Map besteht die volle Validierung (inkl. Prüfsumme)") # Roundtrip: speichern → laden ohne Migration var s := SvmapIO.save_to_file(PFAD, r["data"]) _check(s["ok"], "migrierte Map lässt sich speichern") _check(SvmapIO.load_from_file(PFAD)["ok"], "gespeicherte Datei lädt danach normal") # Echter Fall: lokale test.svmap (falls vorhanden) if FileAccess.file_exists("res://test.svmap"): var t := SvmapIO.load_from_file_migriert(ProjectSettings.globalize_path("res://test.svmap")) _check(t["ok"], "test.svmap lädt mit Migration: %s" % str(t["errors"])) _check(int(t["migration"]["gesamt"]) == 6, "6 Pilze ersetzt")