mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-22 14:32:25 +00:00
295 lines
12 KiB
Markdown
295 lines
12 KiB
Markdown
Serval DNA Testing
|
|
==================
|
|
[Serval Project][], June 2014
|
|
|
|
[Serval DNA][] is tested using a suite of [test scripts](../tests/) written in
|
|
the [Bash][] shell scripting language, using the Serval Project's own [Bash
|
|
Test Framework][]. These scripts are [integration tests][] focussed on the
|
|
Serval DNA component and its external interfaces.
|
|
|
|
Test Framework
|
|
--------------
|
|
|
|
The [Bash Test Framework][] performs common testing work, so that test
|
|
developers can focus on the specifics of their test cases and test cases
|
|
contain a minumum of [boilerplate code][]:
|
|
|
|
* creates a temporary working directory to isolate each test case
|
|
* invokes each test case's set-up, test, finalise, and tear-down functions in
|
|
a defined order, guaranteeing to always call the latter two
|
|
* provides a rich set of assertion functions
|
|
* records the outcome of each test case: PASS, FAIL or ERROR
|
|
* records a detailed log of the execution of each test case
|
|
* removes temporary working directories and files after each test case
|
|
* kills any stray processes after each test case
|
|
* runs test cases in parallel if so directed
|
|
* reports progress during execution
|
|
|
|
Some features that may be added in future are:
|
|
|
|
* conformance with [Test Anything Protocol][TAP]
|
|
* support for a SKIP test outcome
|
|
* formal versioning of the Test Framework and parts of its API, to catch
|
|
incompatibilities between test scripts and Framework upgrades
|
|
|
|
Prerequisites
|
|
-------------
|
|
|
|
The [Bash Test Framework][] requires the following execution environment:
|
|
|
|
* [Bash][] version 3.2.48 or later
|
|
* [GNU grep][] version 2.7 or later
|
|
* [GNU sed][] version 4.2 or later
|
|
* [GNU awk][] version 3.1 or later
|
|
* [pgrep][] and [pkill][] version 593 or later (Solaris) or from procps-ng 3.3
|
|
or later (Linux)
|
|
|
|
Before running any tests, all the executables and other artifacts under test
|
|
(ie, the **servald** executable), plus all test utilities, must be
|
|
[built](../INSTALL.md).
|
|
|
|
Test scripts
|
|
------------
|
|
|
|
Executing a test script without any arguments causes it to run all the test
|
|
cases that it defines, one at a time. The script will terminate once all test
|
|
cases have been run, and its exit status will be zero only if all test cases
|
|
reported PASS.
|
|
|
|
Every test script uses the [Bash Test Framework][] to parse its command line,
|
|
so the following options are supported by all test scripts:
|
|
|
|
* __`-l`__ or __`--list`__ causes the script to print a list of all its test
|
|
cases on standard output, instead of executing them
|
|
|
|
* __`-t`__ or __`--trace`__ sets the Bash `-x` option during execution of each
|
|
test case, which adds much more detail to the test logs
|
|
|
|
* __`-v`__ or __`--verbose`__ causes test logs to be sent to standard output
|
|
during execution of the tests, so the developer can watch a test as it runs
|
|
(this version is incompatible with running tests in parallel)
|
|
|
|
* __`-E`__ or __`--stop-on-error`__ causes the test script to stop running new
|
|
test cases as soon as any test reports ERROR, and to wait for currently
|
|
running test cases to finish
|
|
|
|
* __`-F`__ or __`--stop-on-failure`__ causes the test script to stop running
|
|
new test cases as soon as any test reports FAIL, and to wait for currently
|
|
running test cases to finish
|
|
|
|
* __`-j N`__ or __`--jobs=N`__ causes up to __N__ test cases to be run
|
|
concurrently, which can greatly speed the rate of completion of a large test
|
|
run, since most tests spend much of their time either sleeping or i/o bound
|
|
|
|
* __`-f PREFIX`__ or __`--filter=PREFIX`__ causes only those test cases whose
|
|
names begin with __PREFIX__ to be executed
|
|
|
|
* __`-f N`__ or __`--filter=N`__ causes only test case number __N__ to be
|
|
executed (test cases are numbered in the order they are defined in the
|
|
script)
|
|
|
|
* __`-f M-N`__ or __`--filter=M-N`__ causes only test cases numbers __M__
|
|
through to __N__ (inclusive) to be executed (test cases are numbered in the
|
|
order they are defined in the script); if __M__ is omitted then all cases up
|
|
to number __N__ are executed; if __N__ is omitted then all test cases from
|
|
number __M__ and above are executed
|
|
|
|
* __`-f M,N,...`__ or __`--filter=M,N,...`__ causes only test cases __M__ and
|
|
__N__ (... etc.) to be executed (test cases are numbered in the order they
|
|
are defined in the script)
|
|
|
|
There are other options as well. To see a complete and up-to-date summary, use
|
|
the __`--help`__ option:
|
|
|
|
$ ./tests/all --help
|
|
|
|
Aggregate scripts
|
|
-----------------
|
|
|
|
Some test scripts simply aggregate other scripts, providing a convenient way to
|
|
execute many tests with a single command. Aggregate scripts behave in all
|
|
respects like a normal test script: the command line options and exit status
|
|
are the same.
|
|
|
|
The most notable aggregate script is [tests/all](../tests/all), which runs all
|
|
available tests except long-running, resource-hungry “stress” tests:
|
|
|
|
$ ./tests/all
|
|
1 [PASS.] (logging) By default, only errors and warnings are logged to stderr
|
|
2 [PASS.] (logging) Configure all messages logged to stderr
|
|
3 [PASS.] (logging) Configure no messages logged to stderr
|
|
4 [PASS.] (logging) By Default, all messages are appended to a configured file
|
|
...
|
|
158 [PASS.] (rhizomeprotocol) One way direct pull bundle from configured peer
|
|
159 [PASS.] (rhizomeprotocol) Two-way direct sync bundles with configured peer
|
|
160 [PASS.] (directory_service) Publish and retrieve a directory entry
|
|
161 [PASS.] (directory_service) Ping via relay node
|
|
161 tests, 161 pass, 0 fail, 0 error
|
|
$
|
|
|
|
Test logs
|
|
---------
|
|
|
|
All test scripts write their test logs into the `testlog` sub-directory
|
|
(relative to the current working directory), which has the following structure:
|
|
|
|
./testlog/
|
|
SCRIPTNAME/
|
|
1.FirstTestCaseName.RESULT/
|
|
log.txt
|
|
... other files...
|
|
2.SecondTestCaseName.RESULT/
|
|
log.txt
|
|
... other files...
|
|
SECONDSCRIPTNAME/
|
|
1.first_test_case_name.RESULT/
|
|
log.txt
|
|
... other files...
|
|
2.second_test_case_name.RESULT/
|
|
log.txt
|
|
... other files...
|
|
... more script directories...
|
|
|
|
where `SCRIPTNAME` and `SECONDSCRIPTNAME` are the names of the test scripts,
|
|
`FirstTestCaseName`, `first_test_case_name`, etc. are the names of the tests
|
|
within those scripts, and `RESULT` is either `ERROR`, `FAIL` or `PASS`. An
|
|
aggregate test script writes logfiles for all the test cases it includes under
|
|
its own SCRIPTNAME, not under the names of the scripts it includes.
|
|
|
|
Whenever a test script starts, it deletes its `testlog/SCRIPTNAME` directory
|
|
and all its contents, so the logs from previous runs are lost.
|
|
|
|
Every test case produces a `log.txt` file, and may also produce other files to
|
|
assist diagnosis in case of failure or to supplement a pass result, eg,
|
|
performance statistics, code coverage data, network packet logs for
|
|
reproducibility.
|
|
|
|
Source code coverage
|
|
--------------------
|
|
|
|
The [Bash Test Framework][] has command-line options to support per-test-case
|
|
[source code test coverage][] analysis using [GCC][] and [gcov(1)][]. An
|
|
aggregate coverage analysis can easily be generated with no special options to
|
|
test scripts.
|
|
|
|
To generate code coverage information for [Serval DNA][], modify the standard
|
|
[build](../INSTALL.md) procedure by adding CFLAGS and LDFLAGS arguments to the
|
|
`./configure` step:
|
|
|
|
...
|
|
$ ./configure CFLAGS='-g -O0 --coverage' LDFLAGS='--coverage'
|
|
$ make
|
|
...
|
|
|
|
This will generate one [GCNO][] file for every object file, in the same
|
|
directory as the object file.
|
|
|
|
Once **servald** has been built using these flags, invoking it will generate
|
|
some [GCDA][] coverage data files, one per source file, in the same directory
|
|
as the [GCNO][] files. Repeated invocations will accumulate coverage data in
|
|
the same files. The environment variables `GCOV_PREFIX` and
|
|
`GCOV_PREFIX_STRIP` can be used to change the directory where the [GCDA][] data
|
|
files are written.
|
|
|
|
### Aggregate code coverage
|
|
|
|
To generate aggregate code coverage for a test run:
|
|
|
|
$ make covzero
|
|
$ ./tests/all
|
|
...
|
|
$ make covhtml
|
|
$ www-browser ./coverage_html/index.html
|
|
...
|
|
|
|
The coverage report will reflect exactly the accumulated coverage of all tests
|
|
run between `make covzero` and `make covhtml`. The above example runs all
|
|
tests (except stress tests) but any combination may be run, including manual
|
|
invocations of **servald**. The **servald** executable must be invoked at
|
|
least once after `make covzero`, or `make covhtml` will fail with an error, for
|
|
lack of coverage data.
|
|
|
|
If more tests are run without invoking `make covzero`, then the coverage data
|
|
will sum with the existing coverage data since the last `make covzero`.
|
|
|
|
### Per-test-case code coverage
|
|
|
|
**Note**: Per-test-case coverage support is of very limited use because of
|
|
deficiencies in the coverage data processing utilities (see below).
|
|
|
|
If the __`--coverage`__ option is given to a test script, then it sets the
|
|
`GCOV_PREFIX` and `GCOV_PREFIX_STRIP` environment variables while running each
|
|
test case, causing each case's generated [GCDA][] coverage data files to be
|
|
created under the case's own log directory:
|
|
|
|
./testlog/
|
|
SCRIPTNAME/
|
|
N.TestCaseName.RESULT/
|
|
log.txt
|
|
gcov/
|
|
home/username/src/serval-dna/objs_servald/cli.gcda
|
|
home/username/src/serval-dna/objs_servald/commandline.gcda
|
|
...
|
|
home/username/src/serval-dna/objs_servald/nacl/src/crypto_auth_hmacsha256_ref/hmac.c
|
|
...
|
|
|
|
In theory, these per-test-case [GCDA][] data files could be merged to produce
|
|
coverage data for any desired combination of test cases, but there is currently
|
|
no command-line utility available to perform this merge. The code for merging
|
|
undoubtably exists in the *libgcov* [atexit(3)][] callback, which sums the
|
|
process's accumulated execution counts into any existing [GCDA][] files, but no
|
|
work has been done to extract this code into a utility.
|
|
|
|
If the __`--geninfo`__ option is given (which implies `--coverage`), the test
|
|
framework will invoke [geninfo][] after each test case completes, to generate
|
|
one [lcov][] *tracefile* per case named `coverage.info` located in the case's
|
|
own log directory:
|
|
|
|
./testlog/
|
|
SCRIPTNAME/
|
|
N.TestCaseName.RESULT/
|
|
log.txt
|
|
coverage.info
|
|
|
|
**Note**: The `--geninfo` option must be accompanied by at least one
|
|
__`--gcno-dir=PATH`__ option, or the `TFW_GCNO_PATH` environment variable must
|
|
be set to a list of colon-separated directory paths. The test framework
|
|
recursively searches all these directories looking for [GCNO][] files, which it
|
|
then supplies to [geninfo][], which uses them to find the source files and
|
|
[GCDA][] files produced by `--coverage`.
|
|
|
|
The per-test-case tracefiles produced by [geninfo][] may be merged together
|
|
using the `lcov --add-tracefile` option, and may also be combined into a single
|
|
coverage report by passing many tracefile arguments to the [genhtml][] utility.
|
|
Unfortunately, both of these operations are prohibitively slow, which makes the
|
|
`--geninfo` option of limited use for the time being.
|
|
|
|
-----
|
|
**Copyright 2013 Serval Project Inc.**
|
|
![CC-BY-4.0](./cc-by-4.0.png)
|
|
This document is available under the [Creative Commons Attribution 4.0 International licence][CC BY 4.0].
|
|
|
|
|
|
[Serval Project]: http://www.servalproject.org/
|
|
[CC BY 4.0]: ./LICENSE-DOCUMENTATION.md
|
|
[Serval DNA]: ../README.md
|
|
[Bash]: http://en.wikipedia.org/wiki/Bash_(Unix_shell)
|
|
[Bash Test Framework]: http://developer.servalproject.org/dokuwiki/doku.php?id=content:tech:bash_test_framework
|
|
[GNU grep]: http://www.gnu.org/software/grep/
|
|
[GNU sed]: http://www.gnu.org/software/sed/
|
|
[GNU awk]: http://www.gnu.org/software/gawk/
|
|
[pgrep]: http://en.wikipedia.org/wiki/Pgrep
|
|
[pkill]: http://en.wikipedia.org/wiki/Pkill
|
|
[integration tests]: http://en.wikipedia.org/wiki/Integration_testing
|
|
[boilerplate code]: http://en.wikipedia.org/wiki/Boilerplate_code
|
|
[TAP]: http://en.wikipedia.org/wiki/Test_Anything_Protocol
|
|
[source code test coverage]: http://en.wikipedia.org/wiki/Code_coverage
|
|
[GCC]: https://gcc.gnu.org/
|
|
[gcov(1)]: https://gcc.gnu.org/onlinedocs/gcc/Gcov.html
|
|
[GCNO]: https://gcc.gnu.org/onlinedocs/gcc-3.4.2/gcc/Gcov-Data-Files.html
|
|
[GCDA]: https://gcc.gnu.org/onlinedocs/gcc-3.4.2/gcc/Gcov-Data-Files.html
|
|
[lcov]: http://ltp.sourceforge.net/archive/old_pages/coverage/lcov.php
|
|
[geninfo]: http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php
|
|
[genhtml]: http://ltp.sourceforge.net/coverage/lcov/genhtml.1.php
|
|
[atexit(3)]: http://man7.org/linux/man-pages/man3/atexit.3.html
|