You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
484 lines
21 KiB
484 lines
21 KiB
#!/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 = """<application><component name="ProjectJdkTable">
|
|
|
|
<jdk version="2"> <name value="JDK_OTHER" />
|
|
<type value="JavaSDK" /> </jdk> </component>
|
|
</application>
|
|
"""
|
|
_SAMPLE_XML_CONTENT = """<application>
|
|
<component name="ProjectJdkTable">
|
|
<jdk version="2">
|
|
<name value="JDK_OTHER"/>
|
|
<type value="JavaSDK"/>
|
|
</jdk>
|
|
</component>
|
|
</application>"""
|
|
|
|
@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()
|