测试覆盖率

ForgeIEC通过一套全面的自动化测试进行保护。 每次提交在合并前都会通过117项单元测试进行验证, 这些测试覆盖了完整的IEC 61131-3 Structured Text语言规范、 所有标准功能块和多任务系统。

测试套件概览

套件测试数验证内容
FStCompilerTest101完整的ST语言规范
FStLibraryTest8全部132个标准块(FB + FC)
FCodeGeneratorThreadingTest8多任务调度 + 无锁同步
总计1170个错误

1. ST语言规范(FStCompilerTest)

101项测试验证每个受支持的IEC 61131-3 Structured Text语言结构。 每项测试通过FStCompiler编译一个ST片段,并验证生成的C++代码。

1.1 赋值

测试ST代码验证内容
assignSimplea := 42;简单赋值
assignExpressiona := b + 1;表达式赋值
assignExternalExtVar := 10;VAR_EXTERNAL访问
assignGvlQualifiedGVL.ExtVar := 5;限定GVL路径

1.2 算术运算符

测试ST代码C运算符
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;括号

1.3 比较运算符

测试ST代码C运算符
compareEqualflag := a = b;==
compareNotEqualflag := a <> b;!=
compareLessflag := a < b;<
compareGreaterflag := a > b;>
compareLessEqualflag := a <= b;<=
compareGreaterEqualflag := a >= b;>=

1.4 布尔运算符

测试ST代码C运算符
boolAndflag := flag AND flag;&&
boolOrflag := flag OR flag;||
boolXorflag := flag XOR flag;^
boolNotflag := NOT flag;!

1.5 字面量

测试ST代码验证内容
literalIntegera := 12345;整数
literalRealc := 3.14;浮点数
literalBoolTrueflag := TRUE;布尔值
literalBoolFalseflag := FALSE;布尔值
literalStringtext := 'hello';字符串
literalTimecounter := T#500ms;时间常量

1.6 控制结构

IF / ELSIF / ELSE / END_IF

测试验证内容
ifSimple简单条件
ifElseIf-Else分支
ifElsifELSIF多重分支
ifNested嵌套IF块

FOR / WHILE / REPEAT

测试验证内容
forSimpleFOR idx := 0 TO 10 DO
forWithBy带BY步长的FOR
whileLoopWHILE循环
repeatUntilREPEAT/UNTIL循环

CASE

测试验证内容
caseStatement带多个标签的CASE/OF + switch/case/break

RETURN / EXIT

测试验证内容
returnStatementRETURN → goto __end
exitStatementFOR中的EXIT → break

1.7 功能块(FB调用)

