gcov.exp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. # Copyright (C) 1997-2015 Free Software Foundation, Inc.
  2. # This program is free software; you can redistribute it and/or modify
  3. # it under the terms of the GNU General Public License as published by
  4. # the Free Software Foundation; either version 3 of the License, or
  5. # (at your option) any later version.
  6. #
  7. # This program is distributed in the hope that it will be useful,
  8. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. # GNU General Public License for more details.
  11. #
  12. # You should have received a copy of the GNU General Public License
  13. # along with GCC; see the file COPYING3. If not see
  14. # <http://www.gnu.org/licenses/>.
  15. # Verify various kinds of gcov output: line counts, branch percentages,
  16. # and call return percentages. None of this is language-specific.
  17. global GCOV
  18. #
  19. # clean-gcov -- delete the working files the compiler creates for gcov
  20. #
  21. # TESTCASE is the name of the test.
  22. #
  23. proc clean-gcov { testcase } {
  24. set basename [file tail $testcase]
  25. set base [file rootname $basename]
  26. remote_file host delete $base.gcno $base.gcda \
  27. $basename.gcov $base.h.gcov
  28. }
  29. #
  30. # verify-lines -- check that line counts are as expected
  31. #
  32. # TESTNAME is the name of the test, including unique flags.
  33. # TESTCASE is the name of the test file.
  34. # FILE is the name of the gcov output file.
  35. #
  36. proc verify-lines { testname testcase file } {
  37. #send_user "verify-lines\n"
  38. global subdir
  39. set failed 0
  40. set fd [open $file r]
  41. while { [gets $fd line] >= 0 } {
  42. # We want to match both "-" and "#####" as count as well as numbers,
  43. # since we want to detect lines that shouldn't be marked as covered.
  44. if [regexp "^ *(\[^:]*): *(\[0-9\\-#]+):.*count\\((\[0-9\\-#=]+)\\)(.*)" \
  45. "$line" all is n shouldbe rest] {
  46. if [regexp "^ *{(.*)}" $rest all xfailed] {
  47. switch [dg-process-target $xfailed] {
  48. "N" { continue }
  49. "F" { setup_xfail "*-*-*" }
  50. }
  51. }
  52. if { $is == "" } {
  53. fail "$testname line $n: no data available"
  54. incr failed
  55. } elseif { $is != $shouldbe } {
  56. fail "$testname line $n: is $is:should be $shouldbe"
  57. incr failed
  58. } else {
  59. pass "$testname count for line $n"
  60. }
  61. }
  62. }
  63. close $fd
  64. return $failed
  65. }
  66. #
  67. # verify-intermediate -- check that intermediate file has certain lines
  68. #
  69. # TESTNAME is the name of the test, including unique flags.
  70. # TESTCASE is the name of the test.
  71. # FILE is the name of the gcov output file.
  72. #
  73. # Checks are very loose, they are based on certain tags being present
  74. # in the output. They do not check for exact expected execution
  75. # counts. For that the regular gcov format should be checked.
  76. #
  77. proc verify-intermediate { testname testcase file } {
  78. set failed 0
  79. set srcfile 0
  80. set function 0
  81. set lcount 0
  82. set branch 0
  83. set fd [open $file r]
  84. while { [gets $fd line] >= 0 } {
  85. if [regexp "^file:" $line] {
  86. incr srcfile
  87. }
  88. if [regexp "^function:(\[0-9\]+),(\[0-9\]+),.*" $line] {
  89. incr function
  90. }
  91. if [regexp "^lcount:(\[0-9\]+),(\[0-9\]+)" $line] {
  92. incr lcount
  93. }
  94. if [regexp "^branch:(\[0-9\]+),(taken|nottaken|notexec)" $line] {
  95. incr branch
  96. }
  97. }
  98. # We should see at least one tag of each type
  99. if {$srcfile == 0} {
  100. fail "$testname expected 'file:' tag not found"
  101. incr failed
  102. }
  103. if {$function == 0} {
  104. fail "$testname expected 'function:' tag not found"
  105. incr failed
  106. }
  107. if {$lcount == 0} {
  108. fail "$testname expected 'lcount:' tag not found"
  109. incr failed
  110. }
  111. if {$branch == 0} {
  112. fail "$testname expected 'branch:' tag not found"
  113. incr failed
  114. }
  115. return $failed
  116. }
  117. #
  118. # verify-branches -- check that branch percentages are as expected
  119. #
  120. # TESTNAME is the name of the test, including unique flags.
  121. # TESTCASE is the name of the test file.
  122. # FILE is the name of the gcov output file.
  123. #
  124. # Checks are based on comments in the source file. This means to look for
  125. # branch percentages 10 or 90, 20 or 80, and # 70 or 30:
  126. # /* branch(10, 20, 70) */
  127. # This means that all specified percentages should have been seen by now:
  128. # /* branch(end) */
  129. # All specified percentages must also be seen by the next branch(n) or
  130. # by the end of the file.
  131. #
  132. # Each check depends on the compiler having generated the expected
  133. # branch instructions. Don't check for branches that might be
  134. # optimized away or replaced with predicated instructions.
  135. #
  136. proc verify-branches { testname testcase file } {
  137. #send_user "verify-branches\n"
  138. set failed 0
  139. set shouldbe ""
  140. set fd [open $file r]
  141. set n 0
  142. while { [gets $fd line] >= 0 } {
  143. regexp "^\[^:\]+: *(\[0-9\]+):" "$line" all n
  144. if [regexp "branch" $line] {
  145. verbose "Processing branch line $n: $line" 3
  146. if [regexp "branch\\((\[0-9 \]+)\\)" "$line" all new_shouldbe] {
  147. # All percentages in the current list should have been seen.
  148. if {[llength $shouldbe] != 0} {
  149. fail "$testname line $n: expected branch percentages not found: $shouldbe"
  150. incr failed
  151. set shouldbe ""
  152. }
  153. set shouldbe $new_shouldbe
  154. #send_user "$n: looking for: $shouldbe\n"
  155. # Record the percentages to check for. Replace percentage
  156. # n > 50 with 100-n, since block ordering affects the
  157. # direction of a branch.
  158. for {set i 0} {$i < [llength $shouldbe]} {incr i} {
  159. set num [lindex $shouldbe $i]
  160. if {$num > 50} {
  161. set shouldbe [lreplace $shouldbe $i $i [expr 100 - $num]]
  162. }
  163. }
  164. } elseif [regexp "branch +\[0-9\]+ taken (-\[0-9\]+)%" "$line" \
  165. all taken] {
  166. # Percentages should never be negative.
  167. fail "$testname line $n: negative percentage: $taken"
  168. incr failed
  169. } elseif [regexp "branch +\[0-9\]+ taken (\[0-9\]+)%" "$line" \
  170. all taken] {
  171. #send_user "$n: taken = $taken\n"
  172. # Percentages should never be greater than 100.
  173. if {$taken > 100} {
  174. fail "$testname line $n: branch percentage greater than 100: $taken"
  175. incr failed
  176. }
  177. if {$taken > 50} {
  178. set taken [expr 100 - $taken]
  179. }
  180. # If this percentage is one to check for then remove it
  181. # from the list. It's normal to ignore some reports.
  182. set i [lsearch $shouldbe $taken]
  183. if {$i != -1} {
  184. set shouldbe [lreplace $shouldbe $i $i]
  185. }
  186. } elseif [regexp "branch\\(end\\)" "$line"] {
  187. # All percentages in the list should have been seen by now.
  188. if {[llength $shouldbe] != 0} {
  189. fail "$testname line n: expected branch percentages not found: $shouldbe"
  190. incr failed
  191. }
  192. set shouldbe ""
  193. }
  194. }
  195. }
  196. # All percentages in the list should have been seen.
  197. if {[llength $shouldbe] != 0} {
  198. fail "$testname line $n: expected branch percentages not found: $shouldbe"
  199. incr failed
  200. }
  201. close $fd
  202. return $failed
  203. }
  204. #
  205. # verify-calls -- check that call return percentages are as expected
  206. #
  207. # TESTNAME is the name of the test, including unique flags.
  208. # TESTCASE is the name of the test file.
  209. # FILE is the name of the gcov output file.
  210. #
  211. # Checks are based on comments in the source file. This means to look for
  212. # call return percentages 50, 20, 33:
  213. # /* returns(50, 20, 33) */
  214. # This means that all specified percentages should have been seen by now:
  215. # /* returns(end) */
  216. # All specified percentages must also be seen by the next returns(n) or
  217. # by the end of the file.
  218. #
  219. # Each check depends on the compiler having generated the expected
  220. # call instructions. Don't check for calls that are inserted by the
  221. # compiler or that might be inlined.
  222. #
  223. proc verify-calls { testname testcase file } {
  224. #send_user "verify-calls\n"
  225. set failed 0
  226. set shouldbe ""
  227. set fd [open $file r]
  228. set n 0
  229. while { [gets $fd line] >= 0 } {
  230. regexp "^\[^:\]+: *(\[0-9\]+):" "$line" all n
  231. if [regexp "return" $line] {
  232. verbose "Processing returns line $n: $line" 3
  233. if [regexp "returns\\((\[0-9 \]+)\\)" "$line" all new_shouldbe] {
  234. # All percentages in the current list should have been seen.
  235. if {[llength $shouldbe] != 0} {
  236. fail "$testname line $n: expected return percentages not found: $shouldbe"
  237. incr failed
  238. set shouldbe ""
  239. }
  240. # Record the percentages to check for.
  241. set shouldbe $new_shouldbe
  242. } elseif [regexp "call +\[0-9\]+ returned (-\[0-9\]+)%" "$line" \
  243. all returns] {
  244. # Percentages should never be negative.
  245. fail "$testname line $n: negative percentage: $returns"
  246. incr failed
  247. } elseif [regexp "call +\[0-9\]+ returned (\[0-9\]+)%" "$line" \
  248. all returns] {
  249. # For branches we check that percentages are not greater than
  250. # 100 but call return percentages can be, as for setjmp(), so
  251. # don't count that as an error.
  252. #
  253. # If this percentage is one to check for then remove it
  254. # from the list. It's normal to ignore some reports.
  255. set i [lsearch $shouldbe $returns]
  256. if {$i != -1} {
  257. set shouldbe [lreplace $shouldbe $i $i]
  258. }
  259. } elseif [regexp "returns\\(end\\)" "$line"] {
  260. # All percentages in the list should have been seen by now.
  261. if {[llength $shouldbe] != 0} {
  262. fail "$testname line $n: expected return percentages not found: $shouldbe"
  263. incr failed
  264. }
  265. set shouldbe ""
  266. }
  267. }
  268. }
  269. # All percentages in the list should have been seen.
  270. if {[llength $shouldbe] != 0} {
  271. fail "$testname line $n: expected return percentages not found: $shouldbe"
  272. incr failed
  273. }
  274. close $fd
  275. return $failed
  276. }
  277. # Called by dg-final to run gcov and analyze the results.
  278. #
  279. # ARGS consists of the optional strings "branches" and/or "calls",
  280. # (indicating that these things should be verified) followed by a
  281. # list of arguments to provide to gcov, including the name of the
  282. # source file.
  283. proc run-gcov { args } {
  284. global GCOV
  285. global srcdir subdir
  286. set gcov_args ""
  287. set gcov_verify_calls 0
  288. set gcov_verify_branches 0
  289. set gcov_verify_lines 1
  290. set gcov_verify_intermediate 0
  291. set xfailed 0
  292. foreach a $args {
  293. if { $a == "calls" } {
  294. set gcov_verify_calls 1
  295. } elseif { $a == "branches" } {
  296. set gcov_verify_branches 1
  297. } elseif { $a == "intermediate" } {
  298. set gcov_verify_intermediate 1
  299. set gcov_verify_calls 0
  300. set gcov_verify_branches 0
  301. set gcov_verify_lines 0
  302. } elseif { $gcov_args == "" } {
  303. set gcov_args $a
  304. } else {
  305. switch [dg-process-target $a] {
  306. "N" { return }
  307. "F" { set xfailed 1 }
  308. }
  309. }
  310. }
  311. set testname [testname-for-summary]
  312. # Extract the test file name from the arguments.
  313. set testcase [lindex $gcov_args end]
  314. verbose "Running $GCOV $testcase" 2
  315. set testcase [remote_download host $testcase]
  316. set result [remote_exec host $GCOV $gcov_args]
  317. if { [lindex $result 0] != 0 } {
  318. if { $xfailed } {
  319. setup_xfail "*-*-*"
  320. }
  321. fail "$testname gcov failed: [lindex $result 1]"
  322. clean-gcov $testcase
  323. return
  324. }
  325. # Get the gcov output file after making sure it exists.
  326. set files [glob -nocomplain $testcase.gcov]
  327. if { $files == "" } {
  328. if { $xfailed } {
  329. setup_xfail "*-*-*"
  330. }
  331. fail "$testname gcov failed: $testcase.gov does not exist"
  332. clean-gcov $testcase
  333. return
  334. }
  335. remote_upload host $testcase.gcov $testcase.gcov
  336. # Check that line execution counts are as expected.
  337. if { $gcov_verify_lines } {
  338. # Check that line execution counts are as expected.
  339. set lfailed [verify-lines $testname $testcase $testcase.gcov]
  340. } else {
  341. set lfailed 0
  342. }
  343. # If requested via the .x file, check that branch and call information
  344. # is correct.
  345. if { $gcov_verify_branches } {
  346. set bfailed [verify-branches $testname $testcase $testcase.gcov]
  347. } else {
  348. set bfailed 0
  349. }
  350. if { $gcov_verify_calls } {
  351. set cfailed [verify-calls $testname $testcase $testcase.gcov]
  352. } else {
  353. set cfailed 0
  354. }
  355. if { $gcov_verify_intermediate } {
  356. # Check that intermediate format has the expected format
  357. set ifailed [verify-intermediate $testname $testcase $testcase.gcov]
  358. } else {
  359. set ifailed 0
  360. }
  361. # Report whether the gcov test passed or failed. If there were
  362. # multiple failures then the message is a summary.
  363. set tfailed [expr $lfailed + $bfailed + $cfailed + $ifailed]
  364. if { $xfailed } {
  365. setup_xfail "*-*-*"
  366. }
  367. if { $tfailed > 0 } {
  368. fail "$testname gcov: $lfailed failures in line counts, $bfailed in branch percentages, $cfailed in return percentages, $ifailed in intermediate format"
  369. if { $xfailed } {
  370. clean-gcov $testcase
  371. }
  372. } else {
  373. pass "$testname gcov"
  374. clean-gcov $testcase
  375. }
  376. }