| #!/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. |
| |
| """Functional test for aidegen project files.""" |
| |
| from __future__ import absolute_import |
| from __future__ import print_function |
| |
| import argparse |
| import functools |
| import itertools |
| import json |
| import logging |
| import os |
| import subprocess |
| import sys |
| import xml.etree.ElementTree |
| import xml.parsers.expat |
| |
| from aidegen import aidegen_main |
| from aidegen import constant |
| from aidegen.lib import clion_project_file_gen |
| # pylint: disable=no-name-in-module |
| from aidegen.lib import common_util |
| from aidegen.lib import errors |
| from aidegen.lib import module_info_util |
| from aidegen.lib import project_config |
| from aidegen.lib import project_file_gen |
| |
| from atest import module_info |
| |
| _PRODUCT_DIR = '$PROJECT_DIR$' |
| _ROOT_DIR = os.path.join(common_util.get_android_root_dir(), |
| 'tools/asuite/aidegen_functional_test') |
| _TEST_DATA_PATH = os.path.join(_ROOT_DIR, 'test_data') |
| _VERIFY_COMMANDS_JSON = os.path.join(_TEST_DATA_PATH, 'verify_commands.json') |
| _GOLDEN_SAMPLES_JSON = os.path.join(_TEST_DATA_PATH, 'golden_samples.json') |
| _VERIFY_BINARY_JSON = os.path.join(_TEST_DATA_PATH, 'verify_binary_upload.json') |
| _VERIFY_PRESUBMIT_JSON = os.path.join(_TEST_DATA_PATH, 'verify_presubmit.json') |
| _ANDROID_COMMON = 'android_common' |
| _LINUX_GLIBC_COMMON = 'linux_glibc_common' |
| _SRCS = 'srcs' |
| _JARS = 'jars' |
| _URL = 'url' |
| _TEST_ERROR = 'AIDEGen functional test error: {}-{} is different.' |
| _MSG_NOT_IN_PROJECT_FILE = ('{} is expected, but not found in the created ' |
| 'project file: {}') |
| _MSG_NOT_IN_SAMPLE_DATA = ('{} is unexpected, but found in the created project ' |
| 'file: {}') |
| _ALL_PASS = 'All tests passed!' |
| _GIT_COMMIT_ID_JSON = os.path.join( |
| _TEST_DATA_PATH, 'baseline_code_commit_id.json') |
| _GIT = 'git' |
| _CHECKOUT = 'checkout' |
| _BRANCH = 'branch' |
| _COMMIT = 'commit' |
| _LOG = 'log' |
| _ALL = '--all' |
| _COMMIT_ID_NOT_EXIST_ERROR = ('Commit ID: {} does not exist in path: {}. ' |
| 'Please use "git log" command to check if it ' |
| 'exists. If it does not, try to update your ' |
| 'source files to the latest version or do not ' |
| 'use "repo init --depth=1" command.') |
| _GIT_LOG_ERROR = 'Command "git log -n 1" failed.' |
| _BE_REPLACED = '${config.X86_64GccRoot}' |
| _TO_REPLACE = 'prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9' |
| |
| |
| def _parse_args(args): |
| """Parse command line arguments. |
| |
| Args: |
| args: A list of arguments. |
| |
| Returns: |
| An argparse.Namespace object holding parsed args. |
| """ |
| parser = argparse.ArgumentParser( |
| description=__doc__, |
| formatter_class=argparse.RawDescriptionHelpFormatter, |
| usage='aidegen_functional_test [-c | -u | -b | -a] -v -r') |
| group = parser.add_mutually_exclusive_group() |
| parser.required = False |
| parser.add_argument( |
| 'targets', |
| type=str, |
| nargs='*', |
| default=[''], |
| help='Android module name or path.e.g. frameworks/base') |
| group.add_argument( |
| '-c', |
| '--create-sample', |
| action='store_true', |
| dest='create_sample', |
| help=('Create aidegen project files and write data to sample json file ' |
| 'for aidegen_functional_test to compare.')) |
| parser.add_argument( |
| '-v', |
| '--verbose', |
| action='store_true', |
| help='Show DEBUG level logging.') |
| parser.add_argument( |
| '-r', |
| '--remove_bp_json', |
| action='store_true', |
| help='Remove module_bp_java_deps.json for each use case test.') |
| parser.add_argument( |
| '-m', |
| '--make_clean', |
| action='store_true', |
| help=('Make clean before testing to create a clean environment, the ' |
| 'aidegen_functional_test can run only once if users command it.')) |
| group.add_argument( |
| '-u', |
| '--use_cases', |
| action='store_true', |
| dest='use_cases_verified', |
| help='Verify various use cases of executing aidegen.') |
| group.add_argument( |
| '-b', |
| action='store_true', |
| dest='binary_upload_verified', |
| help=('Verify aidegen\'s use cases by executing different aidegen ' |
| 'commands.')) |
| group.add_argument( |
| '-p', |
| action='store_true', |
| dest='binary_presubmit_verified', |
| help=('Verify aidegen\'s tool in presubmit test by executing' |
| 'different aidegen commands.')) |
| group.add_argument( |
| '-a', |
| '--test-all', |
| action='store_true', |
| dest='test_all_samples', |
| help='Test all modules listed in module-info.json.') |
| group.add_argument( |
| '-n', |
| '--compare-sample-native', |
| action='store_true', |
| dest='compare_sample_native', |
| help=('Compare if sample native project file is the same as generated ' |
| 'by the build system.')) |
| return parser.parse_args(args) |
| |
| |
| def _import_project_file_xml_etree(filename): |
| """Import iml project file and load its data into a dictionary. |
| |
| Args: |
| filename: The input project file name. |
| |
| Returns: |
| A dictionary contains dependent files' data of project file's contents. |
| The samples are like: |
| "srcs": [ |
| ... |
| "file://$PROJECT_DIR$/frameworks/base/cmds/am/src", |
| "file://$PROJECT_DIR$/frameworks/base/cmds/appwidget/src", |
| ... |
| ] |
| "jars": [ |
| ... |
| "jar://$PROJECT_DIR$/out/host/common/obj/**/classes-header.jar!/" |
| ... |
| ] |
| |
| Raises: |
| EnvironmentError and xml parsing or format errors. |
| """ |
| data = {} |
| try: |
| tree = xml.etree.ElementTree.parse(filename) |
| data[_SRCS] = [] |
| root = tree.getroot() |
| for element in root.iter('sourceFolder'): |
| src = element.get(_URL).replace(common_util.get_android_root_dir(), |
| _PRODUCT_DIR) |
| data[_SRCS].append(src) |
| data[_JARS] = [] |
| for element in root.iter('root'): |
| jar = element.get(_URL).replace(common_util.get_android_root_dir(), |
| _PRODUCT_DIR) |
| data[_JARS].append(jar) |
| except (EnvironmentError, ValueError, LookupError, |
| xml.parsers.expat.ExpatError) as err: |
| print("{0}: import error: {1}".format(os.path.basename(filename), err)) |
| raise |
| return data |
| |
| |
| def _get_project_file_names(abs_path): |
| """Get project file name and depenencies name by relative path. |
| |
| Args: |
| abs_path: an absolute module's path. |
| |
| Returns: |
| file_name: a string of the project file name. |
| dep_name: a string of the merged project and dependencies file's name, |
| e.g., frameworks-dependencies.iml. |
| """ |
| # pylint: disable=maybe-no-member |
| code_name = project_file_gen.ProjectFileGenerator.get_unique_iml_name( |
| abs_path) |
| file_name = ''.join([code_name, '.iml']) |
| dep_name = ''.join([constant.KEY_DEPENDENCIES, '.iml']) |
| return file_name, dep_name |
| |
| |
| def _get_unique_module_name(rel_path, filename): |
| """Get a unique project file name or dependencies name by relative path. |
| |
| Args: |
| rel_path: a relative module's path to aosp root path. |
| filename: the file name to be generated in module_in type file name. |
| |
| Returns: |
| A string, the unique file name for the whole module-info.json. |
| """ |
| code_names = rel_path.split(os.sep) |
| code_names[-1] = filename |
| return '-'.join(code_names) |
| |
| |
| def _get_git_current_commit_id(abs_path): |
| """Get target's git checkout command list. |
| |
| When we run command 'git log -n 1' and get the top first git log record, the |
| commit id is next to the specific word 'commit'. |
| |
| Args: |
| abs_path: a string of the absolute path of the target branch. |
| |
| Return: |
| The current git commit id. |
| |
| Raises: |
| Call subprocess.check_output cause subprocess.CalledProcessError. |
| """ |
| cwd = os.getcwd() |
| os.chdir(abs_path) |
| git_log_cmds = [_GIT, _LOG, '-n', '1'] |
| try: |
| out_put = subprocess.check_output(git_log_cmds).decode("utf-8") |
| except subprocess.CalledProcessError: |
| logging.error(_GIT_LOG_ERROR) |
| raise |
| finally: |
| os.chdir(cwd) |
| com_list = out_put.split() |
| return com_list[com_list.index(_COMMIT) + 1] |
| |
| |
| def _get_commit_id_dictionary(): |
| """Get commit id from dictionary of key, value 'module': 'commit id'.""" |
| data_id_dict = {} |
| with open(_GIT_COMMIT_ID_JSON, 'r') as jsfile: |
| data_id_dict = json.load(jsfile) |
| return data_id_dict |
| |
| |
| def _git_checkout_commit_id(abs_path, commit_id): |
| """Command to checkout specific commit id. |
| |
| Change directory to the module's absolute path which users want to get its |
| specific commit id. |
| |
| Args: |
| abs_path: the absolute path of the target branch. E.g., abs_path/.git |
| commit_id: the commit id users want to checkout. |
| |
| Raises: |
| Call git checkout commit id failed, raise errors.CommitIDNotExistError. |
| """ |
| git_chekout_cmds = [_GIT, _CHECKOUT, commit_id] |
| cwd = os.getcwd() |
| try: |
| os.chdir(abs_path) |
| subprocess.check_output(git_chekout_cmds) |
| except subprocess.CalledProcessError: |
| err = _COMMIT_ID_NOT_EXIST_ERROR.format(commit_id, abs_path) |
| logging.error(err) |
| raise errors.CommitIDNotExistError(err) |
| finally: |
| os.chdir(cwd) |
| |
| |
| def _git_checkout_target_commit_id(target, commit_id): |
| """Command to checkout target commit id. |
| |
| Switch code base to specific commit id which is kept in data_id_dict with |
| target: commit_id as key: value. If the data is missing in data_id_dict, the |
| target isn't a selected golden sample raise error for it. |
| |
| Args: |
| target: the string of target's module name or module path to checkout |
| the relevant git to its specific commit id. |
| commit_id: a string represent target's specific commit id. |
| |
| Returns: |
| current_commit_id: the current commit id of the target which should be |
| switched back to. |
| """ |
| atest_module_info = module_info.ModuleInfo() |
| _, abs_path = common_util.get_related_paths(atest_module_info, target) |
| current_commit_id = _get_git_current_commit_id(abs_path) |
| _git_checkout_commit_id(abs_path, commit_id) |
| return current_commit_id |
| |
| |
| def _checkout_baseline_code_to_spec_commit_id(): |
| """Get a dict of target, commit id listed in baseline_code_commit_id.json. |
| |
| To make sure all samples run on the same environment, we need to keep all |
| the baseline code in a specific commit id. For example, all samples should |
| be created in the same specific commit id of the baseline code |
| 'frameworks/base' for comparison except 'frameworks/base' itself. |
| |
| Returns: |
| A dictionary contains target, specific and current commit id. |
| """ |
| spec_and_cur_commit_id_dict = {} |
| data_id_dict = _get_commit_id_dictionary() |
| for target in data_id_dict: |
| commit_id = data_id_dict.get(target, '') |
| current_commit_id = _git_checkout_target_commit_id(target, commit_id) |
| spec_and_cur_commit_id_dict[target] = {} |
| spec_and_cur_commit_id_dict[target]['current'] = current_commit_id |
| return spec_and_cur_commit_id_dict |
| |
| |
| def _generate_target_real_iml_data(target): |
| """Generate single target's real iml file content's data. |
| |
| Args: |
| target: Android module name or path to be create iml data. |
| |
| Returns: |
| data: A dictionary contains key: unique file name and value: iml |
| content. |
| """ |
| data = {} |
| try: |
| aidegen_main.main([target, '-s', '-n', '-v']) |
| except (errors.FakeModuleError, |
| errors.ProjectOutsideAndroidRootError, |
| errors.ProjectPathNotExistError, |
| errors.NoModuleDefinedInModuleInfoError) as err: |
| logging.error(str(err)) |
| return data |
| |
| atest_module_info = module_info.ModuleInfo() |
| rel_path, abs_path = common_util.get_related_paths(atest_module_info, |
| target) |
| for filename in iter(_get_project_file_names(abs_path)): |
| real_iml_file = os.path.join(abs_path, filename) |
| item_name = _get_unique_module_name(rel_path, filename) |
| data[item_name] = _import_project_file_xml_etree(real_iml_file) |
| return data |
| |
| |
| def _generate_sample_json(test_list): |
| """Generate sample iml data. |
| |
| We use all baseline code samples on the version of their own specific commit |
| id which is kept in _GIT_COMMIT_ID_JSON file. We need to switch back to |
| their current commit ids after generating golden samples' data. |
| |
| Args: |
| test_list: a list of module name and module path. |
| |
| Returns: |
| data: a dictionary contains dependent files' data of project file's |
| contents. |
| The sample is like: |
| "frameworks-base.iml": { |
| "srcs": [ |
| .... |
| "file://$PROJECT_DIR$/frameworks/base/cmds/am/src", |
| "file://$PROJECT_DIR$/frameworks/base/cmds/appwidget/src", |
| .... |
| ], |
| "jars": [ |
| .... |
| "jar://$PROJECT_DIR$/out/target/common/**/aapt2.srcjar!/", |
| .... |
| ] |
| } |
| """ |
| data = {} |
| spec_and_cur_commit_id_dict = _checkout_baseline_code_to_spec_commit_id() |
| for target in test_list: |
| data.update(_generate_target_real_iml_data(target)) |
| atest_module_info = module_info.ModuleInfo() |
| for target in spec_and_cur_commit_id_dict: |
| _, abs_path = common_util.get_related_paths(atest_module_info, target) |
| _git_checkout_commit_id( |
| abs_path, spec_and_cur_commit_id_dict[target]['current']) |
| return data |
| |
| |
| def _create_some_sample_json_file(targets): |
| """Write some samples' iml data into a json file. |
| |
| Args: |
| targets: Android module name or path to be create iml data. |
| |
| linked_function: _generate_sample_json() |
| """ |
| data = _generate_sample_json(targets) |
| data_sample = {} |
| with open(_GOLDEN_SAMPLES_JSON, 'r') as infile: |
| try: |
| data_sample = json.load(infile) |
| # pylint: disable=maybe-no-member |
| except json.JSONDecodeError as err: |
| print("Json decode error: {}".format(err)) |
| data_sample = {} |
| data_sample.update(data) |
| with open(_GOLDEN_SAMPLES_JSON, 'w') as outfile: |
| json.dump(data_sample, outfile, indent=4, sort_keys=False) |
| |
| |
| def test_samples(func): |
| """Decorate a function to deal with preparing and verifying staffs of it. |
| |
| Args: |
| func: a function is to be compared its iml data with the json file's |
| data. |
| |
| Returns: |
| The wrapper function. |
| """ |
| |
| @functools.wraps(func) |
| def wrapper(*args, **kwargs): |
| """A wrapper function.""" |
| |
| test_successful = True |
| with open(_GOLDEN_SAMPLES_JSON, 'r') as outfile: |
| data_sample = json.load(outfile) |
| |
| data_real = func(*args, **kwargs) |
| |
| for name in data_real: |
| for item in [_SRCS, _JARS]: |
| s_items = data_sample[name][item] |
| r_items = data_real[name][item] |
| if set(s_items) != set(r_items): |
| diff_iter = _compare_content(name, item, s_items, r_items) |
| if diff_iter: |
| print('\n{} {}'.format( |
| common_util.COLORED_INFO('Test error:'), |
| _TEST_ERROR.format(name, item))) |
| print('{} {} contents are different:'.format( |
| name, item)) |
| for diff in diff_iter: |
| print(diff) |
| test_successful = False |
| if test_successful: |
| print(common_util.COLORED_PASS(_ALL_PASS)) |
| return test_successful |
| |
| return wrapper |
| |
| |
| @test_samples |
| def _test_some_sample_iml(targets=None): |
| """Compare with sample iml's data to assure the project's contents is right. |
| |
| Args: |
| targets: Android module name or path to be create iml data. |
| """ |
| if targets: |
| return _generate_sample_json(targets) |
| return _generate_sample_json(_get_commit_id_dictionary().keys()) |
| |
| |
| @test_samples |
| def _test_all_samples_iml(): |
| """Compare all imls' data with all samples' data. |
| |
| It's to make sure each iml's contents is right. The function is implemented |
| but hasn't been used yet. |
| """ |
| all_module_list = module_info.ModuleInfo().name_to_module_info.keys() |
| return _generate_sample_json(all_module_list) |
| |
| |
| def _compare_content(module_name, item_type, s_items, r_items): |
| """Compare src or jar files' data of two dictionaries. |
| |
| Args: |
| module_name: the test module name. |
| item_type: the type is src or jar. |
| s_items: sample jars' items. |
| r_items: real jars' items. |
| |
| Returns: |
| An iterator of not equal sentences after comparison. |
| """ |
| if item_type == _SRCS: |
| cmp_iter1 = _compare_srcs_content(module_name, s_items, r_items, |
| _MSG_NOT_IN_PROJECT_FILE) |
| cmp_iter2 = _compare_srcs_content(module_name, r_items, s_items, |
| _MSG_NOT_IN_SAMPLE_DATA) |
| else: |
| cmp_iter1 = _compare_jars_content(module_name, s_items, r_items, |
| _MSG_NOT_IN_PROJECT_FILE) |
| cmp_iter2 = _compare_jars_content(module_name, r_items, s_items, |
| _MSG_NOT_IN_SAMPLE_DATA) |
| return itertools.chain(cmp_iter1, cmp_iter2) |
| |
| |
| def _compare_srcs_content(module_name, s_items, r_items, msg): |
| """Compare src or jar files' data of two dictionaries. |
| |
| Args: |
| module_name: the test module name. |
| s_items: sample jars' items. |
| r_items: real jars' items. |
| msg: the message will be written into log file. |
| |
| Returns: |
| An iterator of not equal sentences after comparison. |
| """ |
| for sample in s_items: |
| if sample not in r_items: |
| yield msg.format(sample, module_name) |
| |
| |
| def _compare_jars_content(module_name, s_items, r_items, msg): |
| """Compare src or jar files' data of two dictionaries. |
| |
| AIDEGen treats the jars in folder names 'linux_glib_common' and |
| 'android_common' as the same content. If the paths are different only |
| because of these two names, we ignore it. |
| |
| Args: |
| module_name: the test module name. |
| s_items: sample jars' items. |
| r_items: real jars' items. |
| msg: the message will be written into log file. |
| |
| Returns: |
| An iterator of not equal sentences after comparison. |
| """ |
| for sample in s_items: |
| if sample not in r_items: |
| lnew = sample |
| if constant.LINUX_GLIBC_COMMON in sample: |
| lnew = sample.replace(constant.LINUX_GLIBC_COMMON, |
| constant.ANDROID_COMMON) |
| else: |
| lnew = sample.replace(constant.ANDROID_COMMON, |
| constant.LINUX_GLIBC_COMMON) |
| if not lnew in r_items: |
| yield msg.format(sample, module_name) |
| |
| |
| # pylint: disable=broad-except |
| # pylint: disable=eval-used |
| @common_util.back_to_cwd |
| @common_util.time_logged |
| def _verify_aidegen(verified_file_path, forced_remove_bp_json, |
| is_presubmit=False): |
| """Verify various use cases of executing aidegen. |
| |
| There are two types of running commands: |
| 1. Use 'eval' to run the commands for present codes in aidegen_main.py, |
| such as: |
| aidegen_main.main(['tradefed', '-n', '-v']) |
| 2. Use 'subprocess.check_call' to run the commands for the binary codes of |
| aidegen such as: |
| aidegen tradefed -n -v |
| |
| Remove module_bp_java_deps.json in the beginning of running use cases. If |
| users need to remove module_bp_java_deps.json between each use case they |
| can set forced_remove_bp_json true. |
| |
| Args: |
| verified_file_path: The json file path to be verified. |
| forced_remove_bp_json: Remove module_bp_java_deps.json for each use case |
| test. |
| |
| Raises: |
| There are two type of exceptions: |
| 1. aidegen.lib.errors for projects' or modules' issues such as, |
| ProjectPathNotExistError. |
| 2. Any exceptions other than aidegen.lib.errors such as, |
| subprocess.CalledProcessError. |
| """ |
| bp_json_path = common_util.get_blueprint_json_path( |
| constant.BLUEPRINT_JAVA_JSONFILE_NAME) |
| use_eval = (verified_file_path == _VERIFY_COMMANDS_JSON) |
| try: |
| with open(verified_file_path, 'r') as jsfile: |
| data = json.load(jsfile) |
| except IOError as err: |
| raise errors.JsonFileNotExistError( |
| '%s does not exist, error: %s.' % (verified_file_path, err)) |
| |
| if not is_presubmit: |
| _compare_sample_native_content() |
| |
| os.chdir(common_util.get_android_root_dir()) |
| for use_case in data: |
| print('Use case "{}" is running.'.format(use_case)) |
| if forced_remove_bp_json and os.path.exists(bp_json_path): |
| os.remove(bp_json_path) |
| for cmd in data[use_case]: |
| print('Command "{}" is running.'.format(cmd)) |
| try: |
| if use_eval: |
| eval(cmd) |
| else: |
| subprocess.check_call(cmd, shell=True) |
| except (errors.ProjectOutsideAndroidRootError, |
| errors.ProjectPathNotExistError, |
| errors.NoModuleDefinedInModuleInfoError, |
| errors.IDENotExistError) as err: |
| print('"{}" raises error: {}.'.format(use_case, err)) |
| continue |
| except BaseException: |
| exc_type, _, _ = sys.exc_info() |
| print('"{}.{}" command {}.'.format( |
| use_case, cmd, common_util.COLORED_FAIL('executes failed'))) |
| raise BaseException( |
| 'Unexpected command "{}" exception: {}.'.format( |
| use_case, exc_type)) |
| print('"{}" command {}!'.format( |
| use_case, common_util.COLORED_PASS('test passed'))) |
| print(common_util.COLORED_PASS(_ALL_PASS)) |
| |
| |
| @common_util.back_to_cwd |
| def _make_clean(): |
| """Make a command to clean out folder for a pure environment to test. |
| |
| Raises: |
| Call subprocess.check_call to execute |
| 'build/soong/soong_ui.bash --make-mode clean' and cause |
| subprocess.CalledProcessError. |
| """ |
| try: |
| os.chdir(common_util.get_android_root_dir()) |
| subprocess.check_call( |
| ['build/soong/soong_ui.bash --make-mode clean', '-j'], |
| shell=True) |
| except subprocess.CalledProcessError: |
| print('"build/soong/soong_ui.bash --make-mode clean" command failed.') |
| raise |
| |
| |
| def _read_file_content(path): |
| """Read file's content. |
| |
| Args: |
| path: Path of input file. |
| |
| Returns: |
| A list of content strings. |
| """ |
| with open(path, encoding='utf8') as template: |
| contents = [] |
| for cnt in template: |
| if cnt.startswith('#'): |
| continue |
| contents.append(cnt.rstrip()) |
| return contents |
| |
| |
| # pylint: disable=protected-access |
| def _compare_sample_native_content(): |
| """Compares 'libui' sample module's project file. |
| |
| Compares 'libui' sample module's project file generated by AIDEGen with that |
| generated by the soong build system. Check if their contents are the same. |
| There should be only one different: |
| ${config.X86_64GccRoot} # in the soong build sytem |
| becomes |
| prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9 # in AIDEGen |
| """ |
| target_arch_variant = 'x86_64' |
| env_on = { |
| 'TARGET_PRODUCT': 'aosp_x86_64', |
| 'TARGET_BUILD_VARIANT': 'eng', |
| 'TARGET_ARCH_VARIANT': target_arch_variant, |
| 'SOONG_COLLECT_JAVA_DEPS': 'true', |
| 'SOONG_GEN_CMAKEFILES': '1', |
| 'SOONG_COLLECT_CC_DEPS': '1' |
| } |
| |
| try: |
| project_config.ProjectConfig( |
| aidegen_main._parse_args(['-n', '-v'])).init_environment() |
| module_info_util.generate_merged_module_info(env_on) |
| cc_path = os.path.join(common_util.get_soong_out_path(), |
| constant.BLUEPRINT_CC_JSONFILE_NAME) |
| mod_name = 'libui' |
| mod_info = common_util.get_json_dict(cc_path)['modules'][mod_name] |
| if mod_info: |
| clion_project_file_gen.CLionProjectFileGenerator( |
| mod_info).generate_cmakelists_file() |
| out_dir = os.path.join(common_util.get_android_root_dir(), |
| common_util.get_android_out_dir(), |
| constant.RELATIVE_NATIVE_PATH, |
| mod_info['path'][0]) |
| content1 = _read_file_content(os.path.join( |
| out_dir, mod_name, constant.CLION_PROJECT_FILE_NAME)) |
| cc_file_name = ''.join( |
| [mod_name, '-', target_arch_variant, '-android']) |
| cc_file_path = os.path.join( |
| out_dir, cc_file_name, constant.CLION_PROJECT_FILE_NAME) |
| content2 = _read_file_content(cc_file_path) |
| same = True |
| for lino, (cnt1, cnt2) in enumerate( |
| zip(content1, content2), start=1): |
| if _BE_REPLACED in cnt2: |
| cnt2 = cnt2.replace(_BE_REPLACED, _TO_REPLACE) |
| if cnt1 != cnt2: |
| print('Contents {} and {} are different in line:{}.'.format( |
| cnt1, cnt2, lino)) |
| same = False |
| if same: |
| print('Files {} and {} are the same.'.format( |
| mod_name, cc_file_name)) |
| except errors.BuildFailureError: |
| print('Compare native content failed.') |
| |
| |
| def main(argv): |
| """Main entry. |
| |
| 1. Create the iml file data of each module in module-info.json and write it |
| into single_module.json. |
| 2. Verify every use case of AIDEGen. |
| 3. Compare all or some iml project files' data to the data recorded in |
| single_module.json. |
| |
| Args: |
| argv: A list of system arguments. |
| """ |
| args = _parse_args(argv) |
| common_util.configure_logging(args.verbose) |
| os.environ[constant.AIDEGEN_TEST_MODE] = 'true' |
| |
| if args.make_clean: |
| _make_clean() |
| |
| if args.create_sample: |
| _create_some_sample_json_file(args.targets) |
| elif args.use_cases_verified: |
| _verify_aidegen(_VERIFY_COMMANDS_JSON, args.remove_bp_json) |
| elif args.binary_upload_verified: |
| _verify_aidegen(_VERIFY_BINARY_JSON, args.remove_bp_json) |
| elif args.binary_presubmit_verified: |
| _verify_aidegen(_VERIFY_PRESUBMIT_JSON, args.remove_bp_json, True) |
| elif args.test_all_samples: |
| _test_all_samples_iml() |
| elif args.compare_sample_native: |
| _compare_sample_native_content() |
| else: |
| if not args.targets[0]: |
| _test_some_sample_iml() |
| else: |
| _test_some_sample_iml(args.targets) |
| |
| del os.environ[constant.AIDEGEN_TEST_MODE] |
| |
| |
| if __name__ == '__main__': |
| main(sys.argv[1:]) |