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