Testabdeckung

ForgeIEC wird durch eine umfassende automatisierte Test-Suite abgesichert. Die CI führt 62 Testprogramme aus (CTest-Einträge, gezählt am 22.10.2026 in tests/CMakeLists.txt); sie decken den Structured-Text- Sprachvorrat, die Standard-Funktionsbausteine und das Multi-Task-Threading-System ab. Die drei wichtigsten Suiten:

Test-Suiten im Überblick

SuiteTestsPrüft
FStCompilerTest120ST-Sprachvorrat
FStLibraryTest7Standard-Bausteine (FBs + FCs)
FCodeGeneratorThreadingTest8Multi-Task-Scheduling + Lock-free Sync

1. ST-Sprachvorrat (FStCompilerTest)

Die Tests prüfen jeden unterstützten IEC 61131-3 Structured Text Sprachkonstrukt. Jeder Test kompiliert ein ST-Fragment durch den FStCompiler und verifiziert den generierten C++-Code.

1.1 Zuweisungen

TestST-CodePrüft
assignSimplea := 42;Einfache Zuweisung
assignExpressiona := b + 1;Ausdruck-Zuweisung
assignExternalExtVar := 10;VAR_EXTERNAL Zugriff
assignGvlQualifiedGVL.ExtVar := 5;Qualifizierter GVL-Pfad

1.2 Arithmetische Operatoren

TestST-CodeC-Operator
arithmeticAdda := b + 1;+
arithmeticSuba := b - 1;-
arithmeticMula := b * 2;*
arithmeticDiva := b / 2;/
arithmeticModa := b MOD 3;%
arithmeticPowerc := x ** 2.0;EXPT()
arithmeticNegatea := -b;-(...)
arithmeticParenthesesa := (b + 1) * 2;Klammerung

1.3 Vergleichsoperatoren

TestST-CodeC-Operator
compareEqualflag := a = b;==
compareNotEqualflag := a <> b;!=
compareLessflag := a < b;<
compareGreaterflag := a > b;>
compareLessEqualflag := a <= b;<=
compareGreaterEqualflag := a >= b;>=

1.4 Boolesche Operatoren

TestST-CodeC-Operator
boolAndflag := flag AND flag;&&
boolOrflag := flag OR flag;||
boolXorflag := flag XOR flag;^
boolNotflag := NOT flag;!

1.5 Literale

TestST-CodePrüft
literalIntegera := 12345;Ganzzahl
literalRealc := 3.14;Fließkomma
literalBoolTrueflag := TRUE;Boolescher Wert
literalBoolFalseflag := FALSE;Boolescher Wert
literalStringtext := 'hello';Zeichenkette
literalTimecounter := T#500ms;Zeitkonstante

1.6 Kontrollstrukturen

IF / ELSIF / ELSE / END_IF

TestPrüft
ifSimpleEinfache Bedingung
ifElseIf-Else-Verzweigung
ifElsifMehrfachverzweigung mit ELSIF
ifNestedVerschachtelte IF-Blöcke

FOR / WHILE / REPEAT

TestPrüft
forSimpleFOR idx := 0 TO 10 DO
forWithByFOR mit BY-Schrittweite
whileLoopWHILE-Schleife
repeatUntilREPEAT/UNTIL-Schleife

CASE

TestPrüft
caseStatementCASE/OF mit mehreren Labels + switch/case/break

RETURN / EXIT

TestPrüft
returnStatementRETURN → goto __end
exitStatementEXIT innerhalb FOR → break

1.7 Funktionsbausteine (FB-Aufrufe)

