13af6ab5fSopenharmony_ci#!/usr/bin/env python3
23af6ab5fSopenharmony_ci# coding: utf-8
33af6ab5fSopenharmony_ci
43af6ab5fSopenharmony_ci"""
53af6ab5fSopenharmony_ciCopyright (c) 2021 Huawei Device Co., Ltd.
63af6ab5fSopenharmony_ciLicensed under the Apache License, Version 2.0 (the "License");
73af6ab5fSopenharmony_ciyou may not use this file except in compliance with the License.
83af6ab5fSopenharmony_ciYou may obtain a copy of the License at
93af6ab5fSopenharmony_ci
103af6ab5fSopenharmony_ci    http://www.apache.org/licenses/LICENSE-2.0
113af6ab5fSopenharmony_ci
123af6ab5fSopenharmony_ciUnless required by applicable law or agreed to in writing, software
133af6ab5fSopenharmony_cidistributed under the License is distributed on an "AS IS" BASIS,
143af6ab5fSopenharmony_ciWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
153af6ab5fSopenharmony_ciSee the License for the specific language governing permissions and
163af6ab5fSopenharmony_cilimitations under the License.
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ciDescription: process options and configs for test suite
193af6ab5fSopenharmony_ci"""
203af6ab5fSopenharmony_ci
213af6ab5fSopenharmony_ciimport argparse
223af6ab5fSopenharmony_ciimport logging
233af6ab5fSopenharmony_ciimport os
243af6ab5fSopenharmony_cifrom enum import Enum
253af6ab5fSopenharmony_ci
263af6ab5fSopenharmony_ciimport yaml
273af6ab5fSopenharmony_ciimport json5
283af6ab5fSopenharmony_ci
293af6ab5fSopenharmony_ciimport utils
303af6ab5fSopenharmony_ci
313af6ab5fSopenharmony_ci
323af6ab5fSopenharmony_ciarguments = {}
333af6ab5fSopenharmony_ciconfigs = {}
343af6ab5fSopenharmony_ci
353af6ab5fSopenharmony_ci
363af6ab5fSopenharmony_ciclass TaskResult(Enum):
373af6ab5fSopenharmony_ci    undefined = 0
383af6ab5fSopenharmony_ci    passed = 1
393af6ab5fSopenharmony_ci    failed = 2
403af6ab5fSopenharmony_ci
413af6ab5fSopenharmony_ci
423af6ab5fSopenharmony_ciclass OutputType(Enum):
433af6ab5fSopenharmony_ci    unsigned = 0
443af6ab5fSopenharmony_ci    signed = 1
453af6ab5fSopenharmony_ci    har = 2
463af6ab5fSopenharmony_ci
473af6ab5fSopenharmony_ci
483af6ab5fSopenharmony_ciclass CompilationInfo:
493af6ab5fSopenharmony_ci    def __init__(self):
503af6ab5fSopenharmony_ci        self.result = TaskResult.undefined
513af6ab5fSopenharmony_ci        self.runtime_result = TaskResult.undefined
523af6ab5fSopenharmony_ci        self.error_message = ''
533af6ab5fSopenharmony_ci        self.time = 0
543af6ab5fSopenharmony_ci        self.abc_size = 0
553af6ab5fSopenharmony_ci
563af6ab5fSopenharmony_ci
573af6ab5fSopenharmony_ciclass FullCompilationInfo:
583af6ab5fSopenharmony_ci    def __init__(self):
593af6ab5fSopenharmony_ci        self.debug_info = CompilationInfo()
603af6ab5fSopenharmony_ci        self.release_info = CompilationInfo()
613af6ab5fSopenharmony_ci        self.name = ''
623af6ab5fSopenharmony_ci
633af6ab5fSopenharmony_ci
643af6ab5fSopenharmony_ciclass IncCompilationInfo:
653af6ab5fSopenharmony_ci    def __init__(self):
663af6ab5fSopenharmony_ci        self.debug_info = CompilationInfo()
673af6ab5fSopenharmony_ci        self.release_info = CompilationInfo()
683af6ab5fSopenharmony_ci        self.name = ''
693af6ab5fSopenharmony_ci
703af6ab5fSopenharmony_ci
713af6ab5fSopenharmony_ciclass BytecodeHarCompilationInfo:
723af6ab5fSopenharmony_ci    def __init__(self):
733af6ab5fSopenharmony_ci        self.debug_info = CompilationInfo()
743af6ab5fSopenharmony_ci        self.release_info = CompilationInfo()
753af6ab5fSopenharmony_ci        self.name = ''
763af6ab5fSopenharmony_ci
773af6ab5fSopenharmony_ci
783af6ab5fSopenharmony_ciclass ExternalCompilationInfo:
793af6ab5fSopenharmony_ci    def __init__(self):
803af6ab5fSopenharmony_ci        self.debug_info = CompilationInfo()
813af6ab5fSopenharmony_ci        self.release_info = CompilationInfo()
823af6ab5fSopenharmony_ci        self.name = ''
833af6ab5fSopenharmony_ci
843af6ab5fSopenharmony_ci
853af6ab5fSopenharmony_ciclass BackupInfo:
863af6ab5fSopenharmony_ci    def __init__(self):
873af6ab5fSopenharmony_ci        self.cache_path = ''
883af6ab5fSopenharmony_ci        self.cache_debug = ''
893af6ab5fSopenharmony_ci        self.preview_cache_debug = ''
903af6ab5fSopenharmony_ci        self.hsp_signed_output_debug = ''
913af6ab5fSopenharmony_ci        self.cache_release = ''
923af6ab5fSopenharmony_ci        self.preview_cache_release = ''
933af6ab5fSopenharmony_ci        self.hsp_signed_output_release = ''
943af6ab5fSopenharmony_ci        self.output_debug = []
953af6ab5fSopenharmony_ci        self.output_release = []
963af6ab5fSopenharmony_ci
973af6ab5fSopenharmony_ci
983af6ab5fSopenharmony_ciclass TestTask:
993af6ab5fSopenharmony_ci    def __init__(self):
1003af6ab5fSopenharmony_ci        self.name = ''
1013af6ab5fSopenharmony_ci        self.path = ''
1023af6ab5fSopenharmony_ci        self.bundle_name = ''
1033af6ab5fSopenharmony_ci        self.ability_name = ''
1043af6ab5fSopenharmony_ci        self.type = ''
1053af6ab5fSopenharmony_ci        self.build_path = []
1063af6ab5fSopenharmony_ci        self.output_hap_path = ''
1073af6ab5fSopenharmony_ci        self.output_hap_path_signed = ''
1083af6ab5fSopenharmony_ci        self.output_app_path = ''
1093af6ab5fSopenharmony_ci        self.inc_modify_file = []
1103af6ab5fSopenharmony_ci
1113af6ab5fSopenharmony_ci        self.full_compilation_info = {}
1123af6ab5fSopenharmony_ci        self.incre_compilation_info = {}
1133af6ab5fSopenharmony_ci        self.bytecode_har_compilation_info = {}
1143af6ab5fSopenharmony_ci        self.external_compilation_info = {}
1153af6ab5fSopenharmony_ci        self.preview_compilation_info = {}
1163af6ab5fSopenharmony_ci        self.other_tests = {}
1173af6ab5fSopenharmony_ci
1183af6ab5fSopenharmony_ci        self.backup_info = BackupInfo()
1193af6ab5fSopenharmony_ci
1203af6ab5fSopenharmony_ci
1213af6ab5fSopenharmony_cidef parse_args():
1223af6ab5fSopenharmony_ci    parser = argparse.ArgumentParser()
1233af6ab5fSopenharmony_ci    parser.add_argument('--sdkPath', type=str, dest='sdk_path', default='',
1243af6ab5fSopenharmony_ci                        help='specify sdk path if need to update sdk. Default to use sdk specify in config.yaml')
1253af6ab5fSopenharmony_ci    parser.add_argument('--buildMode', type=str, dest='build_mode', default='all',
1263af6ab5fSopenharmony_ci                        choices=['all', 'assemble', 'preview', 'hotreload', 'hotfix'],
1273af6ab5fSopenharmony_ci                        help='specify build mode')
1283af6ab5fSopenharmony_ci    parser.add_argument('--hapMode', type=str, dest='hap_mode', default='all',
1293af6ab5fSopenharmony_ci                        choices=['all', 'debug', 'release'],
1303af6ab5fSopenharmony_ci                        help='specify hap mode')
1313af6ab5fSopenharmony_ci    parser.add_argument('--compileMode', type=str, dest='compile_mode', default='all',
1323af6ab5fSopenharmony_ci                        choices=['all', 'full', 'incremental', 'bytecode_har', 'external'],
1333af6ab5fSopenharmony_ci                        help='specify compile mode')
1343af6ab5fSopenharmony_ci    parser.add_argument('--testCase', type=str, dest='test_case', default='all',
1353af6ab5fSopenharmony_ci                        choices=['all', 'fa', 'stage', 'compatible8', 'js'],
1363af6ab5fSopenharmony_ci                        help='specify test cases')
1373af6ab5fSopenharmony_ci    parser.add_argument('--testHap', type=str, dest='test_hap', default='all',
1383af6ab5fSopenharmony_ci                        help="specify test haps, option can be 'all' or a list of haps seperated by ','")
1393af6ab5fSopenharmony_ci    parser.add_argument('--imagePath', type=str, dest='image_path', default='',
1403af6ab5fSopenharmony_ci                        help='specify image path if need to update rk/phone images. Default not to update image')
1413af6ab5fSopenharmony_ci    parser.add_argument('--runHaps', dest='run_haps', action='store_true', default=False,
1423af6ab5fSopenharmony_ci                        help='specify whether to verify by running the haps on board.')
1433af6ab5fSopenharmony_ci    parser.add_argument('--logLevel', type=str, dest='log_level', default='error',
1443af6ab5fSopenharmony_ci                        choices=['debug', 'info', 'warn', 'error'],
1453af6ab5fSopenharmony_ci                        help='specify log level of test suite')
1463af6ab5fSopenharmony_ci    parser.add_argument('--logFile', type=str, dest='log_file', default='',
1473af6ab5fSopenharmony_ci                        help='specify the file log outputs to, empty string will output to console')
1483af6ab5fSopenharmony_ci    parser.add_argument('--compileTimeout', type=int, dest='compile_timeout', default=1800,
1493af6ab5fSopenharmony_ci                        help='specify deveco compilation timeout')
1503af6ab5fSopenharmony_ci    global arguments
1513af6ab5fSopenharmony_ci    arguments = parser.parse_args()
1523af6ab5fSopenharmony_ci
1533af6ab5fSopenharmony_ci
1543af6ab5fSopenharmony_cidef parse_configs():
1553af6ab5fSopenharmony_ci    config_yaml = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config.yaml')
1563af6ab5fSopenharmony_ci    with open(config_yaml, 'r') as config_file:
1573af6ab5fSopenharmony_ci        global configs
1583af6ab5fSopenharmony_ci        configs = yaml.safe_load(config_file)
1593af6ab5fSopenharmony_ci
1603af6ab5fSopenharmony_ci
1613af6ab5fSopenharmony_cidef get_sdk_path_in_the_project(task_path):
1623af6ab5fSopenharmony_ci    profile_file = os.path.join(task_path, 'build-profile.json5')
1633af6ab5fSopenharmony_ci    with open(profile_file, 'r', encoding='utf-8') as file:
1643af6ab5fSopenharmony_ci        profile_data = json5.load(file)
1653af6ab5fSopenharmony_ci        api_version = profile_data['app']['products'][0]['compatibleSdkVersion']
1663af6ab5fSopenharmony_ci        if isinstance(api_version, int):
1673af6ab5fSopenharmony_ci            openharmony_sdk_path = configs.get('deveco_openharmony_sdk_path')
1683af6ab5fSopenharmony_ci            return os.path.join(openharmony_sdk_path, str(api_version))
1693af6ab5fSopenharmony_ci        else:
1703af6ab5fSopenharmony_ci            harmonyos_sdk_path = configs.get('deveco_harmonyos_sdk_path')
1713af6ab5fSopenharmony_ci            api_version_file_map = configs.get('api_version_file_name_map')
1723af6ab5fSopenharmony_ci            file_name = api_version_file_map.get(api_version)
1733af6ab5fSopenharmony_ci            return os.path.join(harmonyos_sdk_path, file_name, 'openharmony')
1743af6ab5fSopenharmony_ci
1753af6ab5fSopenharmony_ci
1763af6ab5fSopenharmony_cidef get_ark_disasm_path(task_path):
1773af6ab5fSopenharmony_ci    ark_disasm = 'ark_disasm.exe' if utils.is_windows() else 'ark_disasm'
1783af6ab5fSopenharmony_ci    sdk_path = get_sdk_path_in_the_project(task_path)
1793af6ab5fSopenharmony_ci    return os.path.join(sdk_path, 'toolchains', ark_disasm)
1803af6ab5fSopenharmony_ci
1813af6ab5fSopenharmony_ci
1823af6ab5fSopenharmony_cidef create_test_tasks(haps_list):
1833af6ab5fSopenharmony_ci    task_list = []
1843af6ab5fSopenharmony_ci    test_cases = 'all' if arguments.test_case == 'all' else []
1853af6ab5fSopenharmony_ci    test_haps = 'all' if arguments.test_hap == 'all' else []
1863af6ab5fSopenharmony_ci    if test_cases != 'all':
1873af6ab5fSopenharmony_ci        test_cases = arguments.test_case.split(',')
1883af6ab5fSopenharmony_ci    if test_haps != 'all':
1893af6ab5fSopenharmony_ci        test_haps = arguments.test_hap.split(',')
1903af6ab5fSopenharmony_ci
1913af6ab5fSopenharmony_ci    for hap in haps_list:
1923af6ab5fSopenharmony_ci        if test_cases == 'all' or test_haps == 'all' \
1933af6ab5fSopenharmony_ci           or (test_cases and (hap['type'][0] in test_cases)) \
1943af6ab5fSopenharmony_ci           or (test_haps and (hap['name'] in test_haps)):
1953af6ab5fSopenharmony_ci            if not os.path.exists(hap['path']):
1963af6ab5fSopenharmony_ci                logging.warning("Path of hap %s dosen't exist: %s", hap['name'], hap['path'])
1973af6ab5fSopenharmony_ci                continue
1983af6ab5fSopenharmony_ci            task = TestTask()
1993af6ab5fSopenharmony_ci            task.name = hap['name']
2003af6ab5fSopenharmony_ci            task.path = hap['path']
2013af6ab5fSopenharmony_ci            task.bundle_name = hap['bundle_name']
2023af6ab5fSopenharmony_ci            task.ability_name = hap['ability_name']
2033af6ab5fSopenharmony_ci            task.type = hap['type']
2043af6ab5fSopenharmony_ci            task.hap_module = hap['hap_module']
2053af6ab5fSopenharmony_ci            task.hap_module_path = hap['hap_module_path']
2063af6ab5fSopenharmony_ci            # If it is not a stage model, this HSP module cannot be created.
2073af6ab5fSopenharmony_ci            task.hsp_module = hap.get('hsp_module', '')
2083af6ab5fSopenharmony_ci            task.hsp_module_path = hap.get('hsp_module_path', '')
2093af6ab5fSopenharmony_ci            task.cpp_module = hap['cpp_module']
2103af6ab5fSopenharmony_ci            task.cpp_module_path = hap['cpp_module_path']
2113af6ab5fSopenharmony_ci            task.har_module = hap['har_module']
2123af6ab5fSopenharmony_ci            task.har_module_path = hap['har_module_path']
2133af6ab5fSopenharmony_ci            task.build_path = hap['build_path']
2143af6ab5fSopenharmony_ci            task.preview_path = hap['preview_path']
2153af6ab5fSopenharmony_ci            task.cache_path = hap['cache_path']
2163af6ab5fSopenharmony_ci            task.preview_cache_path = hap['preview_cache_path']
2173af6ab5fSopenharmony_ci            task.hap_output_path = hap['hap_output_path']
2183af6ab5fSopenharmony_ci            task.hap_output_path_signed = hap['hap_output_path_signed']
2193af6ab5fSopenharmony_ci            task.har_output_path_har = hap['har_output_path_har']
2203af6ab5fSopenharmony_ci            task.hsp_output_path = hap.get('hsp_output_path', '')
2213af6ab5fSopenharmony_ci            task.hsp_output_path_signed = hap.get('hsp_output_path_signed', '')
2223af6ab5fSopenharmony_ci            task.hsp_output_path_har = hap.get('hsp_output_path_har', '')
2233af6ab5fSopenharmony_ci            task.cpp_output_path = hap.get('cpp_output_path')
2243af6ab5fSopenharmony_ci            task.cpp_output_path_signed = hap.get('cpp_output_path_signed')
2253af6ab5fSopenharmony_ci            task.main_pages_json_path = hap['main_pages_json_path']
2263af6ab5fSopenharmony_ci            task.inc_modify_file = hap['inc_modify_file']
2273af6ab5fSopenharmony_ci            task.har_modify_file = hap['har_modify_file']
2283af6ab5fSopenharmony_ci            task.hsp_modify_file = hap.get('hsp_modify_file', '')
2293af6ab5fSopenharmony_ci            task.cpp_modify_file = hap['cpp_modify_file']
2303af6ab5fSopenharmony_ci            task.backup_info.cache_path = os.path.join(task.path, 'test_suite_cache')
2313af6ab5fSopenharmony_ci            task.ark_disasm_path = get_ark_disasm_path(task.path)
2323af6ab5fSopenharmony_ci
2333af6ab5fSopenharmony_ci            task_list.append(task)
2343af6ab5fSopenharmony_ci
2353af6ab5fSopenharmony_ci    return task_list
2363af6ab5fSopenharmony_ci
2373af6ab5fSopenharmony_ci
2383af6ab5fSopenharmony_cidef process_options():
2393af6ab5fSopenharmony_ci    parse_args()
2403af6ab5fSopenharmony_ci    utils.init_logger(arguments.log_level, arguments.log_file)
2413af6ab5fSopenharmony_ci    parse_configs()
2423af6ab5fSopenharmony_ci    return create_test_tasks(configs.get('haps'))