S E S P

 Coverage Analysis for Fortran 95 - Using g95 and gcov

 

The Software
Engineering Group

Computational Science & Engineering
CLRC Rutherford Appleton Laboratory


Coverage analysis allows developers to examing where their test deck does not exercise the code. There are many types of coverage analysis including:

  • Statement Coverage - Which lines in the code have been executed and how may times?
  • Decision Coverage - Have boolean expressions in decision statements evaluated to true and false?
  • Condition Coverage - Have all values of the sub-expressions in decision statements evaluated to true and false?
We will only consider statement coverage here.

This example was run on hsl.rl.ac.uk which provides the correct gcov library to use with g95 and the correct version of gcov.

Coverage analysis is performed via the following 3 steps

  1. Compile and link your Fortran source with gfortran or/home/mathsoft/bin/g95 (the full path is important) using the options:
      -fprofile-arcs -ftest-coverage
    It isn't necessary to compile all files with these options, only those for which you require coverage data. A .gcno file is produced for each file compiled.
  1. Run your executable. This produces a .gcda file (for each file compiled with the options above) with coverage results in.
    If the .gcda is left from one run to the next, coverage data are accumulated in this file.
  1. Run GCOV:
      gcov4 <file(s)>
    where the arguments are the source files for which you would like coverage information.

    A summary for each file is printed e.g.

      File 'hellomod.f90'
      Lines executed:100.00% of 6
      hellomod.f90:creating 'hellomod.f90.gcov'

    Look at the .gcov file to see source code annotated with line execution counts.

More details on GCOV can be found with man gcov or gcov4 -h at the command line or at http://gcc.gnu.org/onlinedocs/gcc-3.0/gcc_8.html


Example


1) Compile

gfortran -g -c -fprofile-arcs -ftest-coverage array_test.f90
gfortran -o array_test -fprofile-arcs -ftest-coverage array_test.o

2) Run executable

./array_test
 Sum of array is   1.6777216E+07

3) Run GCOV

gcov4 array_test
array_test.gcno:version '401e', prefer '400R'
array_test.gcda:version '401e', prefer version '400R'
File 'array_test.f90'
Lines executed:100.00% of 7
array_test.f90:creating 'array_test.f90.gcov'

I ignore the warnings about gcno and gcda file versions.

Contents of output file array_test.f90.gcov

        -:    0:Source:array_test.f90
        -:    0:Graph:array_test.gcno
        -:    0:Data:array_test.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:program array_test
        -:    2:
        -:    3:  implicit none
        -:    4:
        -:    5:  integer, parameter          :: array_size = 100000000
        -:    6:  real, dimension(array_size) :: a
        -:    7:  real                        :: total
        -:    8:  integer                     :: i
        -:    9:
        -:   10:  interface
        -:   11:
        -:   12:    subroutine sum_array(array, total)
        -:   13:
        -:   14:      real, dimension(:), intent(in) :: array
        -:   15:      real, intent(out)              :: total
        -:   16:
        -:   17:    end subroutine sum_array
        -:   18:
        -:   19:  end interface
        -:   20:
        1:   21:  forall (i=1:size(a)) a(i) = 1
        -:   22:
        1:   23:  call sum_array(a, total)
        -:   24:
        1:   25:  write(6,*)'Sum of array is ',total
        -:   26:
        -:   27:end program array_test
        -:   28:
        1:   29:subroutine sum_array(array, total)
        -:   30:
        -:   31:  real, dimension(:), intent(in) :: array
        -:   32:  real, intent(out)              :: total
        -:   33:  integer                        :: i
        -:   34:
        1:   35:  total = 0.0
100000001:   36:  do i = 1,size(array)
100000000:   37:    total = total + array(i)
        -:   38:  enddo
        -:   39:
        -:   40:  ! the following doesn't work because total is not updated during iteration
        -:   41:  ! forall (i=1:size(array)) total = total + array(i)
        -:   42:
        -:   43:end subroutine sum_array






 

SESP Homepage