diff --git a/cutterdrcov_plugin/drcov.py b/cutterdrcov_plugin/drcov.py index 827876d..0e4e9b6 100644 --- a/cutterdrcov_plugin/drcov.py +++ b/cutterdrcov_plugin/drcov.py @@ -75,7 +75,65 @@ def dead_module_elimination(modules, bbs): for i in delete: del bbs[i] 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): + 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)] + op = supported_operations.get(lines[0]) + if not op: + 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] + bbs.append(op(dicts)) + 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)) 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()