Site Network: Home |

Gcov and Python3k C coverage

Gcov is a very handy tool. I've been using it for a while now to manually trace the C code coverage of different Python 2.6 modules.

Gcov Usage:

To use gcov with a C source file for code coverage, you have to compile your code with GCC and pass it two arguments at the compile time, "-fprofile-arcs -ftest-coverage". For example if you have a source file named "main.c", you would compile it as:

$gcc -o main -fprofile-arcs -ftest-coverage main.c

The compiler will compile your source file and produce another file named "main.gcno". Now run:

$gcov main

You will see that gcov will report 0% code coverage as you haven't run the compiled code yet. Run the compiled program and then use gcov for code coverage report again:

$./main
$gcov main

Depending on how much code in your program is executed, gcov will report the code coverage percentage, and will also produce two new files named "main.c.gcov" and "main.gcda". "main.c.gcov" is the file that holds the record of what lines were executed in your source file and how many times.

Using Gcov with Python:

There is a bit of a problem with Gcov. You need to statically link all of your code into your program in order to get code coverage analysis on it. Python doesn't do that automatically, and there is no easy configure switch to do it. So you have to manually play with the configurations to get different modules statically linked in. To compile a module statically, one way to do is to copy its entry from Modules/Setup into Modules/Setup.local, and put it under a "*static*" heading (without the quotes).

Lets say you want to compile the "mmap" module statically. First just start your python interpreter and import mmap. Now check for the __file__ attribute of the module:

>>>import mmap
>>>print mmap.__file__

The interpreter will print the module's location on the hard drive from where it was imported. Lets compile this module statically into the python interpreter now. We copy its entry from the Modules/Setup file in the python source tree into Modules/Setup.local, and put it under a *static* heading:

*static*
mmap mmapmodule.c -I$(prefix)/include -fprofile-arcs -ftest-coverage -L$(exec_prefix)/lib -lz -lgcov

The part after mmapmodule.c is to make this module work with gcov so we could get coverage report on it. Now compile your python interpreter and look for mmap's __file__ attribute again. This time you will see no such attribute defined for the module, which means it is built in this time.

Changing current directory into Modules and listing files will show that gcov has produced its data files for the mmapmodule. Run gcov on it to get the current coverage reports.

$gcov mmapmodule

You might get some code coverage for it since the import of the module into your python environment runs some of the initialization code. Had you run gcov on it without importing it first, you would have got 0% code coverage. Here is what I get:

File '/usr/include/sys/sysmacros.h'
Lines executed:0.00% of 6
/usr/include/sys/sysmacros.h:creating 'sysmacros.h.gcov'

File '/usr/include/sys/stat.h'
Lines executed:0.00% of 12
/usr/include/sys/stat.h:creating 'stat.h.gcov'

File './Modules/mmapmodule.c'
Lines executed:0.00% of 476
./Modules/mmapmodule.c:creating 'mmapmodule.c.gcov'
./Modules/mmapmodule.c:cannot open source file

Now lets run the mmap testing code and see how much of the actual code this test suite exercises:

$./python Lib/test/test_mmap.py -v
$cd Modules
$gcov mmapmodule

File '/usr/include/sys/sysmacros.h'
Lines executed:0.00% of 6
/usr/include/sys/sysmacros.h:creating 'sysmacros.h.gcov'

File '/usr/include/sys/stat.h'
Lines executed:0.00% of 12
/usr/include/sys/stat.h:creating 'stat.h.gcov'

File './Modules/mmapmodule.c'
Lines executed:71.64% of 476
./Modules/mmapmodule.c:creating 'mmapmodule.c.gcov'
./Modules/mmapmodule.c:cannot open source file

71.64% of the module is exercised by the test suite.

What's Next:

I have traced the code coverage of a number of modules by now. Next is to look for a way to easily compile a major number of modules statically into the Python interpreter so to easily get an automated code coverage report on it. This can be done by uncommenting appropriate entries for the modules in Module/Setup file, but I've been getting into a few problems with it right now. Solving that is the first task, and then the part of making figleaf do all of this automatically.

0 Comments:

Post a Comment