Getting Started

General Principles

GNATcoverage provides coverage analysis facilities through the gnatcov command-line tool. gnatcov relies on an instrumented execution environment to produce execution traces instead of having to instrument to program itself. GNATemulator provides such an environment, offering support for coverage assessments directly on the target code in cross configurations. Hardware probes might be used as trace producers as well, provided trace data is converted to the format gnatcov expects.

GNATcoverage supports both source and object level coverage criteria: statement, decision, or mcdc coverage for the source level, and instruction or branch coverage for the object level. Once your application is built, a typical analysis proceeds in two steps:

  1. Use gnatcov run to run your application within the instrumented environment, producing <yourapp.trace>:

    gnatcov run <yourapp> [--target=<target>] [--kernel=<kernel>]
  2. Use gnatcov coverage to produce a coverage report from the execution trace, like:

    gnatcov coverage --level=<criterion> --annotate=<report-format>
       [--scos=@<libfiles-list> | -P<root-gpr>] [--routines=@<symbols-list>]
       <yourapp.trace>

Very briefly here:

  • --target selects the execution environment that will know how to produce execution traces, such as <target>-gnatemu for emulated configurations. Not providing this option requests instrumented execution on the native platform, using very system specific means available in only few configurations.
  • --kernel is necessary for cross configurations where an operating system kernel such as VxWorks is required to load and launch your applicative modules on top of the bare machine execution environment.
  • --level specifies the coverage criterion to be assessed (=stmt, =stmt+decision, or =stmt+mcdc for source levels; =insn or =branch for object levels)
  • --annotate specifies the desired output report format (synthetic list of coverage violations, text or html annotated sources, ...)
  • --scos is specific to the source level criteria, to convey the so called Source Coverage Obligations (statements, decisions, ...) to be processed. The argument value in the example here, using the @ notation, is the name of a file which contains the set of Ada ALI files or C GLI files corresponding to the source units of interest. This drives the assessment process and at the same time specifies the set of source units for which a report should be produced.
  • -P might be used instead of –scos, to designate a root GNAT project file from which the set of coverage obligations can be inferred using high level project abstractions such as source units closures or sub-projects dependencies.
  • --routines is specific to the object level criteria, and optional in this case. This conveys the set of object symbol names on which the analysis should focus, if any.

For source coverage assessments, sources must be compiled with -g -fpreserve-control-flow -fdump-scos. Optimization is supported up to -O1 and inlining is allowed. For backwards compatibility, for Ada -gnateS can be used as a synonym of -fdump-scos.

Object coverage analysis proceeds in a similar fashion, with different --level option values. There is no source coverage obligation involved (by definition of object coverage), so no --scos argument, and no specific constraint on the compilation options.

Beyond the simple cases sketched above, GNATcoverage supports advanced capabilities available for both source and object coverage criteria. Two examples are coverage consolidation, computing results for a set of execution traces, and exemption regions, allowing users to define code regions for which coverage violations are expected and legitimate.

The following chapters in this manual provide many more details on the various possible modes of operation. Prior to this, next in this chapter, comes a complete example sequence illustrating steps from compilation to coverage analysis of a very simple Ada program.

Example session

We start from the very basic Ada package below, with a spec and body in source files named ops.ads and ops.adb, exposing a set of very basic named operations over Integer objects:

package Ops is
  type Op_Kind is (Increment, Decrement);
  procedure Apply (Op : Op_Kind; X : in out Integer);
end Ops;

package body Ops is
  procedure Apply (Op : Op_Kind; X : in out Integer) is
  begin
     case Op is
        when Increment => X := X + 1;
        when Decrement => X := X - 1;
     end case;
  end Apply;
end Ops;

We analyse the coverage achieved by the sample unit test driver below, in test_inc.adb, which exercises the Increment operation only:

with Ops;
procedure Test_Inc is
  X : Integer := 4;
begin
  Ops.Apply (Ops.Increment, X);
  pragma Assert (X = 5);
end Test_Inc;

We use the GNAT Pro toolset for powerpc-elf to build, and GNATemulator for the same target (invoked by gnatcov run) to emulate. The executable construction is performed using gprbuild, operating on the following ops.gpr project file:

project Ops is
 for Languages use ("Ada");
 for Source_Dirs use (".");
 for Object_Dir use "obj";
end Ops;

First, we build with this command line:

gprbuild -p --target=powerpc-elf --RTS=powerpc-elf/zfp-prep -Pops.gpr test_inc.adb
 -cargs:Ada -fdump-scos -gnata -cargs -g -fpreserve-control-flow

In this particular case:

  • -p queries the creation of the “obj” object directory if it doesn’t exist. This is where the object, ALI, and executable files will reside.
  • --target and --RTS tell gprbuild which target toolchain and runtime library to use. Here, powerpc-elf and a zero-footprint library tailored for the prep GNATemulator board.
  • -Pops.gpr test_inc.adb designate the project file and the main unit to build.
  • -cargs:Ada sets the Ada specific compilation option and -cargs sets the more general ones in accordance with the guidelines stated earlier.

The build command produces a test_inc executable in the object subdirectory. Our second step is to execute this program within the instrumented execution environment, via GNATemulator, to obtain a test_inc.trace execution trace. We do this with gnatcov run, as follows:

gnatcov run --target=powerpc-elf obj/test_inc

Now, we can analyse the coverage achieved by this execution using gnatcov coverage, for example with the following command line:

gnatcov coverage --level=stmt --annotate=xcov test_inc.trace -Pops.gpr

Here, we request

  • A source statement coverage assessment with --level=stmt,
  • An annotated source report in text format with --annotate=xcov,
  • For the complete set of units involved in the executable, per -Pops.gpr and no specification otherwise in the project file.

This produces annotated sources in the current directory, with ops.adb.xcov quoted below:

examples/starter/src/ops.adb:
67% of 3 lines covered
Coverage level: stmt
 1 .: package body Ops is
 2 .:    procedure Apply (Op : Op_Kind; X : in out Integer) is
 3 .:    begin
 4 +:       case Op is
 5 +:          when Increment => X := X + 1;
 6 -:          when Decrement => X := X - 1;
 7 .:       end case;
 8 .:    end Apply;
 9 .: end Ops;

The analysis results are visible as + / - annotations on source lines, next to the line numbers. The results we have here indicate proper coverage of all the statements except the one dealing with a Decrement operation, indeed never exercised by our driver.

Focus on specific units, excluding the test driver from the analysis closure for example, can be achieved by adding a Coverage package to the project file or by using --scos=obj/ops.ali instead of -P.

Table Of Contents

Previous topic

GNATcoverage User’s Guide [GNATcoverage 1.2.0w (20130520)]

Next topic

Program Execution with gnatcov run

This Page