Skip to content

Commit 9d359e5

Browse files
committed
Introduce subprograms of interest
With this change, users now have the ability for finer-grained filtering - on a subprogram of interest basis. This changes actually provides more than that: filtering per scopes, which are identified by the <filename>:<line> of their specification declaration point for Ada, if they have any (otherwise it is the body declaration point), and by the body declaration point for C / C++. The subprograms of interest filtering is applied after all of the units of interest filtering has been applied. This means that if the users passes --subprograms=<ignored_file>:<line>, it won't be in the coverage report. To implement this, we use the logic implemented to support scope metrics, and refactor it to use trees instead of ad-hoc data structures.
1 parent 5fd3786 commit 9d359e5

29 files changed

+788
-392
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
with Pkg;
2+
3+
procedure Main is
4+
begin
5+
Pkg.Foo (1);
6+
Pkg.Bar;
7+
end Main;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
with Ada.Text_IO; use Ada.Text_IO;
2+
3+
package body Pkg is
4+
procedure Foo (I : Integer) is
5+
begin
6+
Put_Line ("Hello from Foo!");
7+
end Foo;
8+
9+
procedure Bar is
10+
begin
11+
Put_Line ("Hello from Bar!");
12+
end Bar;
13+
14+
end Pkg;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pragma Ada_2012;
2+
3+
package Pkg is
4+
procedure Foo (I : Integer) with Pre => I > 0;
5+
procedure Bar;
6+
end Pkg;
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
"""
2+
Check that the subprograms of interest mechanism works as expected, i.e.
3+
produces the right coverage expectations for source traces, and the right error
4+
message for binary traces.
5+
"""
6+
7+
import os
8+
import os.path
9+
10+
from SCOV.minicheck import build_and_run, check_xcov_reports
11+
from SUITE.context import thistest
12+
from SUITE.cutils import contents_of, Wdir
13+
from SUITE.tutils import gprfor, xcov
14+
from SUITE.gprutils import GPRswitches
15+
16+
tmp = Wdir("tmp_")
17+
18+
cov_args = build_and_run(
19+
gprsw=GPRswitches(
20+
gprfor(srcdirs=os.path.join("..", "src"), mains=["main.adb"])
21+
),
22+
covlevel="stmt",
23+
mains=["main"],
24+
extra_coverage_args=["-axcov"],
25+
)
26+
27+
# Produce a coverage report and a checkpoint with the subprogram switch. Check
28+
# that the coverage report contains only coverage data for the specific
29+
# subprogram for source traces. For binary traces, simply check that the
30+
# gnatcov coverage invocation yields the expected warning.
31+
os.mkdir("xcov_subp")
32+
xcov(
33+
cov_args
34+
+ [
35+
"--save-checkpoint",
36+
"trace.ckpt",
37+
"--subprograms",
38+
f"{os.path.join('..', 'src', 'pkg.ads')}:4",
39+
"--output-dir=xcov_subp",
40+
],
41+
out="coverage.log",
42+
)
43+
if thistest.options.trace_mode == "bin":
44+
thistest.fail_if_no_match(
45+
"gnatcov coverage output",
46+
"warning: Ignoring --subprograms switches as this is not supported with"
47+
" binary traces.",
48+
contents_of("coverage.log"),
49+
)
50+
else:
51+
check_xcov_reports(
52+
"*.xcov",
53+
{
54+
"main.adb.xcov": {},
55+
"pkg.adb.xcov": {"+": {6}},
56+
},
57+
"xcov_subp",
58+
)
59+
60+
# Then check that the checkpoint contains only coverage data for the specific
61+
# subprogram. To do this, produce a new coverage report from the checkpoint
62+
# without using the --subprograms switch.
63+
xcov(
64+
cov_args[:-1]
65+
+ ["--checkpoint", "trace.ckpt", "--output-dir=xcov_no_subp"]
66+
)
67+
check_xcov_reports(
68+
"*.xcov",
69+
{
70+
"main.adb.xcov": {"-": {5, 6}},
71+
"pkg.adb.xcov": {"+": {6}, "-": {11}},
72+
},
73+
"xcov_no_subp",
74+
)
75+
76+
# Also check the warnings when the subprogram switch is ill-formed
77+
78+
# Case 1: missing colon in the argument
79+
xcov(
80+
cov_args + ["--subprograms", "no-colon"],
81+
out="xcov-wrong1.txt",
82+
register_failure=False,
83+
)
84+
thistest.fail_if_no_match(
85+
what="unexpected coverage output",
86+
regexp=r".*Wrong argument passed to --subprograms: .*",
87+
actual=contents_of("xcov-wrong1.txt"),
88+
)
89+
90+
# Case 2: line number is not a number
91+
xcov(
92+
cov_args + ["--subprograms", f"{os.path.join('..', 'src', 'pkg.ads')}:b",],
93+
out="xcov-wrong2.txt",
94+
register_failure=False,
95+
)
96+
thistest.fail_if_no_match(
97+
what="unexpected coverage output",
98+
regexp=r".*Wrong argument passed to --subprograms: .*",
99+
actual=contents_of("xcov-wrong2.txt"),
100+
)
101+
102+
# Case 3: file does not exist
103+
xcov(
104+
cov_args + ["--subprograms", "dumb-file-name:4"],
105+
out="xcov-wrong3.txt",
106+
register_failure=False,
107+
)
108+
thistest.fail_if_no_match(
109+
what="unexpected coverage output",
110+
regexp=r".*Error when parsing --subprograms argument dumb-file-name:4:"
111+
r".*dumb-file-name does not exist",
112+
actual=contents_of("xcov-wrong3.txt"),
113+
)
114+
115+
116+
117+
thistest.result()

