1 # Copyright (C) 1997, 2001, 2007 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with GCC; see the file COPYING3. If not see
15 # <http://www.gnu.org/licenses/>.
17 # Verify various kinds of gcov output: line counts, branch percentages,
18 # and call return percentages. None of this is language-specific.
23 # clean-gcov -- delete the working files the compiler creates for gcov
25 # TESTCASE is the name of the test.
27 proc clean-gcov { testcase } {
28 set basename [file tail $testcase]
29 set base [file rootname $basename]
30 remote_file host delete $base.gcno $base.gcda \
31 $basename.gcov $base.h.gcov
35 # verify-lines -- check that line counts are as expected
37 # TESTCASE is the name of the test.
38 # FILE is the name of the gcov output file.
40 proc verify-lines { testcase file } {
41 #send_user "verify-lines\n"
45 while { [gets $fd line] >= 0 } {
46 # We want to match both "-" and "#####" as count as well as numbers,
47 # since we want to detect lines that shouldn't be marked as covered.
48 if [regexp "^ *(\[^:]*): *(\[0-9\\-#]+):.*count\\((\[0-9\\-#=]+)\\)(.*)" \
49 "$line" all is n shouldbe rest] {
50 if [regexp "^ *{(.*)}" $rest all xfailed] {
51 switch [dg-process-target $xfailed] {
53 "F" { setup_xfail "*-*-*" }
57 fail "$subdir/$testcase:$n:no data available for this line"
59 } elseif { $is != $shouldbe } {
60 fail "$subdir/$testcase:$n:is $is:should be $shouldbe"
63 pass "$subdir/$testcase:$n line count"
72 # verify-branches -- check that branch percentages are as expected
74 # TESTCASE is the name of the test.
75 # FILE is the name of the gcov output file.
77 # Checks are based on comments in the source file. This means to look for
78 # branch percentages 10 or 90, 20 or 80, and # 70 or 30:
79 # /* branch(10, 20, 70) */
80 # This means that all specified percentages should have been seen by now:
82 # All specified percentages must also be seen by the next branch(n) or
83 # by the end of the file.
85 # Each check depends on the compiler having generated the expected
86 # branch instructions. Don't check for branches that might be
87 # optimized away or replaced with predicated instructions.
89 proc verify-branches { testcase file } {
90 #send_user "verify-branches\n"
95 while { [gets $fd line] >= 0 } {
96 regexp "^\[^:\]+: *(\[0-9\]+):" "$line" all n
97 if [regexp "branch" $line] {
98 verbose "Processing branch line $n: $line" 3
99 if [regexp "branch\\((\[0-9 \]+)\\)" "$line" all new_shouldbe] {
100 # All percentages in the current list should have been seen.
101 if {[llength $shouldbe] != 0} {
102 fail "$n: expected branch percentages not found: $shouldbe"
106 set shouldbe $new_shouldbe
107 #send_user "$n: looking for: $shouldbe\n"
108 # Record the percentages to check for. Replace percentage
109 # n > 50 with 100-n, since block ordering affects the
110 # direction of a branch.
111 for {set i 0} {$i < [llength $shouldbe]} {incr i} {
112 set num [lindex $shouldbe $i]
114 set shouldbe [lreplace $shouldbe $i $i [expr 100 - $num]]
117 } elseif [regexp "branch +\[0-9\]+ taken (-\[0-9\]+)%" "$line" \
119 # Percentages should never be negative.
120 fail "$n: negative percentage: $taken"
122 } elseif [regexp "branch +\[0-9\]+ taken (\[0-9\]+)%" "$line" \
124 #send_user "$n: taken = $taken\n"
125 # Percentages should never be greater than 100.
127 fail "$n: percentage greater than 100: $taken"
131 set taken [expr 100 - $taken]
133 # If this percentage is one to check for then remove it
134 # from the list. It's normal to ignore some reports.
135 set i [lsearch $shouldbe $taken]
137 set shouldbe [lreplace $shouldbe $i $i]
139 } elseif [regexp "branch\\(end\\)" "$line"] {
140 # All percentages in the list should have been seen by now.
141 if {[llength $shouldbe] != 0} {
142 fail "$n: expected branch percentages not found: $shouldbe"
149 # All percentages in the list should have been seen.
150 if {[llength $shouldbe] != 0} {
151 fail "$n: expected branch percentages not found: $shouldbe"
159 # verify-calls -- check that call return percentages are as expected
161 # TESTCASE is the name of the test.
162 # FILE is the name of the gcov output file.
164 # Checks are based on comments in the source file. This means to look for
165 # call return percentages 50, 20, 33:
166 # /* returns(50, 20, 33) */
167 # This means that all specified percentages should have been seen by now:
169 # All specified percentages must also be seen by the next returns(n) or
170 # by the end of the file.
172 # Each check depends on the compiler having generated the expected
173 # call instructions. Don't check for calls that are inserted by the
174 # compiler or that might be inlined.
176 proc verify-calls { testcase file } {
177 #send_user "verify-calls\n"
180 set fd [open $file r]
182 while { [gets $fd line] >= 0 } {
183 regexp "^\[^:\]+: *(\[0-9\]+):" "$line" all n
184 if [regexp "return" $line] {
185 verbose "Processing returns line $n: $line" 3
186 if [regexp "returns\\((\[0-9 \]+)\\)" "$line" all new_shouldbe] {
187 # All percentages in the current list should have been seen.
188 if {[llength $shouldbe] != 0} {
189 fail "$n: expected return percentages not found: $shouldbe"
193 # Record the percentages to check for.
194 set shouldbe $new_shouldbe
195 } elseif [regexp "call +\[0-9\]+ returned (-\[0-9\]+)%" "$line" \
197 # Percentages should never be negative.
198 fail "$n: negative percentage: $returns"
200 } elseif [regexp "call +\[0-9\]+ returned (\[0-9\]+)%" "$line" \
202 # For branches we check that percentages are not greater than
203 # 100 but call return percentages can be, as for setjmp(), so
204 # don't count that as an error.
206 # If this percentage is one to check for then remove it
207 # from the list. It's normal to ignore some reports.
208 set i [lsearch $shouldbe $returns]
210 set shouldbe [lreplace $shouldbe $i $i]
212 } elseif [regexp "returns\\(end\\)" "$line"] {
213 # All percentages in the list should have been seen by now.
214 if {[llength $shouldbe] != 0} {
215 fail "$n: expected return percentages not found: $shouldbe"
222 # All percentages in the list should have been seen.
223 if {[llength $shouldbe] != 0} {
224 fail "$n: expected return percentages not found: $shouldbe"
231 # Called by dg-final to run gcov and analyze the results.
233 # ARGS consists of the optional strings "branches" and/or "calls",
234 # (indicating that these things should be verified) followed by a
235 # list of arguments to provide to gcov, including the name of the
238 proc run-gcov { args } {
243 set gcov_verify_calls 0
244 set gcov_verify_branches 0
248 if { $a == "calls" } {
249 set gcov_verify_calls 1
250 } elseif { $a == "branches" } {
251 set gcov_verify_branches 1
252 } elseif { $gcov_args == "" } {
255 switch [dg-process-target $a] {
257 "F" { set xfailed 1 }
262 # Extract the test name from the arguments.
263 set testcase [lindex $gcov_args end]
265 verbose "Running $GCOV $testcase" 2
266 set testcase [remote_download host $testcase]
267 set result [remote_exec host $GCOV $gcov_args]
268 if { [lindex $result 0] != 0 } {
272 fail "$subdir/$testcase gcov failed: [lindex $result 1]"
277 # Get the gcov output file after making sure it exists.
278 set files [glob -nocomplain $testcase.gcov]
279 if { $files == "" } {
283 fail "$subdir/$testcase gcov failed: $testcase.gcov does not exist"
287 remote_upload host $testcase.gcov $testcase.gcov
289 # Check that line execution counts are as expected.
290 set lfailed [verify-lines $testcase $testcase.gcov]
292 # If requested via the .x file, check that branch and call information
294 if { $gcov_verify_branches } {
295 set bfailed [verify-branches $testcase $testcase.gcov]
299 if { $gcov_verify_calls } {
300 set cfailed [verify-calls $testcase $testcase.gcov]
305 # Report whether the gcov test passed or failed. If there were
306 # multiple failures then the message is a summary.
307 set tfailed [expr $lfailed + $bfailed + $cfailed]
311 if { $tfailed > 0 } {
312 fail "$subdir/$testcase gcov: $lfailed failures in line counts, $bfailed in branch percentages, $cfailed in return percentages"
314 pass "$subdir/$testcase gcov"