|
|
|
c-ares Unit Test Suite
|
|
|
|
======================
|
|
|
|
|
|
|
|
|
|
|
|
This directory holds unit tests for the c-ares library. To build the tests:
|
|
|
|
|
|
|
|
- Build the main c-ares library first, in the directory above this. To
|
|
|
|
enable tests of internal functions, configure the library build to expose
|
|
|
|
hidden symbols with `./configure --disable-symbol-hiding`.
|
|
|
|
- Generate a `configure` file by running `autoreconf -iv` (which requires
|
|
|
|
a local installation of
|
|
|
|
[autotools](https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html)).
|
|
|
|
- `./configure`
|
|
|
|
- `make`
|
|
|
|
- Run the tests with `./arestest`, or `./arestest -v` for extra debug info.
|
|
|
|
|
|
|
|
Points to note:
|
|
|
|
|
|
|
|
- The tests are written in C++11, and so need a C++ compiler that supports
|
|
|
|
this. To avoid adding this as a requirement for the library, the
|
|
|
|
configuration and build of the tests is independent from the library.
|
|
|
|
- The tests include some live queries, which will fail when run on a machine
|
|
|
|
without internet connectivity. To skip live tests, run with
|
|
|
|
`./arestest --gtest_filter=-*.Live*`.
|
|
|
|
- The tests include queries of a mock DNS server. This server listens on port
|
|
|
|
5300 by default, but the port can be changed with the `-p 5300` option to
|
|
|
|
`arestest`.
|
|
|
|
|
|
|
|
|
|
|
|
Test Types
|
|
|
|
----------
|
|
|
|
|
|
|
|
The test suite includes various different types of test.
|
|
|
|
|
|
|
|
- There are live tests (`ares-test-live.cc`), which assume that the
|
|
|
|
current machine has a valid DNS setup and connection to the
|
|
|
|
internet; these tests issue queries for real domains but don't
|
|
|
|
particularly check what gets returned. The tests will fail on
|
|
|
|
an offline machine.
|
|
|
|
- There are some mock tests (`ares-test-mock.cc`) that set up a fake DNS
|
|
|
|
server and inject its port into the c-ares library configuration.
|
|
|
|
These tests allow specific response messages to be crafted and
|
|
|
|
injected, and so are likely to be used for many more tests in
|
|
|
|
future.
|
|
|
|
- To make this generation/injection easier, the `dns-proto.h`
|
|
|
|
file includes C++ helper classes for building DNS packets.
|
|
|
|
- Other library entrypoints that don't require network activity
|
|
|
|
(e.g. `ares_parse_*_reply`) are tested directly.
|
|
|
|
- A couple of the tests use a helper method of the test fixture to
|
|
|
|
inject memory allocation failures, using a recent change to the
|
|
|
|
c-ares library that allows override of `malloc`/`free`.
|
|
|
|
- There are some tests of the internal entrypoints of the library
|
|
|
|
(`ares-test-internal.c`), but these are only enabled if the library
|
|
|
|
was configured with `--disable-symbol-hiding` and/or
|
|
|
|
`--enable-expose-statics`.
|
|
|
|
- There is also an entrypoint to allow Clang's
|
|
|
|
[libfuzzer](http://llvm.org/docs/LibFuzzer.html) to drive
|
|
|
|
the packet parsing code in `ares_parse_*_reply`, together with a
|
|
|
|
standalone wrapper for it (`./aresfuzz`) to allow use of command
|
|
|
|
line fuzzers (such as [afl-fuzz](http://lcamtuf.coredump.cx/afl/))
|
|
|
|
for further [fuzz testing](#fuzzing).
|
|
|
|
|
|
|
|
|
|
|
|
Code Coverage Information
|
|
|
|
-------------------------
|
|
|
|
|
|
|
|
To generate code coverage information:
|
|
|
|
|
|
|
|
- Configure both the library and the tests with `./configure
|
|
|
|
--enable-code-coverage` before building. This requires the relevant code
|
|
|
|
coverage tools ([gcov](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html),
|
|
|
|
[lcov](http://ltp.sourceforge.net/coverage/lcov.php)) to be installed locally.
|
|
|
|
- Run the tests with `test/arestest`.
|
|
|
|
- Generate code coverage output with `make code-coverage-capture` in the
|
|
|
|
library directory (i.e. not in `test/`).
|
|
|
|
|
|
|
|
|
|
|
|
Fuzzing
|
|
|
|
-------
|
|
|
|
|
|
|
|
### libFuzzer
|
|
|
|
|
|
|
|
To fuzz the packet parsing code with libFuzzer, follow the main
|
|
|
|
[libFuzzer build instructions](http://llvm.org/docs/LibFuzzer.html#building):
|
|
|
|
|
|
|
|
- Configure the c-ares library and test suite with a recent Clang and a sanitizer, for example:
|
|
|
|
|
|
|
|
```console
|
|
|
|
% export CFLAGS="-fsanitize=address -fsanitize-coverage=edge"
|
|
|
|
% export CC=clang
|
|
|
|
% ./configure --disable-shared && make
|
|
|
|
```
|
|
|
|
- Download and build the libFuzzer code:
|
|
|
|
|
|
|
|
```console
|
|
|
|
% cd test
|
|
|
|
% svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer
|
|
|
|
% clang++ -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer
|
|
|
|
% ar ruv libFuzzer.a Fuzzer*.o
|
|
|
|
```
|
|
|
|
- Link each of the fuzzer entrypoints in with `ares-fuzz.cc`:
|
|
|
|
|
|
|
|
```
|
|
|
|
% $CC $CFLAGS -I.. -c ares-test-fuzz.c
|
|
|
|
% $CC $CFLAGS -I.. -c ares-test-fuzz-name.c
|
|
|
|
% clang++ $CFLAGS ares-test-fuzz.o ../.libs/libcares.a libFuzzer.a -o ares-libfuzzer
|
|
|
|
% clang++ $CFLAGS ares-test-fuzz-name.o ../.libs/libcares.a libFuzzer.a -o ares-libfuzzer-name
|
|
|
|
```
|
|
|
|
- Run the fuzzer using the starting corpus with:
|
|
|
|
|
|
|
|
```console
|
|
|
|
% ./ares-libfuzzer fuzzinput/ # OR
|
|
|
|
% ./ares-libfuzzer-name fuzznames/
|
|
|
|
```
|
|
|
|
|
|
|
|
### AFL
|
|
|
|
|
|
|
|
To fuzz using AFL, follow the
|
|
|
|
[AFL quick start guide](http://lcamtuf.coredump.cx/afl/QuickStartGuide.txt):
|
|
|
|
|
|
|
|
- Download and build AFL.
|
|
|
|
- Configure the c-ares library and test tool to use AFL's compiler wrappers:
|
|
|
|
|
|
|
|
```console
|
|
|
|
% export CC=$AFLDIR/afl-gcc
|
|
|
|
% ./configure --disable-shared && make
|
|
|
|
% cd test && ./configure && make aresfuzz aresfuzzname
|
|
|
|
```
|
|
|
|
|
|
|
|
- Run the AFL fuzzer against the starting corpus:
|
|
|
|
|
|
|
|
```console
|
|
|
|
% mkdir fuzzoutput
|
|
|
|
% $AFLDIR/afl-fuzz -i fuzzinput -o fuzzoutput -- ./aresfuzz # OR
|
|
|
|
% $AFLDIR/afl-fuzz -i fuzznames -o fuzzoutput -- ./aresfuzzname
|
|
|
|
```
|
|
|
|
|
|
|
|
### AFL Persistent Mode
|
|
|
|
|
|
|
|
If a recent version of Clang is available, AFL can use its built-in compiler
|
|
|
|
instrumentation; this configuration also allows the use of a (much) faster
|
|
|
|
persistent mode, where multiple fuzz inputs are run for each process invocation.
|
|
|
|
|
|
|
|
- Download and build a recent AFL, and run `make` in the `llvm_mode`
|
|
|
|
subdirectory to ensure that `afl-clang-fast` gets built.
|
|
|
|
- Configure the c-ares library and test tool to use AFL's clang wrappers that
|
|
|
|
use compiler instrumentation:
|
|
|
|
|
|
|
|
```console
|
|
|
|
% export CC=$AFLDIR/afl-clang-fast
|
|
|
|
% ./configure --disable-shared && make
|
|
|
|
% cd test && ./configure && make aresfuzz
|
|
|
|
```
|
|
|
|
|
|
|
|
- Run the AFL fuzzer (in persistent mode) against the starting corpus:
|
|
|
|
|
|
|
|
```console
|
|
|
|
% mkdir fuzzoutput
|
|
|
|
% $AFLDIR/afl-fuzz -i fuzzinput -o fuzzoutput -- ./aresfuzz
|
|
|
|
```
|
|
|
|
|