SIR(Software-artifact Infrastructure Repository)程序结果对比和覆盖信息收集实验

一、什么是SIR?

SIR———Software-artifact Infrastructure Repository是软件研究领域非常著名的数数据集,因为课程项目涉及到使用该网站上提供的数据集完成软件测试实验报告。因此总结了一下简单的操作和过程复现流程。本文选择的是C语言的Object,项目名为schedule.

二、下载Object和工具tools

进入到SIR的官方网站:https://sir.csc.ncsu.edu/php/。这个网站只针对研究人员开放,因此需要填写一些申请注册信息,在这里提供一个账号:Username:kooleryan; Password:123456

点击左侧的download Objects

在搜索框可以选择Java,C语言或者其他语言的Object:

因为本文是基于的C语言的项目,所以再下载C Object Handbook,上面详细介绍了如何在 SIR 库的 C
语言实验程序集上做实验,包括实验配置,测试脚本生成,错误配置。Download Tools包含了实验工具和脚本的下载,本文用到了其中的mts工具把universe测试用例规格说明转换成对应的测试脚本。

三、程序集文件结构

程序集的文件结构分为两种,新版和旧版(Siemens和space).

新版的文件结构如下图所示:

旧版的文件结构如下图所示:

本文选择的Schedule程序集是老版本的,新版本和老版本的主要区别在于:

(1)新版文件结构中,每个程序集分出了多个版本(v0,v1…),也有对应的正确源代码版本(v0,v1…),其中每个版本的错误程序又有若干个错误可供配置;而旧版文件结构中,每个程序集分出的若干错误程序(v0,v1…)已经包含了单个错误,对应的正确源代码只有一份。

(2)新版的测试用例是以“.universe”为后缀的文件以 mts 工具的格式保存的;而旧版的测试用例是以“universe”文件逐行保存测试程序的参数(没有按照 mts 工具的格式)。

四、使用工具及配置介绍

(1)Linux操作系统环境下。

本实验是基于Linux系统的,因为要使用Lcov和Gcov等工具来收集覆盖率信息。所以如果没有Linux系统的可以安装一个虚拟机,配置Ubuntu系统。

(2)shell常用命令和shell脚本

shell常用命令:首先需要熟悉shell的一些常用命令,这个网上随便一搜到处都是整理好的教程,就像学习一门乐器一样,熟能生巧,只有多操作,才能记下来并且熟练掌握。

shell脚本其实就是在终端的shell命令的集合,只是在开头需要声明#!/bin/s

vim编辑工具的用法:编写shell脚本和c语言源代码我会使用vim编辑器,刚开始使用者来编辑文本对于用惯了windows下的文本编辑器的人来说真的是很痛苦,还是那句话,熟能生巧,多操作,其实很简单,主要掌握几个模式和几个快捷键即可满足基本的使用。

(3)GCC

在linux环境下C语言使用的编译器为gcc,其编译链接的命令十分简单,在这里因为要使用lcov和gcov命令一起,详情参照后面Gcov和Lcov的基础用法。

(4)javamts/mts 工具

mts 工具是用来把.universe 后缀的文件转化为测试脚本的。使用方法参照mts\doc\manual

首先需要进行环境配置,将javamts下的两个Jar包antlr-2.7.6.jar和mts.jar添加到你自己java路径的lib里。

export
CLASSPATH=$CLASSPATH:/usr/lib/jvm/default-java/lib/antlr-2.7.6.jar:/usr/lib/jvm/default-java/lib/mts.jar

然后,执行 mts 命令:

java sir.mts.MakeTestScript
 --stimple-file|-sf <file>:【输入】.universe 文件路径与文件名
中山大学 软件工程实验室
版权所有 请勿翻印 内部资料 请勿外传
 --script-name|-sn <name>:【输出】脚本路径与文件名
 --exe-name|-en <name>:【输入】被运行程序的路径与文件名
 [--experiment-dir|-ed <path>]:【输入】实验路径配置
 [--compare-outputs|-c <comp_dir> [comp_cmd>]]:【输入】oracle 路径,比较命令
 [--compare-type|-ct D|d]
 [--trace|-t]
 [--trace-source-dir|-ts <path>]
 [--trace-name|-tn <name>]
 [--invoke-prefix|-ip <prefix>]
 [--invoke-suffix|-is <suffix>]
 [--exe-prefix|-ep <prefix>]
 [--exe-suffix|-es <suffix> [D]]
 [--java|-j]
 [--target|-tg <script_gen_class>]:【输出】脚本的类型:bash,csh
 [--no-escapes|-nesc]:【输入】输入脚本是否转义
 [--legacy-macros|-lm]
 [--print-config|-pc]
