TEST COVERAGE WITH GCOV
=======================


Is a test coverage program

  - How often each line of code executes
  - What lines of code are actually executed


/* lib.h */
#ifndef LIB_H
#define LIB_H

int libfn1();
int libfn2(int b);

#endif /* LIB_H */


/* lib.cpp */
#include "lib.h"

int libfn1()
{
    int a =5;
    a++;
    return (a);
}

int libfn2( int b)
{
    if (b>10)
    {
        libfn1();
        return(b);
    }
    else
        return(0);
}


/* test.cpp */
#include "lib.h"

int main ()
{
     libfn1();
     libfn2(5);
}




$ g++ --coverage test.cpp lib.cpp  -o test1

  - generates .gcno files (flow graph) per source files
  - instruments teh object code


$ ls
lib.cpp  lib.gcno  lib.h  test1  test.cpp  test.gcno


$ ./test1
$ ls
lib.cpp  lib.gcda  lib.gcno  lib.h  test1  test.cpp  test.gcda  test.gcno


Running the program generates .gcda files, containing the coverage info.



Textual output
--------------

$ gcov -abcfu lib.c
Function '_Z6libfn2i'
Lines executed:60.00% of 5
No branches
No calls

Function '_Z6libfn1v'
Lines executed:100.00% of 4
No branches
No calls

File 'lib.cpp'
Lines executed:77.78% of 9
Branches executed:100.00% of 2
Taken at least once:50.00% of 2
Calls executed:0.00% of 1
Creating 'lib.cpp.gcov'



$ ls
lib.cpp       lib.gcda  lib.h  test.cpp   test.gcno
lib.cpp.gcov  lib.gcno  test1  test.gcda


.gcov files generated

$ cat lib.cpp.gcov
        -:    0:Source:lib.cpp
        -:    0:Graph:lib.gcno
        -:    0:Data:lib.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:#include "lib.h"
        -:    2:
function _Z6libfn1v called 1 returned 100% blocks executed 100%
        1:    3:int libfn1()
        1:    3-block  0
        -:    4:{
        1:    5:    int a =5;
        1:    6:    a++;
        1:    7:    return (a);
        1:    7-block  0
unconditional  0 taken 1
        -:    8:}
        -:    9:
function _Z6libfn2i called 1 returned 100% blocks executed 60%
        1:   10:int libfn2( int b)
        1:   10-block  0
        -:   11:{
        1:   12:    if (b>10)
        1:   12-block  0
branch  0 taken 0 (fallthrough)
branch  1 taken 1
        -:   13:    {
    #####:   14:        libfn1();
    $$$$$:   14-block  0
call    0 never executed
    #####:   15:        return(b);
unconditional  0 never executed
        -:   16:    }
        -:   17:    else
        1:   18:        return(0);
        1:   18-block  0
unconditional  0 taken 1
        -:   19:}
        -:   20:
        -:   21:



HTML output
-----------



$ lcov --directory . --capture --output-file app.info
Capturing coverage data from .
Found gcov version: 4.9.3
Scanning . for .gcda files ...
Found 2 data files in .
Processing test.gcda
geninfo: WARNING: cannot find an entry for lib.cpp.gcov in .gcno file, skipping file!
Processing lib.gcda
Finished .info-file creation

$ genhtml app.info
Reading data file app.info
Found 2 entries.
Found common filename prefix "/home/gsd/work/zolix/tanf/NNG/gmock/mytests/9"
Writing .css and .png files.
Generating output.
Processing file h/lib.cpp
Processing file h/test.cpp
Writing directory view page.
Overall coverage rate:
  lines......: 84.6% (11 of 13 lines)
  functions..: 100.0% (3 of 3 functions)




Problems with gcov
------------------



1. Gcov is thread-safe, e.g. works correctly with multi-threaded applications.
   But uses lock and storing counters for visited lines in close-proximity,
   therefore execution of multithreaded applications is _very_ slow.


2. Statement level coverage can not extract expressions. When there is a
   shortcut operator, we do not know whether the right hand side evaluated.



An expression-level instrumentation and coverage tool
-----------------------------------------------------

MooCov by Gabor Kozar:

https://github.com/shdnx/MooCoverage