Trivial unit testing and coverage checking for C libraries
Recently I added a version script and the start of a test suite (under valgrind) to the Theora video codec. Apart from locating a trivial leak in the encoder, doing so turned up some interesting oddities.
The Version Script lists all public symbols, and tells the linker to only export these. This was added to avoid symbol clashes with other libraries. This usage is similar to a .def file for MSVC. A Version Script also allows pattern matching and definition of multiple API versions.
The tests I added are fairly trivial. One is a 'noop' test which simply creates and destroys each kind of data structure the library provides. By using GNU Automake's TESTS_ENVIRONMENT to (optionally) run the tests under valgrind, we can determine if the library contains memory leaks in its constructors and destructors.
One of the tests uses all of the theora_comment_*() API functions, and checks the correctness of return values and errors. If we're happy that a set of tests covers all API functions, then we can be reasonably happy that if it passes, the API is:
- completely exported by the linker (the test runs at all),
- does not contain any memory leaks (as valgrind doesn't complain),
- and is correctly implemented (as the test passes).
When using GNU Automake, make distcheck will fail if any tests fail. make distcheck should be used to create distribution tarballs, the point being that you ensure all tests pass before release. make distcheck also has other nice benefits like testing that install and uninstall works correctly.
One of the requirements for the theora reference implementation is to minimize dependencies. More detailed testing and analysis can be achieved with check and gcov, but the above is a fairly low-impact approach suitable for most C libraries.
