CodeCoverage

Code Coverage

Coverage analysis shows you how much different code branches get used. This is useful to see if all code is covered by tests and to identify performance problems.

Usage

Since compile and run times are significantly increased by these flags, you may want to only use these flags inside a given dll directory or even just one .c file (e.g. myfile.c):

  1. cd to the build tree for myfile.c, where myfile.o is generated
  2. run "make clean && make EXTRACFLAGS=--coverage LDFLAGS=--coverage"

  3. Then, run a program. E.g. part of the testsuite or a real world application
  4. Now, in the ""build tree"" run "gcov myfile.c", even if there is no myfile.c in that folder
  5. You get a list with some stats of the generated *.c.gcov along with some *.h.gcov
  6. Most likely you want to open myfile.c.gcov

The *.c.gcov file has three columns: the number of times a line was run, the line number, and the actual text of the line. Note: If a line was optimized out by the compiler, it will appear as if it was never run.

There are three states the execution count can have:

  1. ""-"" is for lines without code
  2. ""#####"" are lines which never got executed
  3. A number tells you how often that line got executed, watch out for optimizations which can distort the value of blocks

Example

The following is an example situation where using gcov to determine the coverage of a file could be helpful. We'll use the dlls/advapi32/registry.c file. At the time of this writing, the function RegSetValueW had the following lines in it:

    if (name && name[0])  /* need to create the subkey */
    {
        if ((ret = RegCreateKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
    }

Currently there are a few tests written to test this function. However, these tests don't check that everything is correct. Using gcov and directed tests, we can validate the correctness of this line of code. First, we see what has been tested already by running gcov on the file. To do this, do the following:

cd dlls/advapi32
make clean && make EXTRACFLAGS=--coverage LDFLAGS=--coverage
cd tests
make test
cd ..
gcov registry.c
less registry.c.gcov

The interesting code part looks like this in registry.c.gcov:

        4: 1273:    if (name && name[0])  /* need to create the subkey */
        -: 1274:    {
    #####: 1275:        if ((ret = RegCreateKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
        -: 1276:    }

Line 1275 is never executed, most likely because "name" is never passed to the function. In order to validate this line, we need to do two things. First, we must write the test:

    ret = RegSetValueW(hkey_main, name1W, REG_SZ, string1W, sizeof(string1W));
    ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError());
    test_hkey_main_Value_A(name1A, string1A, sizeof(string1A));
    test_hkey_main_Value_W(name1W, string1W, sizeof(string1W));

Once we add in this test case, we now want to know if the line in question is run by this test and works as expected. You should be in the same directory as in the previous command example. The only difference is that we have to remove the *.gcda files in order to start the count over. (If we leave the files then the number of times the line is run is just added, e.g. line 545 below would be run 19 times.) We remove the *.gcov files because they are out of date and need to be recreated.

rm *.gcda *.gcov
cd tests
make
make test
cd ..
cd ..
gcov registry.c
less registry.c.gcov

The interesting code part looks like this in registry.c.gcov:

        5: 1273:    if (name && name[0])  /* need to create the subkey */
        -: 1274:    {
        1: 1275:        if ((ret = RegCreateKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
        -: 1276:    }

Based on gcov, we now know that line 1275 is executed once. And since all of our other tests have remain unchanged, we can assume that the one time it is executed is to satisfy the testcase we added where we check for it. Thus we have validated a line of code. While this is a cursory example, it demonstrates the potential usefulness of this tool.

See also

CodeCoverage (last edited 2012-02-14 21:23:48 by AustinEnglish)