1c-ares Unit Test Suite 2====================== 3 4 5This directory holds unit tests for the c-ares library. To build the tests: 6 7 - Build the main c-ares library first, in the directory above this. To 8 enable tests of internal functions, configure the library build to expose 9 hidden symbols with `./configure --disable-symbol-hiding`. 10 - Generate a `configure` file by running `autoreconf -iv` (which requires 11 a local installation of 12 [autotools](https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html)). 13 - `./configure` 14 - `make` 15 - Run the tests with `./arestest`, or `./arestest -v` for extra debug info. 16 17Points to note: 18 19 - The tests are written in C++11, and so need a C++ compiler that supports 20 this. To avoid adding this as a requirement for the library, the 21 configuration and build of the tests is independent from the library. 22 - The tests include some live queries, which will fail when run on a machine 23 without internet connectivity. To skip live tests, run with 24 `./arestest --gtest_filter=-*.Live*`. 25 - The tests include queries of a mock DNS server. This server listens on port 26 5300 by default, but the port can be changed with the `-p 5300` option to 27 `arestest`. 28 29 30Test Types 31---------- 32 33The test suite includes various different types of test. 34 35 - There are live tests (`ares-test-live.cc`), which assume that the 36 current machine has a valid DNS setup and connection to the 37 internet; these tests issue queries for real domains but don't 38 particularly check what gets returned. The tests will fail on 39 an offline machine. 40 - There are some mock tests (`ares-test-mock.cc`) that set up a fake DNS 41 server and inject its port into the c-ares library configuration. 42 These tests allow specific response messages to be crafted and 43 injected, and so are likely to be used for many more tests in 44 future. 45 - To make this generation/injection easier, the `dns-proto.h` 46 file includes C++ helper classes for building DNS packets. 47 - Other library entrypoints that don't require network activity 48 (e.g. `ares_parse_*_reply`) are tested directly. 49 - A couple of the tests use a helper method of the test fixture to 50 inject memory allocation failures, using a recent change to the 51 c-ares library that allows override of `malloc`/`free`. 52 - There are some tests of the internal entrypoints of the library 53 (`ares-test-internal.c`), but these are only enabled if the library 54 was configured with `--disable-symbol-hiding` and/or 55 `--enable-expose-statics`. 56 - There is also an entrypoint to allow Clang's 57 [libfuzzer](http://llvm.org/docs/LibFuzzer.html) to drive 58 the packet parsing code in `ares_parse_*_reply`, together with a 59 standalone wrapper for it (`./aresfuzz`) to allow use of command 60 line fuzzers (such as [afl-fuzz](http://lcamtuf.coredump.cx/afl/)) 61 for further [fuzz testing](#fuzzing). 62 63 64Code Coverage Information 65------------------------- 66 67To generate code coverage information: 68 69 - Configure both the library and the tests with `./configure 70 --enable-code-coverage` before building. This requires the relevant code 71 coverage tools ([gcov](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html), 72 [lcov](http://ltp.sourceforge.net/coverage/lcov.php)) to be installed locally. 73 - Run the tests with `test/arestest`. 74 - Generate code coverage output with `make code-coverage-capture` in the 75 library directory (i.e. not in `test/`). 76 77 78Fuzzing 79------- 80 81### libFuzzer 82 83To fuzz the packet parsing code with libFuzzer, follow the main 84[libFuzzer instructions](http://llvm.org/docs/LibFuzzer.html): 85 86 - Configure the c-ares library and test suite with a recent Clang and a sanitizer, for example: 87 88 ```console 89 % export CFLAGS="-fsanitize=fuzzer-no-link,address" 90 % export CC=clang 91 % ./configure --disable-shared && make 92 ``` 93 - Link each of the fuzzer entrypoints in with `ares-fuzz.cc`: 94 95 ``` 96 % clang -I.. -c ares-test-fuzz.c 97 % clang -I.. -c ares-test-fuzz-name.c 98 % clang++ -fsanitize=fuzzer,address ares-test-fuzz.o ../.libs/libcares.a -o ares-libfuzzer 99 % clang++ -fsanitize=fuzzer,address ares-test-fuzz-name.o ../.libs/libcares.a -o ares-libfuzzer-name 100 ``` 101 - Run the fuzzer using the starting corpus with: 102 103 ```console 104 % ./ares-libfuzzer fuzzinput/ # OR 105 % ./ares-libfuzzer-name fuzznames/ 106 ``` 107 108### AFL 109 110To fuzz using AFL, follow the 111[AFL quick start guide](http://lcamtuf.coredump.cx/afl/QuickStartGuide.txt): 112 113 - Download and build AFL. 114 - Configure the c-ares library and test tool to use AFL's compiler wrappers: 115 116 ```console 117 % export CC=$AFLDIR/afl-gcc 118 % ./configure --disable-shared && make 119 % cd test && ./configure && make aresfuzz aresfuzzname 120 ``` 121 122 - Run the AFL fuzzer against the starting corpus: 123 124 ```console 125 % mkdir fuzzoutput 126 % $AFLDIR/afl-fuzz -i fuzzinput -o fuzzoutput -- ./aresfuzz # OR 127 % $AFLDIR/afl-fuzz -i fuzznames -o fuzzoutput -- ./aresfuzzname 128 ``` 129 130### AFL Persistent Mode 131 132If a recent version of Clang is available, AFL can use its built-in compiler 133instrumentation; this configuration also allows the use of a (much) faster 134persistent mode, where multiple fuzz inputs are run for each process invocation. 135 136 - Download and build a recent AFL, and run `make` in the `llvm_mode` 137 subdirectory to ensure that `afl-clang-fast` gets built. 138 - Configure the c-ares library and test tool to use AFL's clang wrappers that 139 use compiler instrumentation: 140 141 ```console 142 % export CC=$AFLDIR/afl-clang-fast 143 % ./configure --disable-shared && make 144 % cd test && ./configure && make aresfuzz 145 ``` 146 147 - Run the AFL fuzzer (in persistent mode) against the starting corpus: 148 149 ```console 150 % mkdir fuzzoutput 151 % $AFLDIR/afl-fuzz -i fuzzinput -o fuzzoutput -- ./aresfuzz 152 ``` 153 154