559 lines
18 KiB
Python
Executable File
559 lines
18 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# Copyright (C) 2022 The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
"""Tests for dependency_analysis.py."""
|
|
|
|
import dependency_analysis
|
|
import queryview_xml
|
|
import soong_module_json
|
|
import unittest
|
|
|
|
|
|
class DependencyAnalysisTest(unittest.TestCase):
|
|
|
|
def test_visit_json_module_graph_post_order_visits_all_in_post_order(self):
|
|
graph = [
|
|
soong_module_json.make_module('q', 'module', [
|
|
soong_module_json.make_dep('a'),
|
|
soong_module_json.make_dep('b'),
|
|
]),
|
|
soong_module_json.make_module('a', 'module', [
|
|
soong_module_json.make_dep('b'),
|
|
soong_module_json.make_dep('c'),
|
|
]),
|
|
soong_module_json.make_module('b', 'module', [
|
|
soong_module_json.make_dep('d'),
|
|
]),
|
|
soong_module_json.make_module('c', 'module', [
|
|
soong_module_json.make_dep('e'),
|
|
]),
|
|
soong_module_json.make_module('d', 'module', []),
|
|
soong_module_json.make_module('e', 'module', []),
|
|
]
|
|
|
|
def only_a(json):
|
|
return json['Name'] == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module['Name'])
|
|
|
|
dependency_analysis.visit_json_module_graph_post_order(
|
|
graph, set(), False, only_a, visit)
|
|
|
|
expected_visited = ['d', 'b', 'e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_json_module_graph_post_order_skips_ignored_by_name_and_transitive(
|
|
self):
|
|
graph = [
|
|
soong_module_json.make_module('a', 'module', [
|
|
soong_module_json.make_dep('b'),
|
|
soong_module_json.make_dep('c'),
|
|
]),
|
|
soong_module_json.make_module('b', 'module', [
|
|
soong_module_json.make_dep('d'),
|
|
]),
|
|
soong_module_json.make_module('c', 'module', [
|
|
soong_module_json.make_dep('e'),
|
|
]),
|
|
soong_module_json.make_module('d', 'module', []),
|
|
soong_module_json.make_module('e', 'module', []),
|
|
]
|
|
|
|
def only_a(json):
|
|
return json['Name'] == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module['Name'])
|
|
|
|
dependency_analysis.visit_json_module_graph_post_order(
|
|
graph, set('b'), False, only_a, visit)
|
|
|
|
expected_visited = ['e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_json_module_graph_post_order_skips_defaults_and_transitive(
|
|
self):
|
|
graph = [
|
|
soong_module_json.make_module('a', 'module', [
|
|
soong_module_json.make_dep('b'),
|
|
soong_module_json.make_dep('c'),
|
|
]),
|
|
soong_module_json.make_module('b', 'module_defaults', [
|
|
soong_module_json.make_dep('d'),
|
|
]),
|
|
soong_module_json.make_module('c', 'module', [
|
|
soong_module_json.make_dep('e'),
|
|
]),
|
|
soong_module_json.make_module('d', 'module', []),
|
|
soong_module_json.make_module('e', 'module', []),
|
|
]
|
|
|
|
def only_a(json):
|
|
return json['Name'] == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module['Name'])
|
|
|
|
dependency_analysis.visit_json_module_graph_post_order(
|
|
graph, set(), False, only_a, visit)
|
|
|
|
expected_visited = ['e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_json_module_graph_post_order_skips_windows_and_transitive(
|
|
self):
|
|
windows_variation = soong_module_json.make_variation('os', 'windows')
|
|
graph = [
|
|
soong_module_json.make_module('a', 'module', [
|
|
soong_module_json.make_dep('b', variations=[windows_variation]),
|
|
soong_module_json.make_dep('c'),
|
|
]),
|
|
soong_module_json.make_module(
|
|
'b',
|
|
'module',
|
|
[
|
|
soong_module_json.make_dep('d'),
|
|
],
|
|
variations=[windows_variation],
|
|
),
|
|
soong_module_json.make_module('c', 'module', [
|
|
soong_module_json.make_dep('e'),
|
|
]),
|
|
soong_module_json.make_module('d', 'module', []),
|
|
soong_module_json.make_module('e', 'module', []),
|
|
]
|
|
|
|
def only_a(json):
|
|
return json['Name'] == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module['Name'])
|
|
|
|
dependency_analysis.visit_json_module_graph_post_order(
|
|
graph, set(), False, only_a, visit)
|
|
|
|
expected_visited = ['e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_json_module_graph_post_order_skips_prebuilt_tag_deps(self):
|
|
graph = [
|
|
soong_module_json.make_module('a', 'module', [
|
|
soong_module_json.make_dep(
|
|
'b', 'android.prebuiltDependencyTag {BaseDependencyTag:{}}'),
|
|
soong_module_json.make_dep('c'),
|
|
]),
|
|
soong_module_json.make_module('b', 'module', [
|
|
soong_module_json.make_dep('d'),
|
|
]),
|
|
soong_module_json.make_module('c', 'module', [
|
|
soong_module_json.make_dep('e'),
|
|
]),
|
|
soong_module_json.make_module('d', 'module', []),
|
|
soong_module_json.make_module('e', 'module', []),
|
|
]
|
|
|
|
def only_a(json):
|
|
return json['Name'] == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module['Name'])
|
|
|
|
dependency_analysis.visit_json_module_graph_post_order(
|
|
graph, set(), False, only_a, visit)
|
|
|
|
expected_visited = ['e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_json_module_graph_post_order_no_infinite_loop_for_self_dep(
|
|
self):
|
|
graph = [
|
|
soong_module_json.make_module('a', 'module',
|
|
[soong_module_json.make_dep('a')]),
|
|
]
|
|
|
|
def only_a(json):
|
|
return json['Name'] == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module['Name'])
|
|
|
|
dependency_analysis.visit_json_module_graph_post_order(
|
|
graph, set(), False, only_a, visit)
|
|
|
|
expected_visited = ['a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_json_module_graph_post_order_visits_all_variants(self):
|
|
graph = [
|
|
soong_module_json.make_module(
|
|
'a',
|
|
'module',
|
|
[
|
|
soong_module_json.make_dep('b'),
|
|
],
|
|
variations=[soong_module_json.make_variation('m', '1')],
|
|
),
|
|
soong_module_json.make_module(
|
|
'a',
|
|
'module',
|
|
[
|
|
soong_module_json.make_dep('c'),
|
|
],
|
|
variations=[soong_module_json.make_variation('m', '2')],
|
|
),
|
|
soong_module_json.make_module('b', 'module', [
|
|
soong_module_json.make_dep('d'),
|
|
]),
|
|
soong_module_json.make_module('c', 'module', [
|
|
soong_module_json.make_dep('e'),
|
|
]),
|
|
soong_module_json.make_module('d', 'module', []),
|
|
soong_module_json.make_module('e', 'module', []),
|
|
]
|
|
|
|
def only_a(json):
|
|
return json['Name'] == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module['Name'])
|
|
|
|
dependency_analysis.visit_json_module_graph_post_order(
|
|
graph, set(), False, only_a, visit)
|
|
|
|
expected_visited = ['d', 'b', 'a', 'e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_json_module_skips_filegroup_with_src_same_as_name(self):
|
|
graph = [
|
|
soong_module_json.make_module(
|
|
'a',
|
|
'filegroup',
|
|
[
|
|
soong_module_json.make_dep('b'),
|
|
],
|
|
json_props=[
|
|
soong_module_json.make_property(
|
|
name='Srcs',
|
|
values=['other_file'],
|
|
),
|
|
],
|
|
),
|
|
soong_module_json.make_module(
|
|
'b',
|
|
'filegroup',
|
|
json_props=[
|
|
soong_module_json.make_property(
|
|
name='Srcs',
|
|
values=['b'],
|
|
),
|
|
],
|
|
),
|
|
]
|
|
|
|
def only_a(json):
|
|
return json['Name'] == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module['Name'])
|
|
|
|
dependency_analysis.visit_json_module_graph_post_order(
|
|
graph, set(), False, only_a, visit)
|
|
|
|
expected_visited = ['a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_json_module_graph_post_order_include_created_by(self):
|
|
graph = [
|
|
soong_module_json.make_module('a', 'module', [
|
|
soong_module_json.make_dep('b'),
|
|
soong_module_json.make_dep('c'),
|
|
]),
|
|
soong_module_json.make_module('b', 'module', created_by='d'),
|
|
soong_module_json.make_module('c', 'module', [
|
|
soong_module_json.make_dep('e'),
|
|
]),
|
|
soong_module_json.make_module('d', 'module', []),
|
|
soong_module_json.make_module('e', 'module', []),
|
|
]
|
|
|
|
def only_a(json):
|
|
return json['Name'] == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module['Name'])
|
|
|
|
dependency_analysis.visit_json_module_graph_post_order(
|
|
graph, set(), False, only_a, visit)
|
|
|
|
expected_visited = ['d', 'b', 'e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_queryview_xml_module_graph_post_order_visits_all(self):
|
|
graph = queryview_xml.make_graph([
|
|
queryview_xml.make_module(
|
|
'//pkg:a', 'a', 'module', dep_names=['//pkg:b', '//pkg:c']),
|
|
queryview_xml.make_module(
|
|
'//pkg:b', 'b', 'module', dep_names=['//pkg:d']),
|
|
queryview_xml.make_module(
|
|
'//pkg:c', 'c', 'module', dep_names=['//pkg:e']),
|
|
queryview_xml.make_module('//pkg:d', 'd', 'module'),
|
|
queryview_xml.make_module('//pkg:e', 'e', 'module'),
|
|
])
|
|
|
|
def only_a(module):
|
|
return module.name == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module.name)
|
|
|
|
dependency_analysis.visit_queryview_xml_module_graph_post_order(
|
|
graph, set(), only_a, visit)
|
|
|
|
expected_visited = ['d', 'b', 'e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_queryview_xml_module_graph_post_order_skips_ignore_by_name(
|
|
self):
|
|
graph = queryview_xml.make_graph([
|
|
queryview_xml.make_module(
|
|
'//pkg:a', 'a', 'module', dep_names=['//pkg:b', '//pkg:c']),
|
|
queryview_xml.make_module(
|
|
'//pkg:b', 'b', 'module', dep_names=['//pkg:d']),
|
|
queryview_xml.make_module(
|
|
'//pkg:c', 'c', 'module', dep_names=['//pkg:e']),
|
|
queryview_xml.make_module('//pkg:d', 'd', 'module'),
|
|
queryview_xml.make_module('//pkg:e', 'e', 'module'),
|
|
])
|
|
|
|
def only_a(module):
|
|
return module.name == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module.name)
|
|
|
|
dependency_analysis.visit_queryview_xml_module_graph_post_order(
|
|
graph, set('b'), only_a, visit)
|
|
|
|
expected_visited = ['e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_queryview_xml_module_graph_post_order_skips_default(self):
|
|
graph = queryview_xml.make_graph([
|
|
queryview_xml.make_module(
|
|
'//pkg:a', 'a', 'module', dep_names=['//pkg:b', '//pkg:c']),
|
|
queryview_xml.make_module(
|
|
'//pkg:b', 'b', 'module_defaults', dep_names=['//pkg:d']),
|
|
queryview_xml.make_module(
|
|
'//pkg:c', 'c', 'module', dep_names=['//pkg:e']),
|
|
queryview_xml.make_module('//pkg:d', 'd', 'module'),
|
|
queryview_xml.make_module('//pkg:e', 'e', 'module'),
|
|
])
|
|
|
|
def only_a(module):
|
|
return module.name == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module.name)
|
|
|
|
dependency_analysis.visit_queryview_xml_module_graph_post_order(
|
|
graph, set(), only_a, visit)
|
|
|
|
expected_visited = ['e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_queryview_xml_module_graph_post_order_skips_cc_prebuilt(self):
|
|
graph = queryview_xml.make_graph([
|
|
queryview_xml.make_module(
|
|
'//pkg:a', 'a', 'module', dep_names=['//pkg:b', '//pkg:c']),
|
|
queryview_xml.make_module(
|
|
'//pkg:b', 'b', 'cc_prebuilt_library', dep_names=['//pkg:d']),
|
|
queryview_xml.make_module(
|
|
'//pkg:c', 'c', 'module', dep_names=['//pkg:e']),
|
|
queryview_xml.make_module('//pkg:d', 'd', 'module'),
|
|
queryview_xml.make_module('//pkg:e', 'e', 'module'),
|
|
])
|
|
|
|
def only_a(module):
|
|
return module.name == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module.name)
|
|
|
|
dependency_analysis.visit_queryview_xml_module_graph_post_order(
|
|
graph, set(), only_a, visit)
|
|
|
|
expected_visited = ['e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_queryview_xml_module_graph_post_order_skips_filegroup_duplicate_name(
|
|
self):
|
|
graph = queryview_xml.make_graph([
|
|
queryview_xml.make_module(
|
|
'//pkg:a', 'a', 'module', dep_names=['//pkg:b', '//pkg:c']),
|
|
queryview_xml.make_module(
|
|
'//pkg:b', 'b', 'filegroup', dep_names=['//pkg:d'], srcs=['b']),
|
|
queryview_xml.make_module(
|
|
'//pkg:c', 'c', 'module', dep_names=['//pkg:e']),
|
|
queryview_xml.make_module('//pkg:d', 'd', 'module'),
|
|
queryview_xml.make_module('//pkg:e', 'e', 'module'),
|
|
])
|
|
|
|
def only_a(module):
|
|
return module.name == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module.name)
|
|
|
|
dependency_analysis.visit_queryview_xml_module_graph_post_order(
|
|
graph, set(), only_a, visit)
|
|
|
|
expected_visited = ['e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_queryview_xml_module_graph_post_order_skips_windows(self):
|
|
graph = queryview_xml.make_graph([
|
|
queryview_xml.make_module(
|
|
'//pkg:a', 'a', 'module', dep_names=['//pkg:b', '//pkg:c']),
|
|
queryview_xml.make_module(
|
|
'//pkg:b',
|
|
'b',
|
|
'module',
|
|
dep_names=['//pkg:d'],
|
|
variant='windows-x86'),
|
|
queryview_xml.make_module(
|
|
'//pkg:c', 'c', 'module', dep_names=['//pkg:e']),
|
|
queryview_xml.make_module('//pkg:d', 'd', 'module'),
|
|
queryview_xml.make_module('//pkg:e', 'e', 'module'),
|
|
])
|
|
|
|
def only_a(module):
|
|
return module.name == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module.name)
|
|
|
|
dependency_analysis.visit_queryview_xml_module_graph_post_order(
|
|
graph, set(), only_a, visit)
|
|
|
|
expected_visited = ['e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_queryview_xml_module_graph_post_order_self_dep_no_infinite_loop(
|
|
self):
|
|
graph = queryview_xml.make_graph([
|
|
queryview_xml.make_module(
|
|
'//pkg:a',
|
|
'a',
|
|
'module',
|
|
dep_names=['//pkg:b--variant1', '//pkg:c']),
|
|
queryview_xml.make_module(
|
|
'//pkg:b--variant1',
|
|
'b',
|
|
'module',
|
|
variant='variant1',
|
|
dep_names=['//pkg:b--variant2']),
|
|
queryview_xml.make_module(
|
|
'//pkg:b--variant2',
|
|
'b',
|
|
'module',
|
|
variant='variant2',
|
|
dep_names=['//pkg:d']),
|
|
queryview_xml.make_module(
|
|
'//pkg:c', 'c', 'module', dep_names=['//pkg:e']),
|
|
queryview_xml.make_module('//pkg:d', 'd', 'module'),
|
|
queryview_xml.make_module('//pkg:e', 'e', 'module'),
|
|
])
|
|
|
|
def only_a(module):
|
|
return module.name == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module.name)
|
|
|
|
dependency_analysis.visit_queryview_xml_module_graph_post_order(
|
|
graph, set(), only_a, visit)
|
|
|
|
expected_visited = ['d', 'b', 'b', 'e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
def test_visit_queryview_xml_module_graph_post_order_skips_prebuilt_with_same_name(
|
|
self):
|
|
graph = queryview_xml.make_graph([
|
|
queryview_xml.make_module(
|
|
'//pkg:a',
|
|
'a',
|
|
'module',
|
|
dep_names=['//other_pkg:prebuilt_a', '//pkg:b', '//pkg:c']),
|
|
queryview_xml.make_module('//other_pkg:prebuilt_a', 'prebuilt_a',
|
|
'prebuilt_module'),
|
|
queryview_xml.make_module(
|
|
'//pkg:b', 'b', 'module', dep_names=['//pkg:d']),
|
|
queryview_xml.make_module(
|
|
'//pkg:c', 'c', 'module', dep_names=['//pkg:e']),
|
|
queryview_xml.make_module('//pkg:d', 'd', 'module'),
|
|
queryview_xml.make_module('//pkg:e', 'e', 'module'),
|
|
])
|
|
|
|
def only_a(module):
|
|
return module.name == 'a'
|
|
|
|
visited_modules = []
|
|
|
|
def visit(module, _):
|
|
visited_modules.append(module.name)
|
|
|
|
dependency_analysis.visit_queryview_xml_module_graph_post_order(
|
|
graph, set(), only_a, visit)
|
|
|
|
expected_visited = ['d', 'b', 'e', 'c', 'a']
|
|
self.assertListEqual(visited_modules, expected_visited)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|