From 887ff6dbf0ca86447f35588939a812be7036614f Mon Sep 17 00:00:00 2001 From: Logan Chien Date: Mon, 26 Feb 2018 19:48:36 +0800 Subject: [PATCH] sourcedr: check_vndk_dep should evaluate recursively Test: ./run_tests.sh Change-Id: Ie85bc0a3d6ba7a7b173ea9361385fd2e4d1b9b4c --- .../sourcedr/blueprint/blueprint.py | 55 +++++++++--- .../blueprint/tests/test_evaluate_default.py | 87 +++++++++++++++++++ 2 files changed, 131 insertions(+), 11 deletions(-) diff --git a/vndk/tools/source-deps-reviewer/sourcedr/blueprint/blueprint.py b/vndk/tools/source-deps-reviewer/sourcedr/blueprint/blueprint.py index bf0be84e7..77f463df3 100755 --- a/vndk/tools/source-deps-reviewer/sourcedr/blueprint/blueprint.py +++ b/vndk/tools/source-deps-reviewer/sourcedr/blueprint/blueprint.py @@ -892,6 +892,46 @@ class RecursiveParser(object): # Transformation #------------------------------------------------------------------------------ +def _build_named_modules_dict(modules): + """Build a name-to-module dict.""" + named_modules = {} + for i, (ident, attrs) in enumerate(modules): + name = attrs.get('name') + if name is not None: + named_modules[name] = [ident, attrs, i] + return named_modules + + +def _po_sorted_modules(modules, named_modules): + """Sort modules in post order.""" + modules = [(ident, attrs, i) for i, (ident, attrs) in enumerate(modules)] + + # Build module dependency graph. + edges = {} + for ident, attrs, module_id in modules: + defaults = attrs.get('defaults') + if defaults: + edges[module_id] = set( + named_modules[default][2] for default in defaults) + + # Traverse module graph in post order. + post_order = [] + visited = set() + + def _traverse(module_id): + visited.add(module_id) + for next_module_id in edges.get(module_id, []): + if next_module_id not in visited: + _traverse(next_module_id) + post_order.append(modules[module_id]) + + for module_id in range(len(modules)): + if module_id not in visited: + _traverse(module_id) + + return post_order + + def evaluate_default(attrs, default_attrs): """Add default attributes if the keys do not exist.""" for key, value in default_attrs.items(): @@ -906,16 +946,9 @@ def evaluate_default(attrs, default_attrs): def evaluate_defaults(modules): """Add default attributes to all modules if the keys do not exist.""" - mods = {} - for ident, attrs in modules: - name = attrs.get('name') - if name is not None: - mods[name] = (ident, attrs) - for i, (ident, attrs) in enumerate(modules): - defaults = attrs.get('defaults') - if defaults is None: - continue - for default in defaults: - attrs = evaluate_default(attrs, mods[default][1]) + named_modules = _build_named_modules_dict(modules) + for ident, attrs, i in _po_sorted_modules(modules, named_modules): + for default in attrs.get('defaults', []): + attrs = evaluate_default(attrs, named_modules[default][1]) modules[i] = (ident, attrs) return modules diff --git a/vndk/tools/source-deps-reviewer/sourcedr/blueprint/tests/test_evaluate_default.py b/vndk/tools/source-deps-reviewer/sourcedr/blueprint/tests/test_evaluate_default.py index 1860787da..324011066 100644 --- a/vndk/tools/source-deps-reviewer/sourcedr/blueprint/tests/test_evaluate_default.py +++ b/vndk/tools/source-deps-reviewer/sourcedr/blueprint/tests/test_evaluate_default.py @@ -131,5 +131,92 @@ class EvaluateDefaultsTest(unittest.TestCase): self.fail('modules without names must not cause KeyErrors') + def test_evaluate_recursive(self): + """Test whether evaluate_defaults() can evaluate defaults + recursively.""" + + modules = [ + ('cc_defaults', { + 'name': 'libfoo-defaults', + 'defaults': ['libtest-defaults'], + 'a': 'libfoo_default_a', + 'b': 'libfoo_default_b', + }), + ('cc_defaults', { + 'name': 'libbar-defaults', + 'a': 'libbar_default_a', + 'b': 'libbar_default_b', + 'c': 'libbar_default_c', + 'd': 'libbar_default_d', + }), + ('cc_defaults', { + 'name': 'libtest-defaults', + 'a': 'libtest_default_a', + 'b': 'libtest_default_b', + 'c': 'libtest_default_c', + 'e': 'libtest_default_e', + }), + ('cc_library', { + 'name': 'libfoo', + 'defaults': ['libfoo-defaults', 'libbar-defaults'], + 'a': 'specified_a', + }), + ] + + modules = evaluate_defaults(modules) + + module = modules[-1][1] + self.assertEqual(module['name'], 'libfoo') + self.assertEqual(module['a'], 'specified_a') + self.assertEqual(module['b'], 'libfoo_default_b') + self.assertEqual(module['c'], 'libtest_default_c') + self.assertEqual(module['d'], 'libbar_default_d') + self.assertEqual(module['e'], 'libtest_default_e') + + + def test_evaluate_recursive_diamond(self): + """Test whether evaluate_defaults() can evaluate diamond defaults + recursively.""" + + modules = [ + ('cc_defaults', { + 'name': 'libfoo-defaults', + 'defaults': ['libtest-defaults'], + 'a': 'libfoo_default_a', + 'b': 'libfoo_default_b', + }), + ('cc_defaults', { + 'name': 'libbar-defaults', + 'defaults': ['libtest-defaults'], + 'a': 'libbar_default_a', + 'b': 'libbar_default_b', + 'c': 'libbar_default_c', + 'd': 'libbar_default_d', + }), + ('cc_defaults', { + 'name': 'libtest-defaults', + 'a': 'libtest_default_a', + 'b': 'libtest_default_b', + 'c': 'libtest_default_c', + 'e': 'libtest_default_e', + }), + ('cc_library', { + 'name': 'libfoo', + 'defaults': ['libfoo-defaults', 'libbar-defaults'], + 'a': 'specified_a', + }), + ] + + modules = evaluate_defaults(modules) + + module = modules[-1][1] + self.assertEqual(module['name'], 'libfoo') + self.assertEqual(module['a'], 'specified_a') + self.assertEqual(module['b'], 'libfoo_default_b') + self.assertEqual(module['c'], 'libtest_default_c') + self.assertEqual(module['d'], 'libbar_default_d') + self.assertEqual(module['e'], 'libtest_default_e') + + if __name__ == '__main__': unittest.main()