MCTK介绍
MCTK,是一款使用Java语言在JTLV平台上开发的基于BDD的符号化模型检测工具,目前版本已经迭代至3.0.0。MCTK3支持RTCTL*和RTCDL*规约的验证及反例生成,开源项目见MCTK3。
以下是我在使用MCTK工具进行模型检测过程中遇到的一些问题和自己的一些疑惑,欢迎大家探讨。
注意:此博客内容记录于2022年8月20日,具有时效性,时间往后项目会有更新。
正文内容
1
edu/wis/jtlv/lib/mc/RTCTLs/RTCTLs_ModelCheckAlg.java文件中,NNF(spec)方法体if(op == Operator.NOT)
代码块第1037-1048行,如图1.1所示。
图1.1
elements[] 对 fChild[] 数组的拷贝为浅拷贝,Spec[] elements = new Spec[fChild.length];
赋值操作是将fChild的地址赋给elements,因此对elements数组的操作实际就是在对fChild数组进行操作。个人认为这里直接使用fChild数组构造NNF即可。(此处为个人见解,并不一定对。)
2022年8月29日更新:elements[elements.length-1] = NNF(new SpecExp(Operator.NOT, elements[elements.length-1]));
此条语句是new了一个新的SpecExp对象,因此开辟了一个新的内存,赋值操作将地址传给了elements[elements.length-1]
,并没有改变原来的fChild数组,这里更正一下。
2
同样也是lib/mc/RTCTLs/RTCTLs_ModelCheckAlg.java文件中,NNF(spec)方法体if (op == Operator.B_UNTIL || op == Operator.B_RELEASES)
代码块第971行,如图2.1所示。
图2.1
f U/R a..b g
,当a=b=0时,应该return NNF(child[2])
,即返回g。
3
继续RTCTLs_ModelCheckAlg.java文件中,NNF(spec)方法体if(op == Operator.NOT)
代码块第1105行,如图3.1所示。
图3.1
框选处应为getTrueSpec()
。
4
env/core/spec/InternalOp.java文件中,第55行unaryOp数组,如图4.1所示。
图4.1
unaryOp数组并未包含EE和AA路径量词(截图中为修改后的unaryOp数组)。
以下通过解析公式E f
说明这种情况可能会引发的错误,InitSpec.java文件中mk_somepath()
方法用于创建操作符为E
的公式,该方法会调用InternalSpecExp
类的构造方法,如图4.2所示。
图4.2
进一步跟进该构造方法,最终发现一处断言,见图4.3。
图4.3
以公式E f
为例,el.length
的值为1,op.numOfOperands()
方法在InternalOp.java文件中,如图4.4。
图4.4
可以看到如果AA
和EE
操作符不在unaryOp
数组里时,该方法会返回值-1,由于-1不等于1,故而assert (op.numOfOperands() == el.length)
断言失败。
由于JVM虚拟机默认关闭断言指令,因此运行图形用户界面时不会抛出断言异常,但使用Junit单元测试是会通过-ea命令行参数启用断言,所以会出现断言异常。
5
lib/mc/RTCTLs/RTCTLs_ModelCheckAlg.java文件中,satEE()
方法可能会返回null,导致satAA()
方法体出现空指针异常,图5.1所示。
图5.1
以下通过验证公式E start
解释。
首先E start
取反并转换为否定范式A !start
,操作符为A
因此会调用satAA()
方法,第779行会再一次取反并转换成否定范式,即E start
。接下来会递归调用sat()
方法,根据操作符为E
进入satEE()
方法体,如下图5.2所示:
图5.2
代码运行过程中并未创建任何测试器,故运行至第741行时返回null并回到satAA()
方法。
图5.3
综上,bddEnegC1
的值为null,但实际值应为start=1
。