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"""Functional test for aidegen project files.""" 18 19from __future__ import absolute_import 20 21import argparse 22import functools 23import itertools 24import json 25import logging 26import os 27import subprocess 28import sys 29import xml.etree.ElementTree 30import xml.parsers.expat 31 32from aidegen import aidegen_main 33from aidegen import constant 34from aidegen.lib import clion_project_file_gen 35from aidegen.lib import common_util 36from aidegen.lib import errors 37from aidegen.lib import module_info_util 38from aidegen.lib import project_config 39from aidegen.lib import project_file_gen 40 41from atest import module_info 42 43_PRODUCT_DIR = '$PROJECT_DIR$' 44_ROOT_DIR = os.path.join(common_util.get_android_root_dir(), 45 'tools/asuite/aidegen_functional_test') 46_TEST_DATA_PATH = os.path.join(_ROOT_DIR, 'test_data') 47_VERIFY_COMMANDS_JSON = os.path.join(_TEST_DATA_PATH, 'verify_commands.json') 48_GOLDEN_SAMPLES_JSON = os.path.join(_TEST_DATA_PATH, 'golden_samples.json') 49_VERIFY_BINARY_JSON = os.path.join(_TEST_DATA_PATH, 'verify_binary_upload.json') 50_ANDROID_COMMON = 'android_common' 51_LINUX_GLIBC_COMMON = 'linux_glibc_common' 52_SRCS = 'srcs' 53_JARS = 'jars' 54_URL = 'url' 55_TEST_ERROR = 'AIDEGen functional test error: {}-{} is different.' 56_MSG_NOT_IN_PROJECT_FILE = ('{} is expected, but not found in the created ' 57 'project file: {}') 58_MSG_NOT_IN_SAMPLE_DATA = ('{} is unexpected, but found in the created project ' 59 'file: {}') 60_ALL_PASS = 'All tests passed!' 61_GIT_COMMIT_ID_JSON = os.path.join( 62 _TEST_DATA_PATH, 'baseline_code_commit_id.json') 63_GIT = 'git' 64_CHECKOUT = 'checkout' 65_BRANCH = 'branch' 66_COMMIT = 'commit' 67_LOG = 'log' 68_ALL = '--all' 69_COMMIT_ID_NOT_EXIST_ERROR = ('Commit ID: {} does not exist in path: {}. ' 70 'Please use "git log" command to check if it ' 71 'exists. If it does not, try to update your ' 72 'source files to the latest version or do not ' 73 'use "repo init --depth=1" command.') 74_GIT_LOG_ERROR = 'Command "git log -n 1" failed.' 75_BE_REPLACED = '${config.X86_64GccRoot}' 76_TO_REPLACE = 'prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9' 77 78 79def _parse_args(args): 80 """Parse command line arguments. 81 82 Args: 83 args: A list of arguments. 84 85 Returns: 86 An argparse.Namespace object holding parsed args. 87 """ 88 parser = argparse.ArgumentParser( 89 description=__doc__, 90 formatter_class=argparse.RawDescriptionHelpFormatter, 91 usage='aidegen_functional_test [-c | -u | -b | -a] -v -r') 92 group = parser.add_mutually_exclusive_group() 93 parser.required = False 94 parser.add_argument( 95 'targets', 96 type=str, 97 nargs='*', 98 default=[''], 99 help='Android module name or path.e.g. frameworks/base') 100 group.add_argument( 101 '-c', 102 '--create-sample', 103 action='store_true', 104 dest='create_sample', 105 help=('Create aidegen project files and write data to sample json file ' 106 'for aidegen_functional_test to compare.')) 107 parser.add_argument( 108 '-v', 109 '--verbose', 110 action='store_true', 111 help='Show DEBUG level logging.') 112 parser.add_argument( 113 '-r', 114 '--remove_bp_json', 115 action='store_true', 116 help='Remove module_bp_java_deps.json for each use case test.') 117 group.add_argument( 118 '-u', 119 '--use_cases', 120 action='store_true', 121 dest='use_cases_verified', 122 help='Verify various use cases of executing aidegen.') 123 group.add_argument( 124 '-b', 125 action='store_true', 126 dest='binary_upload_verified', 127 help=('Verify aidegen\'s use cases by executing different aidegen ' 128 'commands.')) 129 group.add_argument( 130 '-a', 131 '--test-all', 132 action='store_true', 133 dest='test_all_samples', 134 help='Test all modules listed in module-info.json.') 135 group.add_argument( 136 '-n', 137 '--compare-sample-native', 138 action='store_true', 139 dest='compare_sample_native', 140 help=('Compare if sample native project file is the same as generated ' 141 'by the build system.')) 142 return parser.parse_args(args) 143 144 145def _import_project_file_xml_etree(filename): 146 """Import iml project file and load its data into a dictionary. 147 148 Args: 149 filename: The input project file name. 150 151 Returns: 152 A dictionary contains dependent files' data of project file's contents. 153 The samples are like: 154 "srcs": [ 155 ... 156 "file://$PROJECT_DIR$/frameworks/base/cmds/am/src", 157 "file://$PROJECT_DIR$/frameworks/base/cmds/appwidget/src", 158 ... 159 ] 160 "jars": [ 161 ... 162 "jar://$PROJECT_DIR$/out/host/common/obj/**/classes-header.jar!/" 163 ... 164 ] 165 166 Raises: 167 EnvironmentError and xml parsing or format errors. 168 """ 169 data = {} 170 try: 171 tree = xml.etree.ElementTree.parse(filename) 172 data[_SRCS] = [] 173 root = tree.getroot() 174 for element in root.iter('sourceFolder'): 175 src = element.get(_URL).replace(common_util.get_android_root_dir(), 176 _PRODUCT_DIR) 177 data[_SRCS].append(src) 178 data[_JARS] = [] 179 for element in root.iter('root'): 180 jar = element.get(_URL).replace(common_util.get_android_root_dir(), 181 _PRODUCT_DIR) 182 data[_JARS].append(jar) 183 except (EnvironmentError, ValueError, LookupError, 184 xml.parsers.expat.ExpatError) as err: 185 print("{0}: import error: {1}".format(os.path.basename(filename), err)) 186 raise 187 return data 188 189 190def _get_project_file_names(abs_path): 191 """Get project file name and depenencies name by relative path. 192 193 Args: 194 abs_path: an absolute module's path. 195 196 Returns: 197 file_name: a string of the project file name. 198 dep_name: a string of the merged project and dependencies file's name, 199 e.g., frameworks-dependencies.iml. 200 """ 201 code_name = project_file_gen.ProjectFileGenerator.get_unique_iml_name( 202 abs_path) 203 file_name = ''.join([code_name, '.iml']) 204 dep_name = ''.join([constant.KEY_DEPENDENCIES, '.iml']) 205 return file_name, dep_name 206 207 208def _get_unique_module_name(rel_path, filename): 209 """Get a unique project file name or dependencies name by relative path. 210 211 Args: 212 rel_path: a relative module's path to aosp root path. 213 filename: the file name to be generated in module_in type file name. 214 215 Returns: 216 A string, the unique file name for the whole module-info.json. 217 """ 218 code_names = rel_path.split(os.sep) 219 code_names[-1] = filename 220 return '-'.join(code_names) 221 222 223def _get_git_current_commit_id(abs_path): 224 """Get target's git checkout command list. 225 226 When we run command 'git log -n 1' and get the top first git log record, the 227 commit id is next to the specific word 'commit'. 228 229 Args: 230 abs_path: a string of the absolute path of the target branch. 231 232 Return: 233 The current git commit id. 234 235 Raises: 236 Call subprocess.check_output cause subprocess.CalledProcessError. 237 """ 238 cwd = os.getcwd() 239 os.chdir(abs_path) 240 git_log_cmds = [_GIT, _LOG, '-n', '1'] 241 try: 242 out_put = subprocess.check_output(git_log_cmds).decode("utf-8") 243 except subprocess.CalledProcessError: 244 logging.error(_GIT_LOG_ERROR) 245 raise 246 finally: 247 os.chdir(cwd) 248 com_list = out_put.split() 249 return com_list[com_list.index(_COMMIT) + 1] 250 251 252def _get_commit_id_dictionary(): 253 """Get commit id from dictionary of key, value 'module': 'commit id'.""" 254 data_id_dict = {} 255 with open(_GIT_COMMIT_ID_JSON, 'r') as jsfile: 256 data_id_dict = json.load(jsfile) 257 return data_id_dict 258 259 260def _git_checkout_commit_id(abs_path, commit_id): 261 """Command to checkout specific commit id. 262 263 Change directory to the module's absolute path which users want to get its 264 specific commit id. 265 266 Args: 267 abs_path: the absolute path of the target branch. E.g., abs_path/.git 268 commit_id: the commit id users want to checkout. 269 270 Raises: 271 Call git checkout commit id failed, raise errors.CommitIDNotExistError. 272 """ 273 git_chekout_cmds = [_GIT, _CHECKOUT, commit_id] 274 cwd = os.getcwd() 275 try: 276 os.chdir(abs_path) 277 subprocess.check_output(git_chekout_cmds) 278 except subprocess.CalledProcessError: 279 err = _COMMIT_ID_NOT_EXIST_ERROR.format(commit_id, abs_path) 280 logging.error(err) 281 raise errors.CommitIDNotExistError(err) 282 finally: 283 os.chdir(cwd) 284 285 286def _git_checkout_target_commit_id(target, commit_id): 287 """Command to checkout target commit id. 288 289 Switch code base to specific commit id which is kept in data_id_dict with 290 target: commit_id as key: value. If the data is missing in data_id_dict, the 291 target isn't a selected golden sample raise error for it. 292 293 Args: 294 target: the string of target's module name or module path to checkout 295 the relevant git to its specific commit id. 296 commit_id: a string represent target's specific commit id. 297 298 Returns: 299 current_commit_id: the current commit id of the target which should be 300 switched back to. 301 """ 302 atest_module_info = module_info.ModuleInfo() 303 _, abs_path = common_util.get_related_paths(atest_module_info, target) 304 current_commit_id = _get_git_current_commit_id(abs_path) 305 _git_checkout_commit_id(abs_path, commit_id) 306 return current_commit_id 307 308 309def _checkout_baseline_code_to_spec_commit_id(): 310 """Get a dict of target, commit id listed in baseline_code_commit_id.json. 311 312 To make sure all samples run on the same environment, we need to keep all 313 the baseline code in a specific commit id. For example, all samples should 314 be created in the same specific commit id of the baseline code 315 'frameworks/base' for comparison except 'frameworks/base' itself. 316 317 Returns: 318 A dictionary contains target, specific and current commit id. 319 """ 320 spec_and_cur_commit_id_dict = {} 321 data_id_dict = _get_commit_id_dictionary() 322 for target in data_id_dict: 323 commit_id = data_id_dict.get(target, '') 324 current_commit_id = _git_checkout_target_commit_id(target, commit_id) 325 spec_and_cur_commit_id_dict[target] = {} 326 spec_and_cur_commit_id_dict[target]['current'] = current_commit_id 327 return spec_and_cur_commit_id_dict 328 329 330def _generate_target_real_iml_data(target): 331 """Generate single target's real iml file content's data. 332 333 Args: 334 target: Android module name or path to be create iml data. 335 336 Returns: 337 data: A dictionary contains key: unique file name and value: iml 338 content. 339 """ 340 data = {} 341 try: 342 aidegen_main.main([target, '-s', '-n', '-v']) 343 except (errors.FakeModuleError, 344 errors.ProjectOutsideAndroidRootError, 345 errors.ProjectPathNotExistError, 346 errors.NoModuleDefinedInModuleInfoError) as err: 347 logging.error(str(err)) 348 return data 349 350 atest_module_info = module_info.ModuleInfo() 351 rel_path, abs_path = common_util.get_related_paths(atest_module_info, 352 target) 353 for filename in iter(_get_project_file_names(abs_path)): 354 real_iml_file = os.path.join(abs_path, filename) 355 item_name = _get_unique_module_name(rel_path, filename) 356 data[item_name] = _import_project_file_xml_etree(real_iml_file) 357 return data 358 359 360def _generate_sample_json(test_list): 361 """Generate sample iml data. 362 363 We use all baseline code samples on the version of their own specific commit 364 id which is kept in _GIT_COMMIT_ID_JSON file. We need to switch back to 365 their current commit ids after generating golden samples' data. 366 367 Args: 368 test_list: a list of module name and module path. 369 Returns: 370 data: a dictionary contains dependent files' data of project file's 371 contents. 372 The sample is like: 373 "frameworks-base.iml": { 374 "srcs": [ 375 .... 376 "file://$PROJECT_DIR$/frameworks/base/cmds/am/src", 377 "file://$PROJECT_DIR$/frameworks/base/cmds/appwidget/src", 378 .... 379 ], 380 "jars": [ 381 .... 382 "jar://$PROJECT_DIR$/out/target/common/**/aapt2.srcjar!/", 383 .... 384 ] 385 } 386 """ 387 _make_clean() 388 data = {} 389 spec_and_cur_commit_id_dict = _checkout_baseline_code_to_spec_commit_id() 390 for target in test_list: 391 data.update(_generate_target_real_iml_data(target)) 392 atest_module_info = module_info.ModuleInfo() 393 for target in spec_and_cur_commit_id_dict: 394 _, abs_path = common_util.get_related_paths(atest_module_info, target) 395 _git_checkout_commit_id( 396 abs_path, spec_and_cur_commit_id_dict[target]['current']) 397 return data 398 399 400def _create_some_sample_json_file(targets): 401 """Write some samples' iml data into a json file. 402 403 Args: 404 targets: Android module name or path to be create iml data. 405 406 linked_function: _generate_sample_json() 407 """ 408 data = _generate_sample_json(targets) 409 data_sample = {} 410 with open(_GOLDEN_SAMPLES_JSON, 'r') as infile: 411 try: 412 data_sample = json.load(infile) 413 except json.JSONDecodeError as err: 414 print("Json decode error: {}".format(err)) 415 data_sample = {} 416 data_sample.update(data) 417 with open(_GOLDEN_SAMPLES_JSON, 'w') as outfile: 418 json.dump(data_sample, outfile, indent=4, sort_keys=False) 419 420 421def test_samples(func): 422 """Decorate a function to deal with preparing and verifying staffs of it. 423 424 Args: 425 func: a function is to be compared its iml data with the json file's 426 data. 427 428 Returns: 429 The wrapper function. 430 """ 431 432 @functools.wraps(func) 433 def wrapper(*args, **kwargs): 434 """A wrapper function.""" 435 436 test_successful = True 437 with open(_GOLDEN_SAMPLES_JSON, 'r') as outfile: 438 data_sample = json.load(outfile) 439 440 data_real = func(*args, **kwargs) 441 442 for name in data_real: 443 for item in [_SRCS, _JARS]: 444 s_items = data_sample[name][item] 445 r_items = data_real[name][item] 446 if set(s_items) != set(r_items): 447 diff_iter = _compare_content(name, item, s_items, r_items) 448 if diff_iter: 449 print('\n{} {}'.format( 450 common_util.COLORED_INFO('Test error:'), 451 _TEST_ERROR.format(name, item))) 452 print('{} {} contents are different:'.format( 453 name, item)) 454 for diff in diff_iter: 455 print(diff) 456 test_successful = False 457 if test_successful: 458 print(common_util.COLORED_PASS(_ALL_PASS)) 459 return test_successful 460 461 return wrapper 462 463 464@test_samples 465def _test_some_sample_iml(targets=None): 466 """Compare with sample iml's data to assure the project's contents is right. 467 468 Args: 469 targets: Android module name or path to be create iml data. 470 """ 471 if targets: 472 return _generate_sample_json(targets) 473 return _generate_sample_json(_get_commit_id_dictionary().keys()) 474 475 476@test_samples 477def _test_all_samples_iml(): 478 """Compare all imls' data with all samples' data. 479 480 It's to make sure each iml's contents is right. The function is implemented 481 but hasn't been used yet. 482 """ 483 all_module_list = module_info.ModuleInfo().name_to_module_info.keys() 484 return _generate_sample_json(all_module_list) 485 486 487def _compare_content(module_name, item_type, s_items, r_items): 488 """Compare src or jar files' data of two dictionaries. 489 490 Args: 491 module_name: the test module name. 492 item_type: the type is src or jar. 493 s_items: sample jars' items. 494 r_items: real jars' items. 495 496 Returns: 497 An iterator of not equal sentences after comparison. 498 """ 499 if item_type == _SRCS: 500 cmp_iter1 = _compare_srcs_content(module_name, s_items, r_items, 501 _MSG_NOT_IN_PROJECT_FILE) 502 cmp_iter2 = _compare_srcs_content(module_name, r_items, s_items, 503 _MSG_NOT_IN_SAMPLE_DATA) 504 else: 505 cmp_iter1 = _compare_jars_content(module_name, s_items, r_items, 506 _MSG_NOT_IN_PROJECT_FILE) 507 cmp_iter2 = _compare_jars_content(module_name, r_items, s_items, 508 _MSG_NOT_IN_SAMPLE_DATA) 509 return itertools.chain(cmp_iter1, cmp_iter2) 510 511 512def _compare_srcs_content(module_name, s_items, r_items, msg): 513 """Compare src or jar files' data of two dictionaries. 514 515 Args: 516 module_name: the test module name. 517 s_items: sample jars' items. 518 r_items: real jars' items. 519 msg: the message will be written into log file. 520 521 Returns: 522 An iterator of not equal sentences after comparison. 523 """ 524 for sample in s_items: 525 if sample not in r_items: 526 yield msg.format(sample, module_name) 527 528 529def _compare_jars_content(module_name, s_items, r_items, msg): 530 """Compare src or jar files' data of two dictionaries. 531 532 AIDEGen treats the jars in folder names 'linux_glib_common' and 533 'android_common' as the same content. If the paths are different only 534 because of these two names, we ignore it. 535 536 Args: 537 module_name: the test module name. 538 s_items: sample jars' items. 539 r_items: real jars' items. 540 msg: the message will be written into log file. 541 542 Returns: 543 An iterator of not equal sentences after comparison. 544 """ 545 for sample in s_items: 546 if sample not in r_items: 547 lnew = sample 548 if constant.LINUX_GLIBC_COMMON in sample: 549 lnew = sample.replace(constant.LINUX_GLIBC_COMMON, 550 constant.ANDROID_COMMON) 551 else: 552 lnew = sample.replace(constant.ANDROID_COMMON, 553 constant.LINUX_GLIBC_COMMON) 554 if not lnew in r_items: 555 yield msg.format(sample, module_name) 556 557 558# pylint: disable=broad-except 559# pylint: disable=eval-used 560@common_util.back_to_cwd 561@common_util.time_logged 562def _verify_aidegen(verified_file_path, forced_remove_bp_json): 563 """Verify various use cases of executing aidegen. 564 565 There are two types of running commands: 566 1. Use 'eval' to run the commands for present codes in aidegen_main.py, 567 such as: 568 aidegen_main.main(['tradefed', '-n', '-v']) 569 2. Use 'subprocess.check_call' to run the commands for the binary codes of 570 aidegen such as: 571 aidegen tradefed -n -v 572 573 Remove module_bp_java_deps.json in the beginning of running use cases. If 574 users need to remove module_bp_java_deps.json between each use case they 575 can set forced_remove_bp_json true. 576 577 Args: 578 verified_file_path: The json file path to be verified. 579 forced_remove_bp_json: Remove module_bp_java_deps.json for each use case 580 test. 581 582 Raises: 583 There are two type of exceptions: 584 1. aidegen.lib.errors for projects' or modules' issues such as, 585 ProjectPathNotExistError. 586 2. Any exceptions other than aidegen.lib.errors such as, 587 subprocess.CalledProcessError. 588 """ 589 bp_json_path = common_util.get_blueprint_json_path( 590 constant.BLUEPRINT_JAVA_JSONFILE_NAME) 591 use_eval = (verified_file_path == _VERIFY_COMMANDS_JSON) 592 try: 593 with open(verified_file_path, 'r') as jsfile: 594 data = json.load(jsfile) 595 except IOError as err: 596 raise errors.JsonFileNotExistError( 597 '%s does not exist, error: %s.' % (verified_file_path, err)) 598 599 _make_clean() 600 601 _compare_sample_native_content() 602 os.chdir(common_util.get_android_root_dir()) 603 for use_case in data: 604 print('Use case "{}" is running.'.format(use_case)) 605 if forced_remove_bp_json and os.path.exists(bp_json_path): 606 os.remove(bp_json_path) 607 for cmd in data[use_case]: 608 print('Command "{}" is running.'.format(cmd)) 609 try: 610 if use_eval: 611 eval(cmd) 612 else: 613 subprocess.check_call(cmd, shell=True) 614 except (errors.ProjectOutsideAndroidRootError, 615 errors.ProjectPathNotExistError, 616 errors.NoModuleDefinedInModuleInfoError, 617 errors.IDENotExistError) as err: 618 print('"{}" raises error: {}.'.format(use_case, err)) 619 continue 620 except BaseException: 621 exc_type, _, _ = sys.exc_info() 622 print('"{}.{}" command {}.'.format( 623 use_case, cmd, common_util.COLORED_FAIL('executes failed'))) 624 raise BaseException( 625 'Unexpected command "{}" exception: {}.'.format( 626 use_case, exc_type)) 627 print('"{}" command {}!'.format( 628 use_case, common_util.COLORED_PASS('test passed'))) 629 print(common_util.COLORED_PASS(_ALL_PASS)) 630 631 632@common_util.back_to_cwd 633def _make_clean(): 634 """Make a command to clean out folder for a pure environment to test. 635 636 Raises: 637 Call subprocess.check_call to execute 638 'build/soong/soong_ui.bash --make-mode clean' and cause 639 subprocess.CalledProcessError. 640 """ 641 try: 642 os.chdir(common_util.get_android_root_dir()) 643 subprocess.check_call( 644 ['build/soong/soong_ui.bash --make-mode clean', '-j'], 645 shell=True) 646 except subprocess.CalledProcessError: 647 print('"build/soong/soong_ui.bash --make-mode clean" command failed.') 648 raise 649 650 651def _read_file_content(path): 652 """Read file's content. 653 654 Args: 655 path: Path of input file. 656 657 Returns: 658 A list of content strings. 659 """ 660 with open(path, encoding='utf8') as template: 661 contents = [] 662 for cnt in template: 663 if cnt.startswith('#'): 664 continue 665 contents.append(cnt.rstrip()) 666 return contents 667 668 669# pylint: disable=protected-access 670def _compare_sample_native_content(): 671 """Compares 'libui' sample module's project file. 672 673 Compares 'libui' sample module's project file generated by AIDEGen with that 674 generated by the soong build system. Check if their contents are the same. 675 There should be only one different: 676 ${config.X86_64GccRoot} # in the soong build sytem 677 becomes 678 prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9 # in AIDEGen 679 """ 680 target_arch_variant = 'x86_64' 681 env_on = { 682 'TARGET_PRODUCT': 'aosp_x86_64', 683 'TARGET_BUILD_VARIANT': 'eng', 684 'TARGET_ARCH_VARIANT': target_arch_variant, 685 'SOONG_COLLECT_JAVA_DEPS': 'true', 686 'SOONG_GEN_CMAKEFILES': '1', 687 'SOONG_COLLECT_CC_DEPS': '1' 688 } 689 690 try: 691 project_config.ProjectConfig( 692 aidegen_main._parse_args(['-n', '-v'])).init_environment() 693 module_info_util.generate_merged_module_info(env_on) 694 cc_path = os.path.join(common_util.get_soong_out_path(), 695 constant.BLUEPRINT_CC_JSONFILE_NAME) 696 mod_name = 'libui' 697 mod_info = common_util.get_json_dict(cc_path)['modules'][mod_name] 698 if mod_info: 699 clion_project_file_gen.CLionProjectFileGenerator( 700 mod_info).generate_cmakelists_file() 701 out_dir = os.path.join(common_util.get_android_root_dir(), 702 common_util.get_android_out_dir(), 703 constant.RELATIVE_NATIVE_PATH, 704 mod_info['path'][0]) 705 content1 = _read_file_content(os.path.join( 706 out_dir, mod_name, constant.CLION_PROJECT_FILE_NAME)) 707 cc_file_name = ''.join( 708 [mod_name, '-', target_arch_variant, '-android']) 709 cc_file_path = os.path.join( 710 out_dir, cc_file_name, constant.CLION_PROJECT_FILE_NAME) 711 content2 = _read_file_content(cc_file_path) 712 same = True 713 for lino, (cnt1, cnt2) in enumerate( 714 zip(content1, content2), start=1): 715 if _BE_REPLACED in cnt2: 716 cnt2 = cnt2.replace(_BE_REPLACED, _TO_REPLACE) 717 if cnt1 != cnt2: 718 print('Contents {} and {} are different in line:{}.'.format( 719 cnt1, cnt2, lino)) 720 same = False 721 if same: 722 print('Files {} and {} are the same.'.format( 723 mod_name, cc_file_name)) 724 except errors.BuildFailureError: 725 print('Compare native content failed.') 726 727 728def main(argv): 729 """Main entry. 730 731 1. Create the iml file data of each module in module-info.json and write it 732 into single_module.json. 733 2. Verify every use case of AIDEGen. 734 3. Compare all or some iml project files' data to the data recorded in 735 single_module.json. 736 737 Args: 738 argv: A list of system arguments. 739 """ 740 args = _parse_args(argv) 741 common_util.configure_logging(args.verbose) 742 os.environ[constant.AIDEGEN_TEST_MODE] = 'true' 743 if args.create_sample: 744 _create_some_sample_json_file(args.targets) 745 elif args.use_cases_verified: 746 _verify_aidegen(_VERIFY_COMMANDS_JSON, args.remove_bp_json) 747 elif args.binary_upload_verified: 748 _verify_aidegen(_VERIFY_BINARY_JSON, args.remove_bp_json) 749 elif args.test_all_samples: 750 _test_all_samples_iml() 751 elif args.compare_sample_native: 752 _compare_sample_native_content() 753 else: 754 if not args.targets[0]: 755 _test_some_sample_iml() 756 else: 757 _test_some_sample_iml(args.targets) 758 del os.environ[constant.AIDEGEN_TEST_MODE] 759 760 761if __name__ == '__main__': 762 main(sys.argv[1:]) 763