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:
Use gnatcov run to run your application within the instrumented environment, producing <yourapp.trace>:
gnatcov run <yourapp> [--target=<target>] [--kernel=<kernel>]
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:
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.
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:
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
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.