一种基于多目标遗传算法的求解器性能缺陷检测方法

文档序号:26587533发布日期:2021-09-10 19:48阅读:114来源:国知局
一种基于多目标遗传算法的求解器性能缺陷检测方法

1.本发明属于软件测试领域,涉及一种用于自动生成检测求解器性能缺陷的测试用例的技术,具体为一种基于多目标遗传算法的求解器性能缺陷检测方法。


背景技术:

2.smt(the satisfiability modulo theories)是可满足性模理论是一个决策问题,用于解决一阶逻辑公式的可满足性。求解器是旨在解决多种理论约束问题的软件工具。它已经应用到各个领域,包括软件验证和程序测试。但是求解器的错误可能会导致应用程序崩溃,甚至更糟。例如在使用求解器的符号执行中,如果求解器存在性能缺陷,就无法得到正确的分析结果。求解器的性能缺陷是指对于一个给定的输入,求解器无法在规定的时间内完成判定。
3.现有的论文和发明专利对求解器的性能问题关注较少。大多数的发明专利都集中在如何使用求解器解决具体领域的问题。例如一种用于火箭在线轨迹规划的求解器设计方法(专利申请号:cn202011262143.1),此专利提出了一种用于火箭轨迹规划问题的求解器设计方法,能够满足火箭在线轨迹规划问题对求解实时性的需求。但是如果求解器本身存在性能缺陷,就无法保证求解速度。专利一种堆芯数值求解器易扩展软件系统、调用方法及终端(专利申请号:cn202011262143.1)将求解器应用到了终端接口上,便于集成新的数值求解算法和派生满足不同需求的数值求解接口。这些发明专利关注如何使用求解器解决实际问题,但是对与求解器本身的测试关注并不多。2018d blotsky提出了使用遗传算法来自动生成测试用例,检测求解器bug的方法。但是此方法使用随机的搜索策略,以求解器运行时间作为优化目标,无法保证算法的收敛和结果的有效性。存在着算法运行时间长,发现性能缺陷少的问题,并无法保证可以有效的发现求解器的性能问题。
4.综上所述,目前的求解器的性能测试存在以下两方面问题:一是自动生成测试用例时引导信息不足,所以会导致无法找到有效的超时用例用于检测求解器的性能缺陷,就无法有效的检测到求解器潜在的性能错误;二是在搜索过程中缺乏多样性评估,会导致生成结果集中的测试用例重复性较高,无法有效的覆盖测试范围,保证求解器的正确性。


技术实现要素:

5.为解决上述问题,本发明的目的在于提供一种自动生成可以触发求解器性能缺陷的测试用例的方法。本发明通过生成触发求解器性能缺陷的测试用例,有利于检测求解器中潜在的性能缺陷,帮助开发人员测试求解器的更新版本,保证求解器的高可用性。
6.本发明的技术方案:
7.一种基于多目标遗传算法的求解器性能缺陷检测方法,具体步骤如下:
8.步骤1:插桩编译目标求解器
9.具体为:由于在算法运行中需要计算测试用例的代码语句覆盖率,所以需要使用代码覆盖率检测工具对目标求解器进行插桩编译;代码覆盖率检测工具可以生成程序中每
个语句执行的精确计数;插桩编译并不会影响目标求解器的正常运行,只是会在运行过后生成包含语句执行次数信息的文件,用在步骤7中统计测试用例的代码语句覆盖率。
10.步骤2:随机生成种子测试文件集,构成初代种群
11.具体为:随机生成符合smt语法规则的测试用例文件,测试用例文件构成初代种群,即种群中的每个个体都是一个测试文件;种群的大小则代表种群中共包含测试文件的数目。
12.步骤3:通过二元锦标赛选择的方法对初代种群中的种子测试文件进行筛选
13.具体为:使用二元锦标赛选择方法筛选出初代种群中表现优良的测试文件;二元锦标赛的方法是每次从种群中取出两个测试文件,初代的筛选会选取其中使得目标求解器运行时间更长的一个作为表现优良的测试文件。
14.步骤4:种群内优良测试文件进行交叉变异,生成子代种群
15.具体为:选择出优良测试文件后,通过交叉算子和变异算子生成新的测试文件构成子代种群;每次从表现优良测试文件中选取出待操作测试文件,然后通过交叉率和变异率判断该测试文件该进行哪种操作生成新的测试文件,操作不断地进行,直到新的测试文件数目到达规定的种群数目。
16.交叉算子选取两个测试文件交换彼此的断言语句,交叉算子为:为了确保足够的交叉量,选取两个测试文件中断言语句一部分进行交换;如果父母测试文件的断言数量没到到达交换的数量,则交换其中的一条断言语句,即要保证每个测试用例最少有一条断言语句。
17.变异算子是针对单个测试文件操作,变异算子包含:新建变量、删除变量、添加断言语句、删除断言语句、替换断言语句中的字符串和数字、替换断言语句中的函数以及替换类型相同的节点。
18.步骤5:判断算法是否收敛或者到达算法最大迭代次数
19.具体为:判断是否到达算法的最大迭代次数或者算法是否收敛,如果没有则跳转到步骤6,进行算法的迭代;如果已经到达了最大的迭代次数或者算法以及收敛,则跳转到步骤11;算法收敛是指种群的平均适应度在一定的代数内已经没有改变。
20.步骤6:合并父代中的优良测试文件和子代种群的测试文件,产生新的种群
21.具体为:将父代中的优良测试文件和子代种群中的测试文件合并成为新的测试文件集合,即新的种群,进行下一次迭代操作。
22.步骤7:对种群中的测试文件进行适应度评估,分别计算求解器运行时间差、代码覆盖率和测试用例的复杂度
23.具体为:对种群中的每个测试文件进行适应度函数评估,算法中使用三个优化目标指标:目标求解器与基准求解器的运行时间差、目标求解器的代码覆盖率和测试用例的复杂度;第一个优化目标是目标求解器与基准求解器的运行时间差,在指定的超时时间下,使用目标求解器和基准求解器分别运行测试用例,统计两者的用时;使用目标求解器与基准求解器的运行时间差作为第一个适应度得分,在这过程中会生成代码覆盖信息文件和动态跟踪文件;第二个优化目标是目标求解器的代码语句覆盖率,通过代码覆盖信息文件中包含的代码语句执行信息,计算该测试用例运行时目标求解器的代码语句覆盖率(即统计该测试用例执行时覆盖到的代码语句数目和目标求解器总代码语句数的比例)作为第二个
适应度得分;第三个优化目标是为了防止测试用例过度膨胀,通过最小化计算测试用例的复杂度,来使得测试用例的保持一个较小的体积;测试用例的复杂度受到测试用例中断言语句的语句数目和语句内节点的嵌套深度影响,具体的计算方法使用加权分数,处在第n层的节点积n分,遍历每个语句中的所有节点计算加权分数和作为第三个适应度;通过本步骤的操作,每个测试用例都会获得一个三元元组作为适应度得分,参加步骤8的排序。
24.步骤8:对种群中的测试用例进行非支配的帕累托排序,并计算测试用例间的拥挤距离
25.具体为:进行非支配帕累托排序:首先从种群中选取出所有的非支配的测试用例集合作为一个帕累托前沿面;然后将这些测试用例从种群中剔除,再次选取出非支配的测试用例组成新的帕累托前沿面,重复该操作直到所有的测试用例都被加入到帕累托前沿面上;再使用步骤7中每个测试用例在目标求解器运行时生成的动态追踪文件计算测试用例间的拥挤距离,用于步骤9中的选择操作。
26.步骤9:选择种群中表现优良测试用例
27.具体为:使用基于支配的二元锦标赛选择筛选优良的测试用例;经过非支配帕累托排序后,每个测试用例具有两个属性:非支配排序和拥挤距离;当测试用例i和测试用例j进行比较时遵守如下规则:测试用例i的非支配排序优于测试用例j,测试用例i胜出;测试用例i与测试用例j的非支配排序相同,但是测试用例i的拥挤距离大于测试用例j,测试用例i胜出;重复选择操作,直到表现优良的测试用例的数目达到指定的种群大小,构成新的种群。
28.步骤10:对表现优良测试用例进行交叉变异,产生新的子种群
29.具体为:该步骤与步骤4操作相同,得到新的子种群。
30.步骤11:对生成的测试文件进行验证,筛选出触发性能缺陷的测试用例
31.具体为:在足够长的超时时间下让目标求解器重新执行种群中的测试文件;如果测试文件依旧无法被求解,那么将其加入到最终的结果集中;结果集中的测试用例会触发求解器的性能缺陷,算法结束。
32.本发明的有益效果:本发明方法可以通过自动生成测试用例检测到求解器潜在的性能缺陷。通过使用多目标搜索算法,最大化目标求解器与基准求解器的运行时间差、目标求解器的代码覆盖率来增加搜索过程中的引导信息,缩小发现触发性能缺陷的测试文件所需的时间;通过最小化测试用例的复杂度,防止测试用例的体积过度膨胀。同时使用动态追踪文件来计算测试用例间的相似性,保证生成结果集的多样性,使得算法可以寻找到更多的潜在的性能缺陷。本方法适用于求解器开发的每个版本,可以帮助开发人员发现求解器开发过程中的性能缺陷,有效的减少由于求解器自身性能缺陷导致在使用过程中出现的不可遇见的错误。
附图说明
33.图1是本发明的一种基于多目标遗传算法的求解器性能缺陷检测方法的工作流程示意图。
具体实施方式
34.以下结合附图、技术方案以及实例对本发明方法进行详细说明。
35.本实施例中,本发明的方法部署在一台linux服务器上,服务器具体配置如表1所示。本实施例以z3str3作为目标求解器,cvc4作为基准求解器,种群大小为40,交叉率0.75,变异率0.25,最大迭代代数为60代。本方法由种子测试文件生成模块、适应度评估模块、测试文件交叉变异模块、非支配帕累托排序模块、测试用例拥挤度计算模块等模块构成。
36.表1linux服务器配置信息表
37.处理器型号内存操作系统intelcorei9