TestPrüft
fbCallWithInputsMyTon(IN := flag, PT := T#500ms);
fbCallWithOutputAssignMyTimer(IN := flag, Q => flag); — OUT => Zuweisung

1.8 Array-Zugriffe

TestPrüft
arrayReadSubscripta := arr[3];
arrayWriteSubscriptarr[5] := 42;
arrayComputedIndexa := arr[idx + 1];
arrayInForLoopArray-Zugriff in FOR-Schleife

2. Standard-Bibliothek (FStLibraryTest)

Datengetriebene Tests prüfen die Blöcke aus der Standard-Bibliothek (standard_library.sql) automatisch.

2.1 Funktionsbausteine (13 FBs)

TestPrüft
fbSingleInstanceJeder FB einzeln instanziierbar und aufrufbar
fbDoubleInstanceZwei Instanzen desselben FB-Typs gleichzeitig
fbOutputReadAlle Ausgänge nach dem Aufruf lesbar

Abgedeckte FBs: SR, RS, R_TRIG, F_TRIG, CTU, CTD, CTUD, TON, TOF, TP, RTC, SEMA, RampGen

2.2 Funktionen (119 FCs)

TestPrüft
fcCallJede FC mit korrekten Parametern aufrufbar (104 getestet)
fcInExpressionFC-Rückgabewert in Ausdrücken verwendbar

Abgedeckte Kategorien:

  • Arithmetik: ADD, SUB, MUL, DIV, MOD, EXPT, ABS
  • Vergleich: EQ, NE, LT, GT, LE, GE
  • Trigonometrie: SIN, COS, TAN, ASIN, ACOS, ATAN, ATAN2
  • Logarithmus: EXP, LN, LOG, SQRT
  • Selektion: SEL, MUX, LIMIT, MIN, MAX, MOVE, CLAMP
  • String: LEN, LEFT, RIGHT, MID, CONCAT, INSERT, DELETE, REPLACE, FIND
  • Bitshift: SHL, SHR, ROL, ROR
  • Typkonvertierung: 60+ Konvertierungsfunktionen (BOOL_TO_INT, INT_TO_REAL, …)
  • ForgeIEC-Erweiterungen: LERP, MAP_RANGE, HYPOT, DEG, RAD, IK_2Link, CABS, CADD, CMUL, CSUB, CARG, CCONJ, CPOLAR, CRECT

3. Multi-Task-Threading (FCodeGeneratorThreadingTest)

8 Tests prüfen das vollständige Multi-Task-Scheduling-System gemäß der Design-Spezifikation (MT-spec, docs/design/multi-task-scheduler.md).

TestPrüft
singleProgramDefaultTaskEin PROGRAM ohne explizite Task → DefaultTask-Synthese, kein Threading
twoProgramsTwoTasksZwei Tasks → RESOURCE0_start__, Legacy-Shim config_run__, beide Task-Threads
crossPrimitiveAtomicEmissionGeteilte INT-Variable → std::atomic<> Location-Storage, __GET_EXTERNAL_ATOMIC im Body
crossStructuredDoubleBufferGeteilter STRUCT → __DBUF_[2] + thread_local __snap_ + Double-Buffer copy-in/out
localVarNoSyncVariable nur in einem Task → normales __SET_EXTERNAL, kein Atomic
conflictTwoWritersZwei Tasks schreiben dieselbe Variable → Compile-Warnung
singleProgramDefaultTaskBackward-Kompatibilität: bestehende Projekte laufen unverändert

Multi-Task-Architektur

Primary Task (Task 0)          Secondary Tasks (1..N)
    |                               |
    | config_run__()                | RESOURCE0_task_thread__()
    |   ├─ sync_in                  |   ├─ dbuf_rd (copy-in)
    |   ├─ TASK0_body__()           |   ├─ TASKn_body__()
    |   └─ sync_out                 |   └─ dbuf_wr (copy-out)
    |                               |
    | [unter bufferLock]            | [lock-free]

Sync-Mechanismen:

  • CrossPrimitive (BOOL, INT, REAL, …): std::atomic<T> auf der Location-Variable, __GET_EXTERNAL_ATOMIC / __SET_EXTERNAL_ATOMIC im Body-Code
  • CrossStructured (STRUCT, ARRAY, STRING): Double-Buffer __DBUF_[2] mit atomarem Write-Index, thread_local Snapshots __snap_ für Set-Konsistenz