]> git.donarmstrong.com Git - lilypond.git/blob - buildscripts/coverage.py
coverage.py improvements.
[lilypond.git] / buildscripts / coverage.py
1 #!/bin/sh
2 import os
3 import glob
4 import re
5 import sys
6 import optparse
7
8 #File 'accidental-engraver.cc'
9 #Lines executed:87.70% of 252
10
11 def summary (args):
12     results = []
13     for f in args:
14         str = open (f).read ()
15         m = re.search ("File '([^']+.cc)'\s*Lines executed:([0-9.]+)% of ([0-9]+)", str)
16
17         if m and '/usr/lib' in m.group (1):
18             continue
19
20         if m:
21             cov = float (m.group (2))
22             lines = int (m.group (3))
23             pain = lines * (100.0 - cov)
24             file = m.group (1)
25             tup = (pain, locals ().copy())
26
27             results.append(tup)
28
29     results.sort ()
30     results.reverse()
31
32     print 'files sorted by number of untested lines (decreasing)'
33     print
34     print '%5s (%6s): %s' % ('cov %', 'lines', 'file')
35     print '----------------------------------------------'
36
37     for (pain, d) in results:
38         print '%(cov)5.2f (%(lines)6d): %(file)s' % d
39
40
41
42 def read_gcov (f):
43     ls = []
44
45     in_lines = [l for l in open (f).readlines ()]
46     (count_len, line_num_len) = tuple (map (len, in_lines[0].split( ':')[:2]))
47     
48     for l in in_lines:
49         c = l[:count_len].strip ()
50         l = l[count_len+1:]
51         n = int (l[:line_num_len].strip ())
52
53         if n == 0:
54             continue
55         
56         l = l[line_num_len+1:]
57
58         ls.append ((c,n,l))
59         
60     return ls
61
62 def get_chunks (ls):
63     chunks = []
64     chunk = []
65     for (c,n,l) in ls:
66         if '#' in c:
67             chunk.append ((n,l))
68         elif c.strip () != '-' or l == '}\n':
69             if chunk:
70                 chunks.append (chunk)
71                 chunk = []
72             
73     return chunks
74
75 def is_exception_chunk (ch):
76     for (n,l) in ch:
77         for stat in  ('warning', 'error'):
78             if stat in l:
79                 return True
80     return False
81
82 def widen_chunk (ch, ls):
83     nums = [n-1 for (n, l) in ch]
84     (a, b) = (min (nums), max (nums)+1)
85     a -= 1
86     b += 1
87
88     return [(n, l)  for (c, n, l) in ls[a:b]]
89     
90
91 def is_inspection_chunk (ch):
92     for (n,l) in ch:
93         for stat in  ('::print',):
94             if stat in l:
95                 return True
96     return False
97
98 def print_chunk (ch, lines):
99     nums = [n-1 for (n, l) in ch]
100     (a, b) = (min (nums), max (nums)+1)
101     a -= 1
102     b += 1
103     for (c, n, l) in lines[a:b]:
104         sys.stdout.write ('%8s:%8d:%s' % (c,n,l))
105
106
107 def extract_uncovered (file):
108     try:
109         ls = read_gcov (file)
110     except IOError, s :
111         print s
112         return
113         
114     cs = get_chunks (ls)
115     cs = [widen_chunk(c, ls) for c in cs]
116     cs = [c for c in cs if not is_exception_chunk (c)]
117     cs = [c for c in cs if not is_inspection_chunk (c)]
118     for c in cs:
119         print 'Uncovered chunk in', file
120         print_chunk (c, ls)
121         print '\n\n: '
122     
123
124 def main ():
125     p = optparse.OptionParser (usage="usage coverage.py [options] files",
126                                description="")
127     p.add_option ("--summary",
128                   action='store_true',
129                   default=False,
130                   dest="summary")
131     
132     p.add_option ("--uncovered",
133                   default=False,
134                   action='store_true',
135                   dest="uncovered")
136
137     
138     (options, args) = p.parse_args ()
139     
140
141     if options.summary:
142         summary (['%s.gcov-summary' % s for s in args])
143
144     if options.uncovered:
145         for a in args:
146             extract_uncovered ('%s.gcov' % a)
147         
148         
149 if __name__ == '__main__':
150     main ()