;; ============================================================ ;; test_vfl_schema.lsp - Unittest fuer das Glied-Schema (vf_linienzug.lsp) ;; ;; Prueft die reinen Schema-Helfer OHNE Geometrie/BricsCAD-Bau: ;; - vfl-schema-slice-bauen / vfl-schema-slice-werte (Roundtrip) ;; - vfl-schema-feld-pruefen (Validierung Typ + erlaubte Werte) ;; - die Adapter vfl-gf-bogen-slice-bauen/-werte, vfl-es-slice-bauen/-werte ;; (Kompatibilitaet zum bisherigen flachen Journal-Format) ;; ;; Voraussetzung: VarioFoerderer.lsp (inkl. vf_linienzug.lsp) geladen. ;; ;; Aufruf in BricsCAD: ;; (load (strcat (getenv "DXFMAKRO") "/tests/test_vfl_schema.lsp")) ;; TEST_VFL_SCHEMA ;; ;; Speichert tests/output/vfl_schema_results.json (Konvention test_run_all). ;; ============================================================ (setq *tvs-pass* 0 *tvs-fail* 0 *tvs-fails* '()) ;; Ein Assert: erwartet-Wert gleich ist-Wert (equal). Loggt Pass/Fail. (defun tvs-eq (name erwartet ist) (if (equal erwartet ist) (progn (setq *tvs-pass* (1+ *tvs-pass*)) (princ (strcat "\n [PASS] " name))) (progn (setq *tvs-fail* (1+ *tvs-fail*)) (setq *tvs-fails* (cons name *tvs-fails*)) (princ (strcat "\n [FAIL] " name "\n erwartet: " (vl-princ-to-string erwartet) "\n ist: " (vl-princ-to-string ist)))))) ;; Assert: Ausdruck ist nicht-nil (z.B. ein Fehlertext von der Validierung). (defun tvs-truthy (name ist) (if ist (progn (setq *tvs-pass* (1+ *tvs-pass*)) (princ (strcat "\n [PASS] " name))) (progn (setq *tvs-fail* (1+ *tvs-fail*)) (setq *tvs-fails* (cons name *tvs-fails*)) (princ (strcat "\n [FAIL] " name " (erwartet nicht-nil, war nil)"))))) ;; Assert: Ausdruck ist nil (z.B. kein Validierungsfehler). (defun tvs-nil (name ist) (if (null ist) (progn (setq *tvs-pass* (1+ *tvs-pass*)) (princ (strcat "\n [PASS] " name))) (progn (setq *tvs-fail* (1+ *tvs-fail*)) (setq *tvs-fails* (cons name *tvs-fails*)) (princ (strcat "\n [FAIL] " name " (erwartet nil, war " (vl-princ-to-string ist) ")"))))) (defun vfl-schema:tests ( / slice werte) ;; --- GF-Bogen: bauen erzeugt exakt die bisherige flache Struktur --- ;; STEP("GF-Bogen") STR("1") INT(90) STR("1") (setq slice (vfl-gf-bogen-slice-bauen 90 "1")) (tvs-eq "gf-bogen bauen: struktur" (list (cons "STEP" "GF-Bogen") (cons "STR" "1") (cons "INT" 90) (cons "STR" "1")) slice) ;; --- GF-Bogen: Roundtrip bauen -> lesen ergibt (winkel seite) --- (tvs-eq "gf-bogen roundtrip 60/rechts" (list 60 "2") (vfl-gf-bogen-slice-werte (vfl-gf-bogen-slice-bauen 60 "2"))) (tvs-eq "gf-bogen roundtrip 30/links" (list 30 "1") (vfl-gf-bogen-slice-werte (vfl-gf-bogen-slice-bauen 30 "1"))) ;; --- GF-Bogen: die Seite ist der STR NACH dem INT (nicht der menue-STR) --- ;; Genau der Fall, an dem das alte "nach-int"-Flag haengt. (tvs-eq "gf-bogen lesen: seite = STR nach INT" (list 90 "2") (vfl-gf-bogen-slice-werte (list (cons "STEP" "GF-Bogen") (cons "STR" "1") (cons "INT" 90) (cons "STR" "2")))) ;; --- GF-Bogen: Alt-Journal mit Index (1/2/3) statt Winkel wird auf den ;; Default 90 normiert (harte Umstellung, dokumentiertes Verhalten). --- (tvs-eq "gf-bogen lesen: alt-index -> default 90" (list 90 "1") (vfl-gf-bogen-slice-werte (list (cons "STEP" "GF-Bogen") (cons "STR" "1") (cons "INT" 2) (cons "STR" "1")))) ;; --- ES: bauen/lesen Roundtrip (Winkel als STR "30"/"90") --- (setq slice (vfl-es-slice-bauen "30" "2")) (tvs-eq "es bauen: struktur" (list (cons "STEP" "ES") (cons "STR" "30") (cons "STR" "2")) slice) (tvs-eq "es roundtrip 90/links" (list "90" "1") (vfl-es-slice-werte (vfl-es-slice-bauen "90" "1"))) ;; --- Vario-Kurve: generisch bauen/lesen (winkel INT, seite/variante STR) --- (setq slice (vfl-schema-slice-bauen "Vario-Kurve" (list 60 "2" "1"))) (tvs-eq "vario bauen: struktur" (list (cons "STEP" "Vario-Kurve") (cons "INT" 60) (cons "STR" "2") (cons "STR" "1")) slice) (tvs-eq "vario roundtrip" (list 90 "1" "2") (vfl-schema-slice-werte "Vario-Kurve" (vfl-schema-slice-bauen "Vario-Kurve" (list 90 "1" "2")) (list 90 "1" "1"))) ;; --- Vario-Kurve Edit-Adapter (vfl-vario-slice-bauen/-werte) --- ;; Slice: STEP INT(winkel) STR(seite) STR(variante). Roundtrip inkl. Winkel- ;; Normierung (analog GF-Bogen). (setq slice (vfl-vario-slice-bauen 60 "2" "1")) (tvs-eq "vario-adapter bauen: struktur" (list (cons "STEP" "Vario-Kurve") (cons "INT" 60) (cons "STR" "2") (cons "STR" "1")) slice) (tvs-eq "vario-adapter roundtrip 30/rechts/innen" (list 30 "2" "2") (vfl-vario-slice-werte (vfl-vario-slice-bauen 30 "2" "2"))) ;; Alt-Journal/Fremdwert im Winkel -> Default 90 (Normierung) (tvs-eq "vario-adapter: fremdwinkel -> default 90" (list 90 "1" "2") (vfl-vario-slice-werte (list (cons "STEP" "Vario-Kurve") (cons "INT" 2) (cons "STR" "1") (cons "STR" "2")))) ;; Vario-Kurve ist jetzt im Schema (eigenes STEP-Glied) (tvs-truthy "vario-kurve hat schema (eigenes glied)" (vfl-schema-felder "Vario-Kurve")) ;; --- Vario-Kurve schwanz-erhaltende Splice (Regressionstest) --- ;; Die Vario-Kurve steht MITTEN in der VF-Einheit; nach ihren 3 Werten folgen ;; VF-Antworten in derselben Slice. Beim Editieren duerfen NUR die 3 Vario- ;; Felder ersetzt werden, der Schwanz muss erhalten bleiben (sonst verschiebt ;; sich beim Replay die Kette). alt-slice mit Schwanz STR("2") STR("1"): (setq slice (list (cons "STEP" "Vario-Kurve") (cons "INT" 90) (cons "STR" "1") (cons "STR" "2") (cons "STR" "2") (cons "STR" "1"))) ; <- Schwanz (VF-Antworten) (tvs-eq "vario splice: 3 felder ersetzt, schwanz erhalten" (list (cons "STEP" "Vario-Kurve") (cons "INT" 60) (cons "STR" "2") (cons "STR" "1") (cons "STR" "2") (cons "STR" "1")) ; Schwanz unveraendert (vfl-vario-slice-splicen slice 60 "2" "1")) ;; Reader liest trotz Schwanz korrekt die ersten 3 Felder (Vorbelegung): (tvs-eq "vario werte-lesen ignoriert schwanz" (list 90 "1" "2") (vfl-vario-slice-werte slice)) ;; --- Validierung: gueltige Werte -> kein Fehler --- (tvs-nil "validierung gf-bogen winkel 90 ok" (vfl-schema-feld-pruefen '("winkel" "INT" (30 60 90)) 90)) (tvs-nil "validierung seite '2' ok" (vfl-schema-feld-pruefen '("seite" "STR" ("1" "2")) "2")) ;; --- Validierung: falscher Typ -> Fehlertext (nicht-nil) --- ;; Genau der Bug: ein STRING "30" in einem INT-Winkelfeld. (tvs-truthy "validierung winkel als STRING -> fehler" (vfl-schema-feld-pruefen '("winkel" "INT" (30 60 90)) "30")) ;; --- Validierung: Winkel ausserhalb der erlaubten Werte -> Fehlertext --- (tvs-truthy "validierung winkel 45 nicht erlaubt -> fehler" (vfl-schema-feld-pruefen '("winkel" "INT" (30 60 90)) 45)) ;; --- Validierung: Seite ausserhalb ("3") -> Fehlertext --- (tvs-truthy "validierung seite '3' nicht erlaubt -> fehler" (vfl-schema-feld-pruefen '("seite" "STR" ("1" "2")) "3")) ;; --- Schema-Zugriff: unbekanntes Glied (VF-Einheit) -> keine Felder --- (tvs-nil "vf-einheit hat kein schema" (vfl-schema-felder "Horizontal-VF")) ;; --- AS ist bewusst kein STEP-Glied -> slice-bauen liefert nil --- (tvs-nil "as slice-bauen ist nil (praeambel-sonderfall)" (vfl-schema-slice-bauen "AS" (list "90" "1"))) ;; --- VF-Einheit: Sub-Step-Benennung nach Wert-Muster --- ;; 1. STR einer VF-Einheit = fuehrende Menue-Wahl "4" (Horizontal-VF) (tvs-eq "vf-substep: 1. STR = menue" "menue" (car (vfl-vf-substep-benennen (cons "STR" "4") 0))) (tvs-nil "vf-substep: menue '4' ist gueltig" (cdr (vfl-vf-substep-benennen (cons "STR" "4") 0))) ;; menue-Wert ausserhalb ("2") -> Fehlertext (tvs-truthy "vf-substep: menue '2' ungueltig -> fehler" (cdr (vfl-vf-substep-benennen (cons "STR" "2") 0))) ;; spaetere STR "3" = 1-3-Menue-Schritt (ist-ende/naechstes-vf) (tvs-eq "vf-substep: spaetere STR '3' = menue3" "ist-ende/naechstes-vf" (car (vfl-vf-substep-benennen (cons "STR" "3") 1))) ;; spaetere STR "2" = ja/nein bzw. 1-3 (1/2) (tvs-eq "vf-substep: spaetere STR '2' = wahl(1/2)" "wahl(1/2)" (car (vfl-vf-substep-benennen (cons "STR" "2") 1))) ;; DL/REAL = Laenge (tvs-eq "vf-substep: DL = laenge" "laenge" (car (vfl-vf-substep-benennen (cons "DL" 4566.7) 0))) ;; eingebettete Vario-Kurve: INT-Winkel gueltig (tvs-nil "vf-substep: eingebetteter vario-winkel 60 gueltig" (cdr (vfl-vf-substep-benennen (cons "INT" 60) 1))) (tvs-truthy "vf-substep: eingebetteter vario-winkel 45 ungueltig" (cdr (vfl-vf-substep-benennen (cons "INT" 45) 1))) (princ)) ;; Ergebnis-Export (Konvention :export-results fuer test_run_all.lsp) (defun vfl_schema:export-results (out-dir / f pfad) (setq pfad (strcat out-dir "/vfl_schema_results.json")) (setq f (open pfad "w")) (if f (progn (write-line "{" f) (write-line (strcat " \"pass\": " (itoa *tvs-pass*) ",") f) (write-line (strcat " \"fail\": " (itoa *tvs-fail*) ",") f) (write-line (strcat " \"status\": \"" (if (= *tvs-fail* 0) "OK" "FEHLER") "\"") f) (write-line "}" f) (close f) (princ (strcat "\n Ergebnis: " pfad)))) (princ)) (defun c:TEST_VFL_SCHEMA ( / ) (setq *tvs-pass* 0 *tvs-fail* 0 *tvs-fails* '()) (princ "\n================================================================") (princ "\n TEST_VFL_SCHEMA - Glied-Schema (vf_linienzug.lsp)") (princ "\n================================================================") (vfl-schema:tests) (princ "\n\n----------------------------------------------------------------") (princ (strcat "\n Ergebnis: " (itoa *tvs-pass*) " PASS, " (itoa *tvs-fail*) " FAIL")) (if (> *tvs-fail* 0) (progn (princ "\n Fehlgeschlagen:") (foreach n (reverse *tvs-fails*) (princ (strcat "\n - " n))))) (princ "\n================================================================") (princ)) (princ "\nTEST_VFL_SCHEMA geladen. Aufruf: TEST_VFL_SCHEMA") (princ)