From db7fd3c46a043f78781b0e724d2556fda1ac49aa Mon Sep 17 00:00:00 2001 From: Giovanni Lagorio Date: Thu, 7 May 2020 10:10:43 +0200 Subject: [PATCH 1/2] Allow to load ".set" files, which aggregate a set of coverage files --- cutterdrcov_plugin/drcov.py | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/cutterdrcov_plugin/drcov.py b/cutterdrcov_plugin/drcov.py index 827876d..b8b2bdf 100644 --- a/cutterdrcov_plugin/drcov.py +++ b/cutterdrcov_plugin/drcov.py @@ -75,7 +75,53 @@ def dead_module_elimination(modules, bbs): for i in delete: del bbs[i] del modules[i] + + +def process_set_of_files(path): + OP_INTERSECTION = 'intersect' + OP_DIFFERENCE = 'subtract' + OP_UNION = 'union' + supported_operations = {OP_INTERSECTION, OP_DIFFERENCE, OP_UNION} + with open(path, "r") as f: + all_lines = [l.rstrip(' \t\n\r') for l in f.readlines()] + lines = [l for l in all_lines if len(l)] + operation = lines[0] + if operation not in supported_operations: + raise Exception('Unsupported operation') + lines = lines[1:] + if len(lines) == 1: + return load(lines[0]) + files = [load(l) for l in lines] + mod_list = files[0][0] + mod_names = [ m['name'] for m in mod_list ] + if any([m['name'] for m in f[0]] != mod_names for f in files[1:]): + raise Exception('Module lists differ among coverage files') + bbs = [] + for m in range(len(mod_list)): + dicts = [f[1][m] for f in files] + res_dict = {} + bbs.append(res_dict) + if operation == OP_UNION: + for d in dicts: + res_dict.update(d) + else: + first_dict = dicts[0] + other_dicts = dicts[1:] + for bb, size in first_dict.items(): + if operation == OP_INTERSECTION: + to_add = all(bb in d for d in other_dicts) + elif operation == OP_DIFFERENCE: + to_add = all(bb not in d for d in other_dicts) + else: + assert False + if to_add: + res_dict[bb] = size + return [mod_list, bbs] + + def load(path): + if path.endswith(".set"): + return process_set_of_files(path) drcov_file = open(path, "rb") modules = read_module_list(drcov_file) bbs = read_bb_list(drcov_file, len(modules)) From ad94f5cb146972382e428c00d665461830b662c3 Mon Sep 17 00:00:00 2001 From: Giovanni Lagorio Date: Sat, 11 Jul 2020 17:14:00 +0200 Subject: [PATCH 2/2] refactor set operation and add tests --- cutterdrcov_plugin/drcov.py | 58 ++++++++++++++++++++------------- unittest/test_set_operations.py | 28 ++++++++++++++++ 2 files changed, 63 insertions(+), 23 deletions(-) create mode 100644 unittest/test_set_operations.py diff --git a/cutterdrcov_plugin/drcov.py b/cutterdrcov_plugin/drcov.py index b8b2bdf..0e4e9b6 100644 --- a/cutterdrcov_plugin/drcov.py +++ b/cutterdrcov_plugin/drcov.py @@ -77,16 +77,44 @@ def dead_module_elimination(modules, bbs): del modules[i] +def intersect_bbs(bbs): + result = {} + first_dict = bbs[0] + other_dicts = bbs[1:] + for bb, size in first_dict.items(): + if all(bb in d for d in other_dicts): + result[bb] = size + return result + + +def union_bbs(bbs): + result = {} + for d in bbs: + result.update(d) + return result + + +def subtract_bbs(bbs): + result = {} + first_dict = bbs[0] + other_dicts = bbs[1:] + for bb, size in first_dict.items(): + if all(bb not in d for d in other_dicts): + result[bb] = size + return result + + def process_set_of_files(path): - OP_INTERSECTION = 'intersect' - OP_DIFFERENCE = 'subtract' - OP_UNION = 'union' - supported_operations = {OP_INTERSECTION, OP_DIFFERENCE, OP_UNION} + supported_operations = { + 'intersect': intersect_bbs, + 'subtract': subtract_bbs, + 'union': union_bbs + } with open(path, "r") as f: all_lines = [l.rstrip(' \t\n\r') for l in f.readlines()] lines = [l for l in all_lines if len(l)] - operation = lines[0] - if operation not in supported_operations: + op = supported_operations.get(lines[0]) + if not op: raise Exception('Unsupported operation') lines = lines[1:] if len(lines) == 1: @@ -99,23 +127,7 @@ def process_set_of_files(path): bbs = [] for m in range(len(mod_list)): dicts = [f[1][m] for f in files] - res_dict = {} - bbs.append(res_dict) - if operation == OP_UNION: - for d in dicts: - res_dict.update(d) - else: - first_dict = dicts[0] - other_dicts = dicts[1:] - for bb, size in first_dict.items(): - if operation == OP_INTERSECTION: - to_add = all(bb in d for d in other_dicts) - elif operation == OP_DIFFERENCE: - to_add = all(bb not in d for d in other_dicts) - else: - assert False - if to_add: - res_dict[bb] = size + bbs.append(op(dicts)) return [mod_list, bbs] diff --git a/unittest/test_set_operations.py b/unittest/test_set_operations.py new file mode 100644 index 0000000..ab6f776 --- /dev/null +++ b/unittest/test_set_operations.py @@ -0,0 +1,28 @@ +import unittest +import sys +sys.path.append(".") +from cutterdrcov_plugin import drcov + +A = { 1:1, 2:2, 3:3 } +B = { 2:2, 4:4 } +C = { 1:1, 3:3, 5:5 } + +class TestSetOperations(unittest.TestCase): + + def test_union(self): + self.assertEqual(drcov.union_bbs([A]), A) + self.assertEqual(drcov.union_bbs([A, B]), {1:1, 2:2, 3:3, 4:4}) + self.assertEqual(drcov.union_bbs([A, B, C]), {1:1, 2:2, 3:3, 4:4, 5:5}) + + def test_subtract(self): + self.assertEqual(drcov.subtract_bbs([A]), {1:1, 2:2, 3:3}) + self.assertEqual(drcov.subtract_bbs([A, B]), {1:1, 3:3}) + self.assertEqual(drcov.subtract_bbs([A, B, C]), {}) + + def test_intersect(self): + self.assertEqual(drcov.intersect_bbs([A]), A) + self.assertEqual(drcov.intersect_bbs([A, B]), {2:2}) + self.assertEqual(drcov.intersect_bbs([A, B, C]), {}) + +if __name__ == '__main__': + unittest.main()