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 18"""Unittests for ide_util.""" 19 20import os 21import shutil 22import subprocess 23import tempfile 24import unittest 25 26from unittest import mock 27from xml.etree import ElementTree 28 29from aidegen import aidegen_main 30from aidegen import unittest_constants 31from aidegen.lib import android_dev_os 32from aidegen.lib import common_util 33from aidegen.lib import config 34from aidegen.lib import errors 35from aidegen.lib import ide_common_util 36from aidegen.lib import ide_util 37from aidegen.lib import project_config 38from aidegen.lib import project_file_gen 39from aidegen.sdk import jdk_table 40 41 42# pylint: disable=protected-access 43# pylint: disable-msg=too-many-arguments 44# pylint: disable-msg=unused-argument 45class IdeUtilUnittests(unittest.TestCase): 46 """Unit tests for ide_util.py.""" 47 48 _TEST_PRJ_PATH1 = '' 49 _TEST_PRJ_PATH2 = '' 50 _TEST_PRJ_PATH3 = '' 51 _TEST_PRJ_PATH4 = '' 52 _MODULE_XML_SAMPLE = '' 53 _TEST_DIR = None 54 _TEST_XML_CONTENT = """\ 55<application> 56 <component name="FileTypeManager" version="17"> 57 <extensionMap> 58 <mapping ext="pi" type="Python"/> 59 </extensionMap> 60 </component> 61</application>""" 62 _TEST_XML_CONTENT_2 = """\ 63<application> 64 <component name="FileTypeManager" version="17"> 65 <extensionMap> 66 <mapping ext="pi" type="Python"/> 67 <mapping pattern="test" type="a"/> 68 <mapping pattern="TEST_MAPPING" type="a"/> 69 </extensionMap> 70 </component> 71</application>""" 72 73 def setUp(self): 74 """Prepare the testdata related path.""" 75 IdeUtilUnittests._TEST_PRJ_PATH1 = os.path.join( 76 unittest_constants.TEST_DATA_PATH, 'android_facet.iml') 77 IdeUtilUnittests._TEST_PRJ_PATH2 = os.path.join( 78 unittest_constants.TEST_DATA_PATH, 'project/test.java') 79 IdeUtilUnittests._TEST_PRJ_PATH3 = unittest_constants.TEST_DATA_PATH 80 IdeUtilUnittests._TEST_PRJ_PATH4 = os.path.join( 81 unittest_constants.TEST_DATA_PATH, '.idea') 82 IdeUtilUnittests._MODULE_XML_SAMPLE = os.path.join( 83 unittest_constants.TEST_DATA_PATH, 'modules.xml') 84 IdeUtilUnittests._TEST_DIR = tempfile.mkdtemp() 85 86 def tearDown(self): 87 """Clear the testdata related path.""" 88 IdeUtilUnittests._TEST_PRJ_PATH1 = '' 89 IdeUtilUnittests._TEST_PRJ_PATH2 = '' 90 IdeUtilUnittests._TEST_PRJ_PATH3 = '' 91 IdeUtilUnittests._TEST_PRJ_PATH4 = '' 92 shutil.rmtree(IdeUtilUnittests._TEST_DIR) 93 94 @unittest.skip('Skip to use real command to launch IDEA.') 95 def test_run_intellij_sh_in_linux(self): 96 """Follow the target behavior, with sh to show UI, else raise err.""" 97 sh_path = ide_util.IdeLinuxIntelliJ()._get_script_from_system() 98 if sh_path: 99 ide_util_obj = ide_util.IdeUtil() 100 ide_util_obj.config_ide(IdeUtilUnittests._TEST_PRJ_PATH1) 101 ide_util_obj.launch_ide() 102 else: 103 self.assertRaises(subprocess.CalledProcessError) 104 105 @mock.patch.object(ide_util, '_get_linux_ide') 106 @mock.patch.object(ide_util, '_get_mac_ide') 107 def test_get_ide(self, mock_mac, mock_linux): 108 """Test if _get_ide calls the correct respective functions.""" 109 ide_util._get_ide(None, 'j', False, is_mac=True) 110 self.assertTrue(mock_mac.called) 111 ide_util._get_ide(None, 'j', False, is_mac=False) 112 self.assertTrue(mock_linux.called) 113 114 @mock.patch.object(ide_util.IdeBase, '_get_user_preference') 115 @mock.patch.object(config.AidegenConfig, 'set_preferred_version') 116 @mock.patch.object(ide_util.IdeEclipse, '_get_script_from_system') 117 @mock.patch.object(ide_util.IdeIntelliJ, '_get_preferred_version') 118 def test_get_mac_and_linux_ide(self, mock_preference, mock_path, mock_cfg, 119 mock_version): 120 """Test if _get_mac_ide and _get_linux_ide return correct IDE class.""" 121 mock_preference.return_value = None 122 mock_path.return_value = 'path' 123 mock_cfg.return_value = None 124 mock_version.return_value = 'default' 125 self.assertIsInstance(ide_util._get_mac_ide(), ide_util.IdeMacIntelliJ) 126 self.assertIsInstance(ide_util._get_mac_ide(None, 's'), 127 ide_util.IdeMacStudio) 128 self.assertIsInstance(ide_util._get_mac_ide(None, 'e'), 129 ide_util.IdeMacEclipse) 130 131 self.assertIsInstance(ide_util._get_mac_ide(None, 'c'), 132 ide_util.IdeMacCLion) 133 self.assertIsInstance(ide_util._get_linux_ide(), 134 ide_util.IdeLinuxIntelliJ) 135 self.assertIsInstance( 136 ide_util._get_linux_ide(None, 's'), ide_util.IdeLinuxStudio) 137 self.assertIsInstance( 138 ide_util._get_linux_ide(None, 'e'), ide_util.IdeLinuxEclipse) 139 self.assertIsInstance( 140 ide_util._get_linux_ide(None, 'c'), ide_util.IdeLinuxCLion) 141 142 @mock.patch.object(ide_util.IdeIntelliJ, '_set_installed_path') 143 @mock.patch.object(ide_common_util, 'get_script_from_input_path') 144 @mock.patch.object(ide_util.IdeIntelliJ, '_get_script_from_system') 145 def test_init_ideintellij(self, mock_sys, mock_input, mock_set): 146 """Test IdeIntelliJ's __init__ method.""" 147 ide_util.IdeLinuxIntelliJ() 148 self.assertTrue(mock_sys.called) 149 ide_util.IdeMacIntelliJ() 150 self.assertTrue(mock_sys.called) 151 ide_util.IdeLinuxIntelliJ('some_path') 152 self.assertTrue(mock_input.called) 153 self.assertTrue(mock_set.called) 154 ide_util.IdeMacIntelliJ('some_path') 155 self.assertTrue(mock_input.called) 156 self.assertTrue(mock_set.called) 157 158 @mock.patch.object(ide_util.IdeIntelliJ, '_get_preferred_version') 159 @mock.patch.object(ide_util.IdeIntelliJ, '_get_config_root_paths') 160 @mock.patch.object(ide_util.IdeBase, 'apply_optional_config') 161 def test_config_ide(self, mock_config, mock_paths, mock_preference): 162 """Test IDEA, IdeUtil.config_ide won't call base none implement api.""" 163 # Mock SDkConfig flow to not generate real jdk config file. 164 mock_preference.return_value = None 165 module_path = os.path.join(self._TEST_DIR, 'test') 166 idea_path = os.path.join(module_path, '.idea') 167 os.makedirs(idea_path) 168 shutil.copy(IdeUtilUnittests._MODULE_XML_SAMPLE, idea_path) 169 util_obj = ide_util.IdeUtil() 170 util_obj.config_ide(module_path) 171 self.assertFalse(mock_config.called) 172 self.assertFalse(mock_paths.called) 173 174 @mock.patch.object(ide_util.IdeIntelliJ, '_setup_ide') 175 @mock.patch.object(config.AidegenConfig, 'set_preferred_version') 176 @mock.patch.object(os.path, 'isfile') 177 @mock.patch.object(os.path, 'realpath') 178 @mock.patch.object(ide_common_util, 'get_script_from_input_path') 179 @mock.patch.object(ide_common_util, 'get_script_from_internal_path') 180 def test_get_linux_config_1(self, mock_path, mock_path2, mock_path3, 181 mock_is_file, mock_cfg, mock_setup_ide): 182 """Test to get unique config path for linux IDEA case.""" 183 if (not android_dev_os.AndroidDevOS.MAC == 184 android_dev_os.AndroidDevOS.get_os_type()): 185 mock_path.return_value = ['/opt/intellij-ce-2018.3/bin/idea.sh'] 186 mock_path2.return_value = ['/opt/intellij-ce-2018.3/bin/idea.sh'] 187 mock_path3.return_value = '/opt/intellij-ce-2018.3/bin/idea.sh' 188 mock_is_file.return_value = True 189 mock_cfg.return_value = None 190 mock_setup_ide.return_value = None 191 ide_obj = ide_util.IdeLinuxIntelliJ('default_path') 192 self.assertEqual(1, len(ide_obj._get_config_root_paths())) 193 else: 194 self.assertTrue((android_dev_os.AndroidDevOS.MAC == 195 android_dev_os.AndroidDevOS.get_os_type())) 196 197 @mock.patch.object(config.AidegenConfig, 'set_preferred_version') 198 @mock.patch('glob.glob') 199 @mock.patch.object(ide_common_util, 'get_script_from_input_path') 200 @mock.patch.object(ide_common_util, 'get_script_from_internal_path') 201 def test_get_linux_config_2(self, mock_path, mock_path_2, mock_filter, 202 mock_cfg): 203 """Test to get unique config path for linux IDEA case.""" 204 if (not android_dev_os.AndroidDevOS.MAC == 205 android_dev_os.AndroidDevOS.get_os_type()): 206 mock_path.return_value = ['/opt/intelliJ-ce-2018.3/bin/idea.sh'] 207 mock_path_2.return_value = ['/opt/intelliJ-ce-2018.3/bin/idea.sh'] 208 mock_cfg.return_value = None 209 ide_obj = ide_util.IdeLinuxIntelliJ() 210 mock_filter.called = False 211 ide_obj._get_config_root_paths() 212 self.assertFalse(mock_filter.called) 213 else: 214 self.assertTrue((android_dev_os.AndroidDevOS.MAC == 215 android_dev_os.AndroidDevOS.get_os_type())) 216 217 def test_get_mac_config_root_paths(self): 218 """Return None if there's no install path.""" 219 if (android_dev_os.AndroidDevOS.MAC == 220 android_dev_os.AndroidDevOS.get_os_type()): 221 mac_ide = ide_util.IdeMacIntelliJ() 222 mac_ide._installed_path = None 223 self.assertIsNone(mac_ide._get_config_root_paths()) 224 else: 225 self.assertFalse((android_dev_os.AndroidDevOS.MAC == 226 android_dev_os.AndroidDevOS.get_os_type())) 227 228 @mock.patch.object(config.AidegenConfig, 'set_preferred_version') 229 @mock.patch('glob.glob') 230 @mock.patch.object(ide_common_util, 'get_script_from_input_path') 231 @mock.patch.object(ide_common_util, 'get_script_from_internal_path') 232 def test_get_linux_config_root(self, mock_path_1, mock_path_2, mock_filter, 233 mock_cfg): 234 """Test to go filter logic for self download case.""" 235 mock_path_1.return_value = ['/usr/tester/IDEA/IC2018.3.3/bin'] 236 mock_path_2.return_value = ['/usr/tester/IDEA/IC2018.3.3/bin'] 237 mock_cfg.return_value = None 238 ide_obj = ide_util.IdeLinuxIntelliJ() 239 mock_filter.reset() 240 ide_obj._get_config_root_paths() 241 self.assertTrue(mock_filter.called) 242 243 @mock.patch.object(ide_util.IdeBase, '_add_test_mapping_file_type') 244 @mock.patch.object(config.IdeaProperties, 'set_max_file_size') 245 @mock.patch.object(project_file_gen, 'gen_enable_debugger_module') 246 @mock.patch.object(jdk_table.JDKTableXML, 'config_jdk_table_xml') 247 @mock.patch.object(ide_util.IdeBase, '_get_config_root_paths') 248 def test_apply_optional_config(self, mock_path, mock_config_xml, 249 mock_gen_debugger, mock_set_size, 250 mock_test_mapping): 251 """Test basic logic of apply_optional_config.""" 252 ide = ide_util.IdeBase() 253 ide._installed_path = None 254 ide.apply_optional_config() 255 self.assertFalse(mock_path.called) 256 ide._installed_path = 'default_path' 257 ide.apply_optional_config() 258 self.assertTrue(mock_path.called) 259 mock_path.return_value = [] 260 ide.apply_optional_config() 261 self.assertFalse(mock_config_xml.called) 262 mock_path.return_value = ['a'] 263 mock_config_xml.return_value = False 264 ide.apply_optional_config() 265 self.assertFalse(mock_gen_debugger.called) 266 self.assertTrue(mock_set_size.called) 267 mock_config_xml.return_value = True 268 ide.apply_optional_config() 269 self.assertEqual(ide.config_folders, ['a']) 270 self.assertTrue(mock_gen_debugger.called) 271 self.assertTrue(mock_set_size.called) 272 273 @mock.patch('os.path.isfile') 274 @mock.patch.object(ElementTree.ElementTree, 'write') 275 @mock.patch.object(common_util, 'to_pretty_xml') 276 @mock.patch.object(common_util, 'file_generate') 277 @mock.patch.object(ElementTree, 'parse') 278 @mock.patch.object(ElementTree.ElementTree, 'getroot') 279 def test_add_test_mapping_file_type(self, mock_root, mock_parse, 280 mock_file_gen, mock_pretty_xml, 281 mock_write, mock_isfile): 282 """Test basic logic of _add_test_mapping_file_type.""" 283 mock_isfile.return_value = False 284 self.assertFalse(mock_file_gen.called) 285 286 mock_isfile.return_value = True 287 mock_parse.return_value = None 288 self.assertFalse(mock_file_gen.called) 289 290 mock_parse.return_value = ElementTree.ElementTree() 291 mock_root.return_value = ElementTree.fromstring( 292 self._TEST_XML_CONTENT_2) 293 ide_obj = ide_util.IdeBase() 294 ide_obj._add_test_mapping_file_type('') 295 self.assertFalse(mock_file_gen.called) 296 mock_root.return_value = ElementTree.fromstring(self._TEST_XML_CONTENT) 297 ide_obj._add_test_mapping_file_type('') 298 self.assertTrue(mock_pretty_xml.called) 299 self.assertTrue(mock_file_gen.called) 300 301 @mock.patch('os.path.realpath') 302 @mock.patch('os.path.isfile') 303 def test_merge_symbolic_version(self, mock_isfile, mock_realpath): 304 """Test _merge_symbolic_version and _get_real_path.""" 305 symbolic_path = ide_util.IdeLinuxIntelliJ._SYMBOLIC_VERSIONS[0] 306 original_path = 'intellij-ce-2019.1/bin/idea.sh' 307 mock_isfile.return_value = True 308 mock_realpath.return_value = original_path 309 ide_obj = ide_util.IdeLinuxIntelliJ('default_path') 310 merged_version = ide_obj._merge_symbolic_version( 311 [symbolic_path, original_path]) 312 self.assertEqual( 313 merged_version[0], symbolic_path + ' -> ' + original_path) 314 self.assertEqual( 315 ide_obj._get_real_path(merged_version[0]), symbolic_path) 316 317 @mock.patch.object(config.AidegenConfig, 'set_preferred_version') 318 @mock.patch('os.path.isfile') 319 def test_get_application_path(self, mock_isfile, mock_cfg): 320 """Test _get_application_path.""" 321 mock_cfg.return_value = None 322 ide_obj = ide_util.IdeLinuxIntelliJ('default_path') 323 mock_isfile.return_value = True 324 test_path = None 325 self.assertEqual(None, ide_obj._get_application_path(test_path)) 326 327 test_path = 'a/b/c/d-e/f-gh/foo' 328 self.assertEqual(None, ide_obj._get_application_path(test_path)) 329 330 test_path = 'a/b/c/d/intellij/foo' 331 self.assertEqual(None, ide_obj._get_application_path(test_path)) 332 333 test_path = 'a/b/c/d/intellij-efg/foo' 334 self.assertEqual(None, ide_obj._get_application_path(test_path)) 335 336 test_path = 'a/b/c/d/intellij-efg-hi/foo' 337 self.assertEqual(None, ide_obj._get_application_path(test_path)) 338 339 test_path = 'a/b/c/d/intellij-ce-303/foo' 340 self.assertEqual('.IdeaIC303', ide_obj._get_application_path(test_path)) 341 342 test_path = 'a/b/c/d/intellij-ue-303/foo' 343 self.assertEqual('.IntelliJIdea303', ide_obj._get_application_path( 344 test_path)) 345 346 def test_get_ide_util_instance_with_no_launch(self): 347 """Test _get_ide_util_instance with no launch IDE.""" 348 args = aidegen_main._parse_args(['tradefed', '-n']) 349 project_config.ProjectConfig(args) 350 self.assertEqual(ide_util.get_ide_util_instance(args), None) 351 352 @mock.patch.object(config.AidegenConfig, 'set_preferred_version') 353 @mock.patch.object(ide_util.IdeIntelliJ, '_get_preferred_version') 354 def test_get_ide_util_instance_with_success(self, mock_preference, 355 mock_cfg_write): 356 """Test _get_ide_util_instance with success.""" 357 args = aidegen_main._parse_args(['tradefed']) 358 project_config.ProjectConfig(args) 359 mock_cfg_write.return_value = None 360 mock_preference.return_value = '1' 361 self.assertIsInstance( 362 ide_util.get_ide_util_instance(), ide_util.IdeUtil) 363 364 @mock.patch.object(config.AidegenConfig, 'set_preferred_version') 365 @mock.patch.object(ide_util.IdeIntelliJ, '_get_preferred_version') 366 @mock.patch.object(ide_util.IdeUtil, 'is_ide_installed') 367 def test_get_ide_util_instance_with_failure( 368 self, mock_installed, mock_preference, mock_cfg_write): 369 """Test _get_ide_util_instance with failure.""" 370 args = aidegen_main._parse_args(['tradefed']) 371 project_config.ProjectConfig(args) 372 mock_installed.return_value = False 373 mock_cfg_write.return_value = None 374 mock_preference.return_value = '1' 375 with self.assertRaises(errors.IDENotExistError): 376 ide_util.get_ide_util_instance() 377 378 @mock.patch.object(ide_common_util, 'get_scripts_from_dir_path') 379 @mock.patch.object(ide_common_util, '_run_ide_sh') 380 @mock.patch('logging.info') 381 def test_ide_base(self, mock_log, mock_run_ide, mock_run_path): 382 """Test ide_base class.""" 383 # Test raise NotImplementedError. 384 ide_base = ide_util.IdeBase() 385 with self.assertRaises(NotImplementedError): 386 ide_base._get_config_root_paths() 387 388 # Test ide_name. 389 ide_base._ide_name = 'a' 390 self.assertEqual(ide_base.ide_name, 'a') 391 392 # Test _get_ide_cmd. 393 ide_base._installed_path = '/a/b' 394 ide_base.project_abspath = '/x/y' 395 expected_result = 'nohup /a/b /x/y 2>/dev/null >&2 &' 396 self.assertEqual(ide_base._get_ide_cmd(), expected_result) 397 398 # Test launch_ide. 399 mock_run_ide.return_value = True 400 ide_base.launch_ide() 401 self.assertTrue(mock_log.called) 402 403 # Test _get_ide_from_environment_paths. 404 mock_run_path.return_value = '/a/b/idea.sh' 405 ide_base._bin_file_name = 'idea.sh' 406 expected_path = '/a/b/idea.sh' 407 ide_path = ide_base._get_ide_from_environment_paths() 408 self.assertEqual(ide_path, expected_path) 409 410 def test_ide_intellij(self): 411 """Test IdeIntelliJ class.""" 412 # Test raise NotImplementedError. 413 ide_intellij = ide_util.IdeIntelliJ() 414 with self.assertRaises(NotImplementedError): 415 ide_intellij._get_config_root_paths() 416 417 @mock.patch.object(config.AidegenConfig, 'set_preferred_version') 418 @mock.patch.object(config.AidegenConfig, 'preferred_version') 419 @mock.patch.object(ide_common_util, 'ask_preference') 420 @mock.patch.object(config.AidegenConfig, 'deprecated_intellij_version') 421 @mock.patch.object(ide_util.IdeIntelliJ, '_get_all_versions') 422 def test_intellij_get_preferred_version(self, 423 mock_all_versions, 424 mock_deprecated_version, 425 mock_ask_preference, 426 mock_preference, 427 mock_write_cfg): 428 """Test _get_preferred_version for IdeIntelliJ class.""" 429 mock_write_cfg.return_value = None 430 ide_intellij = ide_util.IdeIntelliJ() 431 432 # No IntelliJ version is installed. 433 mock_all_versions.return_value = ['/a/b', '/a/c'] 434 mock_deprecated_version.return_value = True 435 version = ide_intellij._get_preferred_version() 436 self.assertEqual(version, None) 437 438 # Load default preferred version. 439 mock_all_versions.return_value = ['/a/b', '/a/c'] 440 mock_deprecated_version.return_value = False 441 ide_intellij._config_reset = False 442 expected_result = '/a/b' 443 mock_preference.return_value = '/a/b' 444 version = ide_intellij._get_preferred_version() 445 self.assertEqual(version, expected_result) 446 447 # Asking user the preferred version. 448 mock_preference.reset() 449 mock_all_versions.return_value = ['/a/b', '/a/c'] 450 mock_deprecated_version.return_value = False 451 ide_intellij._config_reset = True 452 mock_ask_preference.return_value = '/a/b' 453 version = ide_intellij._get_preferred_version() 454 expected_result = '/a/b' 455 self.assertEqual(version, expected_result) 456 457 mock_all_versions.return_value = ['/a/b', '/a/c'] 458 mock_ask_preference.return_value = None 459 expected_result = '/a/b' 460 mock_preference.return_value = '/a/b' 461 version = ide_intellij._get_preferred_version() 462 self.assertEqual(version, expected_result) 463 464 # The all_versions list has only one version. 465 mock_all_versions.return_value = ['/a/b'] 466 mock_deprecated_version.return_value = False 467 version = ide_intellij._get_preferred_version() 468 self.assertEqual(version, '/a/b') 469 470 @mock.patch.object(ide_util.IdeBase, '_add_test_mapping_file_type') 471 @mock.patch.object(ide_common_util, 'ask_preference') 472 @mock.patch.object(config.IdeaProperties, 'set_max_file_size') 473 @mock.patch.object(project_file_gen, 'gen_enable_debugger_module') 474 @mock.patch.object(ide_util.IdeStudio, '_get_config_root_paths') 475 def test_android_studio_class(self, mock_get_config_paths, 476 mock_gen_debugger, mock_set_size, mock_ask, 477 mock_add_file_type): 478 """Test IdeStudio.""" 479 mock_get_config_paths.return_value = ['path1', 'path2'] 480 mock_gen_debugger.return_value = True 481 mock_set_size.return_value = True 482 mock_ask.return_value = None 483 obj = ide_util.IdeStudio() 484 obj._installed_path = False 485 # Test the native IDE case. 486 obj.project_abspath = os.path.realpath(__file__) 487 obj.apply_optional_config() 488 self.assertEqual(obj.config_folders, []) 489 490 # Test the java IDE case. 491 obj.project_abspath = IdeUtilUnittests._TEST_DIR 492 obj.apply_optional_config() 493 self.assertEqual(obj.config_folders, []) 494 495 mock_get_config_paths.return_value = [] 496 self.assertIsNone(obj.apply_optional_config()) 497 498 @mock.patch.object(ide_common_util, 'ask_preference') 499 def test_studio_get_config_root_paths(self, mock_ask): 500 """Test the method _get_config_root_paths of IdeStudio.""" 501 mock_ask.return_value = None 502 obj = ide_util.IdeStudio() 503 with self.assertRaises(NotImplementedError): 504 obj._get_config_root_paths() 505 506 @mock.patch.object(ide_util.IdeBase, 'apply_optional_config') 507 @mock.patch.object(os.path, 'isdir') 508 @mock.patch.object(os.path, 'isfile') 509 def test_studio_optional_config_apply(self, mock_isfile, mock_isdir, 510 mock_base_implement): 511 """Test IdeStudio.apply_optional_config.""" 512 obj = ide_util.IdeStudio() 513 obj.project_abspath = None 514 # Test no project path case. 515 obj.apply_optional_config() 516 self.assertFalse(mock_isfile.called) 517 self.assertFalse(mock_isdir.called) 518 self.assertFalse(mock_base_implement.called) 519 # Test the native IDE case. 520 obj.project_abspath = '/' 521 mock_isfile.reset_mock() 522 mock_isdir.reset_mock() 523 mock_base_implement.reset_mock() 524 mock_isfile.return_value = True 525 obj.apply_optional_config() 526 self.assertTrue(mock_isfile.called) 527 self.assertFalse(mock_isdir.called) 528 self.assertFalse(mock_base_implement.called) 529 # Test the java IDE case. 530 mock_isfile.reset_mock() 531 mock_isdir.reset_mock() 532 mock_base_implement.reset_mock() 533 mock_isfile.return_value = False 534 mock_isdir.return_value = True 535 obj.apply_optional_config() 536 self.assertTrue(mock_base_implement.called) 537 # Test neither case. 538 mock_isfile.reset_mock() 539 mock_isdir.reset_mock() 540 mock_base_implement.reset_mock() 541 mock_isfile.return_value = False 542 mock_isdir.return_value = False 543 obj.apply_optional_config() 544 self.assertFalse(mock_base_implement.called) 545 546 @mock.patch.object(ide_common_util, 'ask_preference') 547 @mock.patch('os.getenv') 548 def test_linux_android_studio_class(self, mock_get_home, mock_ask): 549 """Test the method _get_config_root_paths of IdeLinuxStudio.""" 550 mock_get_home.return_value = self._TEST_DIR 551 studio_config_dir1 = os.path.join(self._TEST_DIR, '.AndroidStudio3.0') 552 studio_config_dir2 = os.path.join(self._TEST_DIR, '.AndroidStudio3.1') 553 os.makedirs(studio_config_dir1) 554 os.makedirs(studio_config_dir2) 555 expected_result = [studio_config_dir1, studio_config_dir2] 556 mock_ask.return_value = None 557 obj = ide_util.IdeLinuxStudio() 558 config_paths = obj._get_config_root_paths() 559 self.assertEqual(sorted(config_paths), sorted(expected_result)) 560 561 @mock.patch('os.getenv') 562 def test_mac_android_studio_class(self, mock_get_home): 563 """Test the method _get_config_root_paths of IdeMacStudio.""" 564 mock_get_home.return_value = self._TEST_DIR 565 studio_config_dir1 = os.path.join(self._TEST_DIR, 'Library', 566 'Preferences', 'AndroidStudio3.0') 567 studio_config_dir2 = os.path.join(self._TEST_DIR, 'Library', 568 'Preferences', 'AndroidStudio3.1') 569 os.makedirs(studio_config_dir1) 570 os.makedirs(studio_config_dir2) 571 expected_result = [studio_config_dir1, studio_config_dir2] 572 573 obj = ide_util.IdeMacStudio() 574 config_paths = obj._get_config_root_paths() 575 self.assertEqual(sorted(config_paths), sorted(expected_result)) 576 577 @mock.patch('os.access') 578 @mock.patch('glob.glob') 579 def test_eclipse_get_script_from_system(self, mock_glob, mock_file_access): 580 """Test IdeEclipse _get_script_from_system method.""" 581 eclipse = ide_util.IdeEclipse() 582 583 # Test no binary path in _get_script_from_system. 584 eclipse._bin_paths = [] 585 expected_result = None 586 test_result = eclipse._get_script_from_system() 587 self.assertEqual(test_result, expected_result) 588 589 # Test get the matched binary from _get_script_from_system. 590 mock_glob.return_value = ['/a/b/eclipse'] 591 mock_file_access.return_value = True 592 eclipse._bin_paths = ['/a/b/eclipse'] 593 expected_result = '/a/b/eclipse' 594 test_result = eclipse._get_script_from_system() 595 self.assertEqual(test_result, expected_result) 596 597 # Test no matched binary from _get_script_from_system. 598 mock_glob.return_value = [] 599 eclipse._bin_paths = ['/a/b/eclipse'] 600 expected_result = None 601 test_result = eclipse._get_script_from_system() 602 self.assertEqual(test_result, expected_result) 603 604 # Test the matched binary cannot be executed. 605 mock_glob.return_value = ['/a/b/eclipse'] 606 mock_file_access.return_value = False 607 eclipse._bin_paths = ['/a/b/eclipse'] 608 expected_result = None 609 test_result = eclipse._get_script_from_system() 610 self.assertEqual(test_result, expected_result) 611 612 @mock.patch('builtins.input') 613 @mock.patch('os.path.exists') 614 def test_eclipse_get_ide_cmd(self, mock_exists, mock_input): 615 """Test IdeEclipse _get_ide_cmd method.""" 616 # Test open the IDE with the default Eclipse workspace. 617 eclipse = ide_util.IdeEclipse() 618 eclipse.cmd = ['eclipse'] 619 mock_exists.return_value = True 620 expected_result = ('eclipse -data ' 621 '~/Documents/AIDEGen_Eclipse_workspace ' 622 '2>/dev/null >&2 &') 623 test_result = eclipse._get_ide_cmd() 624 self.assertEqual(test_result, expected_result) 625 626 # Test running command without the default workspace. 627 eclipse.cmd = ['eclipse'] 628 mock_exists.return_value = False 629 mock_input.return_value = 'n' 630 expected_result = 'eclipse 2>/dev/null >&2 &' 631 test_result = eclipse._get_ide_cmd() 632 self.assertEqual(test_result, expected_result) 633 634 @mock.patch.object(ide_util.IdeUtil, 'is_ide_installed') 635 @mock.patch.object(project_config.ProjectConfig, 'get_instance') 636 def test_get_ide_util_instance(self, mock_config, mock_ide_installed): 637 """Test get_ide_util_instance.""" 638 # Test is_launch_ide conditions. 639 mock_instance = mock_config.return_value 640 mock_instance.is_launch_ide = False 641 ide_util.get_ide_util_instance() 642 self.assertFalse(mock_ide_installed.called) 643 mock_instance.is_launch_ide = True 644 ide_util.get_ide_util_instance() 645 self.assertTrue(mock_ide_installed.called) 646 647 # Test ide is not installed. 648 mock_ide_installed.return_value = False 649 with self.assertRaises(errors.IDENotExistError): 650 ide_util.get_ide_util_instance() 651 652 @mock.patch.object(ide_util.IdeLinuxVSCode, '_init_installed_path') 653 @mock.patch.object(ide_util.IdeLinuxVSCode, '_get_possible_bin_paths') 654 def test_ide_linux_vscode(self, mock_get_pos, mock_init_inst): 655 """Test IdeLinuxVSCode class.""" 656 ide_util.IdeLinuxVSCode() 657 self.assertTrue(mock_get_pos.called) 658 self.assertTrue(mock_init_inst.called) 659 660 @mock.patch.object(ide_util.IdeMacVSCode, '_init_installed_path') 661 @mock.patch.object(ide_util.IdeMacVSCode, '_get_possible_bin_paths') 662 def test_ide_mac_vscode(self, mock_get_pos, mock_init_inst): 663 """Test IdeMacVSCode class.""" 664 ide_util.IdeMacVSCode() 665 self.assertTrue(mock_get_pos.called) 666 self.assertTrue(mock_init_inst.called) 667 668 def test_get_all_versions(self): 669 """Test _get_all_versions.""" 670 ide = ide_util.IdeIntelliJ() 671 test_result = ide._get_all_versions('a', 'b') 672 self.assertEqual(test_result, ['a', 'b']) 673 674 @mock.patch('logging.warning') 675 def test_get_ide_version(self, mock_warn): 676 """Test _get_ide_version with conditions.""" 677 self.assertEqual( 678 None, ide_util.IdeIntelliJ._get_ide_version('intellij-efg-hi')) 679 self.assertTrue(mock_warn.called) 680 mock_warn.reset_mock() 681 self.assertEqual( 682 '2020.1', 683 ide_util.IdeIntelliJ._get_ide_version('intellij-ue-2020.1')) 684 self.assertFalse(mock_warn.called) 685 mock_warn.reset_mock() 686 self.assertEqual( 687 '303', ide_util.IdeIntelliJ._get_ide_version('intellij-ue-303')) 688 self.assertFalse(mock_warn.called) 689 690 @mock.patch('os.path.join') 691 def test_get_config_dir(self, mock_join): 692 """Test _get_config_dir with conditions.""" 693 config_folder_name = 'IntelliJ2020.1' 694 ide_version = '2020.1' 695 ide_util.IdeIntelliJ._get_config_dir(ide_version, config_folder_name) 696 self.assertTrue( 697 mock_join.called_with( 698 os.getenv('HOME'), '.config', 'JetBrains', config_folder_name)) 699 mock_join.reset_mock() 700 config_folder_name = 'IntelliJ2019.3' 701 ide_version = '2019.3' 702 self.assertTrue( 703 mock_join.called_with( 704 os.getenv('HOME'), config_folder_name, 'config')) 705 mock_join.reset_mock() 706 self.assertEqual(None, ide_util.IdeIntelliJ._get_config_dir( 707 'Not-a-float', config_folder_name)) 708 self.assertFalse(mock_join.called) 709 710 def test_get_config_folder_name(self): 711 """Test _get_config_folder_name with conditions.""" 712 config_folder_name = 'intellij-ce-2019.3' 713 pre_folder = '.IdeaIC' 714 ide_version = '2019.3' 715 expected = ''.join([pre_folder, ide_version]) 716 self.assertEqual(expected, ide_util.IdeIntelliJ._get_config_folder_name( 717 config_folder_name)) 718 config_folder_name = 'intellij-ue-2019.3' 719 pre_folder = '.IntelliJIdea' 720 expected = ''.join([pre_folder, ide_version]) 721 self.assertEqual(expected, ide_util.IdeIntelliJ._get_config_folder_name( 722 config_folder_name)) 723 config_folder_name = 'intellij-ce-2020.1' 724 pre_folder = 'IdeaIC' 725 ide_version = '2020.1' 726 expected = ''.join([pre_folder, ide_version]) 727 self.assertEqual(expected, ide_util.IdeIntelliJ._get_config_folder_name( 728 config_folder_name)) 729 config_folder_name = 'intellij-ue-2020.1' 730 pre_folder = 'IntelliJIdea' 731 expected = ''.join([pre_folder, ide_version]) 732 self.assertEqual(expected, ide_util.IdeIntelliJ._get_config_folder_name( 733 config_folder_name)) 734 config_folder_name = 'intellij-ue-2020.1.4' 735 self.assertEqual(expected, ide_util.IdeIntelliJ._get_config_folder_name( 736 config_folder_name)) 737 config_folder_name = 'intellij-unknown' 738 expected = None 739 self.assertEqual(expected, ide_util.IdeIntelliJ._get_config_folder_name( 740 config_folder_name)) 741 config_folder_name = 'intellij-ue-NotAFloat' 742 self.assertEqual(expected, ide_util.IdeIntelliJ._get_config_folder_name( 743 config_folder_name)) 744 745 746if __name__ == '__main__': 747 unittest.main() 748