Update README.md
This commit is contained in:
parent
e27ed026dd
commit
78396dcb3b
83
README.md
83
README.md
@ -1,9 +1,82 @@
|
|||||||
# CITRUS: C++ Unit Testing for Real-world Usage
|
# CITRUS: C++ Unit Testing for Real-world Usage
|
||||||
|
|
||||||
CITRUS is an implementation of Unit-level Fuzzing for C++ based on random method sequence generation.
|
## Introduction
|
||||||
Implemented using C++14 and backporting library to utilize C++17's `std::optional` feature.
|
|
||||||
|
|
||||||
Tested working on: Ubuntu 16.04, 18.04, 20.04 using LLVM/Clang++ 11.0.1
|
CITRUS is an implementation of Unit-level Testing for C++ based on random method call sequence generation.
|
||||||
|
|
||||||
--
|
CITRUS automatically generates test driver files for the target program `P`, each of which consists of various method calls
|
||||||
Developed by SWTV Lab, KAIST
|
of `P`. In
|
||||||
|
addition, CITRUS improves the test coverage of `P` further
|
||||||
|
by applying **libfuzzer** to change `P`’s state by mutating
|
||||||
|
arguments of the methods.
|
||||||
|
|
||||||
|
For more details, please refer to CITRUS technical paper.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
CITRUS was tested running on Ubuntu 16.04, 18.04, 20.04. The requirements of CITRUS are:
|
||||||
|
1. LLVM/Clang++ 11.0.1,
|
||||||
|
1. LCOV coverage measurement tool (we used a [modified LCOV](https://github.com/henry2cox/lcov/tree/diffcov_initial) for CITRUS development),
|
||||||
|
1. CMake 3.15,
|
||||||
|
1. Python 3.
|
||||||
|
|
||||||
|
We provide a shell script to install all CITRUS requirements. (**root privilege required**)
|
||||||
|
```shell
|
||||||
|
./scripts/dep.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Build Instruction
|
||||||
|
|
||||||
|
To build CITRUS is simply executing the build script
|
||||||
|
```shell
|
||||||
|
./scripts/build.sh
|
||||||
|
```
|
||||||
|
CITRUS will be built in `build` directory.
|
||||||
|
|
||||||
|
|
||||||
|
## Building CITRUS Subjects
|
||||||
|
|
||||||
|
We provide the target programs we use for our experiment at
|
||||||
|
`replication` directory. For simplicity, you can execute the following shell script (from the CITRUS **root** project directory) to build all our experiments subjects.
|
||||||
|
```shell
|
||||||
|
./scripts/bootstrap.sh subjects # to build in subjects dir
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running CITRUS Method Call Sequence Generation
|
||||||
|
|
||||||
|
Currently CITRUS only supports command-line interface.
|
||||||
|
```shell
|
||||||
|
./build/citrus ${TRANS_UNIT} \
|
||||||
|
--obj-dir ${OBJ_DIR} \
|
||||||
|
--src-dir ${SRC_DIR} \
|
||||||
|
--max-depth ${MAX_DEPTH} \
|
||||||
|
--fuzz-timeout ${TIMEOUT} \
|
||||||
|
--xtra-ld "${XTRA_LD}" \
|
||||||
|
--out-prefix ${OUT_PREFIX}
|
||||||
|
```
|
||||||
|
For easier usage, we recommend to write separate shell script(s) to configure the command-line arguments as demonstrated in `run` directory. For example, to run CITRUS on `hjson` library:
|
||||||
|
```shell
|
||||||
|
./run/hjson.sh 43200 tc_hjson subjects/hjson-cpp # 12 hours
|
||||||
|
```
|
||||||
|
where `tc_hjson` represents the target directory where the generated test cases will be put at, and `subjects/hjson-cpp` represents the `hjson` directory.
|
||||||
|
|
||||||
|
## Running CITRUS libfuzzer
|
||||||
|
|
||||||
|
Currently the libfuzzer stage must be manually triggered after the method call sequence generation. CITRUS writes the libfuzzer harness drivers in `out_libfuzzer` directory. Each driver has compilation instruction at the end of the file.
|
||||||
|
|
||||||
|
To ease the libfuzzer stage, we provide `batch_libfuzzer.py` script (i.e., CITRUS already puts this script in `out_libfuzzer` directory) to collect all compilation, running, and test case replaying instructions for libfuzzer stage.
|
||||||
|
```shell
|
||||||
|
# Compilation (from out_libfuzzer directory)
|
||||||
|
python3 batch_libfuzzer gen # initializes the scripts
|
||||||
|
./tst_compile.sh # compile all harness drivers
|
||||||
|
|
||||||
|
# Running libfuzzer
|
||||||
|
./tst_run.sh # default: 5 mins each driver
|
||||||
|
|
||||||
|
# Replaying libfuzzer generated test cases
|
||||||
|
./tst_repl.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
Developed by **SWTV Lab**, **KAIST**
|
||||||
|
@ -5,11 +5,6 @@ TARGET=build/citrus
|
|||||||
TIMEOUT=$1
|
TIMEOUT=$1
|
||||||
OUT_PREFIX=$2
|
OUT_PREFIX=$2
|
||||||
SUBJ_DIR=$3
|
SUBJ_DIR=$3
|
||||||
#USE_FUNC_COMP=$2
|
|
||||||
#FUNC_COMP=
|
|
||||||
#if [[ "${USE_FUNC_COMP^^}" == "NO" ]]; then
|
|
||||||
# FUNC_COMP=__none.txt
|
|
||||||
#fi
|
|
||||||
|
|
||||||
TRANS_UNIT=${SUBJ_DIR}/all.cpp
|
TRANS_UNIT=${SUBJ_DIR}/all.cpp
|
||||||
OBJ_DIR=${SUBJ_DIR}
|
OBJ_DIR=${SUBJ_DIR}
|
||||||
@ -28,5 +23,4 @@ ${TARGET} ${TRANS_UNIT} \
|
|||||||
--max-depth ${MAX_DEPTH} \
|
--max-depth ${MAX_DEPTH} \
|
||||||
--fuzz-timeout ${TIMEOUT} \
|
--fuzz-timeout ${TIMEOUT} \
|
||||||
--xtra-ld "${XTRA_LD}" \
|
--xtra-ld "${XTRA_LD}" \
|
||||||
--out-prefix ${OUT_PREFIX} \
|
--out-prefix ${OUT_PREFIX}
|
||||||
--func-comp ${FUNC_COMP}
|
|
||||||
|
@ -5,12 +5,6 @@ TARGET=build/citrus
|
|||||||
TIMEOUT=$1
|
TIMEOUT=$1
|
||||||
OUT_PREFIX=$2
|
OUT_PREFIX=$2
|
||||||
SUBJ_DIR=$3
|
SUBJ_DIR=$3
|
||||||
FUNC_COMP=__none.txt
|
|
||||||
#USE_FUNC_COMP=$2
|
|
||||||
#FUNC_COMP=func_comp/hjson.txt
|
|
||||||
#if [[ "${USE_FUNC_COMP^^}" == "NO" ]]; then
|
|
||||||
# FUNC_COMP=__none.txt
|
|
||||||
#fi
|
|
||||||
|
|
||||||
TRANS_UNIT=${SUBJ_DIR}/src/hjson_encode.cpp
|
TRANS_UNIT=${SUBJ_DIR}/src/hjson_encode.cpp
|
||||||
OBJ_DIR=${SUBJ_DIR}/build/src/CMakeFiles/hjson.dir
|
OBJ_DIR=${SUBJ_DIR}/build/src/CMakeFiles/hjson.dir
|
||||||
@ -29,5 +23,4 @@ ${TARGET} ${TRANS_UNIT} \
|
|||||||
--max-depth ${MAX_DEPTH} \
|
--max-depth ${MAX_DEPTH} \
|
||||||
--fuzz-timeout ${TIMEOUT} \
|
--fuzz-timeout ${TIMEOUT} \
|
||||||
--xtra-ld "${XTRA_LD}" \
|
--xtra-ld "${XTRA_LD}" \
|
||||||
--out-prefix ${OUT_PREFIX} \
|
--out-prefix ${OUT_PREFIX}
|
||||||
--func-comp ${FUNC_COMP}
|
|
||||||
|
@ -5,11 +5,6 @@ TARGET=build/citrus
|
|||||||
TIMEOUT=$1
|
TIMEOUT=$1
|
||||||
OUT_PREFIX=$2
|
OUT_PREFIX=$2
|
||||||
SUBJ_DIR=$3
|
SUBJ_DIR=$3
|
||||||
#USE_FUNC_COMP=$2
|
|
||||||
#FUNC_COMP=func_comp/json-voorhees.txt
|
|
||||||
#if [[ "${USE_FUNC_COMP^^}" == "NO" ]]; then
|
|
||||||
# FUNC_COMP=__none.txt
|
|
||||||
#fi
|
|
||||||
|
|
||||||
TRANS_UNIT=${SUBJ_DIR}/src/jsonv/all.cpp
|
TRANS_UNIT=${SUBJ_DIR}/src/jsonv/all.cpp
|
||||||
OBJ_DIR=${SUBJ_DIR}/build/CMakeFiles/jsonv.dir/src/jsonv
|
OBJ_DIR=${SUBJ_DIR}/build/CMakeFiles/jsonv.dir/src/jsonv
|
||||||
@ -28,5 +23,4 @@ ${TARGET} ${TRANS_UNIT} \
|
|||||||
--max-depth ${MAX_DEPTH} \
|
--max-depth ${MAX_DEPTH} \
|
||||||
--fuzz-timeout ${TIMEOUT} \
|
--fuzz-timeout ${TIMEOUT} \
|
||||||
--xtra-ld "${XTRA_LD}" \
|
--xtra-ld "${XTRA_LD}" \
|
||||||
--out-prefix ${OUT_PREFIX} \
|
--out-prefix ${OUT_PREFIX}
|
||||||
--func-comp ${FUNC_COMP}
|
|
@ -5,11 +5,6 @@ TARGET=build/citrus
|
|||||||
TIMEOUT=$1
|
TIMEOUT=$1
|
||||||
OUT_PREFIX=$2
|
OUT_PREFIX=$2
|
||||||
SUBJ_DIR=$3
|
SUBJ_DIR=$3
|
||||||
#USE_FUNC_COMP=$2
|
|
||||||
#FUNC_COMP=func_comp/jsonbox.txt
|
|
||||||
#if [[ "${USE_FUNC_COMP^^}" == "NO" ]]; then
|
|
||||||
# FUNC_COMP=__none.txt
|
|
||||||
#fi
|
|
||||||
|
|
||||||
TRANS_UNIT=${SUBJ_DIR}/src/all.cpp
|
TRANS_UNIT=${SUBJ_DIR}/src/all.cpp
|
||||||
OBJ_DIR=${SUBJ_DIR}/build/CMakeFiles/JsonBox.dir/src
|
OBJ_DIR=${SUBJ_DIR}/build/CMakeFiles/JsonBox.dir/src
|
||||||
@ -28,5 +23,4 @@ ${TARGET} ${TRANS_UNIT} \
|
|||||||
--max-depth ${MAX_DEPTH} \
|
--max-depth ${MAX_DEPTH} \
|
||||||
--fuzz-timeout ${TIMEOUT} \
|
--fuzz-timeout ${TIMEOUT} \
|
||||||
--xtra-ld "${XTRA_LD}" \
|
--xtra-ld "${XTRA_LD}" \
|
||||||
--out-prefix ${OUT_PREFIX} \
|
--out-prefix ${OUT_PREFIX}
|
||||||
--func-comp ${FUNC_COMP}
|
|
||||||
|
@ -5,12 +5,6 @@ TARGET=build/citrus
|
|||||||
TIMEOUT=$1
|
TIMEOUT=$1
|
||||||
OUT_PREFIX=$2
|
OUT_PREFIX=$2
|
||||||
SUBJ_DIR=$3
|
SUBJ_DIR=$3
|
||||||
FUNC_COMP=__none.txt
|
|
||||||
#USE_FUNC_COMP=$2
|
|
||||||
#FUNC_COMP=func_comp/jsoncpp.txt
|
|
||||||
#if [[ "${USE_FUNC_COMP^^}" == "NO" ]]; then
|
|
||||||
# FUNC_COMP=__none.txt
|
|
||||||
#fi
|
|
||||||
|
|
||||||
TRANS_UNIT=${SUBJ_DIR}/src/lib_json/all.cpp
|
TRANS_UNIT=${SUBJ_DIR}/src/lib_json/all.cpp
|
||||||
OBJ_DIR=${SUBJ_DIR}/build/src/lib_json/CMakeFiles/jsoncpp_lib.dir
|
OBJ_DIR=${SUBJ_DIR}/build/src/lib_json/CMakeFiles/jsoncpp_lib.dir
|
||||||
@ -29,5 +23,4 @@ ${TARGET} ${TRANS_UNIT} \
|
|||||||
--max-depth ${MAX_DEPTH} \
|
--max-depth ${MAX_DEPTH} \
|
||||||
--fuzz-timeout ${TIMEOUT} \
|
--fuzz-timeout ${TIMEOUT} \
|
||||||
--xtra-ld "${XTRA_LD}" \
|
--xtra-ld "${XTRA_LD}" \
|
||||||
--out-prefix ${OUT_PREFIX} \
|
--out-prefix ${OUT_PREFIX}
|
||||||
--func-comp ${FUNC_COMP}
|
|
||||||
|
@ -5,11 +5,6 @@ TARGET=build/citrus
|
|||||||
TIMEOUT=$1
|
TIMEOUT=$1
|
||||||
OUT_PREFIX=$2
|
OUT_PREFIX=$2
|
||||||
SUBJ_DIR=$3
|
SUBJ_DIR=$3
|
||||||
#USE_FUNC_COMP=$2
|
|
||||||
#FUNC_COMP=func_comp/jvar.txt
|
|
||||||
#if [[ "${USE_FUNC_COMP^^}" == "NO" ]]; then
|
|
||||||
# FUNC_COMP=__none.txt
|
|
||||||
#fi
|
|
||||||
|
|
||||||
TRANS_UNIT=${SUBJ_DIR}/src/all.cpp
|
TRANS_UNIT=${SUBJ_DIR}/src/all.cpp
|
||||||
OBJ_DIR=${SUBJ_DIR}/build/CMakeFiles/jvar.dir/src
|
OBJ_DIR=${SUBJ_DIR}/build/CMakeFiles/jvar.dir/src
|
||||||
@ -28,5 +23,4 @@ ${TARGET} ${TRANS_UNIT} \
|
|||||||
--max-depth ${MAX_DEPTH} \
|
--max-depth ${MAX_DEPTH} \
|
||||||
--fuzz-timeout ${TIMEOUT} \
|
--fuzz-timeout ${TIMEOUT} \
|
||||||
--xtra-ld "${XTRA_LD}" \
|
--xtra-ld "${XTRA_LD}" \
|
||||||
--out-prefix ${OUT_PREFIX} \
|
--out-prefix ${OUT_PREFIX}
|
||||||
--func-comp ${FUNC_COMP}
|
|
||||||
|
@ -5,11 +5,6 @@ TARGET=build/citrus
|
|||||||
TIMEOUT=$1
|
TIMEOUT=$1
|
||||||
OUT_PREFIX=$2
|
OUT_PREFIX=$2
|
||||||
SUBJ_DIR=$3
|
SUBJ_DIR=$3
|
||||||
#USE_FUNC_COMP=$2
|
|
||||||
#FUNC_COMP=func_comp/re2.txt
|
|
||||||
#if [[ "${USE_FUNC_COMP^^}" == "NO" ]]; then
|
|
||||||
# FUNC_COMP=__none.txt
|
|
||||||
#fi
|
|
||||||
|
|
||||||
TRANS_UNIT=${SUBJ_DIR}/re2/all.cpp
|
TRANS_UNIT=${SUBJ_DIR}/re2/all.cpp
|
||||||
OBJ_DIR=${SUBJ_DIR}/build/CMakeFiles/re2.dir/
|
OBJ_DIR=${SUBJ_DIR}/build/CMakeFiles/re2.dir/
|
||||||
@ -28,5 +23,4 @@ ${TARGET} ${TRANS_UNIT} \
|
|||||||
--max-depth ${MAX_DEPTH} \
|
--max-depth ${MAX_DEPTH} \
|
||||||
--fuzz-timeout ${TIMEOUT} \
|
--fuzz-timeout ${TIMEOUT} \
|
||||||
--xtra-ld "${XTRA_LD}" \
|
--xtra-ld "${XTRA_LD}" \
|
||||||
--out-prefix ${OUT_PREFIX} \
|
--out-prefix ${OUT_PREFIX}
|
||||||
--func-comp ${FUNC_COMP}
|
|
||||||
|
@ -5,12 +5,6 @@ TARGET=build/citrus
|
|||||||
TIMEOUT=$1
|
TIMEOUT=$1
|
||||||
OUT_PREFIX=$2
|
OUT_PREFIX=$2
|
||||||
SUBJ_DIR=$3
|
SUBJ_DIR=$3
|
||||||
FUNC_COMP=__none.txt
|
|
||||||
#USE_FUNC_COMP=$2
|
|
||||||
#FUNC_COMP=func_comp/tinyxml2.txt
|
|
||||||
#if [[ "${USE_FUNC_COMP^^}" == "NO" ]]; then
|
|
||||||
# FUNC_COMP=__none.txt
|
|
||||||
#fi
|
|
||||||
|
|
||||||
TRANS_UNIT=${SUBJ_DIR}/tinyxml2.cpp
|
TRANS_UNIT=${SUBJ_DIR}/tinyxml2.cpp
|
||||||
OBJ_DIR=${SUBJ_DIR}/build/CMakeFiles/tinyxml2.dir
|
OBJ_DIR=${SUBJ_DIR}/build/CMakeFiles/tinyxml2.dir
|
||||||
@ -29,5 +23,4 @@ ${TARGET} ${TRANS_UNIT} \
|
|||||||
--max-depth ${MAX_DEPTH} \
|
--max-depth ${MAX_DEPTH} \
|
||||||
--fuzz-timeout ${TIMEOUT} \
|
--fuzz-timeout ${TIMEOUT} \
|
||||||
--xtra-ld "${XTRA_LD}" \
|
--xtra-ld "${XTRA_LD}" \
|
||||||
--out-prefix ${OUT_PREFIX} \
|
--out-prefix ${OUT_PREFIX}
|
||||||
--func-comp ${FUNC_COMP}
|
|
||||||
|
@ -5,12 +5,6 @@ TARGET=build/citrus
|
|||||||
TIMEOUT=$1
|
TIMEOUT=$1
|
||||||
OUT_PREFIX=$2
|
OUT_PREFIX=$2
|
||||||
SUBJ_DIR=$3
|
SUBJ_DIR=$3
|
||||||
FUNC_COMP=__none.txt
|
|
||||||
#USE_FUNC_COMP=$2
|
|
||||||
#FUNC_COMP=func_comp/re2.txt
|
|
||||||
#if [[ "${USE_FUNC_COMP^^}" == "NO" ]]; then
|
|
||||||
# FUNC_COMP=__none.txt
|
|
||||||
#fi
|
|
||||||
|
|
||||||
TRANS_UNIT=${SUBJ_DIR}/src/all.cpp
|
TRANS_UNIT=${SUBJ_DIR}/src/all.cpp
|
||||||
OBJ_DIR=${SUBJ_DIR}/build/CMakeFiles/yaml-cpp.dir/src
|
OBJ_DIR=${SUBJ_DIR}/build/CMakeFiles/yaml-cpp.dir/src
|
||||||
@ -29,5 +23,4 @@ ${TARGET} ${TRANS_UNIT} \
|
|||||||
--max-depth ${MAX_DEPTH} \
|
--max-depth ${MAX_DEPTH} \
|
||||||
--fuzz-timeout ${TIMEOUT} \
|
--fuzz-timeout ${TIMEOUT} \
|
||||||
--xtra-ld "${XTRA_LD}" \
|
--xtra-ld "${XTRA_LD}" \
|
||||||
--out-prefix ${OUT_PREFIX} \
|
--out-prefix ${OUT_PREFIX}
|
||||||
--func-comp ${FUNC_COMP}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user