1090032gbubuntu 18.04.01
38.如图1所示,本发明的种基于多目标遗传算法的求解器性能缺陷检测方法按如下流程进行。插桩编译目标求解器;随机生成初始的种子测试文件集,构建初始种群;对初始种群进行筛选,经过交叉变异生成子种群;合并父代表现优良的测试用例和子种群中的测试用例,对新种群进行适应度评估;对种群中的测试用例进行非支配的帕累托排序,并计算拥挤距离;选择优良的测试用例进行交叉变异生成新种群;验证最终种群中的测试文件,输出可以触发目标求解器性能缺陷的测试文件。
39.本实施例步骤描述时以z3str3作为目标求解器为例,具体步骤可以其他求解器进行调整。具体步骤如下:
40.步骤1:插桩编译目标求解器
41.具体为:使用命令ldflags+='

fprofile

arcs'cflags+='

fprofile

arcs

ftest

coverage'cxxflags+='

fprofile

arcs

ftest

cover age'cppflags+='

fprofile

arcs

ftest

coverage'python3 scripts/mk_make.py对z3str3进行插桩编译,随后z3str3运行时会生成包含代码语句运行次数的“.gcda”文件。
42.步骤2:随机生成种子测试文件集,构成初代种群
43.具体为:使用stringfuzz中的语法生成器生成随机的测试文件,将其封装为instance类,其中包括四个部分:setlogic,declare,assert和checksat。setlogic部分指定了测试用例使用的语法为字符串理论;declare部分声明了可能使用到的变量及其类型;assert部分使用一个列表存储了抽象语法树,每一个语法树都是一条断言语句。checksat部分是测试用例的固定语法,让求解器检查测试用例的满足性。初代种群就是一个集合,其中包含80个instance对象实例。
44.步骤3:通过二元锦标赛选择的方法对初代种群中的种子测试文件进行筛选
45.具体为:从种群中两两挑选出instance对象实例,将表现良好的instance对象实例放入到优良instance对象实例集合中,表现不好的instance对象实例重新放回种群中。重复该操作,直至得到40个优良instance对象实例,构成新的种群。
46.步骤4:种群内优良测试文件进行交叉变异,生成子代种群
47.具体为:从优良测试用例中选择出两个测试用例,然后生成一个0到1之间的随机数,如果生成的随机小于0.25,那么使用交叉算子对这两个测试用例进行交叉操作,得到一个新的子测试用例;如果生成的随机数在0.25到1之间,那么使用变异算子对这两个测试用例分别进行变异操作,得到两个新的子测试用例;将新的子测试用例加入到子种群中,重复
这一操作直到子种群的大小达到40。
48.步骤5:判断算法是否收敛或者到达算法最大迭代次数
49.具体为:随后的每次迭代中都会计算平均适应度,如果连续10代种群的平均适应度已经没有发生改变,那么就认为算法已经收敛;如果不满足收敛条件,但是已经运行到达60代,也判断结束迭代。随后回跳转到步骤11。如果判定失败就跳转到步骤6。
50.步骤6:合并父代中的优良测试文件和子代种群的测试文件,产生新的种群
51.具体为:将父代中表现优良的测试用例集合和新产生的子代种群合并,生成新的种群,参加步骤7的适应度评估。
52.步骤7:对种群中的测试文件进行适应度评估,分别计算求解器运行时间差、代码覆盖率和测试用例的复杂度
53.具体为:顺序的从新种群中顺序取出每个测试用例,将其转为可以被z3str3和cvc4识别的测试文件,对其进行适应度评估。首先在5s的超时时间下使用z3str3和cvc4分别运行该测试文件,得到两个运行时间。使用运行时间差作为第一个适应度得分。在这过程中会生成包含代码覆盖信息的“.gcda”文件,通过python脚本遍历所有的“.gcda”文件。统计代码语句运行的次数来就计算该测试用例的代码语句覆盖率,并以此作为第二个适应度得分。最后,计算测试文件的复杂度。即对每个抽象语法树中的节点进行统计,第一层的节点就积一分,第n层的节点积n分。随后对所有节点得分进行求和运算,最终的结果作为第三个适应度得分。通过这个步骤得操作,每个测试用例都会获得一个三元元组作为适应度得分,参加步骤8的排序。
54.步骤8:对种群中的测试用例进行非支配的帕累托排序,并计算测试用例间的拥挤距离
55.具体为:经过步骤8,种群中所有的测试用例都包含一个适应度得分元组。进行排序事,首先选取出不被其他测试用例支配的测试用例,即没有其他测试用例的各项适应度评分好于这些测试用例。这些测试用例会被选取为第一个帕累托前沿面。然后对种群中剩余的其他测试用例再次会重复上述操作,直到所有的测试用例都被分配到帕累托前沿面上。随后对每个前沿面上的测试用例计算拥挤距离,通过diffoscope工具分析步骤7中生成的动态追踪文件,计算每个测试用例的拥挤距离。
56.步骤9:选择种群中表现优良测试用例
57.具体为:从种群中随机选择两个测试用例,进行比较,如果测试用例i的非支配排序优于测试用例j,测试用例i胜出;测试用例i与测试用例j的非支配排序相同,但是测试用例i的拥挤距离大于测试用例j,测试用例i胜出。重复选择操作,直到表现优良的测试用例的数目40。
58.步骤10:对表现优良测试用例进行交叉变异,产生新的子种群
59.具体为:该步骤与步骤4操作相同,得到新的子种群。
60.步骤11:对生成的测试文件进行验证,筛选出触发性能缺陷的测试用例
61.具体为:将超时时间设置为40分钟,让z3str3重新求解种群中的测试文件。如果测试用例依旧超时,求解器无法求解,那么就发现了一个可以触发求解器性能问题的测试文件,将其记录到结果集中。随后可以将结果集报告给z3str3的开发人员。
62.本发明方法使用代码语句覆盖率信息引导搜索,可以在更短的时间内发现求解器
的性能缺陷;通过最小化测试用例的复杂度,可以帮助开发人员更快的定位缺陷位置;使用独特的测试用例拥挤距离计算方法,可以保证最终测试文件的多样性;本方法可以有效的检测出目标求解器中潜在的性能缺陷,减少由于求解器自身缺陷导致的不可预见的错误。
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1