[--version]
这是我之前看到的一个例子,蒋路径更改后,参照其用法即可:

#set up MTS' CLASSPATH (Java)
export 
CLASSPATH=$CLASSPATH:/usr/lib/jvm/java/lib/antlr-2.7.6.jar:/usr/lib/jvm/java/lib/mts.jar
#generate test scripts
echo "$(date) generate test scripts: fault-$fault"
java sir.mts.MakeTestScript\
 -sf $universe\
 -sn $benchmark_dir/scripts/$fault.sh\
 -en $benchmark_dir/source/$program.exe\
 -ed $benchmark_dir/\
 -c $benchmark_dir/archives/ORACLE/outputs diff\
 -tg bsh -nesc

(5)Gcov和Lcov的基础用法

关于GcoV和Lcov的用法可参考这一篇博客,写得非常的详细,适合新手:https://www.cnblogs.com/turtle-fly/archive/2013/01/09/2851474.html

五、实验流程

(1)选择要执行的程序版本,移到source文件夹中。

可以使用cp -rf强制复制命令,也可以用别的移动命令

cp -rf ${experiment_root}/schedule/versions.alt/versions.orig/v$version/schedule.c ${experiment_root}/schedule/source

(2)gcc 编译:加上-fprofile-arcs -ftest-coverage 选项和lcov命令:


(3)sed 转化 universe 测试脚本为 mts 格式:selab.universe

在testplans.alt文件夹中已经有一个runall.sh,这个直接能运行,是包含了所有的测试用例,但其只是单纯的运行输出结果到outputs,没有覆盖率信息和结果比对。

因为老版本中给的测试用例集格式不是mts直接能使用的,需要先用sed命令进行修改。


(4)mts 根据 selab.universe 生成测试脚本 program.sh

加上-c 命令就是将错误版本的输出结果和Oracle(即正确版本的运行结果)进行比对,最终会输出一个diff_results.txt在outputs文件夹中,里面是所有与Oracle结果不同的测试用例编号。


(5)sed 替 换 测 试 脚 本 program.sh 中 的 语 句 , 生 成 新 脚 本,使其能对每次执行生成的 program.gcno、program. 
gcda、program.gcov 文件进行相应的归档。


(6)执行测试新脚本

如果你使用了cd和一些强制的命令在shell脚本中,请使用source ××.sh来执行脚本。

以上步骤的目的是,本文选择的schedule程序集正确版本为一个,错误版本有9个:

  1. 编译source.alt目录下的正确程序代码。将测试用例集输入到正确程序,将测试用例集输出结果保存到某个目录下。
  2. 编译versions.alt某个错误版本的程序代码,注意添加gcov编译参数。将测试用例集输入到该错误版本程序,将测试用例集输出结果以及每个测试用例覆盖信息文件保存到某个目录下。注意:每次产生覆盖信息文件名是一样的,需要重命名。
  3. 对比每个测试用例在正确程序与错误版本程序的结果,相同即通过,不相同及失败,得出测试用例集的通过和失败情况。


(7)使用 Python把lcov生成的info文件进行进一步处理:

lcov工具会生成.info文件:

*.info文件包含一个或多个源文件所对应的覆盖率信息,一个源文件对应一条“记录”,“记录”中的详细格式如下:

TN: <Test name> 表示测试用例名称,即通过geninfo中的--test-name选项来命名的测试用例名称,默认为空;

SF: <File name> 表示带全路径的源代码文件名;

FN: <函数启始行号>, <函数名>; <函数有效行总数>; <函数有效行总数中被执行个数>

FNDA: <函数被执行的次数>, <函数名>; <函数有效行总数>; <函数有效行总数中被执行个数>

FNF: <函数总数>

FNH: <函数总数中被执行到的个数>

BRDA: <分支所在行号>, <对应的代码块编号>, <分支编号>, <执行的次数>

BRF: <分支总数>

BRH: <分支总数中被执行到的个数>

DA: <代码行号>, <当前行被执行到的次数>

LF: < counts> 代码有效行总数

LH: <counts> 代码有效行总数中被执行到的个数

end_of_record 一条“记录”结束符
 

用python将需要的信息读出来之后转化为矩阵。按照以下矩阵存储信息,最后依据该矩阵进行计算。

具体的shell脚本和Python代码,有需要的同学可以留下邮箱,我私发给你。

猜你喜欢

转载自blog.csdn.net/weixin_39626452/article/details/88919181