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