1. 下载
2. 安装
可以在 Releases 页面直接下载 1.7.2 稳定版本的 Jar 包,或者源码自行打包:
git clone https://github.com/GZoltar/gzoltar
cd gzoltar
mvn package
3. 命令行使用
3.1 官方示例
在 com.gzoltar.cli.examples
中执行:
./run.sh
--instrumentation <online|offline>
[--help]
3.2 D4J示例(分步)
查看官方示例中的 run.sh
,结构如下:
- Envs & Args:
检查 GZOLTAR_CLI_JAR 和 GZOLTAR_AGENT_RT_JAR,准备运行时依赖 JUNIT_JAR 和 HAMCREST_JAR。 - Main:
四个步骤:编译 Compile;收集测试以供运行 listTestMethods;收集覆盖信息 runTestMethods;创建错误报告 faultLocalizationReport。
以 D4J 的 Lang-1b 为对象,对其修改:
- 首先,检查依赖部分的 jar 包路径是否正确。
- 编译部分交给
defects4j compile
命令完成(⭐)。
也可以自己编译(如下,但不推荐❌):
# 将 .java 文件输入到 txt 然后 javac 编译
find /home/ubuntu/lang_1_buggy/src/main/java -name *.java >> src.txt
find /home/ubuntu/lang_1_buggy/src/test/java -name *.java >> test.txt
SRC_DIR=/home/ubuntu/d4j-gzoltar/target/classes
TEST_DIR=/home/ubuntu/d4j-gzoltar/target/tests
# 使用 ISO 编码是因为其中该项目存在 UTF-8 不可映射的字符
javac @src.txt -encoding ISO-8859-1 -d ${SRC_DIR}
# 补充缺少的依赖包
javac -cp ${JUNIT_JAR}:${HAMCREST_JAR}:${COMMONS_IO}:${EASY_MOCK}:${SRC_DIR} @test.txt -encoding ISO-8859-1 -d ${TEST_DIR}
- 列出测试:
这段是官方的参考:
java -cp <project_classpath:gzoltarcli.jar> com.gzoltar.cli.Main listTestMethods \
<list of folders that contain test classes> \
--outputFile <path> \
--includes <test classes/cases to consider, e.g., org.TestFoo#* to include all test cases of test class TestFoo>
对于本例 ,includes 来自 /home/ubuntu/defects4j-2.0.0/framework/projects/<pid>/relevant_tests/<bid>
,借助命令获取:
cat "/home/ubuntu/defects4j-2.0.0/framework/projects/<pid>/relevant_tests/<bid>" | sed 's/$/#*/' | sed ':a;N;$!ba;s/\n/:/g'
java -cp ${JUNIT_JAR}:${HAMCREST_JAR}:${GZOLTAR_CLI_JAR}:${SRC_DIR}:${TEST_DIR} \
com.gzoltar.cli.Main listTestMethods \
/home/ubuntu/d4j-gzoltar/target \
--outputFile /home/ubuntu/d4j-gzoltar/tmp/tests.txt \
--includes ${RELEVANT_TESTS}
- 收集覆盖信息:通过 JavaAgent 完成。
参数 | 含义 | 备注 |
---|---|---|
destfile | java 序列化文件 | gzoltar.ser |
buildlocation | 构建位置 | 源码类路径 |
includes | 包括 | 加载的类 |
excludes | 排除 | 不排除 “” |
inclnolocationclasses | (未知) | false |
output | 输出格式 | “file” |
这里需要注意 includes 的格式( 错误将无法输出.ser文件 ),cli.example 中的示例为:
org.gzoltar.examples.CharacterCounter:org.gzoltar.examples.CharacterCounter\$*
本例中 includes 来自 /home/ubuntu/defects4j-2.0.0/framework/projects/Lang/loaded_classes/1.src
,而 src 中的格式如下:
org.apache.commons.lang3.math.NumberUtils
org.apache.commons.lang3.StringUtils
借助如下命令修改格式:
LOADED_CLASSES_FILE="/home/ubuntu/defects4j-2.0.0/framework/projects/<pid>/loaded_classes/<bid>.src"
NORMAL_CLASSES=$(cat "$LOADED_CLASSES_FILE" | sed 's/$/:/' | sed ':a;N;$!ba;s/\n//g')
INNER_CLASSES=$(cat "$LOADED_CLASSES_FILE" | sed 's/$/$*:/' | sed ':a;N;$!ba;s/\n//g')
LOADED_CLASSES="$NORMAL_CLASSES$INNER_CLASSES"
执行:
java -javaagent:${GZOLTAR_AGENT_JAR}=destfile=<GZOLTAR.ser>,buildlocation=${SRC_DIR},includes=${LOADED_CLASSES},excludes="",inclnolocationclasses=false,output="file" \
-cp ${JUNIT_JAR}:${HAMCREST_JAR}:${GZOLTAR_CLI_JAR}:${SRC_DIR}:${TEST_DIR} \
com.gzoltar.cli.Main runTestMethods \
--testMethods <tests.txt> \ # 上一步生成的文件
--collectCoverage
- 创建错误报告:
java -cp ${SRC_DIR}:${TEST_DIR}:${JUNIT_JAR}:${HAMCREST_JAR}:${GZOLTAR_CLI_JAR} \
com.gzoltar.cli.Main faultLocalizationReport \
--buildLocation ${SRC_DIR} \
--granularity "line" \
--inclPublicMethods \
--inclStaticConstructors \
--inclDeprecatedMethods \
--dataFile <GZOLTAR.ser> \
--outputDirectory "/home/ubuntu/d4j-gzoltar" \
--family "sfl" \
--formula "ochiai" \
--metric "entropy" \
--formatter "txt"
成功生成所需文件!!!
这里对 faultLocalizationReport 仔细分析下:
参数 | 说明 |
---|---|
buildLocation | Java class 文件 |
dataFile | .ser 文件 |
excludes | 不报告的 classes,可用? * : |
family | 错误定位技术族,默认 SBFL/SFL |
formatter | 格式,默认txt,使用 : 分隔 |
formula | 公式,默认 Ochiai,使用 : 分隔 |
granularity | 粒度,默认:line,还有 method 和 class |
help | 帮助,默认 false |
inclDeprecatedMethods | 是否报告已被注释弃用的方法,默认true |
inclPublicMethods | 是否报告每个 class 的 public methods,默认 true |
inclStaticConstructors | 是否报告每个 class 的 public static constructors,默认 false |
includes | 报告的 classes,可用? * : |
metric | 排名指标,默认 ambiguity,使用 : 分隔 |
outputDirectory | 输出目录 |
quiet | suppress all output on stdout |
3.3 脚本化
作者在 Issues-30 给出了可参考框架,项目 Fault-localization-data 也提供了脚本。这里给出一个单项目的脚本(许多细节未处理),稍加修改就可以满足整体脚本化需求。
SCRIPT_DIR=$(pwd)
PID=$1
BID=$2
PROJECT_DIR=/home/ubuntu/${PID}_${BID}_buggy
# Checkout defects4j project
defects4j checkout -p ${PID} -v ${BID}b -w ${PROJECT_DIR}
cd ${PROJECT_DIR}
defects4j compile
SRC_DIR=${PROJECT_DIR}/$(defects4j export -p dir.bin.classes)
TEST_DIR=${PROJECT_DIR}/$(defects4j export -p dir.bin.tests)
LIB_DIR=$(defects4j export -p cp.test)
RELEVANT_TESTS_FILE=${D4J_HOME}/framework/projects/${PID}/relevant_tests/${BID}
RELEVANT_TESTS=$(cat ${RELEVANT_TESTS_FILE} | sed 's/$/#*/' | sed ':a;N;$!ba;s/\n/:/g')
# List test methods
java -cp ${LIB_DIR}:${GZOLTAR_CLI_JAR} \
com.gzoltar.cli.Main listTestMethods \
${TEST_DIR} \
--outputFile ${PROJECT_DIR}/listTestMethods.txt \
--includes ${RELEVANT_TESTS}
SER_FILE=${PROJECT_DIR}/gzoltar.ser
LOADED_CLASSES_FILE=${D4J_HOME}/framework/projects/${PID}/loaded_classes/${BID}.src
NORMAL_CLASSES=$(cat ${LOADED_CLASSES_FILE} | sed 's/$/:/' | sed ':a;N;$!ba;s/\n//g')
INNER_CLASSES=$(cat ${LOADED_CLASSES_FILE} | sed 's/$/$*:/' | sed ':a;N;$!ba;s/\n//g')
LOADED_CLASSES=${NORMAL_CLASSES}${INNER_CLASSES}
# Generate .ser file
java -javaagent:${GZOLTAR_AGENT_JAR}=destfile=${SER_FILE},buildlocation=${SRC_DIR},includes=${LOADED_CLASSES},excludes="",inclnolocationclasses=false,output="file" \
-cp ${GZOLTAR_CLI_JAR}:${LIB_DIR} \
com.gzoltar.cli.Main runTestMethods \
--testMethods ${PROJECT_DIR}/listTestMethods.txt \
--collectCoverage
# Generate report
java -cp ${GZOLTAR_CLI_JAR}:${LIB_DIR} \
com.gzoltar.cli.Main faultLocalizationReport \
--buildLocation ${SRC_DIR} \
--granularity line \
--inclPublicMethods \
--inclStaticConstructors \
--inclDeprecatedMethods \
--dataFile ${SER_FILE} \
--outputDirectory ${PROJECT_DIR} \
--family sfl \
--formula ochiai \
--metric entropy \
--formatter txt
# Simple file processing
MATRIX_FILE=${PROJECT_DIR}/sfl/txt/matrix.txt
SPECTRA_FILE=${PROJECT_DIR}/sfl/txt/spectra.csv
TESTS_FILE=${PROJECT_DIR}/sfl/txt/tests.csv
ARCHIVE_DIR=/home/ubuntu/exec_info/${PID}/${BID}
mkdir -p ${ARCHIVE_DIR}
mv ${MATRIX_FILE} ${ARCHIVE_DIR}/matrix
tail -n +2 ${SPECTRA_FILE} > ${ARCHIVE_DIR}/spectra
tail -n +2 ${TESTS_FILE} > ${ARCHIVE_DIR}/tests
# Copied code
# Remove inner class(es) names (as there is not a .java file for each one)
sed -i -E 's/(\$\w+)\$.*#/\1#/g' ${ARCHIVE_DIR}/spectra
# Remove method name of each row in the spectra file
sed -i 's/#.*:/#/g' ${ARCHIVE_DIR}/spectra
# Replace class name symbol
sed -i 's/\$/./g' ${ARCHIVE_DIR}/spectra
# Verification trigger/failed tests
cat ${D4J_HOME}/framework/projects/${PID}/trigger_tests/${BID} | sed -n 's/--- //p' | sort > ${PROJECT_DIR}/d4j_tests_tmp
grep -w "FAIL" ${ARCHIVE_DIR}/tests | awk -F ',' '{print $1}' | sed -n 's/#/::/p' | sort > ${PROJECT_DIR}/gzoltar_tests_tmp
DIFF_INFO=$(diff ${PROJECT_DIR}/d4j_tests_tmp ${PROJECT_DIR}/gzoltar_tests_tmp)
if [[ -n ${DIFF_INFO} ]]; then
echo -e "${PID}-${BID}:\n${DIFF_INFO}" >> /home/ubuntu/exec_info/${PID}/log
fi
# Delete redundant files
rm -rf ${PROJECT_DIR}
其中 D4J_HOME
| GZOLTAR_CLI_JAR
| GZOLTAR_AGENT_JAR
的配置不在脚本中。
执行示例:./util.sh Lang 3