From 8f598dc67d1f3c016a14f2ce1b8b8db3e58cd481 Mon Sep 17 00:00:00 2001 From: scopedvr-dev Date: Mon, 19 Oct 2026 18:23:56 +0000 Subject: [PATCH] Test-Fix (t_03d0f442): test_library-Katalog-Check datengetrieben statt harte 54 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Die harte Erwartung lib.size() == 54 (15 Basis + 39 Natur-Update) brach bei JEDER Kategorie-Karte: schon der A6-Stand hatte 56 (2 Beispiel-Objekte), nach D1-D5 sind es 317. Der Check ist jetzt datengetrieben: - Basis-Bestand bleibt garantiert: lib.size() >= 54 (Merge-Fundament A6) — der Katalog darf nur wachsen, schrumpfen failt weiterhin. - Neu: Registry <-> Thumbnails deckungsgleich (je OID ein 128px-Thumb, keine verwaisten Thumbs) — fängt vergessene/abgebrochene sync_objects-Läufe. - Neu: OID-Vergleich gegen die gemergte Match-Server-Registry (../scopedvr-match-server, Quelle der Wahrheit aus objects.d/*), wenn das Sibling-Repo liegt; ohne Sibling verkürzt sich der Test statt zu failen. - Testgruppe Registry-Fußpunkt: "alle 54 Objekte" -> dynamische Zahl im Titel. Suite grün auf main: 95/95 checks (ist 317). Beweis Drift-Erkennung: eine injizierte Fremd-OID in der MS-Registry failt den neuen Vergleich gezielt. --- tests/test_library.gd | 60 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/tests/test_library.gd b/tests/test_library.gd index 1151d70..0f0df47 100644 --- a/tests/test_library.gd +++ b/tests/test_library.gd @@ -58,12 +58,68 @@ func _load_manifest() -> Dictionary: return parsed if parsed is Dictionary else {} +## Gemergte Registry aus dem Match-Server-Sibling (Quelle der Wahrheit — +## library/objects.json entsteht dort aus den Fragmenten objects.d/*.json, +## tools/sync_objects.sh zieht die Kopie hierher). Leer, wenn das Sibling +## fehlt (CI/Klon ohne Nachbar-Repo) — der Test verkürzt sich dann statt zu failen. +func _match_server_registry() -> Dictionary: + var base := ProjectSettings.globalize_path("res://") + for k in [base + "../scopedvr-match-server", base + "../../scopedvr-match-server"]: + var path: String = k + "/library/objects.json" + if FileAccess.file_exists(path): + var parsed: Variant = JSON.parse_string(FileAccess.get_file_as_string(path)) + return parsed if parsed is Dictionary else {} + return {} + + func _test_manifest_load() -> void: print("Testgruppe: Bibliothek laden (library/objects.json)") var manifest := _load_manifest() _check(not manifest.is_empty(), "Manifest lädt und ist ein Objekt") var lib: Dictionary = manifest.get("objects", {}) - _check(lib.size() == 54, "Katalog hat die 54 Objekte (15 Basis + 39 Natur-Update, ist %d)" % lib.size()) + # Datengetrieben statt harte Zahl: Der Basis-Bestand (54 Objekte aus dem + # Merge-Fundament A6) muss IMMER erhalten bleiben — der Katalog darf nur + # wachsen (A6-Beispiele, D1 Wände, D2 Absperrungen, D3 Gebäude, D4 Props, + # D5 Natur, ...). Eine exakte Zahl hier bricht bei jeder Kategorie-Karte. + _check(lib.size() >= 54, "Katalog enthält mindestens die 54 Basis-Objekte (ist %d)" % lib.size()) + # Registry ↔ Thumbnails deckungsgleich: sync_objects.sh zieht objects.json + # UND rendert je Objekt einen Thumb. Drift (Objekt ohne Thumb oder verwaister + # Thumb) zeigt einen nicht gelaufenen/abgebrochenen Sync. + var fehlen_thumb: Array = [] + var verwaist_thumb: Array = [] + var tdir := DirAccess.open("res://library/thumbs") + if tdir != null: + var thumbs: Dictionary = {} + tdir.list_dir_begin() + var f := tdir.get_next() + while not f.is_empty(): + if f.ends_with(".png"): + thumbs[f.get_basename()] = true + f = tdir.get_next() + tdir.list_dir_end() + for oid in lib.keys(): + if not thumbs.has(str(oid)): + fehlen_thumb.append(str(oid)) + for t in thumbs.keys(): + if not lib.has(t): + verwaist_thumb.append(str(t)) + _check(fehlen_thumb.is_empty() and verwaist_thumb.is_empty(), + "Registry und Thumbnails deckungsgleich (fehlen %d, verwaist %d)" % [fehlen_thumb.size(), verwaist_thumb.size()]) + # Alle OIDs der Match-Server-Fragmente sind in der Editor-Kopie (wenn das + # Sibling-Repo neben dem Editor liegt, wie in tools/sync_objects.sh). + var ms := _match_server_registry() + if not ms.is_empty(): + var ms_ids: Dictionary = ms.get("objects", {}) + var fehlt_editor: Array = [] + var fehlt_ms: Array = [] + for oid in ms_ids.keys(): + if not lib.has(str(oid)): + fehlt_editor.append(str(oid)) + for oid in lib.keys(): + if not ms_ids.has(str(oid)): + fehlt_ms.append(str(oid)) + _check(fehlt_editor.is_empty() and fehlt_ms.is_empty(), + "Editor-Registry deckt alle OIDs des Match-Server-Merges ab (fehlen Editor %d / MS %d)" % [fehlt_editor.size(), fehlt_ms.size()]) var all_ok := true for oid in lib.keys(): var entry: Dictionary = lib[oid] @@ -401,7 +457,7 @@ func _test_placement_foot_convention() -> void: ## Ghost UND Viewport-Bauer nutzen, kommt aus derselben Registry-Kollision ## (MeshShapes.half_height). func _test_mesh_foot_point_registry() -> void: - print("Testgruppe: Registry-Fußpunkt — Mesh-Unterseite == pos (alle 54 Objekte)") + print("Testgruppe: Registry-Fußpunkt — Mesh-Unterseite == pos (alle Katalog-Objekte, ist %d)" % _load_manifest().get("objects", {}).size()) var manifest := _load_manifest() var lib: Dictionary = manifest.get("objects", {}) var bad_primitiv: Array = []