Sam Trenholme's webpage
Support this website

MaraDNS 3.5.0015

 

August 29 2020

I have released MaraDNS 3.5.0015, with coLunacyDNS declared stable. 523 words

==Making coLunacyDNS stable==

To declare coLunacyDNS stable, I first had to declare it feature complete: I will add no more features to coLunacyDNS (for now). Instead, I tested coLunacyDNS to make it stable.

So, I began testing coLunacyDNS, with a handful of informal tests to make sure it ran correctly. It did. But, then, I asked myself this: How can I see how many of coLunacyDNS’s lines we are running to make sure we are testing all of the code?

==gcov==

The tool to use with C language programs to see which lines we are testing against is gcov. There was no need for me to find and install gcov; it was included when I installed GCC on my CentOS 8 development system.

Some points about gcov:

  • To run gcov, we need to add the flags -fprofile-arcs -ftest-coverage when compiling our programs.
  • Only the files which we wish to measure test coverage for need to be compiled with these special flags. gcov will still happily measure test coverage, even if it uses libraries or routines not being measured.
  • We only need to run gcov once after running all of the tests, unless we wish to see a running tally of test coverage.
  • If a program is terminated abnormally (yes, SIGTERM is abnormal termination), then we will not get updated coverage results for the program. I had to alter the coLunacyDNS program to, when compiled in special test mode, have SIGALRM signal the coLunacyDNS service to break its main loop and terminate normally.
  • The files which gcov uses to tally results have the names (in CentOS 8) .gcda and .gcno. The process running the compiled program needs to be able to write to those files for test coverage to be updated.

Here’s a simple example of gcov in action:

$ cat > foo.c
#include <stdio.h>
int main() {
  puts("Hello, world!");
  return 0;
}
$ gcc -o foo foo.c -fprofile-arcs -ftest-coverage
$ ./foo
Hello, world!
$ gcov foo.c
File 'foo.c'
Lines executed:100.00% of 3
Creating 'foo.c.gcov'
$ cat foo.c.gcov
        -:    0:Source:foo.c
        -:    0:Graph:foo.gcno
        -:    0:Data:foo.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:#include <stdio.h>
        -:    2:
        1:    3:int main() {
        1:    4:  puts("Hello, world!");
        1:    5:  return 0;
        -:    6:}

If a line is not run, the .gcov file will have something that looks like this:

    #####:  123:  foo = bar;

==coLunacyDNS’s test coverage==

As of the MaraDNS 3.5.0015 release, coLunacyDNS has 92.73% test coverage. Some notes:

  • I compile coLunacyDNS in a special test mode when running the coverage tests.
  • Certain sanity and security tests which should be in the production code can not be readily run via a test (e.g. code which initializes the random number generator if not initialized, but the C code has already set it up), so I use #ifdef GCOV to hide those sanity tests in test mode.
  • #ifdef GCOV also adds the ability to run some code which can not be easily tested for (e.g. certain kinds of socket errors).

My goal is to get 100% test coverage, provided I #ifdef out code which can not be readily tested.

==Getting MaraDNS==

MaraDNS is available, as always, on its download page:

https://maradns.samiam.org/download.html

Did you know that all of my blog entries are available in a free to download eBook at https://www.samiam.org/blog/ebooks.html.