1#!/usr/bin/env python3
2# coding: utf-8
3
4"""
5Copyright (c) 2021 Huawei Device Co., Ltd.
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17
18Description: process options and configs for test suite
19"""
20
21import argparse
22import logging
23import os
24from enum import Enum
25
26import yaml
27import json5
28
29import utils
30
31
32arguments = {}
33configs = {}
34
35
36class TaskResult(Enum):
37    undefined = 0
38    passed = 1
39    failed = 2
40
41
42class OutputType(Enum):
43    unsigned = 0
44    signed = 1
45    har = 2
46
47
48class CompilationInfo:
49    def __init__(self):
50        self.result = TaskResult.undefined
51        self.runtime_result = TaskResult.undefined
52        self.error_message = ''
53        self.time = 0
54        self.abc_size = 0
55
56
57class FullCompilationInfo:
58    def __init__(self):
59        self.debug_info = CompilationInfo()
60        self.release_info = CompilationInfo()
61        self.name = ''
62
63
64class IncCompilationInfo:
65    def __init__(self):
66        self.debug_info = CompilationInfo()
67        self.release_info = CompilationInfo()
68        self.name = ''
69
70
71class BytecodeHarCompilationInfo:
72    def __init__(self):
73        self.debug_info = CompilationInfo()
74        self.release_info = CompilationInfo()
75        self.name = ''
76
77
78class ExternalCompilationInfo:
79    def __init__(self):
80        self.debug_info = CompilationInfo()
81        self.release_info = CompilationInfo()
82        self.name = ''
83
84
85class BackupInfo:
86    def __init__(self):
87        self.cache_path = ''
88        self.cache_debug = ''
89        self.preview_cache_debug = ''
90        self.hsp_signed_output_debug = ''
91        self.cache_release = ''
92        self.preview_cache_release = ''
93        self.hsp_signed_output_release = ''
94        self.output_debug = []
95        self.output_release = []
96
97
98class TestTask:
99    def __init__(self):
100        self.name = ''
101        self.path = ''
102        self.bundle_name = ''
103        self.ability_name = ''
104        self.type = ''
105        self.build_path = []
106        self.output_hap_path = ''
107        self.output_hap_path_signed = ''
108        self.output_app_path = ''
109        self.inc_modify_file = []
110
111        self.full_compilation_info = {}
112        self.incre_compilation_info = {}
113        self.bytecode_har_compilation_info = {}
114        self.external_compilation_info = {}
115        self.preview_compilation_info = {}
116        self.other_tests = {}
117
118        self.backup_info = BackupInfo()
119
120
121def parse_args():
122    parser = argparse.ArgumentParser()
123    parser.add_argument('--sdkPath', type=str, dest='sdk_path', default='',
124                        help='specify sdk path if need to update sdk. Default to use sdk specify in config.yaml')
125    parser.add_argument('--buildMode', type=str, dest='build_mode', default='all',
126                        choices=['all', 'assemble', 'preview', 'hotreload', 'hotfix'],
127                        help='specify build mode')
128    parser.add_argument('--hapMode', type=str, dest='hap_mode', default='all',
129                        choices=['all', 'debug', 'release'],
130                        help='specify hap mode')
131    parser.add_argument('--compileMode', type=str, dest='compile_mode', default='all',
132                        choices=['all', 'full', 'incremental', 'bytecode_har', 'external'],
133                        help='specify compile mode')
134    parser.add_argument('--testCase', type=str, dest='test_case', default='all',
135                        choices=['all', 'fa', 'stage', 'compatible8', 'js'],
136                        help='specify test cases')
137    parser.add_argument('--testHap', type=str, dest='test_hap', default='all',
138                        help="specify test haps, option can be 'all' or a list of haps seperated by ','")
139    parser.add_argument('--imagePath', type=str, dest='image_path', default='',
140                        help='specify image path if need to update rk/phone images. Default not to update image')
141    parser.add_argument('--runHaps', dest='run_haps', action='store_true', default=False,
142                        help='specify whether to verify by running the haps on board.')
143    parser.add_argument('--logLevel', type=str, dest='log_level', default='error',
144                        choices=['debug', 'info', 'warn', 'error'],
145                        help='specify log level of test suite')
146    parser.add_argument('--logFile', type=str, dest='log_file', default='',
147                        help='specify the file log outputs to, empty string will output to console')
148    parser.add_argument('--compileTimeout', type=int, dest='compile_timeout', default=1800,
149                        help='specify deveco compilation timeout')
150    global arguments
151    arguments = parser.parse_args()
152
153
154def parse_configs():
155    config_yaml = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config.yaml')
156    with open(config_yaml, 'r') as config_file:
157        global configs
158        configs = yaml.safe_load(config_file)
159
160
161def get_sdk_path_in_the_project(task_path):
162    profile_file = os.path.join(task_path, 'build-profile.json5')
163    with open(profile_file, 'r', encoding='utf-8') as file:
164        profile_data = json5.load(file)
165        api_version = profile_data['app']['products'][0]['compatibleSdkVersion']
166        if isinstance(api_version, int):
167            openharmony_sdk_path = configs.get('deveco_openharmony_sdk_path')
168            return os.path.join(openharmony_sdk_path, str(api_version))
169        else:
170            harmonyos_sdk_path = configs.get('deveco_harmonyos_sdk_path')
171            api_version_file_map = configs.get('api_version_file_name_map')
172            file_name = api_version_file_map.get(api_version)
173            return os.path.join(harmonyos_sdk_path, file_name, 'openharmony')
174
175
176def get_ark_disasm_path(task_path):
177    ark_disasm = 'ark_disasm.exe' if utils.is_windows() else 'ark_disasm'
178    sdk_path = get_sdk_path_in_the_project(task_path)
179    return os.path.join(sdk_path, 'toolchains', ark_disasm)
180
181
182def create_test_tasks(haps_list):
183    task_list = []
184    test_cases = 'all' if arguments.test_case == 'all' else []
185    test_haps = 'all' if arguments.test_hap == 'all' else []
186    if test_cases != 'all':
187        test_cases = arguments.test_case.split(',')
188    if test_haps != 'all':
189        test_haps = arguments.test_hap.split(',')
190
191    for hap in haps_list:
192        if test_cases == 'all' or test_haps == 'all' \
193           or (test_cases and (hap['type'][0] in test_cases)) \
194           or (test_haps and (hap['name'] in test_haps)):
195            if not os.path.exists(hap['path']):
196                logging.warning("Path of hap %s dosen't exist: %s", hap['name'], hap['path'])
197                continue
198            task = TestTask()
199            task.name = hap['name']
200            task.path = hap['path']
201            task.bundle_name = hap['bundle_name']
202            task.ability_name = hap['ability_name']
203            task.type = hap['type']
204            task.hap_module = hap['hap_module']
205            task.hap_module_path = hap['hap_module_path']
206            # If it is not a stage model, this HSP module cannot be created.
207            task.hsp_module = hap.get('hsp_module', '')
208            task.hsp_module_path = hap.get('hsp_module_path', '')
209            task.cpp_module = hap['cpp_module']
210            task.cpp_module_path = hap['cpp_module_path']
211            task.har_module = hap['har_module']
212            task.har_module_path = hap['har_module_path']
213            task.build_path = hap['build_path']
214            task.preview_path = hap['preview_path']
215            task.cache_path = hap['cache_path']
216            task.preview_cache_path = hap['preview_cache_path']
217            task.hap_output_path = hap['hap_output_path']
218            task.hap_output_path_signed = hap['hap_output_path_signed']
219            task.har_output_path_har = hap['har_output_path_har']
220            task.hsp_output_path = hap.get('hsp_output_path', '')
221            task.hsp_output_path_signed = hap.get('hsp_output_path_signed', '')
222            task.hsp_output_path_har = hap.get('hsp_output_path_har', '')
223            task.cpp_output_path = hap.get('cpp_output_path')
224            task.cpp_output_path_signed = hap.get('cpp_output_path_signed')
225            task.main_pages_json_path = hap['main_pages_json_path']
226            task.inc_modify_file = hap['inc_modify_file']
227            task.har_modify_file = hap['har_modify_file']
228            task.hsp_modify_file = hap.get('hsp_modify_file', '')
229            task.cpp_modify_file = hap['cpp_modify_file']
230            task.backup_info.cache_path = os.path.join(task.path, 'test_suite_cache')
231            task.ark_disasm_path = get_ark_disasm_path(task.path)
232
233            task_list.append(task)
234
235    return task_list
236
237
238def process_options():
239    parse_args()
240    utils.init_logger(arguments.log_level, arguments.log_file)
241    parse_configs()
242    return create_test_tasks(configs.get('haps'))