1#!/usr/bin/env python 2""" 3Summarize the information in the given coverage files. 4 5Emits the number of rules covered or the percentage of rules covered depending 6on whether --num-rules has been used to specify the total number of rules. 7""" 8from __future__ import print_function 9 10import argparse 11import struct 12 13 14class FileFormatError(Exception): 15 pass 16 17 18def backend_int_pair(s): 19 backend, sep, value = s.partition("=") 20 if sep is None: 21 raise argparse.ArgumentTypeError("'=' missing, expected name=value") 22 if not backend: 23 raise argparse.ArgumentTypeError("Expected name=value") 24 if not value: 25 raise argparse.ArgumentTypeError("Expected name=value") 26 return backend, int(value) 27 28 29def main(): 30 parser = argparse.ArgumentParser(description=__doc__) 31 parser.add_argument("input", nargs="+") 32 parser.add_argument( 33 "--num-rules", 34 type=backend_int_pair, 35 action="append", 36 metavar="BACKEND=NUM", 37 help="Specify the number of rules for a backend", 38 ) 39 args = parser.parse_args() 40 41 covered_rules = {} 42 43 for input_filename in args.input: 44 with open(input_filename, "rb") as input_fh: 45 data = input_fh.read() 46 pos = 0 47 while data: 48 backend, _, data = data.partition("\0") 49 pos += len(backend) 50 pos += 1 51 52 if len(backend) == 0: 53 raise FileFormatError() 54 (backend,) = struct.unpack("%ds" % len(backend), backend) 55 56 while data: 57 if len(data) < 8: 58 raise FileFormatError() 59 (rule_id,) = struct.unpack("Q", data[:8]) 60 pos += 8 61 data = data[8:] 62 if rule_id == (2**64) - 1: 63 break 64 covered_rules[backend] = covered_rules.get(backend, {}) 65 covered_rules[backend][rule_id] = ( 66 covered_rules[backend].get(rule_id, 0) + 1 67 ) 68 69 num_rules = dict(args.num_rules) 70 for backend, rules_for_backend in covered_rules.items(): 71 if backend in num_rules: 72 print( 73 "%s: %3.2f%% of rules covered" 74 % (backend, float(len(rules_for_backend)) / num_rules[backend]) 75 * 100 76 ) 77 else: 78 print("%s: %d rules covered" % (backend, len(rules_for_backend))) 79 80 81if __name__ == "__main__": 82 main() 83