Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/littlefs-project/littlefs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/coverage.py')
-rwxr-xr-xscripts/coverage.py191
1 files changed, 130 insertions, 61 deletions
diff --git a/scripts/coverage.py b/scripts/coverage.py
index 6f1f54f..b3a90ed 100755
--- a/scripts/coverage.py
+++ b/scripts/coverage.py
@@ -55,8 +55,9 @@ def collect(paths, **args):
for (file, func), (hits, count) in reduced_funcs.items():
# discard internal/testing functions (test_* injected with
# internal testing)
- if func.startswith('__') or func.startswith('test_'):
- continue
+ if not args.get('everything'):
+ if func.startswith('__') or func.startswith('test_'):
+ continue
# discard .8449 suffixes created by optimizer
func = re.sub('\.[0-9]+', '', func)
results.append((file, func, hits, count))
@@ -65,6 +66,15 @@ def collect(paths, **args):
def main(**args):
+ def openio(path, mode='r'):
+ if path == '-':
+ if 'r' in mode:
+ return os.fdopen(os.dup(sys.stdin.fileno()), 'r')
+ else:
+ return os.fdopen(os.dup(sys.stdout.fileno()), 'w')
+ else:
+ return open(path, mode)
+
# find coverage
if not args.get('use'):
# find *.info files
@@ -82,14 +92,16 @@ def main(**args):
results = collect(paths, **args)
else:
- with open(args['use']) as f:
+ with openio(args['use']) as f:
r = csv.DictReader(f)
results = [
( result['file'],
- result['function'],
- int(result['hits']),
- int(result['count']))
- for result in r]
+ result['name'],
+ int(result['coverage_hits']),
+ int(result['coverage_count']))
+ for result in r
+ if result.get('coverage_hits') not in {None, ''}
+ if result.get('coverage_count') not in {None, ''}]
total_hits, total_count = 0, 0
for _, _, hits, count in results:
@@ -98,14 +110,19 @@ def main(**args):
# find previous results?
if args.get('diff'):
- with open(args['diff']) as f:
- r = csv.DictReader(f)
- prev_results = [
- ( result['file'],
- result['function'],
- int(result['hits']),
- int(result['count']))
- for result in r]
+ try:
+ with openio(args['diff']) as f:
+ r = csv.DictReader(f)
+ prev_results = [
+ ( result['file'],
+ result['name'],
+ int(result['coverage_hits']),
+ int(result['coverage_count']))
+ for result in r
+ if result.get('coverage_hits') not in {None, ''}
+ if result.get('coverage_count') not in {None, ''}]
+ except FileNotFoundError:
+ prev_results = []
prev_total_hits, prev_total_count = 0, 0
for _, _, hits, count in prev_results:
@@ -114,14 +131,36 @@ def main(**args):
# write results to CSV
if args.get('output'):
- with open(args['output'], 'w') as f:
- w = csv.writer(f)
- w.writerow(['file', 'function', 'hits', 'count'])
- for file, func, hits, count in sorted(results):
- w.writerow((file, func, hits, count))
+ merged_results = co.defaultdict(lambda: {})
+ other_fields = []
+
+ # merge?
+ if args.get('merge'):
+ try:
+ with openio(args['merge']) as f:
+ r = csv.DictReader(f)
+ for result in r:
+ file = result.pop('file', '')
+ func = result.pop('name', '')
+ result.pop('coverage_hits', None)
+ result.pop('coverage_count', None)
+ merged_results[(file, func)] = result
+ other_fields = result.keys()
+ except FileNotFoundError:
+ pass
+
+ for file, func, hits, count in results:
+ merged_results[(file, func)]['coverage_hits'] = hits
+ merged_results[(file, func)]['coverage_count'] = count
+
+ with openio(args['output'], 'w') as f:
+ w = csv.DictWriter(f, ['file', 'name', *other_fields, 'coverage_hits', 'coverage_count'])
+ w.writeheader()
+ for (file, func), result in sorted(merged_results.items()):
+ w.writerow({'file': file, 'name': func, **result})
# print results
- def dedup_entries(results, by='function'):
+ def dedup_entries(results, by='name'):
entries = co.defaultdict(lambda: (0, 0))
for file, func, hits, count in results:
entry = (file if by == 'file' else func)
@@ -147,23 +186,59 @@ def main(**args):
- (old_hits/old_count if old_count else 1.0)))
return diff
+ def sorted_entries(entries):
+ if args.get('coverage_sort'):
+ return sorted(entries, key=lambda x: (-(x[1][0]/x[1][1] if x[1][1] else -1), x))
+ elif args.get('reverse_coverage_sort'):
+ return sorted(entries, key=lambda x: (+(x[1][0]/x[1][1] if x[1][1] else -1), x))
+ else:
+ return sorted(entries)
+
+ def sorted_diff_entries(entries):
+ if args.get('coverage_sort'):
+ return sorted(entries, key=lambda x: (-(x[1][2]/x[1][3] if x[1][3] else -1), x))
+ elif args.get('reverse_coverage_sort'):
+ return sorted(entries, key=lambda x: (+(x[1][2]/x[1][3] if x[1][3] else -1), x))
+ else:
+ return sorted(entries, key=lambda x: (-x[1][6], x))
+
def print_header(by=''):
if not args.get('diff'):
print('%-36s %19s' % (by, 'hits/line'))
else:
print('%-36s %19s %19s %11s' % (by, 'old', 'new', 'diff'))
- def print_entries(by='function'):
+ def print_entry(name, hits, count):
+ print("%-36s %11s %7s" % (name,
+ '%d/%d' % (hits, count)
+ if count else '-',
+ '%.1f%%' % (100*hits/count)
+ if count else '-'))
+
+ def print_diff_entry(name,
+ old_hits, old_count,
+ new_hits, new_count,
+ diff_hits, diff_count,
+ ratio):
+ print("%-36s %11s %7s %11s %7s %11s%s" % (name,
+ '%d/%d' % (old_hits, old_count)
+ if old_count else '-',
+ '%.1f%%' % (100*old_hits/old_count)
+ if old_count else '-',
+ '%d/%d' % (new_hits, new_count)
+ if new_count else '-',
+ '%.1f%%' % (100*new_hits/new_count)
+ if new_count else '-',
+ '%+d/%+d' % (diff_hits, diff_count),
+ ' (%+.1f%%)' % (100*ratio) if ratio else ''))
+
+ def print_entries(by='name'):
entries = dedup_entries(results, by=by)
if not args.get('diff'):
print_header(by=by)
- for name, (hits, count) in sorted(entries.items()):
- print("%-36s %11s %7s" % (name,
- '%d/%d' % (hits, count)
- if count else '-',
- '%.1f%%' % (100*hits/count)
- if count else '-'))
+ for name, (hits, count) in sorted_entries(entries.items()):
+ print_entry(name, hits, count)
else:
prev_entries = dedup_entries(prev_results, by=by)
diff = diff_entries(prev_entries, entries)
@@ -173,45 +248,28 @@ def main(**args):
for name, (
old_hits, old_count,
new_hits, new_count,
- diff_hits, diff_count, ratio) in sorted(diff.items(),
- key=lambda x: (-x[1][6], x)):
+ diff_hits, diff_count, ratio) in sorted_diff_entries(
+ diff.items()):
if ratio or args.get('all'):
- print("%-36s %11s %7s %11s %7s %11s%s" % (name,
- '%d/%d' % (old_hits, old_count)
- if old_count else '-',
- '%.1f%%' % (100*old_hits/old_count)
- if old_count else '-',
- '%d/%d' % (new_hits, new_count)
- if new_count else '-',
- '%.1f%%' % (100*new_hits/new_count)
- if new_count else '-',
- '%+d/%+d' % (diff_hits, diff_count),
- ' (%+.1f%%)' % (100*ratio) if ratio else ''))
+ print_diff_entry(name,
+ old_hits, old_count,
+ new_hits, new_count,
+ diff_hits, diff_count,
+ ratio)
def print_totals():
if not args.get('diff'):
- print("%-36s %11s %7s" % ('TOTAL',
- '%d/%d' % (total_hits, total_count)
- if total_count else '-',
- '%.1f%%' % (100*total_hits/total_count)
- if total_count else '-'))
+ print_entry('TOTAL', total_hits, total_count)
else:
ratio = ((total_hits/total_count
if total_count else 1.0)
- (prev_total_hits/prev_total_count
if prev_total_count else 1.0))
- print("%-36s %11s %7s %11s %7s %11s%s" % ('TOTAL',
- '%d/%d' % (prev_total_hits, prev_total_count)
- if prev_total_count else '-',
- '%.1f%%' % (100*prev_total_hits/prev_total_count)
- if prev_total_count else '-',
- '%d/%d' % (total_hits, total_count)
- if total_count else '-',
- '%.1f%%' % (100*total_hits/total_count)
- if total_count else '-',
- '%+d/%+d' % (total_hits-prev_total_hits,
- total_count-prev_total_count),
- ' (%+.1f%%)' % (100*ratio) if ratio else ''))
+ print_diff_entry('TOTAL',
+ prev_total_hits, prev_total_count,
+ total_hits, total_count,
+ total_hits-prev_total_hits, total_count-prev_total_count,
+ ratio)
if args.get('quiet'):
pass
@@ -222,7 +280,7 @@ def main(**args):
print_entries(by='file')
print_totals()
else:
- print_entries(by='function')
+ print_entries(by='name')
print_totals()
if __name__ == "__main__":
@@ -243,12 +301,23 @@ if __name__ == "__main__":
help="Don't do any work, instead use this CSV file.")
parser.add_argument('-d', '--diff',
help="Specify CSV file to diff code size against.")
+ parser.add_argument('-m', '--merge',
+ help="Merge with an existing CSV file when writing to output.")
parser.add_argument('-a', '--all', action='store_true',
help="Show all functions, not just the ones that changed.")
- parser.add_argument('--files', action='store_true',
+ parser.add_argument('-A', '--everything', action='store_true',
+ help="Include builtin and libc specific symbols.")
+ parser.add_argument('-s', '--coverage-sort', action='store_true',
+ help="Sort by coverage.")
+ parser.add_argument('-S', '--reverse-coverage-sort', action='store_true',
+ help="Sort by coverage, but backwards.")
+ parser.add_argument('-F', '--files', action='store_true',
help="Show file-level coverage.")
- parser.add_argument('-s', '--summary', action='store_true',
+ parser.add_argument('-Y', '--summary', action='store_true',
help="Only show the total coverage.")
parser.add_argument('-q', '--quiet', action='store_true',
help="Don't show anything, useful with -o.")
+ parser.add_argument('--build-dir',
+ help="Specify the relative build directory. Used to map object files \
+ to the correct source files.")
sys.exit(main(**vars(parser.parse_args())))