#!/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 common_util.""" import logging import os import unittest from unittest import mock from xml.etree import ElementTree from aidegen import constant from aidegen import unittest_constants from aidegen.lib import common_util from aidegen.lib import errors from atest import module_info # pylint: disable=too-many-arguments # pylint: disable=protected-access class AidegenCommonUtilUnittests(unittest.TestCase): """Unit tests for common_util.py""" _TEST_XML_CONTENT = """ """ _SAMPLE_XML_CONTENT = """ """ @mock.patch('os.getcwd') @mock.patch('os.path.isabs') @mock.patch.object(common_util, 'get_android_root_dir') def test_get_related_paths(self, mock_get_root, mock_is_abspath, mock_cwd): """Test get_related_paths with different conditions.""" mod_info = mock.MagicMock() mod_info.is_module.return_value = True mod_info.get_paths.return_value = {} mock_is_abspath.return_value = False self.assertEqual((None, None), common_util.get_related_paths( mod_info, unittest_constants.TEST_MODULE)) mock_get_root.return_value = unittest_constants.TEST_PATH mod_info.get_paths.return_value = [unittest_constants.TEST_MODULE] expected = (unittest_constants.TEST_MODULE, os.path.join( unittest_constants.TEST_PATH, unittest_constants.TEST_MODULE)) self.assertEqual( expected, common_util.get_related_paths( mod_info, unittest_constants.TEST_MODULE)) mod_info.is_module.return_value = False mod_info.get_module_names.return_value = True self.assertEqual(expected, common_util.get_related_paths( mod_info, unittest_constants.TEST_MODULE)) self.assertEqual(('', unittest_constants.TEST_PATH), common_util.get_related_paths( mod_info, constant.WHOLE_ANDROID_TREE_TARGET)) mod_info.is_module.return_value = False mod_info.get_module_names.return_value = False mock_is_abspath.return_value = True mock_get_root.return_value = '/a' self.assertEqual(('b/c', '/a/b/c'), common_util.get_related_paths(mod_info, '/a/b/c')) mock_is_abspath.return_value = False mock_cwd.return_value = '/a' mock_get_root.return_value = '/a' self.assertEqual(('b/c', '/a/b/c'), common_util.get_related_paths(mod_info, 'b/c')) @mock.patch('os.getcwd') @mock.patch.object(common_util, 'is_android_root') @mock.patch.object(common_util, 'get_android_root_dir') def test_get_related_paths_2( self, mock_get_root, mock_is_root, mock_getcwd): """Test get_related_paths with different conditions.""" mock_get_root.return_value = '/a' mod_info = mock.MagicMock() # Test get_module_names returns False, user inputs a relative path of # current directory. mod_info.is_mod.return_value = False rel_path = 'b/c/d' abs_path = '/a/b/c/d' mod_info.get_paths.return_value = [rel_path] mod_info.get_module_names.return_value = False mock_getcwd.return_value = '/a/b/c' input_target = 'd' # expected tuple: (rel_path, abs_path) expected = (rel_path, abs_path) result = common_util.get_related_paths(mod_info, input_target) self.assertEqual(expected, result) # Test user doesn't input target and current working directory is the # android root folder. mock_getcwd.return_value = '/a' mock_is_root.return_value = True expected = ('', '/a') result = common_util.get_related_paths(mod_info, target=None) self.assertEqual(expected, result) # Test user doesn't input target and current working directory is not # android root folder. mock_getcwd.return_value = '/a/b' mock_is_root.return_value = False expected = ('b', '/a/b') result = common_util.get_related_paths(mod_info, target=None) self.assertEqual(expected, result) result = common_util.get_related_paths(mod_info, target='.') self.assertEqual(expected, result) @mock.patch.object(common_util, 'is_android_root') @mock.patch.object(common_util, 'get_related_paths') def test_is_target_android_root(self, mock_get_rel, mock_get_root): """Test is_target_android_root with different conditions.""" mod_info = mock.MagicMock() mock_get_rel.return_value = None, unittest_constants.TEST_PATH mock_get_root.return_value = True self.assertTrue( common_util.is_target_android_root( mod_info, [unittest_constants.TEST_MODULE])) mock_get_rel.return_value = None, '' mock_get_root.return_value = False self.assertFalse( common_util.is_target_android_root( mod_info, [unittest_constants.TEST_MODULE])) @mock.patch.object(common_util, 'get_android_root_dir') @mock.patch.object(common_util, 'has_build_target') @mock.patch('os.path.isdir') @mock.patch.object(common_util, 'get_related_paths') def test_check_module(self, mock_get, mock_isdir, mock_has_target, mock_get_root): """Test if _check_module raises errors with different conditions.""" mod_info = mock.MagicMock() mock_get.return_value = None, None with self.assertRaises(errors.FakeModuleError) as ctx: common_util.check_module(mod_info, unittest_constants.TEST_MODULE) expected = common_util.FAKE_MODULE_ERROR.format( unittest_constants.TEST_MODULE) self.assertEqual(expected, str(ctx.exception)) mock_get_root.return_value = unittest_constants.TEST_PATH mock_get.return_value = None, unittest_constants.TEST_MODULE with self.assertRaises(errors.ProjectOutsideAndroidRootError) as ctx: common_util.check_module(mod_info, unittest_constants.TEST_MODULE) expected = common_util.OUTSIDE_ROOT_ERROR.format( unittest_constants.TEST_MODULE) self.assertEqual(expected, str(ctx.exception)) mock_get.return_value = None, unittest_constants.TEST_PATH mock_isdir.return_value = False with self.assertRaises(errors.ProjectPathNotExistError) as ctx: common_util.check_module(mod_info, unittest_constants.TEST_MODULE) expected = common_util.PATH_NOT_EXISTS_ERROR.format( unittest_constants.TEST_MODULE) self.assertEqual(expected, str(ctx.exception)) mock_isdir.return_value = True mock_has_target.return_value = False mock_get.return_value = None, os.path.join(unittest_constants.TEST_PATH, 'test.jar') with self.assertRaises(errors.NoModuleDefinedInModuleInfoError) as ctx: common_util.check_module(mod_info, unittest_constants.TEST_MODULE) expected = common_util.NO_MODULE_DEFINED_ERROR.format( unittest_constants.TEST_MODULE) self.assertEqual(expected, str(ctx.exception)) self.assertFalse(common_util.check_module(mod_info, '', False)) self.assertFalse(common_util.check_module(mod_info, 'nothing', False)) @mock.patch.object(common_util, 'check_module') def test_check_modules(self, mock_check): """Test _check_modules with different module lists.""" mod_info = mock.MagicMock() common_util._check_modules(mod_info, []) self.assertEqual(mock_check.call_count, 0) common_util._check_modules(mod_info, ['module1', 'module2']) self.assertEqual(mock_check.call_count, 2) target = 'nothing' mock_check.return_value = False self.assertFalse(common_util._check_modules(mod_info, [target], False)) @mock.patch.object(common_util, 'get_android_root_dir') def test_get_abs_path(self, mock_get_root): """Test get_abs_path handling.""" mock_get_root.return_value = unittest_constants.TEST_DATA_PATH self.assertEqual(unittest_constants.TEST_DATA_PATH, common_util.get_abs_path('')) test_path = os.path.join(unittest_constants.TEST_DATA_PATH, 'test.jar') self.assertEqual(test_path, common_util.get_abs_path(test_path)) self.assertEqual(test_path, common_util.get_abs_path('test.jar')) def test_is_target(self): """Test is_target handling.""" self.assertTrue( common_util.is_target('packages/apps/tests/test.a', ['.so', '.a'])) self.assertTrue( common_util.is_target('packages/apps/tests/test.so', ['.so', '.a'])) self.assertFalse( common_util.is_target( 'packages/apps/tests/test.jar', ['.so', '.a'])) @mock.patch.object(logging, 'basicConfig') def test_configure_logging(self, mock_log_config): """Test configure_logging with different arguments.""" common_util.configure_logging(True) log_format = common_util._LOG_FORMAT datefmt = common_util._DATE_FORMAT level = common_util.logging.DEBUG self.assertTrue( mock_log_config.called_with( level=level, format=log_format, datefmt=datefmt)) common_util.configure_logging(False) level = common_util.logging.INFO self.assertTrue( mock_log_config.called_with( level=level, format=log_format, datefmt=datefmt)) @mock.patch.object(common_util, '_check_modules') @mock.patch.object(module_info, 'ModuleInfo') def test_get_atest_module_info(self, mock_modinfo, mock_check_modules): """Test get_atest_module_info handling.""" common_util.get_atest_module_info() self.assertEqual(mock_modinfo.call_count, 1) mock_modinfo.reset_mock() mock_check_modules.return_value = False common_util.get_atest_module_info(['nothing']) self.assertEqual(mock_modinfo.call_count, 2) @mock.patch('builtins.open', create=True) def test_read_file_content(self, mock_open): """Test read_file_content handling.""" expacted_data1 = 'Data1' file_a = 'fileA' mock_open.side_effect = [ mock.mock_open(read_data=expacted_data1).return_value ] self.assertEqual(expacted_data1, common_util.read_file_content(file_a)) mock_open.assert_called_once_with(file_a, encoding='utf8') @mock.patch('os.getenv') @mock.patch.object(common_util, 'get_android_root_dir') def test_get_android_out_dir(self, mock_get_android_root_dir, mock_getenv): """Test get_android_out_dir handling.""" root = 'my/path-to-root/master' default_root = 'out' android_out_root = 'eng_out' mock_get_android_root_dir.return_value = root mock_getenv.side_effect = ['', ''] self.assertEqual(default_root, common_util.get_android_out_dir()) mock_getenv.side_effect = [android_out_root, ''] self.assertEqual(android_out_root, common_util.get_android_out_dir()) mock_getenv.side_effect = ['', default_root] self.assertEqual(os.path.join(default_root, os.path.basename(root)), common_util.get_android_out_dir()) mock_getenv.side_effect = [android_out_root, default_root] self.assertEqual(android_out_root, common_util.get_android_out_dir()) def test_has_build_target(self): """Test has_build_target handling.""" mod_info = mock.MagicMock() mod_info.path_to_module_info = {'a/b/c': {}} rel_path = 'a/b' self.assertTrue(common_util.has_build_target(mod_info, rel_path)) rel_path = 'd/e' self.assertFalse(common_util.has_build_target(mod_info, rel_path)) @mock.patch('os.path.expanduser') def test_remove_user_home_path(self, mock_expanduser): """ Test replace the user home path to a constant string.""" mock_expanduser.return_value = '/usr/home/a' test_string = '/usr/home/a/test/dir' expect_string = '$USER_HOME$/test/dir' result_path = common_util.remove_user_home_path(test_string) self.assertEqual(result_path, expect_string) def test_io_error_handle(self): """Test io_error_handle handling.""" err = "It's an IO error." def some_io_error_func(): raise IOError(err) with self.assertRaises(IOError) as context: decorator = common_util.io_error_handle(some_io_error_func) decorator() self.assertTrue(err in context.exception) @mock.patch.object(common_util, '_show_env_setup_msg_and_exit') @mock.patch('os.environ.get') def test_get_android_root_dir(self, mock_get_env, mock_show_msg): """Test get_android_root_dir handling.""" root = 'root' mock_get_env.return_value = root expected = common_util.get_android_root_dir() self.assertEqual(root, expected) root = '' mock_get_env.return_value = root common_util.get_android_root_dir() self.assertTrue(mock_show_msg.called) # pylint: disable=no-value-for-parameter def test_check_args(self): """Test check_args handling.""" with self.assertRaises(TypeError): decorator = common_util.check_args(name=str, text=str) decorator(parse_rule(None, 'text')) with self.assertRaises(TypeError): decorator = common_util.check_args(name=str, text=str) decorator(parse_rule('Paul', '')) with self.assertRaises(TypeError): decorator = common_util.check_args(name=str, text=str) decorator(parse_rule(1, 2)) @mock.patch.object(common_util, 'get_blueprint_json_path') @mock.patch.object(common_util, 'get_android_out_dir') @mock.patch.object(common_util, 'get_android_root_dir') def test_get_blueprint_json_files_relative_dict( self, mock_get_root, mock_get_out, mock_get_path): """Test get_blueprint_json_files_relative_dict function,""" mock_get_root.return_value = 'a/b' mock_get_out.return_value = 'out' mock_get_path.return_value = 'out/soong/bp_java_file' path_compdb = os.path.join('a/b', 'out', 'soong', constant.RELATIVE_COMPDB_PATH, constant.COMPDB_JSONFILE_NAME) data = { constant.GEN_JAVA_DEPS: 'a/b/out/soong/bp_java_file', constant.GEN_CC_DEPS: 'a/b/out/soong/bp_java_file', constant.GEN_COMPDB: path_compdb, constant.GEN_RUST: 'a/b/out/soong/bp_java_file' } self.assertEqual( data, common_util.get_blueprint_json_files_relative_dict()) @mock.patch('os.environ.get') def test_get_lunch_target(self, mock_get_env): """Test get_lunch_target.""" mock_get_env.return_value = "test" self.assertEqual( common_util.get_lunch_target(), '{"lunch target": "test-test"}') def test_to_pretty_xml(self): """Test to_pretty_xml.""" root = ElementTree.fromstring(self._TEST_XML_CONTENT) pretty_xml = common_util.to_pretty_xml(root) self.assertEqual(pretty_xml, self._SAMPLE_XML_CONTENT) def test_to_to_boolean(self): """Test to_boolean function with conditions.""" self.assertTrue(common_util.to_boolean('True')) self.assertTrue(common_util.to_boolean('true')) self.assertTrue(common_util.to_boolean('T')) self.assertTrue(common_util.to_boolean('t')) self.assertTrue(common_util.to_boolean('1')) self.assertFalse(common_util.to_boolean('False')) self.assertFalse(common_util.to_boolean('false')) self.assertFalse(common_util.to_boolean('F')) self.assertFalse(common_util.to_boolean('f')) self.assertFalse(common_util.to_boolean('0')) self.assertFalse(common_util.to_boolean('')) @mock.patch.object(os.path, 'exists') @mock.patch.object(common_util, 'get_android_root_dir') def test_find_git_root(self, mock_get_root, mock_exist): """Test find_git_root.""" mock_get_root.return_value = '/a/b' mock_exist.return_value = True self.assertEqual(common_util.find_git_root('c/d'), '/a/b/c/d') mock_exist.return_value = False self.assertEqual(common_util.find_git_root('c/d'), None) def test_determine_language_ide(self): """Test determine_language_ide function.""" ide = 'u' lang = 'u' self.assertEqual((constant.JAVA, constant.IDE_INTELLIJ), common_util.determine_language_ide(lang, ide)) self.assertEqual((constant.JAVA, constant.IDE_INTELLIJ), common_util.determine_language_ide( lang, ide, ['some_module'])) self.assertEqual((constant.C_CPP, constant.IDE_CLION), common_util.determine_language_ide( lang, ide, None, ['some_module'])) self.assertEqual((constant.RUST, constant.IDE_VSCODE), common_util.determine_language_ide( lang, ide, None, None, ['some_module'])) lang = 'j' self.assertEqual((constant.JAVA, constant.IDE_INTELLIJ), common_util.determine_language_ide(lang, ide)) ide = 'c' self.assertEqual((constant.C_CPP, constant.IDE_CLION), common_util.determine_language_ide(lang, ide)) ide = 'j' lang = 'u' self.assertEqual((constant.JAVA, constant.IDE_INTELLIJ), common_util.determine_language_ide(lang, ide)) lang = 'j' self.assertEqual((constant.JAVA, constant.IDE_INTELLIJ), common_util.determine_language_ide(lang, ide)) ide = 'c' self.assertEqual((constant.C_CPP, constant.IDE_CLION), common_util.determine_language_ide(lang, ide)) lang = 'c' ide = 'u' self.assertEqual((constant.C_CPP, constant.IDE_CLION), common_util.determine_language_ide(lang, ide)) ide = 'j' self.assertEqual((constant.JAVA, constant.IDE_INTELLIJ), common_util.determine_language_ide(lang, ide)) @mock.patch('zipfile.ZipFile.extractall') @mock.patch('zipfile.ZipFile') def test_unzip_file(self, mock_zipfile, mock_extract): """Test unzip_file function.""" src = 'a/b/c.zip' dest = 'a/b/d' common_util.unzip_file(src, dest) mock_zipfile.assert_called_with(src, 'r') self.assertFalse(mock_extract.called) @mock.patch('os.walk') def test_check_java_or_kotlin_file_exists(self, mock_walk): """Test check_java_or_kotlin_file_exists with conditions.""" root_dir = 'a/path/to/dir' folder = 'path/to/dir' target = 'test.java' abs_path = os.path.join(root_dir, folder) mock_walk.return_value = [(root_dir, [folder], [target])] self.assertTrue(common_util.check_java_or_kotlin_file_exists(abs_path)) target = 'test.kt' abs_path = os.path.join(root_dir, folder) mock_walk.return_value = [(root_dir, [folder], [target])] self.assertTrue(common_util.check_java_or_kotlin_file_exists(abs_path)) target = 'test.cpp' mock_walk.return_value = [(root_dir, [folder], [target])] self.assertFalse(common_util.check_java_or_kotlin_file_exists(abs_path)) # Only VS Code IDE supports Rust projects right now. lang = 'r' ide = 'u' self.assertEqual((constant.RUST, constant.IDE_VSCODE), common_util.determine_language_ide(lang, ide)) lang = 'r' ide = 'v' self.assertEqual((constant.RUST, constant.IDE_VSCODE), common_util.determine_language_ide(lang, ide)) lang = 'r' ide = 'j' self.assertEqual((constant.RUST, constant.IDE_VSCODE), common_util.determine_language_ide(lang, ide)) lang = 'r' ide = 'c' self.assertEqual((constant.RUST, constant.IDE_VSCODE), common_util.determine_language_ide(lang, ide)) # pylint: disable=unused-argument def parse_rule(self, name, text): """A test function for test_check_args.""" if __name__ == '__main__': unittest.main()