1#!/usr/bin/env python3 2# 3# Copyright 2018 - 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 project_file_gen.""" 18 19import logging 20import os 21import shutil 22import unittest 23from unittest import mock 24 25from aidegen import unittest_constants 26from aidegen.idea import xml_gen 27from aidegen.lib import common_util 28from aidegen.lib import config 29from aidegen.lib import project_config 30from aidegen.lib import project_file_gen 31from aidegen.lib import project_info 32from aidegen.project import project_splitter 33 34 35# pylint: disable=protected-access 36# pylint: disable-msg=too-many-arguments 37class AidegenProjectFileGenUnittest(unittest.TestCase): 38 """Unit tests for project_file_gen.py.""" 39 40 maxDiff = None 41 _TEST_DATA_PATH = unittest_constants.TEST_DATA_PATH 42 _ANDROID_PROJECT_PATH = unittest_constants.ANDROID_PROJECT_PATH 43 _PROJECT_PATH = os.path.join(_TEST_DATA_PATH, 'project') 44 _ANDROID_FACET_SAMPLE = os.path.join(_TEST_DATA_PATH, 'android_facet.iml') 45 _PROJECT_FACET_SAMPLE = os.path.join(_TEST_DATA_PATH, 'project_facet.iml') 46 _MODULE_DEP_SAMPLE = os.path.join(_TEST_DATA_PATH, 'module_dependency.iml') 47 _IML_SAMPLE = os.path.join(_TEST_DATA_PATH, 'test.iml') 48 _DEPENDENCIES_IML_SAMPLE = os.path.join(_TEST_DATA_PATH, 'dependencies.iml') 49 _MODULE_XML_SAMPLE = os.path.join(_TEST_DATA_PATH, 'modules.xml') 50 _MAIN_MODULE_XML_SAMPLE = os.path.join(_TEST_DATA_PATH, 51 'modules_only_self_module.xml') 52 _ENABLE_DEBUGGER_MODULE_SAMPLE = os.path.join( 53 _TEST_DATA_PATH, 'modules_with_enable_debugger.xml') 54 _IML_PATH = os.path.join(_ANDROID_PROJECT_PATH, 'android_project.iml') 55 _DEPENDENCIES_IML_PATH = os.path.join(_ANDROID_PROJECT_PATH, 56 'dependencies.iml') 57 _IDEA_PATH = os.path.join(_ANDROID_PROJECT_PATH, '.idea') 58 _MODULE_PATH = os.path.join(_IDEA_PATH, 'modules.xml') 59 _SOURCE_SAMPLE = os.path.join(_TEST_DATA_PATH, 'source.iml') 60 _SRCJAR_SAMPLE = os.path.join(_TEST_DATA_PATH, 'srcjar.iml') 61 _AOSP_FOLDER = '/aosp' 62 _TEST_SOURCE_LIST = [ 63 'a/b/c/d', 'a/b/c/d/e', 'a/b/c/d/e/f', 'a/b/c/d/f', 'e/f/a', 'e/f/b/c', 64 'e/f/g/h' 65 ] 66 _ANDROID_SOURCE_RELATIVE_PATH = 'test_data/project' 67 _SAMPLE_CONTENT_LIST = ['a/b/c/d', 'e/f'] 68 _SAMPLE_TRIMMED_SOURCE_LIST = ['a/b/c/d', 'e/f/a', 'e/f/b/c', 'e/f/g/h'] 69 70 def _init_project_config(self, args): 71 """Initialize project configurations.""" 72 self.assertIsNotNone(args) 73 pconfig = project_config.ProjectConfig(args) 74 pconfig.init_environment() 75 76 @mock.patch.object(project_config, 'ProjectConfig') 77 @mock.patch.object(project_info, 'ProjectInfo') 78 def test_generate_modules_xml(self, mock_project, mock_config): 79 """Test _generate_modules_xml.""" 80 mock_config.is_launch_ide = True 81 mock_project.project_absolute_path = self._ANDROID_PROJECT_PATH 82 pfile_gen = project_file_gen.ProjectFileGenerator(mock_project) 83 # Test for main project. 84 try: 85 pfile_gen._generate_modules_xml([]) 86 project_file_gen.update_enable_debugger(self._ANDROID_PROJECT_PATH) 87 test_module = common_util.read_file_content(self._MODULE_PATH) 88 finally: 89 shutil.rmtree(self._IDEA_PATH) 90 sample_module = common_util.read_file_content(self._MODULE_XML_SAMPLE) 91 self.assertEqual(test_module, sample_module) 92 93 # Test for sub projects which only has self module. 94 try: 95 pfile_gen._generate_modules_xml() 96 project_file_gen.update_enable_debugger(self._ANDROID_PROJECT_PATH) 97 test_module = common_util.read_file_content(self._MODULE_PATH) 98 finally: 99 shutil.rmtree(self._IDEA_PATH) 100 sample_module = common_util.read_file_content( 101 self._MAIN_MODULE_XML_SAMPLE) 102 self.assertEqual(test_module, sample_module) 103 104 @mock.patch.object(project_file_gen, '_get_all_git_path') 105 @mock.patch.object(xml_gen, 'write_ignore_git_dirs_file') 106 @mock.patch.object(xml_gen, 'gen_vcs_xml') 107 @mock.patch.object(common_util, 'get_android_root_dir') 108 @mock.patch.object(common_util, 'find_git_root') 109 @mock.patch.object(project_info, 'ProjectInfo') 110 def test_merge_project_vcs_xmls(self, mock_project, mock_get_git_root, 111 mock_get_root, mock_write, mock_ignore_git, 112 mock_all_git_path): 113 """Test _merge_project_vcs_xmls.""" 114 mock_get_root.return_value = '/a/b' 115 mock_project.project_absolute_path = '/a/b/c' 116 mock_project.project_relative_path = 'c' 117 mock_get_git_root.return_value = '/a/b/c' 118 project_file_gen._merge_project_vcs_xmls([mock_project]) 119 self.assertTrue(mock_write.called_with('/a/b/c', '/a/b/c')) 120 mock_project.project_absolute_path = '/a/b' 121 mock_project.project_relative_path = None 122 mock_get_git_root.return_value = None 123 mock_all_git_path.return_value = ['/a', '/b'] 124 project_file_gen._merge_project_vcs_xmls([mock_project]) 125 self.assertTrue(mock_write.called_with('/a/b', [None])) 126 self.assertTrue(mock_ignore_git.called_with('/a/b', ['/a', '/b'])) 127 128 @mock.patch.object(project_info, 'ProjectInfo') 129 def test_copy_project_files(self, mock_project): 130 """Test _copy_constant_project_files.""" 131 mock_project.project_absolute_path = self._ANDROID_PROJECT_PATH 132 project_file_gen.ProjectFileGenerator( 133 mock_project)._copy_constant_project_files() 134 self.assertTrue( 135 os.path.isfile( 136 os.path.join(self._IDEA_PATH, 137 project_file_gen._CODE_STYLE_FOLDER, 138 'codeStyleConfig.xml'))) 139 140 self.assertTrue( 141 os.path.isfile( 142 os.path.join(self._IDEA_PATH, 143 project_file_gen._INSPECTION_FOLDER, 144 'profiles_settings.xml'))) 145 146 self.assertTrue( 147 os.path.isfile( 148 os.path.join(self._IDEA_PATH, 149 project_file_gen._INSPECTION_FOLDER, 150 'Aidegen_Inspections.xml'))) 151 152 self.assertTrue( 153 os.path.isfile( 154 os.path.join(self._IDEA_PATH, 155 project_file_gen._COPYRIGHT_FOLDER, 156 'Apache_2.xml'))) 157 self.assertTrue( 158 os.path.isfile( 159 os.path.join(self._IDEA_PATH, 160 project_file_gen._COPYRIGHT_FOLDER, 161 'profiles_settings.xml'))) 162 shutil.rmtree(self._IDEA_PATH) 163 164 @mock.patch.object(logging, 'error') 165 @mock.patch.object(shutil, 'copy') 166 @mock.patch.object(os.path, 'exists') 167 def test_generate_git_ignore(self, mock_path_exist, mock_copy, 168 mock_loggin_error): 169 """Test _generate_git_ignore.""" 170 mock_path_exist.return_value = True 171 project_file_gen._generate_git_ignore( 172 common_util.get_aidegen_root_dir()) 173 self.assertFalse(mock_copy.called) 174 175 # Test for creating symlink exception. 176 mock_path_exist.return_value = False 177 mock_copy.side_effect = OSError() 178 project_file_gen._generate_git_ignore( 179 common_util.get_aidegen_root_dir()) 180 self.assertTrue(mock_loggin_error.called) 181 182 def test_filter_out_source_paths(self): 183 """Test _filter_out_source_paths.""" 184 test_set = {'a/a.java', 'b/b.java', 'c/c.java'} 185 module_relpath = {'a', 'c'} 186 expected_result = {'b/b.java'} 187 result_set = project_file_gen._filter_out_source_paths(test_set, 188 module_relpath) 189 self.assertEqual(result_set, expected_result) 190 191 @mock.patch.object(project_config, 'ProjectConfig') 192 @mock.patch.object(project_info, 'ProjectInfo') 193 def test_update_enable_debugger(self, mock_project, mock_config): 194 """Test update_enable_debugger.""" 195 mock_config.is_launch_ide = True 196 enable_debugger_iml = '/path/to/enable_debugger/enable_debugger.iml' 197 sample_module = common_util.read_file_content( 198 self._ENABLE_DEBUGGER_MODULE_SAMPLE) 199 mock_project.project_absolute_path = self._ANDROID_PROJECT_PATH 200 pfile_gen = project_file_gen.ProjectFileGenerator(mock_project) 201 try: 202 pfile_gen._generate_modules_xml([]) 203 project_file_gen.update_enable_debugger(self._ANDROID_PROJECT_PATH, 204 enable_debugger_iml) 205 test_module = common_util.read_file_content(self._MODULE_PATH) 206 self.assertEqual(test_module, sample_module) 207 finally: 208 shutil.rmtree(self._IDEA_PATH) 209 210 @mock.patch.object(common_util, 'find_git_root') 211 @mock.patch.object(project_file_gen.ProjectFileGenerator, 212 '_generate_modules_xml') 213 @mock.patch.object(project_info, 'ProjectInfo') 214 def test_generate_intellij_project_file(self, mock_project, 215 mock_gen_xml, mock_get_git_path): 216 """Test generate_intellij_project_file.""" 217 mock_project.project_absolute_path = self._ANDROID_PROJECT_PATH 218 mock_get_git_path.return_value = 'git/path' 219 project_gen = project_file_gen.ProjectFileGenerator(mock_project) 220 project_gen.project_info.is_main_project = False 221 project_gen.generate_intellij_project_file() 222 self.assertFalse(mock_gen_xml.called) 223 project_gen.project_info.is_main_project = True 224 project_gen.generate_intellij_project_file() 225 self.assertTrue(mock_gen_xml.called) 226 227 @mock.patch.object(os, 'walk') 228 def test_get_all_git_path(self, mock_os_walk): 229 """Test _get_all_git_path.""" 230 # Test .git folder exists. 231 mock_os_walk.return_value = [('/root', ['.git', 'a'], None)] 232 test_result = list(project_file_gen._get_all_git_path('/root')) 233 expected_result = ['/root'] 234 self.assertEqual(test_result, expected_result) 235 236 # Test .git folder does not exist. 237 mock_os_walk.return_value = [('/root', ['a'], None)] 238 test_result = list(project_file_gen._get_all_git_path('/root')) 239 expected_result = [] 240 self.assertEqual(test_result, expected_result) 241 242 @mock.patch.object(common_util, 'file_generate') 243 @mock.patch.object(os.path, 'isfile') 244 def test_generate_test_mapping_schema(self, mock_is_file, 245 mock_file_generate): 246 """Test _generate_test_mapping_schema.""" 247 mock_is_file.return_value = False 248 project_file_gen._generate_test_mapping_schema('') 249 self.assertFalse(mock_file_generate.called) 250 mock_is_file.return_value = True 251 project_file_gen._generate_test_mapping_schema('') 252 self.assertTrue(mock_file_generate.called) 253 254 @mock.patch.object(project_file_gen, 'update_enable_debugger') 255 @mock.patch.object(config.AidegenConfig, 'create_enable_debugger_module') 256 def test_gen_enable_debugger_module(self, mock_create_module, 257 mock_update_module): 258 """Test gen_enable_debugger_module.""" 259 android_sdk_path = None 260 project_file_gen.gen_enable_debugger_module('a', android_sdk_path) 261 self.assertFalse(mock_create_module.called) 262 mock_create_module.return_value = False 263 project_file_gen.gen_enable_debugger_module('a', 'b') 264 self.assertFalse(mock_update_module.called) 265 mock_create_module.return_value = True 266 project_file_gen.gen_enable_debugger_module('a', 'b') 267 self.assertTrue(mock_update_module.called) 268 269 @mock.patch.object(project_config.ProjectConfig, 'get_instance') 270 @mock.patch.object(project_file_gen, '_merge_project_vcs_xmls') 271 @mock.patch.object(project_file_gen.ProjectFileGenerator, 272 'generate_intellij_project_file') 273 @mock.patch.object(project_splitter.ProjectSplitter, 'gen_projects_iml') 274 @mock.patch.object(project_splitter.ProjectSplitter, 275 'gen_framework_srcjars_iml') 276 @mock.patch.object(project_splitter.ProjectSplitter, 277 'revise_source_folders') 278 @mock.patch.object(project_splitter.ProjectSplitter, 'get_dependencies') 279 @mock.patch.object(common_util, 'get_android_root_dir') 280 @mock.patch.object(project_info, 'ProjectInfo') 281 def test_generate_ide_project_files(self, mock_project, mock_get_root, 282 mock_get_dep, mock_revise_src, 283 mock_gen_framework_srcjars, 284 mock_gen_projects_iml, mock_gen_file, 285 mock_merge_vcs, mock_project_config): 286 """Test generate_ide_project_files.""" 287 mock_get_root.return_value = '/aosp' 288 mock_project.project_absolute_path = '/aosp' 289 mock_project.project_relative_path = '' 290 project_cfg = mock.Mock() 291 mock_project_config.return_value = project_cfg 292 project_cfg.full_repo = True 293 gen_proj = project_file_gen.ProjectFileGenerator 294 gen_proj.generate_ide_project_files([mock_project]) 295 self.assertTrue(mock_get_dep.called) 296 self.assertTrue(mock_revise_src.called) 297 self.assertTrue(mock_gen_framework_srcjars.called) 298 self.assertTrue(mock_gen_projects_iml.called) 299 self.assertTrue(mock_gen_file.called) 300 self.assertTrue(mock_merge_vcs.called) 301 302 303if __name__ == '__main__': 304 unittest.main() 305