8 #File 'accidental-engraver.cc'
9 #Lines executed:87.70% of 252
14 str = open (f).read ()
15 m = re.search ("File '([^']+.cc)'\s*Lines executed:([0-9.]+)% of ([0-9]+)", str)
17 if m and '/usr/lib' in m.group (1):
21 cov = float (m.group (2))
22 lines = int (m.group (3))
23 pain = lines * (100.0 - cov)
25 tup = (pain, locals ().copy())
32 print 'files sorted by number of untested lines (decreasing)'
34 print '%5s (%6s): %s' % ('cov %', 'lines', 'file')
35 print '----------------------------------------------'
37 for (pain, d) in results:
38 print '%(cov)5.2f (%(lines)6d): %(file)s' % d
41 def __init__ (self, range, coverage_count, all_lines, file):
42 assert coverage_count >= 0
43 assert type (range) == type (())
45 self.coverage_count = coverage_count
47 self.all_lines = all_lines
51 return self.range[1] - self.range[0]
54 return ''.join ([l[2] for l in self.lines()])
57 return self.all_lines[self.range[0]:
60 self.range = (min (self.range[0] -1, 0),
63 print 'chunk in', self.file
64 for (c, n, l) in self.lines ():
70 sys.stdout.write ('%8s:%8d:%s' % (cov, n, l))
72 def uncovered_score (self):
75 class SchemeChunk (Chunk):
76 def uncovered_score (self):
78 if (text.startswith ('(define ')
79 and not text.startswith ('(define (')):
82 if (text.startswith ('(define-public ')
83 and not text.startswith ('(define-public (')):
86 return len ([l for (c,n,l) in self.lines() if (c == 0)])
91 in_lines = [l for l in open (f).readlines ()]
92 (count_len, line_num_len) = tuple (map (len, in_lines[0].split (':')[:2]))
95 c = l[:count_len].strip ()
97 n = int (l[:line_num_len].strip ())
109 l = l[line_num_len+1:]
115 def get_c_chunks (ls, file):
121 if not (c == last_c or c < 0 and l != '}\n'):
122 if chunk and last_c >= 0:
123 nums = [n-1 for (n, l) in chunk]
124 chunks.append (Chunk ((min (nums), max (nums)+1),
134 def get_scm_chunks (ls, file):
140 nums = [n-1 for (n, l) in chunk]
141 chunks.append (SchemeChunk ((min (nums), max (nums)+1),
142 max (last_c, 0), ls, file))
146 for (cov_count, line_number, line) in ls:
147 if line.startswith ('('):
151 chunk.append ((line_number, line))
157 def widen_chunk (ch, ls):
161 return [(n, l) for (c, n, l) in ls[a:b]]
164 def extract_chunks (file):
166 ls = read_gcov (file)
173 cs = get_scm_chunks (ls, file)
175 cs = get_c_chunks (ls, file)
179 def filter_uncovered (chunks):
181 if c.coverage_count > 0:
185 for stat in ('warning', 'error', 'print', 'scm_gc_mark'):
190 return [c for c in chunks if interesting (c)]
194 p = optparse.OptionParser (usage="usage coverage.py [options] files",
196 p.add_option ("--summary",
201 p.add_option ("--hotspots",
206 p.add_option ("--uncovered",
212 (options, args) = p.parse_args ()
216 summary (['%s.gcov-summary' % s for s in args])
218 if options.uncovered or options.hotspots:
222 if name.endswith ('scm'):
227 chunks += extract_chunks (name)
229 if options.uncovered:
230 chunks = filter_uncovered (chunks)
231 chunks = [(c.uncovered_score (), c) for c in chunks]
232 elif options.hotspots:
233 chunks = [((c.coverage_count, -c.length()), c) for c in chunks]
238 for (score, c) in chunks:
243 if __name__ == '__main__':