1#!/usr/bin/env python3 2# 3# Copyright 2020 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""Unittests for source_splitter.""" 18 19import os 20import shutil 21import tempfile 22import unittest 23from unittest import mock 24 25from aidegen import unittest_constants 26from aidegen.idea import iml 27from aidegen.lib import common_util 28from aidegen.lib import project_config 29from aidegen.lib import project_info 30from aidegen.project import source_splitter 31 32 33# pylint: disable=protected-access 34class ProjectSplitterUnittest(unittest.TestCase): 35 """Unit tests for ProjectSplitter class.""" 36 37 _TEST_DIR = None 38 _TEST_PATH = unittest_constants.TEST_DATA_PATH 39 _SAMPLE_EXCLUDE_FOLDERS = [ 40 '\n <excludeFolder url="file://%s/.idea" />' % _TEST_PATH, 41 '\n <excludeFolder url="file://%s/out" />' % _TEST_PATH, 42 ] 43 44 def setUp(self): 45 """Prepare the testdata related data.""" 46 projects = [] 47 targets = ['a', 'b', 'c', 'framework'] 48 ProjectSplitterUnittest._TEST_DIR = tempfile.mkdtemp() 49 for i, target in enumerate(targets): 50 with mock.patch.object(project_info, 'ProjectInfo') as proj_info: 51 projects.append(proj_info(target, i == 0)) 52 projects[0].project_relative_path = 'src1' 53 projects[0].source_path = { 54 'source_folder_path': {'src1', 'src2', 'other1'}, 55 'test_folder_path': {'src1/tests'}, 56 'jar_path': {'jar1.jar'}, 57 'jar_module_path': dict(), 58 'r_java_path': set(), 59 'srcjar_path': {'srcjar1.srcjar'} 60 } 61 projects[1].project_relative_path = 'src2' 62 projects[1].source_path = { 63 'source_folder_path': {'src2', 'src2/src3', 'src2/lib', 'other2'}, 64 'test_folder_path': {'src2/tests'}, 65 'jar_path': set(), 66 'jar_module_path': dict(), 67 'r_java_path': set(), 68 'srcjar_path': {'srcjar2.srcjar'} 69 } 70 projects[2].project_relative_path = 'src2/src3' 71 projects[2].source_path = { 72 'source_folder_path': {'src2/src3', 'src2/lib'}, 73 'test_folder_path': {'src2/src3/tests'}, 74 'jar_path': {'jar3.jar'}, 75 'jar_module_path': dict(), 76 'r_java_path': set(), 77 'srcjar_path': {'srcjar3.srcjar'} 78 } 79 projects[3].project_relative_path = 'frameworks/base' 80 projects[3].source_path = { 81 'source_folder_path': set(), 82 'test_folder_path': set(), 83 'jar_path': set(), 84 'jar_module_path': dict(), 85 'r_java_path': set(), 86 'srcjar_path': {'framework.srcjar', 'other.srcjar'} 87 } 88 with mock.patch.object(project_config.ProjectConfig, 89 'get_instance') as proj_cfg: 90 config = mock.Mock() 91 config.full_repo = False 92 proj_cfg.return_value = config 93 self.split_projs = source_splitter.ProjectSplitter(projects) 94 95 def tearDown(self): 96 """Clear the testdata related path.""" 97 self.split_projs = None 98 shutil.rmtree(ProjectSplitterUnittest._TEST_DIR) 99 iml.IMLGenerator.USED_NAME_CACHE.clear() 100 101 @mock.patch.object(common_util, 'get_android_root_dir') 102 @mock.patch.object(project_config.ProjectConfig, 'get_instance') 103 @mock.patch('builtins.any') 104 def test_init(self, mock_any, mock_project, mock_root): 105 """Test initialize the attributes.""" 106 self.assertEqual(len(self.split_projs._projects), 4) 107 mock_any.return_value = False 108 mock_root.return_value = ProjectSplitterUnittest._TEST_DIR 109 with mock.patch.object(project_info, 'ProjectInfo') as proj_info: 110 config = mock.Mock() 111 config.full_repo = False 112 mock_project.return_value = config 113 project = source_splitter.ProjectSplitter(proj_info(['a'], True)) 114 self.assertFalse(project._framework_exist) 115 config.full_repo = True 116 project = source_splitter.ProjectSplitter(proj_info(['a'], True)) 117 self.assertEqual(project._full_repo_iml, 118 os.path.basename( 119 ProjectSplitterUnittest._TEST_DIR)) 120 121 @mock.patch.object(source_splitter.ProjectSplitter, 122 '_remove_duplicate_sources') 123 @mock.patch.object(source_splitter.ProjectSplitter, 124 '_keep_local_sources') 125 @mock.patch.object(source_splitter.ProjectSplitter, 126 '_collect_all_srcs') 127 def test_revise_source_folders(self, mock_copy_srcs, mock_keep_srcs, 128 mock_remove_srcs): 129 """Test revise_source_folders.""" 130 self.split_projs.revise_source_folders() 131 self.assertTrue(mock_copy_srcs.called) 132 self.assertTrue(mock_keep_srcs.called) 133 self.assertTrue(mock_remove_srcs.called) 134 135 def test_collect_all_srcs(self): 136 """Test _collect_all_srcs.""" 137 self.split_projs._collect_all_srcs() 138 sources = self.split_projs._all_srcs 139 expected_srcs = {'src1', 'src2', 'src2/src3', 'src2/lib', 'other1', 140 'other2'} 141 self.assertEqual(sources['source_folder_path'], expected_srcs) 142 expected_tests = {'src1/tests', 'src2/tests', 'src2/src3/tests'} 143 self.assertEqual(sources['test_folder_path'], expected_tests) 144 145 def test_keep_local_sources(self): 146 """Test _keep_local_sources.""" 147 self.split_projs._collect_all_srcs() 148 self.split_projs._keep_local_sources() 149 srcs1 = self.split_projs._projects[0].source_path 150 srcs2 = self.split_projs._projects[1].source_path 151 srcs3 = self.split_projs._projects[2].source_path 152 all_srcs = self.split_projs._all_srcs 153 expected_srcs1 = {'src1'} 154 expected_srcs2 = {'src2', 'src2/src3', 'src2/lib'} 155 expected_srcs3 = {'src2/src3'} 156 expected_all_srcs = {'other1', 'other2'} 157 expected_all_tests = set() 158 self.assertEqual(srcs1['source_folder_path'], expected_srcs1) 159 self.assertEqual(srcs2['source_folder_path'], expected_srcs2) 160 self.assertEqual(srcs3['source_folder_path'], expected_srcs3) 161 self.assertEqual(all_srcs['source_folder_path'], expected_all_srcs) 162 self.assertEqual(all_srcs['test_folder_path'], expected_all_tests) 163 164 def test_remove_duplicate_sources(self): 165 """Test _remove_duplicate_sources.""" 166 self.split_projs._collect_all_srcs() 167 self.split_projs._keep_local_sources() 168 self.split_projs._remove_duplicate_sources() 169 srcs2 = self.split_projs._projects[1].source_path 170 srcs3 = self.split_projs._projects[2].source_path 171 expected_srcs2 = {'src2', 'src2/lib'} 172 expected_srcs3 = {'src2/src3'} 173 self.assertEqual(srcs2['source_folder_path'], expected_srcs2) 174 self.assertEqual(srcs3['source_folder_path'], expected_srcs3) 175 176 def test_get_dependencies(self): 177 """Test get_dependencies.""" 178 iml.IMLGenerator.USED_NAME_CACHE.clear() 179 self.split_projs.get_dependencies() 180 dep1 = ['framework_srcjars', 'base', 'src2', 'dependencies'] 181 dep2 = ['framework_srcjars', 'base', 'dependencies'] 182 dep3 = ['framework_srcjars', 'base', 'src2', 'dependencies'] 183 self.assertEqual(self.split_projs._projects[0].dependencies, dep1) 184 self.assertEqual(self.split_projs._projects[1].dependencies, dep2) 185 self.assertEqual(self.split_projs._projects[2].dependencies, dep3) 186 187 @mock.patch.object(common_util, 'get_android_root_dir') 188 def test_gen_framework_srcjars_iml(self, mock_root): 189 """Test gen_framework_srcjars_iml.""" 190 mock_root.return_value = self._TEST_DIR 191 self.split_projs._projects[0].dep_modules = { 192 'framework-all': { 193 'module_name': 'framework-all', 194 'path': ['frameworks/base'], 195 'srcjars': ['framework.srcjar'], 196 'iml_name': 'framework_srcjars' 197 } 198 } 199 self.split_projs._framework_exist = False 200 self.split_projs.gen_framework_srcjars_iml() 201 expected_srcjars = [ 202 'other.srcjar', 203 'srcjar1.srcjar', 204 'srcjar2.srcjar', 205 'srcjar3.srcjar', 206 ] 207 expected_path = os.path.join(self._TEST_DIR, 208 'frameworks/base/framework_srcjars.iml') 209 self.split_projs._framework_exist = True 210 self.split_projs.revise_source_folders() 211 iml_path = self.split_projs.gen_framework_srcjars_iml() 212 srcjars = self.split_projs._all_srcs['srcjar_path'] 213 self.assertEqual(sorted(list(srcjars)), expected_srcjars) 214 self.assertEqual(iml_path, expected_path) 215 216 @mock.patch.object(iml.IMLGenerator, 'create') 217 @mock.patch.object(common_util, 'get_android_root_dir') 218 def test_gen_dependencies_iml(self, mock_root, mock_create_iml): 219 """Test _gen_dependencies_iml.""" 220 mock_root.return_value = self._TEST_DIR 221 self.split_projs.revise_source_folders() 222 self.split_projs._framework_exist = False 223 self.split_projs._gen_dependencies_iml() 224 self.split_projs._framework_exist = True 225 self.split_projs._gen_dependencies_iml() 226 self.assertTrue(mock_create_iml.called) 227 228 @mock.patch.object(source_splitter, 'get_exclude_content') 229 @mock.patch.object(project_config.ProjectConfig, 'get_instance') 230 @mock.patch.object(iml.IMLGenerator, 'create') 231 @mock.patch.object(common_util, 'get_android_root_dir') 232 def test_gen_projects_iml(self, mock_root, mock_create_iml, mock_project, 233 mock_get_excludes): 234 """Test gen_projects_iml.""" 235 mock_root.return_value = self._TEST_DIR 236 config = mock.Mock() 237 mock_project.return_value = config 238 config.exclude_paths = [] 239 self.split_projs.revise_source_folders() 240 self.split_projs.gen_projects_iml() 241 self.assertTrue(mock_create_iml.called) 242 self.assertFalse(mock_get_excludes.called) 243 config.exclude_paths = ['a'] 244 self.split_projs.gen_projects_iml() 245 self.assertTrue(mock_get_excludes.called) 246 247 def test_get_exclude_content(self): 248 """Test get_exclude_content.""" 249 exclude_folders = source_splitter.get_exclude_content(self._TEST_PATH) 250 self.assertEqual(self._SAMPLE_EXCLUDE_FOLDERS, exclude_folders) 251 252 253if __name__ == '__main__': 254 unittest.main() 255