#!/usr/bin/env python3 # # Copyright 2019 - 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 clion_project_file_gen.""" import os import unittest from unittest import mock from io import StringIO from aidegen import constant from aidegen import templates from aidegen.lib import clion_project_file_gen from aidegen.lib import common_util from aidegen.lib import errors from aidegen.lib import native_module_info # pylint: disable=protected-access # pylint: disable=too-many-arguments class ClionProjectFileGenUnittests(unittest.TestCase): """Unit tests for clion_project_file_gen.py.""" _FLAG_LIST = ['a', 'b'] _FLAG_DICT = {clion_project_file_gen._KEY_FLAG: _FLAG_LIST} _MOD_INFO = {clion_project_file_gen._KEY_GLOBAL_COMMON_FLAGS: _FLAG_DICT} _MOD_PATH = 'path_to_mod' _PATH_DICT = {'path': [_MOD_PATH]} _MOD_NAME = 'M' _MOD_NAME_DICT = {'module_name': _MOD_NAME} _ROOT_DIR = 'path_to_root' _SRC_PATH = 'path_to_src' _SRC_DICT = {constant.KEY_SRCS: [_SRC_PATH]} def test_init_without_mod_info(self): """Test __init__ without mod_info.""" with self.assertRaises(errors.ModuleInfoEmptyError): clion_project_file_gen.CLionProjectFileGenerator({}) @mock.patch('os.path.exists') def test_init_with_mod_info_without_mod_name(self, mock_exists): """Test __init__ with mod_info but without the module name.""" mod_info = dict(self._MOD_INFO) mod_info.update(self._PATH_DICT) mock_exists.return_value = True with self.assertRaises(errors.NoModuleNameDefinedInModuleInfoError): clion_project_file_gen.CLionProjectFileGenerator(mod_info) @mock.patch('os.path.exists') def test_init_with_mod_info_without_mod_path(self, mock_exists): """Test __init__ with mod_info but without the module path.""" mod_info = dict(self._MOD_INFO) mod_info.update(self._MOD_NAME_DICT) mock_exists.return_value = True with self.assertRaises(errors.NoPathDefinedInModuleInfoError): clion_project_file_gen.CLionProjectFileGenerator(mod_info) @mock.patch.object(os, 'makedirs') @mock.patch.object(os.path, 'exists') @mock.patch.object(clion_project_file_gen.CLionProjectFileGenerator, 'get_cmakelists_file_dir') @mock.patch.object(clion_project_file_gen.CLionProjectFileGenerator, 'get_module_path') def test_init_with_mod_info_makedir( self, mock_get_path, mock_get_cmake, mock_exists, mock_mkdirs): """Test __init__ with mod_info and check if need to make dir.""" mod_info = dict(self._MOD_INFO) mod_info.update(self._MOD_NAME_DICT) mock_get_path.return_value = self._MOD_PATH mock_get_cmake.return_value = self._SRC_PATH mock_exists.return_value = True clion_project_file_gen.CLionProjectFileGenerator(mod_info) self.assertFalse(mock_mkdirs.called) mock_mkdirs.mock_reset() mock_exists.return_value = False clion_project_file_gen.CLionProjectFileGenerator(mod_info) self.assertTrue(mock_mkdirs.called) @mock.patch('os.path.exists') def test_write_header(self, mock_exists): """Test _write_header function.""" hfile = StringIO() mock_exists.return_value = True mod_info = dict(self._MOD_INFO) mod_info.update(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) clion_gen._write_header(hfile) hfile.seek(0) content = hfile.read() expected = templates.CMAKELISTS_HEADER.replace( clion_project_file_gen._MIN_VERSION_TOKEN, clion_project_file_gen._MINI_VERSION) expected = expected.replace( clion_project_file_gen._PROJECT_NAME_TOKEN, clion_gen.mod_name) expected = expected.replace( clion_project_file_gen._ANDOIR_ROOT_TOKEN, common_util.get_android_root_dir()) self.assertEqual(content, expected) @mock.patch('os.path.exists') def test_write_c_compiler_paths(self, mock_exists): """Test _write_c_compiler_paths function.""" hfile = StringIO() c_lang_path = 'c_lang_path' cpp_lang_path = 'cpp_lang_path' native_module_info.NativeModuleInfo.c_lang_path = c_lang_path native_module_info.NativeModuleInfo.cpp_lang_path = cpp_lang_path mock_exists.return_value = True mod_info = dict(self._MOD_INFO) mod_info.update(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) clion_gen._write_c_compiler_paths(hfile) hfile.seek(0) content = hfile.read() expected = clion_project_file_gen._SET_C_COMPILER.format( c_lang_path) + clion_project_file_gen._SET_CXX_COMPILER.format( cpp_lang_path) self.assertEqual(content, expected) @mock.patch('os.path.exists') def test_write_source_files_without_content(self, mock_exists): """Test _write_source_files function without content.""" hfile = StringIO() mock_exists.return_value = True mod_info = dict(self._MOD_INFO) mod_info.update(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) clion_gen._write_source_files(hfile) hfile.seek(0) content = hfile.read() expected = '' self.assertEqual(content, expected) @mock.patch('os.path.exists') def test_write_source_files_with_content(self, mock_exists): """Test _write_source_files function with content.""" hfile = StringIO() mod_info = dict(self._MOD_INFO) mod_info.update(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) mod_info.update(self._SRC_DICT) mock_exists.return_value = True clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) clion_gen._write_source_files(hfile) hfile.seek(0) content = hfile.read() srcs = clion_project_file_gen._build_cmake_path(self._SRC_PATH, ' ') header = clion_project_file_gen._LIST_APPEND_HEADER src_heads = [' ', clion_project_file_gen._SOURCE_FILES_HEADER, '\n'] tail = ')\n' expected = header + ''.join(src_heads) + srcs + '\n' + tail self.assertEqual(content, expected) @mock.patch('os.path.exists') def test_write_flags_without_content(self, mock_exists): """Test _write_flags function without content.""" hfile = StringIO() mod_info = dict(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) key = clion_project_file_gen._KEY_GLOBAL_COMMON_FLAGS mock_exists.return_value = True clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) clion_gen._write_flags(hfile, key, True, True) hfile.seek(0) content = hfile.read() expected = clion_project_file_gen._FLAGS_DICT.get(key, '') self.assertEqual(content, expected) @mock.patch('os.path.exists') def test_parse_compiler_parameters_without_flag(self, mock_exists): """Test _parse_compiler_parameters function without flag.""" mod_info = dict(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) mock_exists.return_value = True clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) result = clion_gen._parse_compiler_parameters( clion_project_file_gen._KEY_GLOBAL_COMMON_FLAGS) self.assertEqual(result, None) @mock.patch('os.path.exists') def test_parse_compiler_parameters_with_flag(self, mock_exists): """Test _parse_compiler_parameters function with flag.""" mod_info = dict(self._MOD_INFO) mod_info.update(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) expected = { constant.KEY_HEADER: [], constant.KEY_SYSTEM: [], clion_project_file_gen._KEY_FLAG: self._FLAG_LIST, clion_project_file_gen._KEY_SYSTEM_ROOT: '', clion_project_file_gen._KEY_RELATIVE: {} } mock_exists.return_value = True clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) flag = clion_project_file_gen._KEY_GLOBAL_COMMON_FLAGS ret = clion_gen._parse_compiler_parameters(flag) self.assertEqual(ret, expected) @mock.patch.object(clion_project_file_gen, '_write_all_flags') @mock.patch.object(clion_project_file_gen, '_write_all_relative_file_path_flags') @mock.patch.object(clion_project_file_gen, '_write_all_include_directories') def test_translate_to_cmake_with_empty_dict( self, mock_write_all_inc, mock_write_rel, mock_write_all_flags): """Test _translate_to_cmake function with empty dictionary.""" hfile = StringIO() params_dict = { constant.KEY_HEADER: [], constant.KEY_SYSTEM: [], clion_project_file_gen._KEY_FLAG: [], clion_project_file_gen._KEY_SYSTEM_ROOT: '', clion_project_file_gen._KEY_RELATIVE: {} } clion_project_file_gen._translate_to_cmake(hfile, params_dict, True, True) hfile.seek(0) content = hfile.read() self.assertEqual(content, '') self.assertTrue(mock_write_all_inc.call_count, 2) self.assertTrue(mock_write_rel, 2) self.assertTrue(mock_write_all_flags, 2) mock_write_all_inc.mock_reset() mock_write_rel.mock_reset() mock_write_all_flags.mock_reset() clion_project_file_gen._translate_to_cmake(hfile, params_dict, False, True) hfile.seek(0) content = hfile.read() self.assertEqual(content, '') self.assertTrue(mock_write_all_inc.call_count, 2) self.assertTrue(mock_write_rel, 1) self.assertTrue(mock_write_all_flags, 1) mock_write_all_inc.mock_reset() mock_write_rel.mock_reset() mock_write_all_flags.mock_reset() clion_project_file_gen._translate_to_cmake(hfile, params_dict, True, False) hfile.seek(0) content = hfile.read() self.assertEqual(content, '') self.assertTrue(mock_write_all_inc.call_count, 2) self.assertTrue(mock_write_rel, 1) self.assertTrue(mock_write_all_flags, 1) @mock.patch.object(clion_project_file_gen, '_write_all_flags') @mock.patch.object(clion_project_file_gen, '_write_all_relative_file_path_flags') @mock.patch.object(clion_project_file_gen, '_write_all_include_directories') def test_translate_to_cmake_with_system_root_info( self, mock_write_all_inc, mock_write_rel, mock_write_all_flags): """Test _translate_to_cmake function with empty dictionary.""" hfile = StringIO() root = 'path_to_root' params_dict = { constant.KEY_HEADER: [], constant.KEY_SYSTEM: [], clion_project_file_gen._KEY_FLAG: [], clion_project_file_gen._KEY_SYSTEM_ROOT: root, clion_project_file_gen._KEY_RELATIVE: {} } clion_project_file_gen._translate_to_cmake(hfile, params_dict, True, False) hfile.seek(0) content = hfile.read() path = os.path.join( root, clion_project_file_gen._USR, clion_project_file_gen._INCLUDE) expected = clion_project_file_gen._INCLUDE_SYSTEM.format( clion_project_file_gen._build_cmake_path(path)) self.assertEqual(content, expected) self.assertTrue(mock_write_all_inc.call_count, 2) self.assertTrue(mock_write_rel, 1) self.assertTrue(mock_write_all_flags, 1) def test_write_all_relative_flags_without_content(self): """Test _write_all_relative_file_path_flags function without content.""" hfile = StringIO() clion_project_file_gen._write_all_relative_file_path_flags( hfile, {}, '') hfile.seek(0) content = hfile.read() self.assertEqual(content, '') def test_write_all_relative_flags_with_content(self): """Test _write_all_relative_file_path_flags function with content.""" hfile = StringIO() flag = 'flag' path = 'path_to_rel' tag = '_CMAKE_C_FLAGS' clion_project_file_gen._write_all_relative_file_path_flags( hfile, {flag: path}, tag) hfile.seek(0) content = hfile.read() expected = clion_project_file_gen._SET_RELATIVE_PATH.format( tag, clion_project_file_gen._add_dollar_sign(tag), flag, clion_project_file_gen._build_cmake_path(path)) self.assertEqual(content, expected) def test_add_dollar_sign(self): """Test _add_dollar_sign function.""" param = 'ANDROID' expected = '${ANDROID}' result = clion_project_file_gen._add_dollar_sign(param) self.assertEqual(expected, result) def test_write_all_flags_without_content(self): """Test _write_all_flags function without content.""" hfile = StringIO() clion_project_file_gen._write_all_flags(hfile, [], '') hfile.seek(0) content = hfile.read() self.assertEqual(content, '') def test_write_all_flags_with_content(self): """Test _write_all_flags function with content.""" hfile = StringIO() flag = 'flag' tag = '_CMAKE_C_FLAGS' clion_project_file_gen._write_all_flags(hfile, [flag], tag) hfile.seek(0) content = hfile.read() expected = clion_project_file_gen._SET_ALL_FLAGS.format( tag, clion_project_file_gen._add_dollar_sign(tag), flag) self.assertEqual(content, expected) def test_build_cmake_path_without_tag(self): """Test _build_cmake_path function without tag.""" param = 'prebuilts/clang/host/linux-x86/clang-r370808/bin/clang' expected = ('${ANDROID_ROOT}/prebuilts/clang/host/linux-x86/' 'clang-r370808/bin/clang') result = clion_project_file_gen._build_cmake_path(param) self.assertEqual(expected, result) def test_build_cmake_path_with_tag(self): """Test _build_cmake_path function with tag.""" param = 'prebuilts/clang/host/linux-x86/clang-r370808/bin/clang' tag = ' ' expected = (' ${ANDROID_ROOT}/prebuilts/clang/host/linux-x86/' 'clang-r370808/bin/clang') result = clion_project_file_gen._build_cmake_path(param, tag) self.assertEqual(expected, result) def test_write_all_includes_without_content(self): """Test _write_all_includes function without content.""" hfile = StringIO() clion_project_file_gen._write_all_includes(hfile, [], True) hfile.seek(0) content = hfile.read() self.assertEqual(content, '') clion_project_file_gen._write_all_includes(hfile, [], False) hfile.seek(0) content = hfile.read() self.assertEqual(content, '') def test_write_all_includes_with_content(self): """Test _write_all_includes function with content.""" hfile = StringIO() include = 'path_to_include' clion_project_file_gen._write_all_includes(hfile, [include], True) hfile.seek(0) content = hfile.read() system = clion_project_file_gen._SYSTEM head = clion_project_file_gen._INCLUDE_DIR.format(system) middle = clion_project_file_gen._SET_INCLUDE_FORMAT.format( clion_project_file_gen._build_cmake_path(include)) tail = clion_project_file_gen._END_WITH_TWO_BLANK_LINES expected = head + middle + tail self.assertEqual(content, expected) hfile = StringIO() clion_project_file_gen._write_all_includes(hfile, [include], False) hfile.seek(0) content = hfile.read() head = clion_project_file_gen._INCLUDE_DIR.format('') expected = head + middle + tail self.assertEqual(content, expected) @mock.patch('os.path.exists') @mock.patch.object(clion_project_file_gen, '_translate_to_cmake') @mock.patch.object(clion_project_file_gen.CLionProjectFileGenerator, '_parse_compiler_parameters') def test_write_flags_with_content( self, mock_parse, mock_translate, mock_exists): """Test _write_flags function with content.""" mock_exists.return_value = True hfile = StringIO() mod_info = dict(self._MOD_INFO) mod_info.update(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) mock_exists.return_value = True clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) key = clion_project_file_gen._KEY_GLOBAL_COMMON_FLAGS clion_gen._write_flags(hfile, key, True, True) self.assertTrue(mock_parse.called) self.assertTrue(mock_translate.called) @mock.patch('os.path.exists') @mock.patch.object(clion_project_file_gen, '_translate_to_cmake') @mock.patch.object(clion_project_file_gen.CLionProjectFileGenerator, '_parse_compiler_parameters') def test_write_flags_with_content_key_not_exists( self, mock_parse, mock_translate, mock_exists): """Test _write_flags function with content, key not in _FLAGS_DICT.""" mock_exists.return_value = True hfile = StringIO() mod_info = dict(self._MOD_INFO) mod_info.update(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) key = constant.KEY_PATH clion_gen._write_flags(hfile, key, True, True) self.assertFalse(mock_parse.called) self.assertFalse(mock_translate.called) def test_write_all_include_directories_without_content(self): """Test _write_all_include_directories function without content.""" hfile = StringIO() clion_project_file_gen._write_all_include_directories(hfile, [], True) hfile.seek(0) content = hfile.read() self.assertEqual(content, '') clion_project_file_gen._write_all_include_directories(hfile, [], False) hfile.seek(0) content = hfile.read() self.assertEqual(content, '') @mock.patch.object(clion_project_file_gen, '_write_all_headers') @mock.patch.object(clion_project_file_gen, '_write_all_includes') def test_write_all_include_directories_with_content(self, mock_includes, mock_headers): """Test _write_all_include_directories function with content.""" hfile = StringIO() includes = ['path_to_include'] clion_project_file_gen._write_all_include_directories( hfile, includes, True) self.assertTrue(mock_includes.called) self.assertTrue(mock_headers.called) clion_project_file_gen._write_all_include_directories( hfile, includes, False) self.assertTrue(mock_includes.called) self.assertTrue(mock_headers.called) def test_write_all_headers_without_content(self): """Test _write_all_headers function without content.""" hfile = StringIO() clion_project_file_gen._write_all_headers(hfile, []) hfile.seek(0) content = hfile.read() self.assertEqual(content, '') def test_write_all_headers_with_content(self): """Test _write_all_headers function with content.""" hfile = StringIO() include = 'path_to_include' clion_project_file_gen._write_all_headers(hfile, [include]) hfile.seek(0) content = hfile.read() head = clion_project_file_gen._GLOB_RECURSE_TMP_HEADERS middle = clion_project_file_gen._ALL_HEADER_FILES.format( clion_project_file_gen._build_cmake_path(include)) tail1 = clion_project_file_gen._END_WITH_ONE_BLANK_LINE tail2 = clion_project_file_gen._APPEND_SOURCE_FILES expected = head + middle + tail1 + tail2 self.assertEqual(content, expected) def test_cleanup_executable_name(self): """Test _cleanup_executable_name function with conditions.""" mod_name = 'android.frameworks.bufferhub@1.0-service' result = 'android.frameworks.bufferhub-1.0-service' self.assertEqual( result, clion_project_file_gen._cleanup_executable_name(mod_name)) mod_name = 'libui' result = 'libui' self.assertEqual( result, clion_project_file_gen._cleanup_executable_name(mod_name)) @mock.patch('os.path.exists') @mock.patch('builtins.open') @mock.patch.object(clion_project_file_gen.CLionProjectFileGenerator, '_write_cmakelists_file') def test_generate_cmakelists_file(self, mock_write, mock_open, mock_exists): """Test generate_cmakelists_file with handlings.""" mock_exists.return_value = True mod_info = dict(self._MOD_INFO) mod_info.update(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) clion_gen.generate_cmakelists_file() self.assertTrue(mock_open.called) self.assertTrue(mock_write.called) @mock.patch('os.path.exists') @mock.patch.object(clion_project_file_gen.CLionProjectFileGenerator, '_write_tail') @mock.patch.object(clion_project_file_gen.CLionProjectFileGenerator, '_write_cmakelists_flags') @mock.patch.object(clion_project_file_gen.CLionProjectFileGenerator, '_write_source_files') @mock.patch.object(clion_project_file_gen.CLionProjectFileGenerator, '_write_c_compiler_paths') @mock.patch.object(clion_project_file_gen.CLionProjectFileGenerator, '_write_header') def test_write_cmakelists_file(self, mock_head, mock_comp, mock_src, mock_flag, mock_tail, mock_exists): """Test _write_cmakelists_file with handlings.""" mock_exists.return_value = True mod_info = dict(self._MOD_INFO) mod_info.update(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) hfile = StringIO() clion_gen._write_cmakelists_file(hfile) self.assertTrue(mock_head.called) self.assertTrue(mock_comp.called) self.assertTrue(mock_src.called) self.assertTrue(mock_flag.called) self.assertTrue(mock_tail.called) @mock.patch('os.path.exists') @mock.patch.object(clion_project_file_gen.CLionProjectFileGenerator, '_write_flags') def test_write_cmakelists_flags(self, mock_flags, mock_exists): """Test _write_cmakelists_file with handlings.""" mock_exists.return_value = True mod_info = dict(self._MOD_INFO) mod_info.update(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) hfile = StringIO() clion_gen._write_cmakelists_flags(hfile) self.assertEqual(mock_flags.call_count, 9) @mock.patch('os.path.exists') def test_write_tail(self, mock_exists): """Test _write_tail with handlings.""" mock_exists.return_value = True mod_info = dict(self._MOD_INFO) mod_info.update(self._PATH_DICT) mod_info.update(self._MOD_NAME_DICT) clion_gen = clion_project_file_gen.CLionProjectFileGenerator(mod_info) hfile = StringIO() clion_gen._write_tail(hfile) hfile.seek(0) content = hfile.read() expected = clion_project_file_gen._ADD_EXECUTABLE_HEADER.format( clion_project_file_gen._cleanup_executable_name(clion_gen.mod_name), clion_project_file_gen._add_dollar_sign( clion_project_file_gen._SOURCE_FILES_HEADER)) self.assertEqual(content, expected) def test_get_module_path(self): """Test get_module_path function with conditions.""" path_b = 'a/b/path_a_to_A' path_c = 'a/c/path_a_to_A' path_d = 'a/d/path_a_to_A' mod_info = { 'module_name': 'A_Mod', 'path': [ path_b, path_c, path_d, ] } res = clion_project_file_gen.CLionProjectFileGenerator.get_module_path( mod_info) self.assertEqual(res, path_b) res = clion_project_file_gen.CLionProjectFileGenerator.get_module_path( mod_info, 'a/b') self.assertEqual(res, path_b) res = clion_project_file_gen.CLionProjectFileGenerator.get_module_path( mod_info, 'a/c') self.assertEqual(res, path_c) res = clion_project_file_gen.CLionProjectFileGenerator.get_module_path( mod_info, 'a/d') self.assertEqual(res, path_d) if __name__ == '__main__': unittest.main()