xref: /openbsd/gnu/usr.bin/gcc/gcc/testsuite/lib/gcov.exp (revision c87b03e5)
1*c87b03e5Sespie#   Copyright (C) 1997, 2001 Free Software Foundation, Inc.
2*c87b03e5Sespie
3*c87b03e5Sespie# This program is free software; you can redistribute it and/or modify
4*c87b03e5Sespie# it under the terms of the GNU General Public License as published by
5*c87b03e5Sespie# the Free Software Foundation; either version 2 of the License, or
6*c87b03e5Sespie# (at your option) any later version.
7*c87b03e5Sespie#
8*c87b03e5Sespie# This program is distributed in the hope that it will be useful,
9*c87b03e5Sespie# but WITHOUT ANY WARRANTY; without even the implied warranty of
10*c87b03e5Sespie# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11*c87b03e5Sespie# GNU General Public License for more details.
12*c87b03e5Sespie#
13*c87b03e5Sespie# You should have received a copy of the GNU General Public License
14*c87b03e5Sespie# along with this program; if not, write to the Free Software
15*c87b03e5Sespie# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*c87b03e5Sespie
17*c87b03e5Sespie# Verify various kinds of gcov output: line counts, branch percentages,
18*c87b03e5Sespie# and call return percentages.  None of this is language-specific.
19*c87b03e5Sespie
20*c87b03e5Sespieglobal GCOV
21*c87b03e5Sespie
22*c87b03e5Sespie#
23*c87b03e5Sespie# clean-gcov -- delete the working files the compiler creates for gcov
24*c87b03e5Sespie#
25*c87b03e5Sespie# TESTCASE is the name of the test.
26*c87b03e5Sespie#
27*c87b03e5Sespieproc clean-gcov { testcase } {
28*c87b03e5Sespie    set basename [file tail $testcase]
29*c87b03e5Sespie    set base [file rootname $basename]
30*c87b03e5Sespie    remote_file host delete $base.bb $base.bbg $base.da $basename.gcov
31*c87b03e5Sespie}
32*c87b03e5Sespie
33*c87b03e5Sespie#
34*c87b03e5Sespie# verify-lines -- check that line counts are as expected
35*c87b03e5Sespie#
36*c87b03e5Sespie# TESTCASE is the name of the test.
37*c87b03e5Sespie# FILE is the name of the gcov output file.
38*c87b03e5Sespie#
39*c87b03e5Sespieproc verify-lines { testcase file } {
40*c87b03e5Sespie    #send_user "verify-lines\n"
41*c87b03e5Sespie    set failed 0
42*c87b03e5Sespie    set fd [open $file r]
43*c87b03e5Sespie    while { [gets $fd line] >= 0 } {
44*c87b03e5Sespie	if [regexp "^ *(\[^:]*): *(\[0-9\]+):.*count\\((\[0-9\]+)\\)" \
45*c87b03e5Sespie		"$line" all is n shouldbe] {
46*c87b03e5Sespie	    if { $is == "" } {
47*c87b03e5Sespie		fail "$n:no data available for this line"
48*c87b03e5Sespie		incr failed
49*c87b03e5Sespie	    } elseif { $is != $shouldbe } {
50*c87b03e5Sespie		fail "$n:is $is:should be $shouldbe"
51*c87b03e5Sespie		incr failed
52*c87b03e5Sespie	    }
53*c87b03e5Sespie	}
54*c87b03e5Sespie    }
55*c87b03e5Sespie    return $failed
56*c87b03e5Sespie}
57*c87b03e5Sespie
58*c87b03e5Sespie#
59*c87b03e5Sespie# verify-branches -- check that branch percentages are as expected
60*c87b03e5Sespie#
61*c87b03e5Sespie# TESTCASE is the name of the test.
62*c87b03e5Sespie# FILE is the name of the gcov output file.
63*c87b03e5Sespie#
64*c87b03e5Sespie# Checks are based on comments in the source file.  This means to look for
65*c87b03e5Sespie# branch percentages 10 or 90, 20 or 80, and # 70 or 30:
66*c87b03e5Sespie#     /* branch(10, 20, 70) */
67*c87b03e5Sespie# This means that all specified percentages should have been seen by now:
68*c87b03e5Sespie#     /* branch(end) */
69*c87b03e5Sespie# All specified percentages must also be seen by the next branch(n) or
70*c87b03e5Sespie# by the end of the file.
71*c87b03e5Sespie#
72*c87b03e5Sespie# Each check depends on the compiler having generated the expected
73*c87b03e5Sespie# branch instructions.  Don't check for branches that might be
74*c87b03e5Sespie# optimized away or replaced with predicated instructions.
75*c87b03e5Sespie#
76*c87b03e5Sespieproc verify-branches { testcase file } {
77*c87b03e5Sespie    #send_user "verify-branches\n"
78*c87b03e5Sespie    set failed 0
79*c87b03e5Sespie    set shouldbe ""
80*c87b03e5Sespie    set fd [open $file r]
81*c87b03e5Sespie    set n 0
82*c87b03e5Sespie    while { [gets $fd line] >= 0 } {
83*c87b03e5Sespie	regexp "^\[^:\]+: *(\[0-9\]+):" "$line" all n
84*c87b03e5Sespie	if [regexp "branch" $line] {
85*c87b03e5Sespie	    verbose "Processing branch line $n: $line" 3
86*c87b03e5Sespie	    if [regexp "branch\\((\[0-9 \]+)\\)" "$line" all new_shouldbe] {
87*c87b03e5Sespie		# All percentages in the current list should have been seen.
88*c87b03e5Sespie		if {[llength $shouldbe] != 0} {
89*c87b03e5Sespie		    fail "$n: expected branch percentages not found: $shouldbe"
90*c87b03e5Sespie		    incr failed
91*c87b03e5Sespie		    set shouldbe ""
92*c87b03e5Sespie		}
93*c87b03e5Sespie		set shouldbe $new_shouldbe
94*c87b03e5Sespie		#send_user "$n: looking for: $shouldbe\n"
95*c87b03e5Sespie	        # Record the percentages to check for. Replace percentage
96*c87b03e5Sespie		# n > 50 with 100-n, since block ordering affects the
97*c87b03e5Sespie		# direction of a branch.
98*c87b03e5Sespie		for {set i 0} {$i < [llength $shouldbe]} {incr i} {
99*c87b03e5Sespie		    set num [lindex $shouldbe $i]
100*c87b03e5Sespie		    if {$num > 50} {
101*c87b03e5Sespie			set shouldbe [lreplace $shouldbe $i $i [expr 100 - $num]]
102*c87b03e5Sespie		    }
103*c87b03e5Sespie		}
104*c87b03e5Sespie	    } elseif [regexp "branch +\[0-9\]+ taken (-\[0-9\]+)%" "$line" \
105*c87b03e5Sespie			all taken] {
106*c87b03e5Sespie		# Percentages should never be negative.
107*c87b03e5Sespie		fail "$n: negative percentage: $taken"
108*c87b03e5Sespie		incr failed
109*c87b03e5Sespie	    } elseif [regexp "branch +\[0-9\]+ taken (\[0-9\]+)%" "$line" \
110*c87b03e5Sespie			all taken] {
111*c87b03e5Sespie		#send_user "$n: taken = $taken\n"
112*c87b03e5Sespie		# Percentages should never be greater than 100.
113*c87b03e5Sespie		if {$taken > 100} {
114*c87b03e5Sespie		    fail "$n: percentage greater than 100: $taken"
115*c87b03e5Sespie		    incr failed
116*c87b03e5Sespie		}
117*c87b03e5Sespie		if {$taken > 50} {
118*c87b03e5Sespie		    set taken [expr 100 - $taken]
119*c87b03e5Sespie		}
120*c87b03e5Sespie		# If this percentage is one to check for then remove it
121*c87b03e5Sespie		# from the list.  It's normal to ignore some reports.
122*c87b03e5Sespie		set i [lsearch $shouldbe $taken]
123*c87b03e5Sespie		if {$i != -1} {
124*c87b03e5Sespie		    set shouldbe [lreplace $shouldbe $i $i]
125*c87b03e5Sespie		}
126*c87b03e5Sespie	    } elseif [regexp "branch\\(end\\)" "$line"] {
127*c87b03e5Sespie		# All percentages in the list should have been seen by now.
128*c87b03e5Sespie		if {[llength $shouldbe] != 0} {
129*c87b03e5Sespie		    fail "$n: expected branch percentages not found: $shouldbe"
130*c87b03e5Sespie		    incr failed
131*c87b03e5Sespie		}
132*c87b03e5Sespie		set shouldbe ""
133*c87b03e5Sespie	    }
134*c87b03e5Sespie	}
135*c87b03e5Sespie    }
136*c87b03e5Sespie    # All percentages in the list should have been seen.
137*c87b03e5Sespie    if {[llength $shouldbe] != 0} {
138*c87b03e5Sespie	fail "$n: expected branch percentages not found: $shouldbe"
139*c87b03e5Sespie	incr failed
140*c87b03e5Sespie    }
141*c87b03e5Sespie    close $fd
142*c87b03e5Sespie    return $failed
143*c87b03e5Sespie}
144*c87b03e5Sespie
145*c87b03e5Sespie#
146*c87b03e5Sespie# verify-calls -- check that call return percentages are as expected
147*c87b03e5Sespie#
148*c87b03e5Sespie# TESTCASE is the name of the test.
149*c87b03e5Sespie# FILE is the name of the gcov output file.
150*c87b03e5Sespie#
151*c87b03e5Sespie# Checks are based on comments in the source file.  This means to look for
152*c87b03e5Sespie# call return percentages 50, 20, 33:
153*c87b03e5Sespie#     /* returns(50, 20, 33) */
154*c87b03e5Sespie# This means that all specified percentages should have been seen by now:
155*c87b03e5Sespie#     /* returns(end) */
156*c87b03e5Sespie# All specified percentages must also be seen by the next returns(n) or
157*c87b03e5Sespie# by the end of the file.
158*c87b03e5Sespie#
159*c87b03e5Sespie# Each check depends on the compiler having generated the expected
160*c87b03e5Sespie# call instructions.  Don't check for calls that are inserted by the
161*c87b03e5Sespie# compiler or that might be inlined.
162*c87b03e5Sespie#
163*c87b03e5Sespieproc verify-calls { testcase file } {
164*c87b03e5Sespie    #send_user "verify-calls\n"
165*c87b03e5Sespie    set failed 0
166*c87b03e5Sespie    set shouldbe ""
167*c87b03e5Sespie    set fd [open $file r]
168*c87b03e5Sespie    set n 0
169*c87b03e5Sespie    while { [gets $fd line] >= 0 } {
170*c87b03e5Sespie	regexp "^\[^:\]+: *(\[0-9\]+):" "$line" all n
171*c87b03e5Sespie	if [regexp "returns" $line] {
172*c87b03e5Sespie	    verbose "Processing returns line $n: $line" 3
173*c87b03e5Sespie	    if [regexp "returns\\((\[0-9 \]+)\\)" "$line" all new_shouldbe] {
174*c87b03e5Sespie		# All percentages in the current list should have been seen.
175*c87b03e5Sespie		if {[llength $shouldbe] != 0} {
176*c87b03e5Sespie		    fail "$n: expected return percentages not found: $shouldbe"
177*c87b03e5Sespie		    incr failed
178*c87b03e5Sespie		    set shouldbe ""
179*c87b03e5Sespie		}
180*c87b03e5Sespie	        # Record the percentages to check for.
181*c87b03e5Sespie		set shouldbe $new_shouldbe
182*c87b03e5Sespie	    } elseif [regexp "call +\[0-9\]+ returns (-\[0-9\]+)%" "$line" \
183*c87b03e5Sespie			all returns] {
184*c87b03e5Sespie		# Percentages should never be negative.
185*c87b03e5Sespie		fail "$n: negative percentage: $returns"
186*c87b03e5Sespie		incr failed
187*c87b03e5Sespie	    } elseif [regexp "call +\[0-9\]+ returns (\[0-9\]+)%" "$line" \
188*c87b03e5Sespie			all returns] {
189*c87b03e5Sespie		# For branches we check that percentages are not greater than
190*c87b03e5Sespie		# 100 but call return percentages can be, as for setjmp(), so
191*c87b03e5Sespie		# don't count that as an error.
192*c87b03e5Sespie		#
193*c87b03e5Sespie		# If this percentage is one to check for then remove it
194*c87b03e5Sespie		# from the list.  It's normal to ignore some reports.
195*c87b03e5Sespie		set i [lsearch $shouldbe $returns]
196*c87b03e5Sespie		if {$i != -1} {
197*c87b03e5Sespie		    set shouldbe [lreplace $shouldbe $i $i]
198*c87b03e5Sespie		}
199*c87b03e5Sespie	    } elseif [regexp "returns\\(end\\)" "$line"] {
200*c87b03e5Sespie		# All percentages in the list should have been seen by now.
201*c87b03e5Sespie		if {[llength $shouldbe] != 0} {
202*c87b03e5Sespie		    fail "$n: expected return percentages not found: $shouldbe"
203*c87b03e5Sespie		    incr failed
204*c87b03e5Sespie		}
205*c87b03e5Sespie		set shouldbe ""
206*c87b03e5Sespie	    }
207*c87b03e5Sespie	}
208*c87b03e5Sespie    }
209*c87b03e5Sespie    # All percentages in the list should have been seen.
210*c87b03e5Sespie    if {[llength $shouldbe] != 0} {
211*c87b03e5Sespie	fail "$n: expected return percentages not found: $shouldbe"
212*c87b03e5Sespie	incr failed
213*c87b03e5Sespie    }
214*c87b03e5Sespie    close $fd
215*c87b03e5Sespie    return $failed
216*c87b03e5Sespie}
217*c87b03e5Sespie
218*c87b03e5Sespie# Called by dg-final to run gcov and analyze the results.
219*c87b03e5Sespie#
220*c87b03e5Sespie# ARGS is the options to pass to gcov followed by the name of the
221*c87b03e5Sespie# test source file.
222*c87b03e5Sespie
223*c87b03e5Sespieproc run-gcov { args } {
224*c87b03e5Sespie    global GCOV
225*c87b03e5Sespie    global srcdir subdir
226*c87b03e5Sespie
227*c87b03e5Sespie    # Extract the test name from the arguments.
228*c87b03e5Sespie    set testcase [lindex $args end]
229*c87b03e5Sespie
230*c87b03e5Sespie    # Get special options for this test from the .x script, if present.
231*c87b03e5Sespie    # This can include:
232*c87b03e5Sespie    #   gcov_execute_xfail     string to pass to setup_xfail
233*c87b03e5Sespie    #   gcov_verify_xfail      string to pass to setup_xfail
234*c87b03e5Sespie    #   gcov_verify_branches   if defined, check branch percentages
235*c87b03e5Sespie    #   gcov_verify_calls      if defined, check call return percentages
236*c87b03e5Sespie    if [file exists [file rootname $srcdir/$subdir/$testcase].x] {
237*c87b03e5Sespie	set done_p 0
238*c87b03e5Sespie	catch "set done_p \[source [file rootname $srcdir/$subdir/$testcase].x\]"
239*c87b03e5Sespie	if { $done_p } {
240*c87b03e5Sespie	    return
241*c87b03e5Sespie	}
242*c87b03e5Sespie    }
243*c87b03e5Sespie
244*c87b03e5Sespie    if [info exists gcov_execute_xfail] {
245*c87b03e5Sespie	eval setup_xfail [split $gcov_execute_xfail]
246*c87b03e5Sespie    }
247*c87b03e5Sespie
248*c87b03e5Sespie    verbose "Running $GCOV $testcase" 2
249*c87b03e5Sespie    set testcase [remote_download host $testcase];
250*c87b03e5Sespie    set result [remote_exec host $GCOV $args];
251*c87b03e5Sespie    if { [lindex $result 0] != 0 } {
252*c87b03e5Sespie	fail "$subdir/$testcase gcov failed: [lindex $result 1]"
253*c87b03e5Sespie	clean-gcov $testcase
254*c87b03e5Sespie	return
255*c87b03e5Sespie    }
256*c87b03e5Sespie
257*c87b03e5Sespie    # Get the gcov output file after making sure it exists.
258*c87b03e5Sespie    set files [glob -nocomplain $testcase.gcov]
259*c87b03e5Sespie    if { $files == "" } {
260*c87b03e5Sespie        fail "$subdir/$testcase gcov failed: $testcase.gcov does not exist"
261*c87b03e5Sespie        clean-gcov $testcase
262*c87b03e5Sespie        return;
263*c87b03e5Sespie    }
264*c87b03e5Sespie    remote_upload host $testcase.gcov $testcase.gcov;
265*c87b03e5Sespie
266*c87b03e5Sespie    if [info exists gcov_verify_xfail] {
267*c87b03e5Sespie	eval setup_xfail [split $gcov_verify_xfail]
268*c87b03e5Sespie    }
269*c87b03e5Sespie
270*c87b03e5Sespie    # Check that line execution counts are as expected.
271*c87b03e5Sespie    set lfailed [verify-lines $testcase $testcase.gcov]
272*c87b03e5Sespie
273*c87b03e5Sespie    # If requested via the .x file, check that branch and call information
274*c87b03e5Sespie    # is correct.
275*c87b03e5Sespie    if [info exists gcov_verify_branches] {
276*c87b03e5Sespie	set bfailed [verify-branches $testcase $testcase.gcov]
277*c87b03e5Sespie    } else {
278*c87b03e5Sespie	set bfailed 0
279*c87b03e5Sespie    }
280*c87b03e5Sespie    if [info exists gcov_verify_calls] {
281*c87b03e5Sespie	set cfailed [verify-calls $testcase $testcase.gcov]
282*c87b03e5Sespie    } else {
283*c87b03e5Sespie	set cfailed 0
284*c87b03e5Sespie    }
285*c87b03e5Sespie
286*c87b03e5Sespie    # Report whether the gcov test passed or failed.  If there were
287*c87b03e5Sespie    # multiple failures then the message is a summary.
288*c87b03e5Sespie    set tfailed [expr $lfailed + $bfailed + $cfailed]
289*c87b03e5Sespie    if { $tfailed > 0 } {
290*c87b03e5Sespie	fail "$subdir/$testcase gcov: $lfailed failures in line counts, $bfailed in branch percentages, $cfailed in return percentages"
291*c87b03e5Sespie    } else {
292*c87b03e5Sespie	pass "$subdir/$testcase gcov"
293*c87b03e5Sespie	clean-gcov $testcase
294*c87b03e5Sespie    }
295*c87b03e5Sespie}
296