9 #File 'accidental-engraver.cc'
10 #Lines executed:87.70% of 252
15 str = open (f
).read ()
16 m
= re
.search ("File '([^']+.cc)'\s*Lines executed:([0-9.]+)% of ([0-9]+)", str)
18 if m
and '/usr/lib' in m
.group (1):
22 cov
= float (m
.group (2))
23 lines
= int (m
.group (3))
24 pain
= lines
* (100.0 - cov
)
26 tup
= (pain
, locals ().copy())
33 print 'files sorted by number of untested lines (decreasing)'
35 print '%5s (%6s): %s' % ('cov %', 'lines', 'file')
36 print '----------------------------------------------'
38 for (pain
, d
) in results
:
39 print '%(cov)5.2f (%(lines)6d): %(file)s' % d
42 def __init__ (self
, range, coverage_count
, all_lines
, file):
43 assert coverage_count
>= 0
44 assert type (range) == type (())
46 self
.coverage_count
= coverage_count
48 self
.all_lines
= all_lines
52 return self
.range[1] - self
.range[0]
55 return ''.join ([l
[2] for l
in self
.lines()])
58 return self
.all_lines
[self
.range[0]:
61 self
.range = (min (self
.range[0] -1, 0),
64 print 'chunk in', self
.file
65 for (c
, n
, l
) in self
.lines ():
71 sys
.stdout
.write ('%8s:%8d:%s' % (cov
, n
, l
))
73 def uncovered_score (self
):
76 class SchemeChunk (Chunk
):
77 def uncovered_score (self
):
79 if (text
.startswith ('(define ')
80 and not text
.startswith ('(define (')):
83 if text
.startswith ('(use-modules '):
86 if (text
.startswith ('(define-public ')
87 and not text
.startswith ('(define-public (')):
90 return len ([l
for (c
,n
,l
) in self
.lines() if (c
== 0)])
95 in_lines
= [l
for l
in open (f
).readlines ()]
96 (count_len
, line_num_len
) = tuple (map (len, in_lines
[0].split (':')[:2]))
99 c
= l
[:count_len
].strip ()
101 n
= int (l
[:line_num_len
].strip ())
113 l
= l
[line_num_len
+1:]
119 def get_c_chunks (ls
, file):
125 if not (c
== last_c
or c
< 0 and l
!= '}\n'):
126 if chunk
and last_c
>= 0:
127 nums
= [n
-1 for (n
, l
) in chunk
]
128 chunks
.append (Chunk ((min (nums
), max (nums
)+1),
138 def get_scm_chunks (ls
, file):
144 nums
= [n
-1 for (n
, l
) in chunk
]
145 chunks
.append (SchemeChunk ((min (nums
), max (nums
)+1),
146 max (last_c
, 0), ls
, file))
150 for (cov_count
, line_number
, line
) in ls
:
151 if line
.startswith ('('):
155 chunk
.append ((line_number
, line
))
161 def widen_chunk (ch
, ls
):
165 return [(n
, l
) for (c
, n
, l
) in ls
[a
:b
]]
168 def extract_chunks (file):
170 ls
= read_gcov (file)
177 cs
= get_scm_chunks (ls
, file)
179 cs
= get_c_chunks (ls
, file)
183 def filter_uncovered (chunks
):
185 if c
.coverage_count
> 0:
189 for stat
in ('warning', 'error', 'print', 'scm_gc_mark'):
194 return [c
for c
in chunks
if interesting (c
)]
198 p
= optparse
.OptionParser (usage
="usage coverage.py [options] files",
200 p
.add_option ("--summary",
205 p
.add_option ("--hotspots",
210 p
.add_option ("--uncovered",
216 (options
, args
) = p
.parse_args ()
220 summary (['%s.gcov-summary' % s
for s
in args
])
222 if options
.uncovered
or options
.hotspots
:
226 if name
.endswith ('scm'):
231 chunks
+= extract_chunks (name
)
233 if options
.uncovered
:
234 chunks
= filter_uncovered (chunks
)
235 chunks
= [(c
.uncovered_score (), c
) for c
in chunks
if c
.uncovered_score() > 0]
236 elif options
.hotspots
:
237 chunks
= [((c
.coverage_count
, -c
.length()), c
) for c
in chunks
]
242 for (score
, c
) in chunks
:
247 if __name__
== '__main__':