You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
490 lines
19 KiB
490 lines
19 KiB
#!/usr/bin/env python3
|
|
#
|
|
# Copyright 2018, 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.
|
|
|
|
"""Unittests for project_info."""
|
|
|
|
import logging
|
|
import os
|
|
import shutil
|
|
import tempfile
|
|
import unittest
|
|
from unittest import mock
|
|
|
|
from aidegen import constant
|
|
from aidegen import unittest_constants
|
|
from aidegen.lib import common_util
|
|
from aidegen.lib import project_info
|
|
from aidegen.lib import project_config
|
|
from aidegen.lib import source_locator
|
|
|
|
_MODULE_INFO = {
|
|
'm1': {
|
|
'class': ['JAVA_LIBRARIES'],
|
|
'dependencies': ['m2', 'm6'],
|
|
'path': ['m1']
|
|
},
|
|
'm2': {
|
|
'class': ['JAVA_LIBRARIES'],
|
|
'dependencies': ['m3', 'm4']
|
|
},
|
|
'm3': {
|
|
'class': ['JAVA_LIBRARIES'],
|
|
'dependencies': []
|
|
},
|
|
'm4': {
|
|
'class': ['JAVA_LIBRARIES'],
|
|
'dependencies': ['m6']
|
|
},
|
|
'm5': {
|
|
'class': ['JAVA_LIBRARIES'],
|
|
'dependencies': []
|
|
},
|
|
'm6': {
|
|
'class': ['JAVA_LIBRARIES'],
|
|
'dependencies': ['m2']
|
|
},
|
|
}
|
|
_EXPECT_DEPENDENT_MODULES = {
|
|
'm1': {
|
|
'class': ['JAVA_LIBRARIES'],
|
|
'dependencies': ['m2', 'm6'],
|
|
'path': ['m1'],
|
|
'depth': 0
|
|
},
|
|
'm2': {
|
|
'class': ['JAVA_LIBRARIES'],
|
|
'dependencies': ['m3', 'm4'],
|
|
'depth': 1
|
|
},
|
|
'm3': {
|
|
'class': ['JAVA_LIBRARIES'],
|
|
'dependencies': [],
|
|
'depth': 2
|
|
},
|
|
'm4': {
|
|
'class': ['JAVA_LIBRARIES'],
|
|
'dependencies': ['m6'],
|
|
'depth': 2
|
|
},
|
|
'm6': {
|
|
'class': ['JAVA_LIBRARIES'],
|
|
'dependencies': ['m2'],
|
|
'depth': 1
|
|
},
|
|
}
|
|
|
|
|
|
# pylint: disable=protected-access
|
|
# pylint: disable=invalid-name
|
|
class ProjectInfoUnittests(unittest.TestCase):
|
|
"""Unit tests for project_info.py"""
|
|
|
|
def setUp(self):
|
|
"""Initialize arguments for ProjectInfo."""
|
|
self.args = mock.MagicMock()
|
|
self.args.module_name = 'm1'
|
|
self.args.project_path = ''
|
|
self.args.ide = ['j']
|
|
self.args.no_launch = True
|
|
self.args.depth = 0
|
|
self.args.android_tree = False
|
|
self.args.skip_build = True
|
|
self.args.targets = ['m1']
|
|
self.args.verbose = False
|
|
self.args.ide_installed_path = None
|
|
self.args.config_reset = False
|
|
self.args.language = ['j']
|
|
|
|
@mock.patch('atest.module_info.ModuleInfo')
|
|
def test_get_dep_modules(self, mock_module_info):
|
|
"""Test get_dep_modules recursively find dependent modules."""
|
|
mock_module_info.name_to_module_info = _MODULE_INFO
|
|
mock_module_info.is_module.return_value = True
|
|
mock_module_info.get_paths.return_value = ['m1']
|
|
mock_module_info.get_module_names.return_value = ['m1']
|
|
project_info.ProjectInfo.modules_info = mock_module_info
|
|
proj_info = project_info.ProjectInfo(self.args.module_name, False)
|
|
self.assertEqual(proj_info.dep_modules, _EXPECT_DEPENDENT_MODULES)
|
|
|
|
@mock.patch.object(project_info.ProjectInfo,
|
|
'_get_modules_under_project_path')
|
|
@mock.patch.object(project_info.ProjectInfo, 'get_dep_modules')
|
|
def test_init(self, mock_get_deps, mock_get_sub_modules):
|
|
"""Test init."""
|
|
project_info.ProjectInfo(constant.FRAMEWORK_ALL, False)
|
|
self.assertTrue(mock_get_deps.called)
|
|
self.assertFalse(mock_get_sub_modules.called)
|
|
|
|
@mock.patch.object(common_util, 'get_android_root_dir')
|
|
def test_get_target_name(self, mock_get_root):
|
|
"""Test get_target_name with different conditions."""
|
|
mock_get_root.return_value = unittest_constants.TEST_DATA_PATH
|
|
self.assertEqual(
|
|
project_info.ProjectInfo.get_target_name(
|
|
unittest_constants.TEST_MODULE,
|
|
unittest_constants.TEST_DATA_PATH),
|
|
os.path.basename(unittest_constants.TEST_DATA_PATH))
|
|
self.assertEqual(
|
|
project_info.ProjectInfo.get_target_name(
|
|
unittest_constants.TEST_MODULE, unittest_constants.TEST_PATH),
|
|
unittest_constants.TEST_MODULE)
|
|
|
|
# pylint: disable=too-many-locals
|
|
@mock.patch('logging.info')
|
|
@mock.patch.object(common_util, 'get_android_root_dir')
|
|
@mock.patch('atest.module_info.ModuleInfo')
|
|
@mock.patch('atest.atest_utils.build')
|
|
def test_locate_source(self, mock_atest_utils_build, mock_module_info,
|
|
mock_get_root, mock_info):
|
|
"""Test locate_source handling."""
|
|
mock_atest_utils_build.build.return_value = True
|
|
test_root_path = os.path.join(tempfile.mkdtemp(), 'test')
|
|
shutil.copytree(unittest_constants.TEST_DATA_PATH, test_root_path)
|
|
mock_get_root.return_value = test_root_path
|
|
generated_jar = ('out/soong/.intermediates/packages/apps/test/test/'
|
|
'android_common/generated.jar')
|
|
locate_module_info = dict(unittest_constants.MODULE_INFO)
|
|
locate_module_info['installed'] = [generated_jar]
|
|
mock_module_info.is_module.return_value = True
|
|
mock_module_info.get_paths.return_value = [
|
|
unittest_constants.MODULE_PATH
|
|
]
|
|
mock_module_info.get_module_names.return_value = [
|
|
unittest_constants.TEST_MODULE
|
|
]
|
|
project_config.ProjectConfig(self.args)
|
|
project_info_obj = project_info.ProjectInfo(
|
|
mock_module_info.get_paths()[0])
|
|
project_info_obj.dep_modules = {
|
|
unittest_constants.TEST_MODULE: locate_module_info
|
|
}
|
|
project_info_obj._init_source_path()
|
|
# Show warning when the jar not exists after build the module.
|
|
result_jar = set()
|
|
project_info_obj.locate_source()
|
|
self.assertEqual(project_info_obj.source_path['jar_path'], result_jar)
|
|
self.assertTrue(mock_info.called)
|
|
|
|
# Test collects source and test folders.
|
|
result_source = set(['packages/apps/test/src/main/java'])
|
|
result_test = set(['packages/apps/test/tests'])
|
|
self.assertEqual(project_info_obj.source_path['source_folder_path'],
|
|
result_source)
|
|
self.assertEqual(project_info_obj.source_path['test_folder_path'],
|
|
result_test)
|
|
|
|
@mock.patch.object(project_info, 'batch_build_dependencies')
|
|
@mock.patch.object(common_util, 'get_android_root_dir')
|
|
@mock.patch('atest.module_info.ModuleInfo')
|
|
@mock.patch('atest.atest_utils.build')
|
|
def test_locate_source_with_skip_build(self, mock_atest_utils_build,
|
|
mock_module_info, mock_get_root,
|
|
mock_batch):
|
|
"""Test locate_source handling."""
|
|
mock_atest_utils_build.build.return_value = True
|
|
test_root_path = os.path.join(tempfile.mkdtemp(), 'test')
|
|
shutil.copytree(unittest_constants.TEST_DATA_PATH, test_root_path)
|
|
mock_get_root.return_value = test_root_path
|
|
generated_jar = ('out/soong/.intermediates/packages/apps/test/test/'
|
|
'android_common/generated.jar')
|
|
locate_module_info = dict(unittest_constants.MODULE_INFO)
|
|
locate_module_info['installed'] = [generated_jar]
|
|
mock_module_info.is_module.return_value = True
|
|
mock_module_info.get_paths.return_value = [
|
|
unittest_constants.MODULE_PATH
|
|
]
|
|
mock_module_info.get_module_names.return_value = [
|
|
unittest_constants.TEST_MODULE
|
|
]
|
|
args = mock.MagicMock()
|
|
args.module_name = 'm1'
|
|
args.project_path = ''
|
|
args.ide = ['j']
|
|
args.no_launch = True
|
|
args.depth = 0
|
|
args.android_tree = False
|
|
args.skip_build = True
|
|
args.targets = ['m1']
|
|
args.verbose = False
|
|
args.ide_installed_path = None
|
|
args.config_reset = False
|
|
args.language = ['j']
|
|
project_config.ProjectConfig(args)
|
|
project_info_obj = project_info.ProjectInfo(
|
|
mock_module_info.get_paths()[0])
|
|
project_info_obj.dep_modules = {
|
|
unittest_constants.TEST_MODULE: locate_module_info
|
|
}
|
|
project_info_obj._init_source_path()
|
|
project_info_obj.locate_source()
|
|
self.assertFalse(mock_batch.called)
|
|
|
|
args.ide = ['v']
|
|
args.skip_build = False
|
|
project_config.ProjectConfig(args)
|
|
project_info_obj = project_info.ProjectInfo(
|
|
mock_module_info.get_paths()[0])
|
|
project_info_obj.dep_modules = {
|
|
unittest_constants.TEST_MODULE: locate_module_info
|
|
}
|
|
project_info_obj._init_source_path()
|
|
project_info_obj.locate_source()
|
|
self.assertFalse(mock_batch.called)
|
|
|
|
def test_separate_build_target(self):
|
|
"""Test separate_build_target."""
|
|
test_list = ['1', '22', '333', '4444', '55555', '1', '7777777']
|
|
targets = []
|
|
sample = [['1', '22', '333'], ['4444'], ['55555', '1'], ['7777777']]
|
|
for start, end in iter(
|
|
project_info._separate_build_targets(test_list, 9)):
|
|
targets.append(test_list[start:end])
|
|
self.assertEqual(targets, sample)
|
|
|
|
def test_separate_build_target_with_length_short(self):
|
|
"""Test separate_build_target with length short."""
|
|
test_list = ['1']
|
|
sample = [['1']]
|
|
targets = []
|
|
for start, end in iter(
|
|
project_info._separate_build_targets(test_list, 9)):
|
|
targets.append(test_list[start:end])
|
|
self.assertEqual(targets, sample)
|
|
|
|
@mock.patch.object(project_info.ProjectInfo, 'locate_source')
|
|
@mock.patch('atest.module_info.ModuleInfo')
|
|
def test_rebuild_jar_once(self, mock_module_info, mock_locate_source):
|
|
"""Test rebuild the jar/srcjar only one time."""
|
|
mock_module_info.get_paths.return_value = ['m1']
|
|
project_info.ProjectInfo.modules_info = mock_module_info
|
|
proj_info = project_info.ProjectInfo(self.args.module_name, False)
|
|
proj_info.locate_source(build=False)
|
|
self.assertEqual(mock_locate_source.call_count, 1)
|
|
proj_info.locate_source(build=True)
|
|
self.assertEqual(mock_locate_source.call_count, 2)
|
|
|
|
@mock.patch('builtins.print')
|
|
@mock.patch('builtins.format')
|
|
@mock.patch('atest.atest_utils.build')
|
|
def test_build_target(self, mock_build, mock_format, mock_print):
|
|
"""Test _build_target."""
|
|
build_argument = ['-k', 'j']
|
|
test_targets = ['mod_1', 'mod_2']
|
|
build_argument.extend(test_targets)
|
|
mock_build.return_value = False
|
|
project_info._build_target(test_targets)
|
|
self.assertTrue(mock_build.called_with((build_argument, True)))
|
|
self.assertTrue(mock_format.called_with('\n'.join(test_targets)))
|
|
self.assertTrue(mock_print.called)
|
|
mock_print.reset_mock()
|
|
mock_format.reset_mock()
|
|
mock_build.reset_mock()
|
|
|
|
mock_build.return_value = True
|
|
project_info._build_target(test_targets)
|
|
self.assertTrue(mock_build.called_with((build_argument, True)))
|
|
self.assertFalse(mock_format.called)
|
|
self.assertFalse(mock_print.called)
|
|
mock_print.reset_mock()
|
|
mock_format.reset_mock()
|
|
mock_build.reset_mock()
|
|
|
|
@mock.patch.object(project_info, '_build_target')
|
|
@mock.patch.object(project_info, '_separate_build_targets')
|
|
@mock.patch.object(logging, 'info')
|
|
def test_batch_build_dependencies(self, mock_log, mock_sep, mock_build):
|
|
"""Test batch_build_dependencies."""
|
|
mock_sep.return_value = [(0, 1)]
|
|
project_info.batch_build_dependencies({'m1', 'm2'})
|
|
self.assertTrue(mock_log.called)
|
|
self.assertTrue(mock_sep.called)
|
|
self.assertEqual(mock_build.call_count, 1)
|
|
|
|
@mock.patch('os.path.relpath')
|
|
def test_get_rel_project_out_soong_jar_path(self, mock_rel):
|
|
"""Test _get_rel_project_out_soong_jar_path."""
|
|
out_dir = 'a/b/out/soong'
|
|
mock_rel.return_value = out_dir
|
|
proj_info = project_info.ProjectInfo(self.args.module_name, False)
|
|
expected = os.sep.join(
|
|
[out_dir, constant.INTERMEDIATES, 'm1']) + os.sep
|
|
self.assertEqual(
|
|
expected, proj_info._get_rel_project_out_soong_jar_path())
|
|
|
|
def test_update_iml_dep_modules(self):
|
|
"""Test _update_iml_dep_modules with conditions."""
|
|
project1 = mock.Mock()
|
|
project1.source_path = {
|
|
'source_folder_path': [], 'test_folder_path': [], 'r_java_path': [],
|
|
'srcjar_path': [], 'jar_path': []
|
|
}
|
|
project1.dependencies = []
|
|
project2 = mock.Mock()
|
|
project2.iml_name = 'm2'
|
|
project2.rel_out_soong_jar_path = 'out/soong/.intermediates/m2'
|
|
project_info.ProjectInfo.projects = [project1, project2]
|
|
project_info._update_iml_dep_modules(project1)
|
|
self.assertEqual([], project1.dependencies)
|
|
project1.source_path = {
|
|
'source_folder_path': [], 'test_folder_path': [], 'r_java_path': [],
|
|
'srcjar_path': [],
|
|
'jar_path': ['out/soong/.intermediates/m2/a/b/any.jar']
|
|
}
|
|
project_info._update_iml_dep_modules(project1)
|
|
self.assertEqual(['m2'], project1.dependencies)
|
|
|
|
|
|
class MultiProjectsInfoUnittests(unittest.TestCase):
|
|
"""Unit tests for MultiProjectsInfo class."""
|
|
|
|
@mock.patch.object(project_info.ProjectInfo, '__init__')
|
|
@mock.patch.object(project_info.ProjectInfo, 'get_dep_modules')
|
|
@mock.patch.object(project_info.ProjectInfo,
|
|
'_get_robolectric_dep_module')
|
|
@mock.patch.object(project_info.ProjectInfo,
|
|
'_get_modules_under_project_path')
|
|
@mock.patch.object(common_util, 'get_related_paths')
|
|
def test_collect_all_dep_modules(self, mock_relpath, mock_sub_modules_path,
|
|
mock_robo_module, mock_get_dep_modules,
|
|
mock_init):
|
|
"""Test _collect_all_dep_modules."""
|
|
mock_init.return_value = None
|
|
mock_relpath.return_value = ('path/to/sub/module', '')
|
|
mock_sub_modules_path.return_value = 'sub_module'
|
|
mock_robo_module.return_value = 'robo_module'
|
|
expected = set(project_info._CORE_MODULES)
|
|
expected.update({'sub_module', 'robo_module'})
|
|
proj = project_info.MultiProjectsInfo(['a'])
|
|
proj.project_module_names = set('framework-all')
|
|
proj.collect_all_dep_modules()
|
|
self.assertTrue(mock_get_dep_modules.called_with(expected))
|
|
|
|
@mock.patch.object(logging, 'debug')
|
|
@mock.patch.object(source_locator, 'ModuleData')
|
|
@mock.patch.object(project_info.ProjectInfo, '__init__')
|
|
def test_gen_folder_base_dependencies(self, mock_init, mock_module_data,
|
|
mock_log):
|
|
"""Test _gen_folder_base_dependencies."""
|
|
mock_init.return_value = None
|
|
proj = project_info.MultiProjectsInfo(['a'])
|
|
module = mock.Mock()
|
|
mock_module_data.return_value = module
|
|
mock_module_data.module_path = ''
|
|
proj.gen_folder_base_dependencies(mock_module_data)
|
|
self.assertTrue(mock_log.called)
|
|
mock_module_data.module_path = 'a/b'
|
|
mock_module_data.src_dirs = ['a/b/c']
|
|
mock_module_data.test_dirs = []
|
|
mock_module_data.r_java_paths = []
|
|
mock_module_data.srcjar_paths = []
|
|
mock_module_data.jar_files = []
|
|
mock_module_data.dep_paths = []
|
|
proj.gen_folder_base_dependencies(mock_module_data)
|
|
expected = {
|
|
'a/b': {
|
|
'src_dirs': ['a/b/c'],
|
|
'test_dirs': [],
|
|
'r_java_paths': [],
|
|
'srcjar_paths': [],
|
|
'jar_files': [],
|
|
'dep_paths': [],
|
|
}
|
|
}
|
|
self.assertEqual(proj.path_to_sources, expected)
|
|
mock_module_data.srcjar_paths = ['x/y.srcjar']
|
|
proj.gen_folder_base_dependencies(mock_module_data)
|
|
expected = {
|
|
'a/b': {
|
|
'src_dirs': ['a/b/c'],
|
|
'test_dirs': [],
|
|
'r_java_paths': [],
|
|
'srcjar_paths': ['x/y.srcjar'],
|
|
'jar_files': [],
|
|
'dep_paths': [],
|
|
}
|
|
}
|
|
self.assertEqual(proj.path_to_sources, expected)
|
|
|
|
@mock.patch.object(source_locator, 'ModuleData')
|
|
@mock.patch.object(project_info.ProjectInfo, '__init__')
|
|
def test_add_framework_base_path(self, mock_init, mock_module_data):
|
|
"""Test _gen_folder_base_dependencies."""
|
|
mock_init.return_value = None
|
|
proj = project_info.MultiProjectsInfo(['a'])
|
|
module = mock.Mock()
|
|
mock_module_data.return_value = module
|
|
mock_module_data.module_path = 'frameworks/base'
|
|
mock_module_data.module_name = 'framework-other'
|
|
mock_module_data.src_dirs = ['a/b/c']
|
|
mock_module_data.test_dirs = []
|
|
mock_module_data.r_java_paths = []
|
|
mock_module_data.srcjar_paths = ['x/y.srcjar']
|
|
mock_module_data.jar_files = []
|
|
mock_module_data.dep_paths = []
|
|
proj.gen_folder_base_dependencies(mock_module_data)
|
|
expected = {
|
|
'frameworks/base': {
|
|
'dep_paths': [],
|
|
'jar_files': [],
|
|
'r_java_paths': [],
|
|
'src_dirs': ['a/b/c'],
|
|
'srcjar_paths': [],
|
|
'test_dirs': [],
|
|
}
|
|
}
|
|
self.assertDictEqual(proj.path_to_sources, expected)
|
|
|
|
@mock.patch.object(source_locator, 'ModuleData')
|
|
@mock.patch.object(project_info.ProjectInfo, '__init__')
|
|
def test_add_framework_srcjar_path(self, mock_init, mock_module_data):
|
|
"""Test _gen_folder_base_dependencies."""
|
|
mock_init.return_value = None
|
|
proj = project_info.MultiProjectsInfo(['a'])
|
|
module = mock.Mock()
|
|
mock_module_data.return_value = module
|
|
mock_module_data.module_path = 'frameworks/base'
|
|
mock_module_data.module_name = 'framework-all'
|
|
mock_module_data.src_dirs = ['a/b/c']
|
|
mock_module_data.test_dirs = []
|
|
mock_module_data.r_java_paths = []
|
|
mock_module_data.srcjar_paths = ['x/y.srcjar']
|
|
mock_module_data.jar_files = []
|
|
mock_module_data.dep_paths = []
|
|
proj.gen_folder_base_dependencies(mock_module_data)
|
|
expected = {
|
|
'frameworks/base': {
|
|
'dep_paths': [],
|
|
'jar_files': [],
|
|
'r_java_paths': [],
|
|
'src_dirs': ['a/b/c'],
|
|
'srcjar_paths': [],
|
|
'test_dirs': [],
|
|
},
|
|
'frameworks/base/framework_srcjars': {
|
|
'dep_paths': ['frameworks/base'],
|
|
'jar_files': [],
|
|
'r_java_paths': [],
|
|
'src_dirs': [],
|
|
'srcjar_paths': ['x/y.srcjar'],
|
|
'test_dirs': [],
|
|
}
|
|
}
|
|
self.assertDictEqual(proj.path_to_sources, expected)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|