This is the source tree for CutEr, a concolic unit testing tool for Erlang.
CAUTION: This tool is still under heavy development
Copyright 2014-2017 by Aggelos Giantsios, Nikolaos Papaspyrou and Kostis Sagonas.
This program is distributed under the GPL, version 3 or later. Please see the COPYING file for details.
In order to use CutEr, you need the following programs:
- Erlang/OTP
We support releases Erlang/OTP 17.x or later. Note that using a pre-built package or binaries will not suffice if the library modules have not been compiled with debug information. In that case, you will need to build and install Erlang/OTP from source.
Download the latest source code distribution of Erlang/OTP or clone the Erlang/OTP github repository:
git clone https://github.com/erlang/otp.git
Then follow the instructions in INSTALL.md for building and installing Erlang/OTP.
- Python 2.x
Download and install the latest Python 2.x distribution.
Also, you need to install the protobuf package (version 3.2.0). You can install it for your user with
pip install --user protobuf==3.2.0
or globally with
sudo pip install protobuf==3.2.0
- Z3 Theorem Prover
Download the v4.5.0 Z3 release
or clone the z3-4.5.0
tag of Z3 from its git repository:
git clone -b z3-4.5.0 --depth 1 https://github.com/Z3Prover/z3.git
For your convenience, we include here a list of commands to build from source and install the v4.5.0 Z3 release:
cd z3 ; python scripts/mk_make.py --python
cd build ; make
sudo make install
If this sequence of commands does not work for you, follow the instructions in Z3's GitHub repository. Also, make sure that Z3Py (Python Interface) is installed.
- Protocol Buffer Compiler
Download the 3.2.0 version of protoc for your OS and follow the instructions in readme.txt.
If you have a Linux or an OSX system, then you can run the provided fetch_protoc.sh
script and follow the instructions.
./fetch_protoc.sh
-
Download CutEr's sources or clone this repository:
git clone https://github.com/aggelgian/cuter.git
-
[Optional] If you want to run the full test suite of CutEr, you will also need PropEr and meck. You can install them independently or go to CutEr's base directory and run:
git submodule init && git submodule update git submodule foreach make
-
Configure and compile CutEr. For a default build use:
autoconf ./configure # see Note below make depend make
[If required] Note that if you have installed protoc using
fetch_protoc.sh
then you need to specify the path of protoc to the configure script using a command like the following:./configure --with-protoc=$PWD/lib/protoc-3.2.0/bin/protoc
-
[Optional] In order to run the tests you need to install the parsimonious Python package (version 0.7.0). You can install it for your user with
pip install --user parsimonious==0.7.0
or globally with
sudo pip install parsimonious==0.7.0
Now you can build and run the unit & functional tests with
make test
-
[Optional] You can also run Dialyzer with
make dialyzer
-
Add CutEr's base directory to your Erlang library path by updating the
ERL_LIBS
environment variable. Just addexport ERL_LIBS=/full/path/to/cuter:$ERL_LIBS
to your shell startup file (e.g.
~/.bashrc
for Bash).
Let's say that you have a simple module foo
that just contains
the exported function bar/2
. The source file foo.erl
is:
-module(foo).
-export([bar/2]).
-spec bar([number()], [number()]) -> number().
bar([], Ys) -> lists:sum(Ys);
bar([X|Xs], [Y|Ys]) -> X * Y + bar(Xs, Ys).
For single file tests, such as the above, the simplest way to run CutEr
is to use the cuter
script as follows:
./cuter foo bar '[[1], [2]]'
i.e. supply it with three arguments: the module name, the function name,
and the list of arguments for the call that will act as a seed for the
concolic execution of the unit under test. If there is no foo.beam
file, the cuter
script will automatically compile the foo.erl
file
and create a .beam file with debug information.
Alternatively, go to the directory of the source file and compile it with debug information:
erlc +debug_info foo.erl
CutEr can then be invoked by calling the cuter:run/3
function:
erl -noshell -eval "cuter:run(foo, bar, [[1], [2]])" -s init stop
This will report a list of inputs that lead to runtime errors, for
example foo:bar([0], [])
and foo:bar([3,2,1], [0.0,0])
.
To sum up, cuter:run/3
is called as cuter:run(M, F, As)
where
M
is the moduleF
is the functionAs
is the list of arguments of the seed input
There is also a cuter:run/4
function that takes these three arguments
but also a numeric argument Depth
that denotes the depth of the search
(i.e. roughly the number of branches that will be explored). This depth
can also be specified as an option of the cuter
script:
./cuter foo bar '[[1], [2]]' -d 42
CutEr provides more API functions that also come with options that control the concolic execution of Erlang programs. These will be explained in a set of forthcoming tutorials. In the meantime, you can find out about them by the command:
./cuter --help
and by browsing the source code of CutEr.
Have fun with the tool!