tools/gnatcov/annotations-cobertura.adb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,8 @@ package body Annotations.Cobertura is
253253

254254
Pp.Need_Sources := False;
255255

256-
Annotations.Generate_Report (Pp, True, Subdir => "cobertura");
256+
Annotations.Generate_Report
257+
(Pp, True, Context.Subps_Of_Interest, Subdir => "cobertura");
257258
Free (Pp.Source_Prefix_Pattern);
258259
end Generate_Report;
259260

tools/gnatcov/annotations-dynamic_html.adb

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,10 @@ package body Annotations.Dynamic_Html is
150150

151151
procedure Pretty_Print_End_File (Pp : in out Dynamic_Html);
152152

153-
procedure Pretty_Print_Scope_Entity
154-
(Pp : in out Dynamic_Html;
155-
Scope_Ent : Scope_Entity);
153+
procedure Pretty_Print_Scope_Entities
154+
(Pp : in out Dynamic_Html;
155+
File : Source_File_Index;
156+
Scope_Entities : Scope_Entities_Tree);
156157

157158
procedure Pretty_Print_Start_Line
158159
(Pp : in out Dynamic_Html;
@@ -294,8 +295,9 @@ package body Annotations.Dynamic_Html is
294295
begin
295296
Annotations.Generate_Report
296297
(Pp,
297-
Show_Details => True,
298-
Subdir => "html");
298+
Show_Details => True,
299+
Subp_Of_Interest => Context.Subps_Of_Interest,
300+
Subdir => "html");
299301
end Generate_Report;
300302

301303
------------------------
@@ -516,15 +518,18 @@ package body Annotations.Dynamic_Html is
516518
Append (Pp.Source_List, Simplified);
517519
end Pretty_Print_End_File;
518520

519-
-------------------------------
520-
-- Pretty_Print_Scope_Entity --
521-
-------------------------------
521+
---------------------------------
522+
-- Pretty_Print_Scope_Entities --
523+
---------------------------------
522524

523-
procedure Pretty_Print_Scope_Entity
524-
(Pp : in out Dynamic_Html;
525-
Scope_Ent : Scope_Entity)
525+
procedure Pretty_Print_Scope_Entities
526+
(Pp : in out Dynamic_Html;
527+
File : Source_File_Index;
528+
Scope_Entities : Scope_Entities_Tree)
526529
is
527-
function To_JSON (Scope_Ent : Scope_Entity) return JSON_Value;
530+
use Scope_Entities_Trees;
531+
532+
function To_JSON (Cur : Cursor) return JSON_Value;
528533
-- Convert a scope entity to a JSON scoped metric: compute line and
529534
-- obligation statistics for the given scope and recursively for
530535
-- child scopes. Store the result as a JSON object, with the name and
@@ -534,37 +539,41 @@ package body Annotations.Dynamic_Html is
534539
-- To_JSON --
535540
-------------
536541

