# 在 Linux 中設定 Defects4j (以v1.2.0為例)
> 引用 Defects4J github https://github.com/rjust/defects4j
> 引用 TingWei 學長寫的 "[新的虛擬機 Defects4j 設定](https://hackmd.io/@saID5sq_QhCsFgtxP02KkA/Defects4J_Set#%E6%96%B0%E7%9A%84%E8%99%9B%E6%93%AC%E6%A9%9FDefects4j%E8%A8%AD%E5%AE%9A%E3%80%82)"
## 環境要求 (Requirements)
創建新的虛擬機後先更新。
```
sudo apt update
sudo apt upgrade -y
```
> 有些linux版本沒有unzip,需要自己下載
> `sudo apt install unzip`
### 1. 下載 Java 1.7 (僅適用 Defects4j v1.5.0 以前的版本)
因為新版ubuntu可能已經不再適用Java 7,所以透過這樣的步驟實現。
( 如果要其他已經無法下載的java版本,可從Oracle上找 )
下載 [Java 1.7.10.tar.gz](https://drive.google.com/file/d/18hfujRsl0yO7DYTcl87-32CVzA1P6bJX/view?pli=1)
> 若用到 Defects4j v2.0.0 以後,請下載 Java 1.8。
> 補充1.8的檔案 [Java 1.8.tar.gz](https://drive.google.com/file/d/1q90flX7bUSYJZdHsR589ric4lgRv_nRU/view)
建立一個存放 Java 7 的資料夾,輸入下列指令。
```
cd ../..
cd opt
sudo mkdir JDK
```
回到 Downloads 資料夾,並將剛剛下載的檔案解壓縮到建立的資料夾。
```
cd ~
cd Downloads
sudo tar -zxvf jdk-7u80-linux-x64.tar.gz -C /opt/JDK
```
設定環境變數。
```
sudo nano ~/.bashrc
```
在環境變數設定檔案最後面加上,加入完成之後Ctrl+O儲存。
(注意: 這是我存 Java 7 的資料夾位置,若存的位置不一樣要自己改。)
```
export JAVA_HOME=/opt/JDK/jdk1.7.0_80
export PATH=$JAVA_HOME/bin:$PATH
```
執行環境設定。
```
source ~/.bashrc
```
確認有成功安裝。
```
java -version
javac -version
```
### 2. 安裝 Git >= 1.9
```
sudo apt-get install git -y
git --version
```
### 3. 安裝 SVN >= 1.8
```
sudo apt install subversion -y
svn --version
```
### 4. 安裝 Perl >= 5.0.10
```
sudo apt install perl -y
sudo apt list --installed | grep -i perl
```
> 若之後實驗遇到 "Can't locate DBI.pm in @INC" 的錯誤
> 再執行以下命令以安裝 DBI 模組:
> `sudo apt-get install libdbi-perl`
### 5. 安裝 cpanminus
```
sudo apt-get install cpanminus -y
```
### 6. 安裝 curl
```
sudo apt install curl -y
```
### 7. 安裝 maven
```
sudo apt install maven -y
```
### 8. 安裝 ANT
下載 ANT 的壓縮檔案。
[ant 1.9.16](https://drive.google.com/file/d/1A-sRvJlBbAfhznxUTfsQlB4KF3jl8Gzq/view)
建立一個給ANT的資料夾。
```
cd ../../..
cd opt
sudo mkdir ANT
```
回到Downloads,並解壓縮,之後設定環境變數。
```
cd ~
cd Downloads
sudo tar -zxvf apache-ant-1.9.16-bin.tar.gz -C /opt/ANT/
```
設定環境變數。
```
sudo nano ~/.bashrc
```
在環境變數設定檔案最後面加上,加入完成之後Ctrl+O儲存。
```
export ANT_HOME=/opt/ANT/apache-ant-1.9.16
export PATH=$ANT_HOME/bin:$PATH
```
執行環境設定,並確認有安裝成功。
```
source ~/.bashrc
ant -version
```
## Getting started
### 1. 下載 Defects4J,並切換到需要的版本
```
git clone https://github.com/rjust/defects4j.git
cd defects4j
git checkout v1.2.0
```
確認切換版本成功。
```
git describe --tags
```
### 2. 初始化 Defects4J
在初始化之前,需先修改2個檔案內容(get_repos.sh 和 init.sh)。
> 因為原本的內容有些網址已被刪除,若直接按原檔案執行會出現404。
1. project_repos 資料夾中的 `get_repos.sh`
修改內容如下(可直接整個複製貼上)
:::spoiler get_repos.sh
```
#!/usr/bin/env bash
set -e
# The name of the archive that contains all project repos
ARCHIVE=defects4j-repos.zip
main() {
# The BSD version of stat does not support --version or -c
if stat --version &> /dev/null; then
# GNU version
cmd="stat -c %Y $ARCHIVE"
else
# BSD version
cmd="stat -f %m $ARCHIVE"
fi
if [ -e $ARCHIVE ]; then
old=$($cmd)
else
old=0
fi
# Only download repos if the server has a newer file
download_url "https://defects4j.org/downloads/$ARCHIVE"
new=$($cmd)
# Exit if no newer file is available
[ "$old" == "$new" ] && exit 0
# Remove old files
clean
# Extract new repos
unzip -q -u $ARCHIVE && mv defects4j/project_repos/* . && rm -r defects4j
}
clean() {
rm -rf \
closure-compiler.git \
commons-lang.git \
commons-math.git \
jfreechart \
joda-time.git \
README
}
# MacOS does not install the timeout command by default.
if [ "$(uname)" = "Darwin" ] ; then
function timeout() { perl -e 'alarm shift; exec @ARGV' "$@"; }
fi
# Download the remote resource to a local file of the same name, if the
# remote resource is newer. Works around connections that hang. Takes a
# single command-line argument, a URL.
download_url() {
BASENAME=`basename ${@: -1}`
if [ "$(uname)" = "Darwin" ] ; then
wget -nv -N "$@"
else
timeout 300 curl -s -S -R -L -O -z "$BASENAME" "$@" || (echo "retrying curl $@" && rm -f "$BASENAME" && curl -R -L -O -z "$BASENAME" "$@")
fi
}
main
```
:::
2. `init.sh`
修改內容如下(可直接整個複製貼上)
:::spoiler init.sh
```
#!/usr/bin/env bash
#
# Exit the shell script immediately if any of the subsequent commands fails.
# immediately
set -e
#
# TODO: Major and the coverage tools should be moved to framework/lib
################################################################################
# This script initializes Defects4J. In particular, it downloads and sets up:
# - the project's version control repositories
# - the Major mutation framework
# - the supported test generation tools
# - the supported code coverage tools (TODO)
################################################################################
HOST_URL="https://defects4j.org/downloads"
# Directories for project repositories and external libraries
BASE="$(cd "$(dirname "$0")"; pwd)"
DIR_REPOS="$BASE/project_repos"
DIR_LIB_GEN="$BASE/framework/lib/test_generation/generation"
DIR_LIB_RT="$BASE/framework/lib/test_generation/runtime"
DIR_LIB_GRADLE="$BASE/framework/lib/build_systems/gradle"
################################################################################
main() {
echo "Checking system configuration ... "
# Check whether wget is available on OSX
if [ "$(uname)" = "Darwin" ] ; then
if ! wget --version > /dev/null 2>&1; then
print_error_and_exit "Couldn't find wget to download dependencies. Please install wget and re-run this script."
fi
fi
# Check whether curl is available
if ! curl --version > /dev/null 2>&1; then
print_error_and_exit "Couldn't find curl to download dependencies. Please install curl and re-run this script."
fi
# Check whether unzip is available
if ! unzip -v > /dev/null 2>&1; then
print_error_and_exit "Couldn't find unzip to extract dependencies. Please install unzip and re-run this script."
fi
# Create lib folders if necessary
mkdir -p "$DIR_LIB_GEN" && mkdir -p "$DIR_LIB_RT" && mkdir -p "$DIR_LIB_GRADLE"
############################################################################
#
# Download project repositories if necessary
#
echo "Setting up project repositories ... "
cd "$DIR_REPOS" && ./get_repos.sh
############################################################################
#
# Download Major
#
# Adapt Major's default wrapper scripts:
# - set headless to true to support Chart on machines without X.
# - do not mutate code unless an MML is specified (for historical reasons,
# major v1 was sometimes called without specifying an MML to simply act as
# javac; Major v2+'s default is to generate all mutants as opposed to none).
#
echo
echo "Setting up Major ... "
MAJOR_VERSION="3.0.1"
MAJOR_URL="https://mutation-testing.org/downloads"
MAJOR_ZIP="major-${MAJOR_VERSION}_jre11.zip"
cd "$BASE" && rm -rf major \
&& download_url_and_unzip "$MAJOR_URL/$MAJOR_ZIP" \
&& rm "$MAJOR_ZIP" \
&& perl -pi -e '$_ .= qq( -Djava.awt.headless=true \\\n) if /CodeCacheSize/' \
major/bin/ant \
&& perl -pi -e '$_ .= qq(\nif [ -z "\$MML" ]; then javac \$*; exit \$?; fi\n) if /^REFACTOR=/' \
major/bin/major \
&& perl -pi -e '$_ = qq(REFACTOR=\${REFACTOR:-"enable.decl.refactor enable.method.refactor"}\n) if /^REFACTOR=/' \
major/bin/major \
############################################################################
#
# Download EvoSuite
#
echo
echo "Setting up EvoSuite ... "
EVOSUITE_VERSION="0.2.0"
EVOSUITE_URL="https://github.com/EvoSuite/evosuite/releases/download/v${EVOSUITE_VERSION}"
EVOSUITE_JAR="evosuite-${EVOSUITE_VERSION}.jar"
EVOSUITE_RT_JAR="evosuite-standalone-runtime-${EVOSUITE_VERSION}.jar"
cd "$DIR_LIB_GEN" && download_url "$EVOSUITE_URL/$EVOSUITE_JAR"
cd "$DIR_LIB_RT" && download_url "$EVOSUITE_URL/$EVOSUITE_RT_JAR"
# Set symlinks for the supported version of EvoSuite
(cd "$DIR_LIB_GEN" && ln -sf "$EVOSUITE_JAR" "evosuite-current.jar")
(cd "$DIR_LIB_RT" && ln -sf "$EVOSUITE_RT_JAR" "evosuite-rt.jar")
############################################################################
#
# Download Randoop
#
echo
echo "Setting up Randoop ... "
RANDOOP_VERSION="4.0.4"
RANDOOP_URL="https://github.com/randoop/randoop/releases/download/v${RANDOOP_VERSION}"
RANDOOP_ZIP="randoop-${RANDOOP_VERSION}.zip"
RANDOOP_JAR="randoop-all-${RANDOOP_VERSION}.jar"
REPLACECALL_JAR="replacecall-${RANDOOP_VERSION}.jar"
COVEREDCLASS_JAR="covered-class-${RANDOOP_VERSION}.jar"
(cd "$DIR_LIB_GEN" && download_url_and_unzip "$RANDOOP_URL/$RANDOOP_ZIP")
# Set symlink for the supported version of Randoop
(cd "$DIR_LIB_GEN" && ln -sf "randoop-${RANDOOP_VERSION}/$RANDOOP_JAR" "randoop-current.jar")
(cd "$DIR_LIB_GEN" && ln -sf "randoop-${RANDOOP_VERSION}/$REPLACECALL_JAR" "replacecall-current.jar")
(cd "$DIR_LIB_GEN" && ln -sf "randoop-${RANDOOP_VERSION}/$COVEREDCLASS_JAR" "covered-class-current.jar")
(cd "$DIR_LIB_GEN" && ln -sf "randoop-${RANDOOP_VERSION}/jacocoagent.jar" "jacocoagent.jar")
############################################################################
#
# Download build system dependencies
#
echo
echo "Setting up Gradle dependencies ... "
cd "$DIR_LIB_GRADLE"
GRADLE_DISTS_ZIP=defects4j-gradle-dists.zip
GRADLE_DEPS_ZIP=defects4j-gradle-deps.zip
old_dists_ts=0
old_deps_ts=0
if [ -e $GRADLE_DISTS_ZIP ]; then
old_dists_ts=$(get_modification_timestamp $GRADLE_DISTS_ZIP)
fi
if [ -e $GRADLE_DEPS_ZIP ]; then
old_deps_ts=$(get_modification_timestamp $GRADLE_DEPS_ZIP)
fi
# Only download archive if the server has a newer file
download_url $HOST_URL/$GRADLE_DISTS_ZIP
download_url $HOST_URL/$GRADLE_DEPS_ZIP
new_dists_ts=$(get_modification_timestamp $GRADLE_DISTS_ZIP)
new_deps_ts=$(get_modification_timestamp $GRADLE_DEPS_ZIP)
# Update gradle distributions/dependencies if a newer archive was available
[ "$old_dists_ts" != "$new_dists_ts" ] && mkdir "dists" && unzip -q -u $GRADLE_DISTS_ZIP -d "dists"
[ "$old_deps_ts" != "$new_deps_ts" ] && unzip -q -u $GRADLE_DEPS_ZIP
cd "$BASE"
############################################################################
#
# Download utility programs
#
echo
echo "Setting up utility programs ... "
BUILD_ANALYZER_VERSION="0.0.1"
BUILD_ANALYZER_JAR=build-analyzer-$BUILD_ANALYZER_VERSION.jar
BUILD_ANALYZER_URL="https://github.com/jose/build-analyzer/releases/download/v$BUILD_ANALYZER_VERSION/$BUILD_ANALYZER_JAR"
BUILD_ANALYZER_JAR_LOCAL="analyzer.jar"
cd "$BASE/framework/lib" && download_url "$BUILD_ANALYZER_URL"
rm -f "$BUILD_ANALYZER_JAR_LOCAL"
ln -s "$BUILD_ANALYZER_JAR" "$BUILD_ANALYZER_JAR_LOCAL"
echo
echo "Defects4J successfully initialized."
}
################################################################################
#
# Utility functions
#
# Print an error message and terminate the script.
# Takes one argument, a custom error message.
# Prints the supplied error message and a script termination notice to stderr.
# Terminates the script with exit code 1.
print_error_and_exit() {
echo -e "${1} \nTerminating initialization... " >&2
exit 1
}
# MacOS does not install the timeout command by default.
if [ "$(uname)" = "Darwin" ] ; then
function timeout() { perl -e 'alarm shift; exec @ARGV' "$@"; }
fi
# Download the remote resource to a local file of the same name.
# Takes a single argument, a URL.
# Skips the download if the remote resource is newer.
# Works around connections that hang.
download_url() {
if [ "$#" -ne 1 ]; then
echo "Illegal number of arguments"
fi
URL=$1
echo "Downloading ${URL}"
if [ "$(uname)" = "Darwin" ] ; then
wget -nv -N "$URL" || print_error_and_exit "Could not download $URL"
echo "Downloaded $URL"
else
BASENAME="$(basename "$URL")"
if [ -f "$BASENAME" ]; then
ZBASENAME="-z $BASENAME"
else
ZBASENAME=""
fi
(timeout 300 curl -s -S -R -L -O "$ZBASENAME" "$URL" || (echo "retrying curl $URL" && rm -f "$BASENAME" && curl -R -L -O "$URL")) && echo "Downloaded $URL"
fi
}
# Download the remote resource and unzip it.
# Takes a single argument, a URL.
# Skips the download if the local file of the same name is newer.
# Works around connections that hang and corrupted downloads.
download_url_and_unzip() {
if [ "$#" -ne 1 ]; then
echo "Illegal number of arguments"
fi
URL=$1
BASENAME="$(basename "$URL")"
download_url "$URL"
if ! unzip -o "$BASENAME" > /dev/null ; then
echo "retrying download and unzip"
rm -rf "$BASENAME"
download_url "$URL"
unzip -o "$BASENAME"
fi
}
# Get time of last data modification of a file
get_modification_timestamp() {
local USAGE="Usage: get_modification_timestamp <file>"
if [ "$#" != 1 ]; then
print_error_and_exit "$USAGE"
fi
local f="$1"
# The BSD version of stat does not support --version or -c
if stat --version &> /dev/null; then
# GNU version
cmd="stat -c %Y $f"
else
# BSD version
cmd="stat -f %m $f"
fi
local ts; ts=$($cmd)
echo "$ts"
}
main
```
:::
修改完成後即可執行初始化。
```
./init.sh
```
> 若初始化結果仍有錯誤,請詳讀錯誤內容,
> 重新確認 sh檔中對應的網址是否存在,以及網址的內容是否與版本相符合。
> 例如: 確認Major網址https://mutation-testing.org/downloads/ 是否為version 3.0.1
補充說明: 上面init.sh檔案中的工具可能有些版本不相容,所以請自行確認你要使用到的工具是否有版本問題,並切換。
更新: 我要用到major做mutation(人工植入bug),但上面major v3.0.1 和 defects4j v1.2.0 不相容,所以我會用下面init_fixed.sh (將 major 改成 v1.3.2)
:::spoiler init_fixed.sh
```
#!/usr/bin/env bash
#
# Exit the shell script immediately if any of the subsequent commands fails.
# immediately
set -e
#
# TODO: Major and the coverage tools should be moved to framework/lib
################################################################################
# This script initializes Defects4J. In particular, it downloads and sets up:
# - the project's version control repositories
# - the Major mutation framework
# - the supported test generation tools
# - the supported code coverage tools (TODO)
################################################################################
HOST_URL="https://defects4j.org/downloads"
# Directories for project repositories and external libraries
BASE="$(cd "$(dirname "$0")"; pwd)"
DIR_REPOS="$BASE/project_repos"
DIR_LIB_GEN="$BASE/framework/lib/test_generation/generation"
DIR_LIB_RT="$BASE/framework/lib/test_generation/runtime"
DIR_LIB_GRADLE="$BASE/framework/lib/build_systems/gradle"
################################################################################
main() {
echo "Checking system configuration ... "
# Check whether wget is available on OSX
if [ "$(uname)" = "Darwin" ] ; then
if ! wget --version > /dev/null 2>&1; then
print_error_and_exit "Couldn't find wget to download dependencies. Please install wget and re-run this script."
fi
fi
# Check whether curl is available
if ! curl --version > /dev/null 2>&1; then
print_error_and_exit "Couldn't find curl to download dependencies. Please install curl and re-run this script."
fi
# Check whether unzip is available
if ! unzip -v > /dev/null 2>&1; then
print_error_and_exit "Couldn't find unzip to extract dependencies. Please install unzip and re-run this script."
fi
# Create lib folders if necessary
mkdir -p "$DIR_LIB_GEN" && mkdir -p "$DIR_LIB_RT" && mkdir -p "$DIR_LIB_GRADLE"
############################################################################
#
# Download project repositories if necessary
#
echo "Setting up project repositories ... "
cd "$DIR_REPOS" && ./get_repos.sh
############################################################################
#
# Download Major
#
# Adapt Major's default wrapper scripts:
# - set headless to true to support Chart on machines without X.
# - do not mutate code unless an MML is specified (for historical reasons,
# major v1 was sometimes called without specifying an MML to simply act as
# javac; Major v2+'s default is to generate all mutants as opposed to none).
#
echo
echo "Setting up Major ... "
MAJOR_VERSION="1.3.2"
MAJOR_URL="https://mutation-testing.org/downloads"
MAJOR_ZIP="major-${MAJOR_VERSION}_jre7.zip"
# Download & unzip Major into $BASE/major
cd "$BASE"
rm -rf major
download_url_and_unzip "$MAJOR_URL/$MAJOR_ZIP"
rm -f "$MAJOR_ZIP"
# Normalize ant wrapper name: some packages ship .ant instead of ant
if [ ! -f major/bin/ant ] && [ -f major/bin/.ant ]; then
cp major/bin/.ant major/bin/ant
fi
# Set headless=true to support Chart on machines without X
if [ -f major/bin/ant ]; then
perl -pi -e '$_ .= qq( -Djava.awt.headless=true \\\n) if /CodeCacheSize/' major/bin/ant
fi
# If MML is empty, act like javac (avoid mutating unless explicitly requested)
if [ -f major/bin/major ]; then
perl -pi -e '$_ .= qq(\nif [ -z "\$MML" ]; then javac \$*; exit \$?; fi\n) if /^REFACTOR=/' major/bin/major
perl -pi -e '$_ = qq(REFACTOR=\${REFACTOR:-"enable.decl.refactor enable.method.refactor"}\n) if /^REFACTOR=/' major/bin/major
fi
############################################################################
#
# Download EvoSuite
#
echo
echo "Setting up EvoSuite ... "
EVOSUITE_VERSION="1.0.6"
EVOSUITE_URL="https://github.com/EvoSuite/evosuite/releases/download/v${EVOSUITE_VERSION}"
EVOSUITE_JAR="evosuite-${EVOSUITE_VERSION}.jar"
EVOSUITE_RT_JAR="evosuite-standalone-runtime-${EVOSUITE_VERSION}.jar"
cd "$DIR_LIB_GEN" && download_url "$EVOSUITE_URL/$EVOSUITE_JAR"
cd "$DIR_LIB_RT" && download_url "$EVOSUITE_URL/$EVOSUITE_RT_JAR"
# Set symlinks for the supported version of EvoSuite
(cd "$DIR_LIB_GEN" && ln -sf "$EVOSUITE_JAR" "evosuite-current.jar")
(cd "$DIR_LIB_RT" && ln -sf "$EVOSUITE_RT_JAR" "evosuite-rt.jar")
############################################################################
#
# Download Randoop
#
echo
echo "Setting up Randoop ... "
RANDOOP_VERSION="4.0.4"
RANDOOP_URL="https://github.com/randoop/randoop/releases/download/v${RANDOOP_VERSION}"
RANDOOP_ZIP="randoop-${RANDOOP_VERSION}.zip"
RANDOOP_JAR="randoop-all-${RANDOOP_VERSION}.jar"
REPLACECALL_JAR="replacecall-${RANDOOP_VERSION}.jar"
COVEREDCLASS_JAR="covered-class-${RANDOOP_VERSION}.jar"
(cd "$DIR_LIB_GEN" && download_url_and_unzip "$RANDOOP_URL/$RANDOOP_ZIP")
# Set symlink for the supported version of Randoop
(cd "$DIR_LIB_GEN" && ln -sf "randoop-${RANDOOP_VERSION}/$RANDOOP_JAR" "randoop-current.jar")
(cd "$DIR_LIB_GEN" && ln -sf "randoop-${RANDOOP_VERSION}/$REPLACECALL_JAR" "replacecall-current.jar")
(cd "$DIR_LIB_GEN" && ln -sf "randoop-${RANDOOP_VERSION}/$COVEREDCLASS_JAR" "covered-class-current.jar")
(cd "$DIR_LIB_GEN" && ln -sf "randoop-${RANDOOP_VERSION}/jacocoagent.jar" "jacocoagent.jar")
############################################################################
#
# Download build system dependencies
#
echo
echo "Setting up Gradle dependencies ... "
cd "$DIR_LIB_GRADLE"
GRADLE_DISTS_ZIP=defects4j-gradle-dists.zip
GRADLE_DEPS_ZIP=defects4j-gradle-deps.zip
old_dists_ts=0
old_deps_ts=0
if [ -e $GRADLE_DISTS_ZIP ]; then
old_dists_ts=$(get_modification_timestamp $GRADLE_DISTS_ZIP)
fi
if [ -e $GRADLE_DEPS_ZIP ]; then
old_deps_ts=$(get_modification_timestamp $GRADLE_DEPS_ZIP)
fi
# Only download archive if the server has a newer file
download_url $HOST_URL/$GRADLE_DISTS_ZIP
download_url $HOST_URL/$GRADLE_DEPS_ZIP
new_dists_ts=$(get_modification_timestamp $GRADLE_DISTS_ZIP)
new_deps_ts=$(get_modification_timestamp $GRADLE_DEPS_ZIP)
# Update gradle distributions/dependencies if a newer archive was available
[ "$old_dists_ts" != "$new_dists_ts" ] && mkdir "dists" && unzip -q -u $GRADLE_DISTS_ZIP -d "dists"
[ "$old_deps_ts" != "$new_deps_ts" ] && unzip -q -u $GRADLE_DEPS_ZIP
cd "$BASE"
############################################################################
#
# Download utility programs
#
echo
echo "Setting up utility programs ... "
BUILD_ANALYZER_VERSION="0.0.1"
BUILD_ANALYZER_JAR=build-analyzer-$BUILD_ANALYZER_VERSION.jar
BUILD_ANALYZER_URL="https://github.com/jose/build-analyzer/releases/download/v$BUILD_ANALYZER_VERSION/$BUILD_ANALYZER_JAR"
BUILD_ANALYZER_JAR_LOCAL="analyzer.jar"
cd "$BASE/framework/lib" && download_url "$BUILD_ANALYZER_URL"
rm -f "$BUILD_ANALYZER_JAR_LOCAL"
ln -s "$BUILD_ANALYZER_JAR" "$BUILD_ANALYZER_JAR_LOCAL"
echo
echo "Defects4J successfully initialized."
}
################################################################################
#
# Utility functions
#
# Print an error message and terminate the script.
# Takes one argument, a custom error message.
# Prints the supplied error message and a script termination notice to stderr.
# Terminates the script with exit code 1.
print_error_and_exit() {
echo -e "${1} \nTerminating initialization... " >&2
exit 1
}
# MacOS does not install the timeout command by default.
if [ "$(uname)" = "Darwin" ] ; then
function timeout() { perl -e 'alarm shift; exec @ARGV' "$@"; }
fi
# Download the remote resource to a local file of the same name.
# Takes a single argument, a URL.
# Skips the download if the remote resource is newer.
# Works around connections that hang.
download_url() {
if [ "$#" -ne 1 ]; then
echo "Illegal number of arguments"
fi
URL=$1
echo "Downloading ${URL}"
if [ "$(uname)" = "Darwin" ] ; then
wget -nv -N "$URL" || print_error_and_exit "Could not download $URL"
echo "Downloaded $URL"
else
BASENAME="$(basename "$URL")"
if [ -f "$BASENAME" ]; then
ZBASENAME="-z $BASENAME"
else
ZBASENAME=""
fi
(timeout 300 curl -f -sS -R -L $ZBASENAME -O "$URL" || (echo "retrying curl $URL" && rm -f "$BASENAME" && curl -f -sS -R -L -O "$URL")) && echo "Downloaded $URL"
fi
}
# Download the remote resource and unzip it.
# Takes a single argument, a URL.
# Skips the download if the local file of the same name is newer.
# Works around connections that hang and corrupted downloads.
download_url_and_unzip() {
if [ "$#" -ne 1 ]; then
echo "Illegal number of arguments"
fi
URL=$1
BASENAME="$(basename "$URL")"
download_url "$URL"
if ! unzip -o "$BASENAME" > /dev/null ; then
echo "retrying download and unzip"
rm -rf "$BASENAME"
download_url "$URL"
unzip -o "$BASENAME"
fi
}
# Get time of last data modification of a file
get_modification_timestamp() {
local USAGE="Usage: get_modification_timestamp <file>"
if [ "$#" != 1 ]; then
print_error_and_exit "$USAGE"
fi
local f="$1"
# The BSD version of stat does not support --version or -c
if stat --version &> /dev/null; then
# GNU version
cmd="stat -c %Y $f"
else
# BSD version
cmd="stat -f %m $f"
fi
local ts; ts=$($cmd)
echo "$ts"
}
main
```
:::
### 3. 設定 Defects4J 環境變數
```
sudo nano ~/.bashrc
```
輸入以下環境變數。
```
export PATH=$PATH:~/defects4j/framework/bin
export DEFECTS4J_HOME=~/defects4j
```
執行環境設定,並確認能夠使用defects4j指令。
```
source ~/.bashrc
defects4j
```
(若想要知道"defects4j"這個指令在哪裡就輸入"`whereis defects4j`",就能取得位置。)
### 4. 使用 Defects4J (以 Chart 為例)
輸入指令能夠查看 Chart 整體的資訊。
```
defects4j info -p Chart
```
輸入指令則是查看 Chart-1 的詳細資訊。
```
defects4j info -p Chart -b 1
```
下載 Chart-1 (存放位置自訂)。
```
defects4j checkout -p [Project名稱] -v [project的版本][b表示buggy version] -w [要存放的位置,最後的"chart_1_buggy"表示資料夾要存甚麼名稱,可以自訂]
defects4j checkout -p Chart -v 1b -w ~/d4j_project/Chart/chart_1_buggy
```
進到 Chart-1 的資料夾中,輸入指令可編譯或測試。
```
defects4j compile
defects4j test
```
## 自動 compile 所有的 bug-id
可以建立一個 sh檔,自動把所有的資料下載下來。
### 1. 建立一個想要存放 defects4j project 的資料夾
( p.s. : 要建立各個專案資料夾,不然容易出錯。)
( p.s. : 變數看清楚,常常因為變數問題出錯。)
> 我是在Home下建立一個 "d4j_project" 資料夾,
> 在裡面再建立 "chart"、"closure"、"math"、"time"、"lang" 資料夾,
> 可以直接打開 Document 手動添加。
### 2. 建立一個 sh檔
> 名稱設定為"all_D4J"。
```
touch all_D4J.sh
```
### 3. 寫入 sh檔內容
:::spoiler all_D4J.sh
```
dir=~/d4j_project/ # Store the buggy projects.
proj=Chart
proj2=chart
for bug_id in $(seq 1 26)
do
cd ~/defects4j/
defects4j checkout -p $proj -v ${bug_id}b -w ${dir}${proj2}/${proj2}_${bug_id}_buggy
#cd to checkout folder
cd ${dir}${proj2}/${proj2}_${bug_id}_buggy
defects4j compile
defects4j test
done
proj=Closure
proj2=closure
for bug_id in $(seq 1 133)
do
cd ~/defects4j/
defects4j checkout -p $proj -v ${bug_id}b -w ${dir}${proj2}/${proj2}_${bug_id}_buggy
#cd to checkout folder
cd ${dir}${proj2}/${proj2}_${bug_id}_buggy
defects4j compile
defects4j test
done
proj=Math
proj2=math
for bug_id in $(seq 1 106)
do
cd ~/defects4j/
defects4j checkout -p $proj -v ${bug_id}b -w ${dir}${proj2}/${proj2}_${bug_id}_buggy
#cd to checkout folder
cd ${dir}${proj2}/${proj2}_${bug_id}_buggy
defects4j compile
defects4j test
done
proj=Time
proj2=time
for bug_id in $(seq 1 27)
do
cd ~/defects4j/
defects4j checkout -p $proj -v ${bug_id}b -w ${dir}${proj2}/${proj2}_${bug_id}_buggy
#cd to checkout folder
cd ${dir}${proj2}/${proj2}_${bug_id}_buggy
defects4j compile
defects4j test
done
proj=Lang
proj2=lang
for bug_id in $(seq 1 65)
do
cd ~/defects4j/
defects4j checkout -p $proj -v ${bug_id}b -w ${dir}${proj2}/${proj2}_${bug_id}_buggy
#cd to checkout folder
cd ${dir}${proj2}/${proj2}_${bug_id}_buggy
defects4j compile
defects4j test
done
```
:::
### 4. 將 sh檔加入執行權限,並執行
```
chmod +x all_D4J.sh
./all_D4J.sh
```