测试验证内容
fbCallWithInputsMyTon(IN := flag, PT := T#500ms);
fbCallWithOutputAssignMyTimer(IN := flag, Q => flag); — OUT =>赋值

1.8 数组访问

测试验证内容
arrayReadSubscripta := arr[3];
arrayWriteSubscriptarr[5] := 42;
arrayComputedIndexa := arr[idx + 1];
arrayInForLoopFOR循环中的数组访问

1.9 类型转换

编译器识别XXX_TO_YYY模式并生成符合IEC标准的 C风格强制转换((TYPE)value)。

测试ST代码生成结果
typeConvIntToRealINT_TO_REAL(a)(REAL)a
convRealToIntREAL_TO_INT(c)(INT)c
convBoolToIntBOOL_TO_INT(flag)(INT)flag
convIntToBoolINT_TO_BOOL(a)(BOOL)a
convDintToRealDINT_TO_REAL(counter)(REAL)counter
convIntToDintINT_TO_DINT(a)(DINT)a

1.10 结构体成员访问

测试验证内容
structMemberAccesspos.x := 42;data__->pos.value.x

1.11 跨任务变量(多任务)

测试验证内容
crossPrimitiveGet__GET_EXTERNAL_ATOMIC 用于无锁读取
crossPrimitiveSet__SET_EXTERNAL_ATOMIC 用于无锁写入
crossStructuredGet__snap_ 线程本地快照访问
crossStructuredMemberAccess__snap_Struct.field 访问

1.12 标准功能块

每个IEC标准FB作为实例创建并调用:

测试FB类型验证内容
fbTonTON接通延时
fbTofTOF断开延时
fbTpTP脉冲定时器
fbCtuCTU递增计数器
fbCtdCTD递减计数器
fbRtrigR_TRIG上升沿
fbFtrigF_TRIG下降沿
fbRsRS复位优先
fbSrSR置位优先

1.13 标准函数

类别测试数函数
数学12ABS, SQRT, SIN, COS, TAN, ASIN, ACOS, ATAN, EXP, LN, LOG, TRUNC
选择4SEL, LIMIT, MIN, MAX
字符串6LEN, LEFT, RIGHT, MID, CONCAT, FIND
位移4SHL, SHR, ROL, ROR
类型转换6INT_TO_REAL, REAL_TO_INT, BOOL_TO_INT, …

1.14 边界情况

测试验证内容
complexNestedExpression嵌套表达式
multipleStatementsOnSeparateLines多行程序
emptyBody空POU体
commentOnlyBody仅注释
caseInsensitiveKeywordsIF/if/If
caseInsensitiveVariables大小写不敏感

2. 标准库(FStLibraryTest)

8项数据驱动测试自动验证标准库(standard_library.sql)中的 全部132个块

2.1 功能块(13个FB)

测试验证内容
fbSingleInstance每个FB可单独实例化和调用
fbDoubleInstance同一FB类型的两个实例同时使用
fbOutputRead调用后所有输出可读

覆盖的FB: SR, RS, R_TRIG, F_TRIG, CTU, CTD, CTUD, TON, TOF, TP, RTC, SEMA, RampGen

2.2 函数(119个FC)

测试验证内容
fcCall每个FC可使用正确参数调用(104个已测试)
fcInExpressionFC返回值可在表达式中使用

覆盖的类别:

  • 算术: ADD, SUB, MUL, DIV, MOD, EXPT, ABS
  • 比较: EQ, NE, LT, GT, LE, GE
  • 三角函数: SIN, COS, TAN, ASIN, ACOS, ATAN, ATAN2
  • 对数: EXP, LN, LOG, SQRT
  • 选择: SEL, MUX, LIMIT, MIN, MAX, MOVE, CLAMP
  • 字符串: LEN, LEFT, RIGHT, MID, CONCAT, INSERT, DELETE, REPLACE, FIND
  • 位移: SHL, SHR, ROL, ROR
  • 类型转换: 60+转换函数(BOOL_TO_INT, INT_TO_REAL, …)
  • ForgeIEC扩展: LERP, MAP_RANGE, HYPOT, DEG, RAD, IK_2Link, CABS, CADD, CMUL, CSUB, CARG, CCONJ, CPOLAR, CRECT

3. 多任务(FCodeGeneratorThreadingTest)

8项测试按照设计规范(MT-spec, docs/design/multi-task-scheduler.md) 验证完整的多任务调度系统。

测试验证内容
singleProgramDefaultTask无显式任务的单个PROGRAM → DefaultTask合成,无线程
twoProgramsTwoTasks两个任务 → RESOURCE0_start__、Legacy-Shim config_run__、两个任务线程
crossPrimitiveAtomicEmission共享INT变量 → std::atomic<> Location存储,体内__GET_EXTERNAL_ATOMIC
crossStructuredDoubleBuffer共享STRUCT → __DBUF_[2] + thread_local __snap_ + 双缓冲区拷入/拷出
localVarNoSync仅在一个任务中的变量 → 普通__SET_EXTERNAL,无Atomic
conflictTwoWriters两个任务写入同一变量 → 编译警告
singleProgramDefaultTask向后兼容:现有项目无需修改即可运行

多任务架构

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)
    |                               |
    | [在bufferLock下]              | [lock-free]

同步机制:

  • CrossPrimitive(BOOL, INT, REAL, …):Location变量上的std::atomic<T>,体代码中的__GET_EXTERNAL_ATOMIC / __SET_EXTERNAL_ATOMIC
  • CrossStructured(STRUCT, ARRAY, STRING):带原子写入索引的双缓冲区__DBUF_[2],用于Set一致性的thread_local快照__snap_

质量保证

自动化验证

测试在每次构建时通过-DBUILD_TESTS=ON运行。 已准备好CI管道(Forgejo Actions)集成。

数据驱动测试

库测试(FStLibraryTest)直接从standard_library.sql读取块定义。 添加新块时会自动进行测试——无需手动创建测试用例。

完整性

测试套件覆盖了ForgeIEC所支持的完整IEC 61131-3 Structured Text 语言规范:

  • 所有运算符(算术、比较、布尔、位移)
  • 所有控制结构(IF, FOR, WHILE, REPEAT, CASE)
  • 所有字面量类型(Integer, Real, Bool, String, Time)
  • 所有标准FB和FC(132个块)
  • 数组和结构体访问
  • GVL限定变量
  • 跨任务同步(Atomics + 双缓冲区)
  • 类型转换(C强制转换生成)