537-
function To_JSON (Scope_Ent : Scope_Entity) return JSON_Value is
542+
function To_JSON (Cur : Cursor) return JSON_Value
543+
is
544+
Scope_Ent : constant Scope_Entity := Element (Cur);
545+
Child : Cursor := First_Child (Cur);
546+
538547
Scope_Metrics_JSON : constant JSON_Value := Create_Object;
539548
Children_Scope_Metrics_JSON : JSON_Array;
540-
FI : constant File_Info_Access :=
541-
Get_File (First_Sloc (Scope_Ent.From).Source_File);
542-
Line_Stats : constant Li_Stat_Array :=
549+
-- Representation of the scope metrics for the html format
550+
551+
Line_Stats : constant Li_Stat_Array :=
543552
Line_Metrics
544-
(FI,
553+
(Get_File (File),
545554
First_Sloc (Scope_Ent.From).L.Line,
546555
Last_Sloc (Scope_Ent.To).L.Line);
547-
Ob_Stats : constant Ob_Stat_Array :=
556+
Ob_Stats : constant Ob_Stat_Array :=
548557
Obligation_Metrics (Scope_Ent.From, Scope_Ent.To);
549558
begin
550559
Scope_Metrics_JSON.Set_Field ("scopeName", Scope_Ent.Name);
551560
Scope_Metrics_JSON.Set_Field ("scopeLine", Scope_Ent.Sloc.Line);
552561
Scope_Metrics_JSON.Set_Field ("stats", To_JSON (Line_Stats));
553562
Scope_Metrics_JSON.Set_Field ("enAllStats", To_JSON (Ob_Stats));
554-
for Child_Scope_Ent of Scope_Ent.Children loop
555-
Append
556-
(Children_Scope_Metrics_JSON,
557-
To_JSON (Child_Scope_Ent.all));
563+
while Has_Element (Child) loop
564+
Append (Children_Scope_Metrics_JSON, To_JSON (Child));
565+
Child := Next_Sibling (Child);
558566
end loop;
559567
Scope_Metrics_JSON.Set_Field
560-
("children",
561-
Create (Children_Scope_Metrics_JSON));
568+
("children", Create (Children_Scope_Metrics_JSON));
562569
return Scope_Metrics_JSON;
563570
end To_JSON;
564571

565572
begin
566-
Pp.Scope_Metrics := To_JSON (Scope_Ent);
567-
end Pretty_Print_Scope_Entity;
573+
for Cur in Scope_Entities.Iterate_Children (Scope_Entities.Root) loop
574+
Pp.Scope_Metrics := To_JSON (Cur);
575+
end loop;
576+
end Pretty_Print_Scope_Entities;
568577

569578
-----------------------------
570579
-- Pretty_Print_Start_Line --

tools/gnatcov/annotations-html.adb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ package body Annotations.Html is
224224
Annotations.Generate_Report
225225
(Pp,
226226
Show_Details,
227+
Context.Subps_Of_Interest,
227228
Subdir => (if Show_Details then "shtml+" else "shtml"));
228229
end Generate_Report;
229230

tools/gnatcov/annotations-report.adb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ package body Annotations.Report is
242242
Open_Report_File (Final_Report_Name.all);
243243
end if;
244244

245-
Annotations.Generate_Report (Pp, True);
245+
Annotations.Generate_Report (Pp, True, Context.Subps_Of_Interest);
246246
Close_Report_File;
247247
end Generate_Report;
248248

tools/gnatcov/annotations-xcov.adb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ package body Annotations.Xcov is
8888
Annotations.Generate_Report
8989
(Pp,
9090
Show_Details,
91+
Context.Subps_Of_Interest,
9192
Subdir => (if Pp.Show_Details then "xcov+" else "xcov"),
9293
Clean_Pattern => "*.xcov");
9394
end Generate_Report;

tools/gnatcov/annotations-xml.adb

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,10 @@ package body Annotations.Xml is
138138

139139
procedure Pretty_Print_End_File (Pp : in out Xml_Pretty_Printer);
140140

141-
procedure Pretty_Print_Scope_Entity
142-
(Pp : in out Xml_Pretty_Printer;
143-
Scope_Ent : Scope_Entity);
141+
procedure Pretty_Print_Scope_Entities
142+
(Pp : in out Xml_Pretty_Printer;
143+
File : Source_File_Index;
144+
Scope_Entities : Scope_Entities_Tree);
144145

145146
procedure Pretty_Print_Start_Line
146147
(Pp : in out Xml_Pretty_Printer;
@@ -293,7 +294,8 @@ package body Annotations.Xml is
293294
Context => Context,
294295
others => <>);
295296
begin
296-
Annotations.Generate_Report (Pp, True, Subdir => "xml");
297+
Annotations.Generate_Report
298+
(Pp, True, Context.Subps_Of_Interest, Subdir => "xml");
297299
end Generate_Report;
298300

299301
-------
@@ -565,36 +567,54 @@ package body Annotations.Xml is
565567
Dest_Index);
566568
end Pretty_Print_Start_File;
567569

568-
-------------------------------
569-
-- Pretty_Print_Scope_Entity --
570-
-------------------------------
570+
---------------------------------
571+
-- Pretty_Print_Scope_Entities --
572+
---------------------------------
571573

572-
procedure Pretty_Print_Scope_Entity
573-
(Pp : in out Xml_Pretty_Printer;
574-
Scope_Ent : Scope_Entity)
574+
procedure Pretty_Print_Scope_Entities
575+
(Pp : in out Xml_Pretty_Printer;
576+
File : Source_File_Index;
577+
Scope_Entities : Scope_Entities_Tree)
575578
is
576-
FI : constant File_Info_Access :=
577-
Get_File (First_Sloc (Scope_Ent.From).Source_File);
578-
begin
579-
Pp.ST ("scope_metric",
580-
A ("scope_name", Scope_Ent.Name)
581-
& A ("scope_line", Img (Scope_Ent.Sloc.Line)));
582-
Print_Coverage_Li_Stats
583-
(Pp,
584-
Line_Metrics
585-
(FI,
586-
First_Sloc (Scope_Ent.From).L.Line,
587-
Last_Sloc (Scope_Ent.To).L.Line),
588-
Dest_Compilation_Unit);
589-
Print_Coverage_Ob_Stats
590-
(Pp,
591-
Obligation_Metrics (Scope_Ent.From, Scope_Ent.To),
592-
Dest_Compilation_Unit);
593-
for Child of Scope_Ent.Children loop
594-
Pp.Pretty_Print_Scope_Entity (Child.all);
579+
use Scope_Entities_Trees;
580+
581+
procedure Pp_Scope_Entity (Cur : Cursor);
582+
583+
---------------------
584+
-- Pp_Scope_Entity --
585+
---------------------
586+
587+
procedure Pp_Scope_Entity (Cur : Cursor)
588+
is
589+
Scope_Ent : constant Scope_Entity := Element (Cur);
590+
Child : Cursor := First_Child (Cur);
591+
begin
592+
Pp.ST ("scope_metric",
593+
A ("scope_name", Scope_Ent.Name)
594+
& A ("scope_line", Img (Scope_Ent.Sloc.Line)));
595+
Print_Coverage_Li_Stats
596+
(Pp,
597+
Line_Metrics
598+
(Get_File (File),
599+
First_Sloc (Scope_Ent.From).L.Line,
600+
Last_Sloc (Scope_Ent.To).L.Line),
601+
Dest_Compilation_Unit);
602+
Print_Coverage_Ob_Stats
603+
(Pp,
604+
Obligation_Metrics (Scope_Ent.From, Scope_Ent.To),
605+
Dest_Compilation_Unit);
606+
while Has_Element (Child) loop
607+
Pp_Scope_Entity (Child);
608+
Child := Next_Sibling (Child);
609+
end loop;
610+
Pp.ET ("scope_metric");
611+
end Pp_Scope_Entity;
612+
613+
begin
614+
for Cur in Scope_Entities.Iterate_Children (Scope_Entities.Root) loop
615+
Pp_Scope_Entity (Cur);
595616
end loop;
596-
Pp.ET ("scope_metric");
597-
end Pretty_Print_Scope_Entity;
617+
end Pretty_Print_Scope_Entities;
598618

599619
----------------------------------------
600620
-- Pretty_Print_Start_Instruction_Set --

0 commit comments

Comments
 (0)