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: Use ark to execute ts/js files 19""" 20 21import os 22import sys 23import re 24import glob 25import argparse 26import subprocess 27import signal 28import time 29import json 30 31DEFAULT_TIMEOUT = 300 32DEFAULT_PGO_THRESHOLD = 10 33TARGET_PLATFORM = ['x64', 'arm64'] 34PRODUCT_LIST = ['hispark_taurus', 'rk3568', 'baltimore'] 35TARGET_PRODUCT_MAP = {'x64': 0, 'arm64': 1} 36 37def parse_args(): 38 parser = argparse.ArgumentParser() 39 parser.add_argument('name', metavar='file|path', type=str, help='test case name: file or path') 40 parser.add_argument('-a', '--all', action='store_true', help='run all test cases on path') 41 parser.add_argument('-p', '--product', metavar='name', 42 help='product name, default is hispark_taurus on x64, rk3568 on arm64, baltimore on arm64') 43 parser.add_argument('-t', '--tool', metavar='opt', 44 help='run tool supported opt: aot, int(c interpreter tool), asmint(asm interpreter tool), node(v8), qjs, hermes') 45 parser.add_argument('-f', '--frontend', metavar='opt', 46 help='run frontend supported opt: ts2abc (slow), es2abc (quick not released)') 47 parser.add_argument('-s', '--step', metavar='opt', 48 help='run step supported opt: abc, pack, aot, aotd, run, rund, asmint, asmintd, int, intd') 49 parser.add_argument('-d', '--debug', action='store_true', help='run on debug mode') 50 parser.add_argument('--arm64', action='store_true', help='run on arm64 platform') 51 parser.add_argument('--device', action='store_true', help='run on device') 52 parser.add_argument('--copy-path', metavar='path', help='copy bins to device') 53 parser.add_argument('-m', '--module', action='store_true', help='frontend compile with module') 54 parser.add_argument('--frontend-args', metavar='args', help='pass to frontend args') 55 parser.add_argument('--aot-args', metavar='args', help='pass to aot compiler args') 56 parser.add_argument('--jsvm-args', metavar='args', help='pass to jsvm args') 57 parser.add_argument('-i', '--info', action='store_true', help='add log level of info to args') 58 parser.add_argument('-c', '--clean', action='store_true', help='clean output files') 59 parser.add_argument('--npm', action='store_true', help='npm install') 60 parser.add_argument('--bt', dest='builtin', action='store_true', help='aot compile with lib_ark_builtins.d.ts') 61 parser.add_argument('--pgo', action='store_true', 62 help=f'aot compile with pgo, default threshold is {DEFAULT_PGO_THRESHOLD}') 63 parser.add_argument('--pgo-th', metavar='n', default=DEFAULT_PGO_THRESHOLD, type=int, 64 help=f'pgo hotness threshold, default is {DEFAULT_PGO_THRESHOLD}') 65 parser.add_argument('--sign', metavar='name', 66 help='sign level, default is system_core, other is normal, system_basic') 67 parser.add_argument('--timeout', metavar='n', default=DEFAULT_TIMEOUT, type=int, 68 help=f'specify seconds of test timeout, default is {DEFAULT_TIMEOUT}') 69 parser.add_argument('-e', '--env', action='store_true', help='print LD_LIBRARY_PATH') 70 arguments = parser.parse_args() 71 return arguments 72 73def run_and_print(cmd): 74 print(cmd) 75 os.system(cmd) 76 77def run_command(cmd, timeout=DEFAULT_TIMEOUT): 78 proc = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) 79 code_format = 'UTF-8' 80 try: 81 (msg, errs) = proc.communicate(timeout=timeout) 82 ret_code = proc.poll() 83 if errs: 84 ret_code = 2 85 except subprocess.TimeoutExpired: 86 proc.kill() 87 proc.terminate() 88 os.kill(proc.pid, signal.SIGTERM) 89 return (1, '', f'exec command timeout {timeout}s') 90 return (ret_code, msg.decode(code_format), errs.decode(code_format)) 91 92def match_list_name(list, name): 93 for str in list: 94 found = str.find(name) 95 if (found == 0): 96 return str 97 return '' 98 99def get_module_name(hap_dir): 100 with open(f'{hap_dir}/module.json') as f: 101 data = json.load(f) 102 if len(data): 103 return data['module']['name'] 104 else: 105 return 'entry' 106 107def get_bundle_name(hap_dir): 108 with open(f'{hap_dir}/module.json') as f: 109 data = json.load(f) 110 if len(data): 111 return data['app']['bundleName'] 112 else: 113 return 'entry' 114 115class ArkTest(): 116 def __init__(self, args): 117 self.args = args 118 self.self_dir = os.path.abspath(sys.argv[0]) 119 self.hap_abc = 'ets/modules.abc' 120 self.place_dir = 'arkcompiler/ets_runtime/test' 121 if not args.device and self.self_dir.find(self.place_dir) < 0: 122 print(f'pls place this script at: {self.place_dir}') 123 sys.exit(1) 124 125 self.ohdir = os.path.abspath(f'{self.self_dir}/../../../..') 126 self.product = PRODUCT_LIST[TARGET_PRODUCT_MAP['x64']] 127 self.builtin = '' 128 self.arm64 = False 129 if args.step == 'hap': 130 self.arm64 = True 131 if args.arm64: 132 self.product = PRODUCT_LIST[TARGET_PRODUCT_MAP['arm64']] 133 self.arm64 = True 134 if args.product: 135 self.product = match_list_name(PRODUCT_LIST, args.product) 136 self.step = 'all' 137 if args.step: 138 self.step = args.step 139 if args.clean: 140 self.step = 'clean' 141 self.expect = 'expect_output.txt' 142 search_type_list = ['.ts', '.js', '.abc'] 143 self.types = {'all': ['.ts', '.js'], 144 'abc': ['.ts', '.js'], 145 'pack': ['.an'], 146 'aot': search_type_list, 147 'aotd': search_type_list, 148 'run': search_type_list, 149 'rund': search_type_list, 150 'asmint': search_type_list, 151 'asmintd': search_type_list, 152 'int': search_type_list, 153 'intd': search_type_list, 154 'clean': search_type_list} 155 156 product_dir = f'{self.ohdir}/out/{self.product}' 157 libs_dir_x64_release = (f'{self.ohdir}/prebuilts/clang/ohos/linux-x86_64/llvm/lib:' 158 f'{product_dir}/clang_x64/arkcompiler/ets_runtime:' 159 f'{product_dir}/clang_x64/thirdparty/icu:' 160 f'{product_dir}/clang_x64/thirdparty/zlib') 161 libs_dir_x64_debug = (f'{self.ohdir}/prebuilts/clang/ohos/linux-x86_64/llvm/lib:' 162 f'{product_dir}/clang_x64/exe.unstripped/clang_x64/arkcompiler/ets_runtime:' 163 f'{product_dir}/clang_x64/lib.unstripped/clang_x64/arkcompiler/ets_runtime:' 164 f'{product_dir}/clang_x64/lib.unstripped/clang_x64/test/test:' 165 f'{product_dir}/clang_x64/lib.unstripped/clang_x64/thirdparty/icu:' 166 f'{product_dir}/clang_x64/lib.unstripped/clang_x64/thirdparty/zlib') 167 libs_dir_arm64_release = (f'{self.ohdir}/prebuilts/clang/ohos/linux-x86_64/llvm/lib/aarch64-linux-ohos/c++/:' 168 f'{product_dir}/arkcompiler/ets_runtime/:' 169 f'{product_dir}/utils/utils_base/:' 170 f'{product_dir}/thirdparty/icu:' 171 f'{product_dir}/thirdparty/zlib:' 172 f'{product_dir}/common/dsoftbus/:' 173 f'{product_dir}/commonlibrary/c_utils:' 174 f'{product_dir}/systemabilitymgr/samgr:' 175 f'{product_dir}/hiviewdfx/hisysevent_native:' 176 f'{product_dir}/common/common:' 177 f'{product_dir}/securec/thirdparty_bounds_checking_function:' 178 f'{product_dir}/hiviewdfx/faultloggerd:' 179 f'{product_dir}/thirdparty/bounds_checking_function:' 180 f'{product_dir}/hiviewdfx/hilog_native:' 181 f'{product_dir}/startup/init:' 182 f'{product_dir}/thirdparty/cjson:' 183 f'{product_dir}/lib.unstripped/common/dsoftbus:' 184 f'{product_dir}/security/selinux:' 185 f'{product_dir}/hiviewdfx/hitrace_native/:' 186 f'{product_dir}/communication/ipc/:' 187 f'{product_dir}/distributedschedule/samgr_standard:' 188 f'{product_dir}/security/access_token:' 189 f'{product_dir}/communication/dsoftbus:' 190 f'{product_dir}/startup/startup_l2/:' 191 f'{product_dir}/security/huks/:' 192 f'{product_dir}/clang_x64/thirdparty/icu:' 193 f'{product_dir}/clang_x64/thirdparty/zlib:' 194 f'{product_dir}/clang_x64/arkcompiler/ets_runtime') 195 libs_dir_arm64_debug = (f'{self.ohdir}/prebuilts/clang/ohos/linux-x86_64/llvm/lib/aarch64-linux-ohos/c++/:' 196 f'{product_dir}/lib.unstripped/arkcompiler/ets_runtime/:' 197 f'{product_dir}/utils/utils_base/:' 198 f'{product_dir}/thirdparty/icu:' 199 f'{product_dir}/thirdparty/zlib:' 200 f'{product_dir}/common/dsoftbus/:' 201 f'{product_dir}/commonlibrary/c_utils:' 202 f'{product_dir}/systemabilitymgr/samgr:' 203 f'{product_dir}/hiviewdfx/hisysevent_native:' 204 f'{product_dir}/common/common:' 205 f'{product_dir}/securec/thirdparty_bounds_checking_function:' 206 f'{product_dir}/hiviewdfx/faultloggerd:' 207 f'{product_dir}/thirdparty/bounds_checking_function:' 208 f'{product_dir}/hiviewdfx/hilog_native:' 209 f'{product_dir}/startup/init:' 210 f'{product_dir}/thirdparty/cjson:' 211 f'{product_dir}/security/selinux:' 212 f'{product_dir}/hiviewdfx/hitrace_native/:' 213 f'{product_dir}/communication/ipc/:' 214 f'{product_dir}/distributedschedule/samgr_standard:' 215 f'{product_dir}/security/access_token:' 216 f'{product_dir}/communication/dsoftbus:' 217 f'{product_dir}/startup/startup_l2/:' 218 f'{product_dir}/security/huks/:' 219 f'{product_dir}/clang_x64/thirdparty/icu/:' 220 f'{product_dir}/clang_x64/thirdparty/zlib/:' 221 f'{product_dir}/clang_x64/arkcompiler/ets_runtime') 222 libs_dir = [[libs_dir_x64_release, libs_dir_x64_debug], [libs_dir_arm64_release, libs_dir_arm64_debug]] 223 bins_dir = [['clang_x64/arkcompiler', 'clang_x64/exe.unstripped/clang_x64/arkcompiler'], 224 ['arkcompiler', 'exe.unstripped/arkcompiler']] 225 icu_arg = f'--icu-data-path={self.ohdir}/third_party/icu/ohos_icu4j/data' 226 self.libs_dir = libs_dir[self.arm64][args.debug] 227 self.compiler = f'{product_dir}/{bins_dir[0][args.debug]}/ets_runtime/ark_aot_compiler' 228 self.jsvm = f'{product_dir}/{bins_dir[self.arm64][args.debug]}/ets_runtime/ark_js_vm' 229 self.ts2abc = f'node --expose-gc {product_dir}/clang_x64/arkcompiler/ets_frontend/build/src/index.js' 230 self.es2abc = f'{product_dir}/clang_x64/arkcompiler/ets_frontend/es2abc' 231 self.frontend = self.ts2abc 232 if not args.frontend: 233 args.frontend = 'ts2abc' 234 if args.frontend not in ['ts2abc', 'es2abc']: 235 print(f'not supported frontend: {args.frontend}') 236 sys.exit(1) 237 if args.frontend == 'es2abc': 238 self.frontend = self.es2abc 239 abcmode = {'ts2abc': ['--merge-abc', '--merge-abc -m'], 240 'es2abc': ['--merge-abc', '--merge-abc --module']} 241 self.abcmode = abcmode[args.frontend][args.module] 242 self.frontend_args = '' 243 self.aot_args = '' 244 self.jsvm_args = icu_arg 245 if args.device: 246 self.jsvm_args = '' 247 if self.builtin: 248 self.aot_args = f'{self.aot_args} --builtins-dts={self.builtin}.abc' 249 self.pgo = False 250 if args.pgo: 251 self.pgo = True 252 self.aot_args = (f'{self.aot_args} --enable-pgo-profiler=true --compiler-pgo-hotness-threshold={args.pgo_th}' 253 f' --compiler-pgo-profiler-path=pgo_file_name.ap') 254 if args.frontend_args: 255 self.frontend_args = f'{self.frontend_args} {args.frontend_args}' 256 if args.aot_args: 257 self.aot_args = f'{self.aot_args} {args.aot_args}' 258 if args.jsvm_args: 259 self.jsvm_args = f'{self.jsvm_args} {args.jsvm_args}' 260 if args.info: 261 self.aot_args = f'{self.aot_args} --log-level=info' 262 self.jsvm_args = f'{self.jsvm_args} --log-level=info' 263 self.runner = '' 264 self.runnerd = 'gdb --args' 265 if self.arm64 or args.device: 266 if self.step[:3] != 'aot': 267 self.runner = 'qemu-aarch64' 268 self.runnerd = 'qemu-aarch64 -cpu max,sve=off -g 123456' 269 self.aot_args = f'{self.aot_args} --compiler-target-triple=aarch64-unknown-linux-gnu' 270 self.test_count = 0 271 self.fail_cases = [] 272 os.environ['LD_LIBRARY_PATH'] = self.libs_dir 273 if args.env: 274 print(f'export LD_LIBRARY_PATH={self.libs_dir}') 275 sys.exit(0) 276 if args.copy_path: 277 run_and_print(f'hdc shell mount -o remount,rw /') 278 run_and_print(f'hdc file send {args.copy_path}\\ark_aot_compiler /system/bin/') 279 run_and_print(f'hdc shell chmod a+x /system/bin/ark_aot_compiler') 280 run_and_print(f'hdc file send {args.copy_path}\\ark_js_vm /system/bin/') 281 run_and_print(f'hdc shell chmod a+x /system/bin/ark_js_vm') 282 sys.exit(0) 283 if args.npm: 284 index_dir = f'{product_dir}/clang_x64/arkcompiler/ets_frontend/build/src' 285 os.system(f'cd {index_dir}/.. && npm install') 286 sys.exit(0) 287 if args.sign: 288 self.sign_hap(self.args.name) 289 sys.exit(0) 290 291 def run_cmd(self, cmd): 292 print(cmd) 293 ret = run_command(cmd, self.args.timeout) 294 if ret[0]: 295 print(ret[2]) 296 return ret 297 298 def run_test(self, file): 299 self.test_count += 1 300 basename = os.path.basename(f'{file}') 301 type = os.path.splitext(basename)[-1] 302 name = os.path.splitext(basename)[0] 303 dir = os.path.dirname(file) 304 out_case_dir = f'{dir}' 305 hap_dir = 'null' 306 hap_name = 'null' 307 module_name = 'null' 308 if self.step == 'hap' or self.step == 'pack': 309 hap_dir = os.path.abspath(f'{out_case_dir}/..') 310 hap_name = os.path.basename(hap_dir) 311 module_name = get_module_name(hap_dir) 312 abc_file = f'{os.path.splitext(file)[0]}.abc' 313 if self.pgo: 314 pgo_file = f'{hap_dir}/ap/{module_name}' 315 self.aot_args = self.aot_args.replace('pgo_file_name', pgo_file) 316 cmd_map = { 317 'node': f'node {self.frontend_args} {file}', 318 'qjs': f'qjs {self.frontend_args} {file}', 319 'hermes': f'hermes {self.frontend_args} {file}', 320 'abc': f'{self.frontend} {self.frontend_args} {self.abcmode} --output {abc_file} {file}', 321 'pack': [f'mkdir -p {out_case_dir}/../an/arm64-v8a', 322 f'mv {out_case_dir}/{name}.an {hap_dir}/an/arm64-v8a/{module_name}.an', 323 f'mv {out_case_dir}/{name}.ai {hap_dir}/an/arm64-v8a/{module_name}.ai', 324 f'cd {out_case_dir}/.. && rm -f ../{hap_name}.hap && zip -r -q ../{hap_name}.hap *', 325 f'mv {hap_dir}/an/arm64-v8a/{module_name}.an {out_case_dir}/{name}.an', 326 f'mv {hap_dir}/an/arm64-v8a/{module_name}.ai {out_case_dir}/{name}.ai', 327 f'rm -rf {hap_dir}/an'], 328 'aot': f'{self.compiler} {self.aot_args} --aot-file={out_case_dir}/{name} {abc_file}', 329 'aotd': f'{self.runnerd} {self.compiler} {self.aot_args} --aot-file={out_case_dir}/{name} {abc_file}', 330 'run': f'{self.runner} {self.jsvm} {self.jsvm_args} --aot-file={out_case_dir}/{name} --entry-point={name} {abc_file}', 331 'rund': f'{self.runnerd} {self.jsvm} {self.jsvm_args} --aot-file={out_case_dir}/{name} --entry-point={name} {abc_file}', 332 'asmint': f'{self.runner} {self.jsvm} {self.jsvm_args} --entry-point={name} {abc_file}', 333 'asmintd': f'{self.runnerd} {self.jsvm} {self.jsvm_args} --entry-point={name} {abc_file}', 334 'int': f'{self.runner} {self.jsvm} {self.jsvm_args} --asm-interpreter=0 --entry-point={name} {abc_file}', 335 'intd': f'{self.runnerd} {self.jsvm} {self.jsvm_args} --asm-interpreter=0 --entry-point={name} {abc_file}', 336 'clean': f'rm -f {out_case_dir}/{name}.abc {out_case_dir}/{name}.an {out_case_dir}/{name}.ai', 337 'cleanhap': f'rm -rf {hap_dir}/an {out_case_dir}/{name}.an {out_case_dir}/{name}.ai'} 338 if self.builtin: 339 if self.frontend == self.ts2abc: 340 cmd = f'{self.ts2abc} {self.builtin}.ts -m --merge-abc -q -b' 341 elif self.frontend == self.es2abc: 342 cmd = (f'{self.es2abc} --module --merge-abc --extension=ts ' 343 f'--output={self.builtin}.abc {self.builtin}.ts') 344 print(cmd) 345 os.system(cmd) 346 if self.step == 'hap': 347 self.step = 'aot' 348 perf_start = time.perf_counter() 349 cmd = cmd_map[self.step] 350 print(cmd) 351 os.system(cmd) 352 perf_end = time.perf_counter() 353 abc_size = os.path.getsize(file) / 1024 / 1024 354 an_size = os.path.getsize(f'{out_case_dir}/{name}.an') / 1024 / 1024 355 print(f'test: {file} abc_size: {abc_size: .1f}MB an_size: {an_size:.1f}MB ' 356 f'expand: {an_size / abc_size: .1f} time: {perf_end - perf_start: .1f}s') 357 self.step = 'pack' 358 if self.step == 'pack': 359 for cmd in cmd_map[self.step]: 360 print(cmd) 361 os.system(cmd) 362 print(f'packed hap: {hap_name}.hap') 363 print(f'sign --------------------------------------------') 364 self.sign_hap(f'{hap_name}.hap') 365 return 366 if self.step == 'clean': 367 if os.path.isfile(f'{hap_dir}/{self.hap_abc}'): 368 self.step = 'cleanhap' 369 if self.args.tool == 'node': 370 ret = self.run_cmd(cmd_map['node']) 371 self.judge_test(file, ret) 372 return 373 if self.args.tool == 'qjs': 374 ret = self.run_cmd(cmd_map['qjs']) 375 self.judge_test(file, ret) 376 return 377 if self.args.tool == 'hermes': 378 ret = self.run_cmd(cmd_map['hermes']) 379 self.judge_test(file, ret) 380 return 381 if not self.args.tool: 382 self.args.tool = 'aot' 383 if self.args.tool not in ['aot', 'asmint', 'int']: 384 print(f'not supported tool: {self.args.tool}') 385 sys.exit(1) 386 if self.args.device: 387 ret = self.run_test_on_device(file) 388 return 389 if self.step != 'all': 390 # gdb should use the os.system 391 cmd = cmd_map[self.step] 392 print(cmd) 393 if self.arm64 and self.step[-1:] == 'd' and self.step[:3] != 'aot': 394 print(f'gdb-client start: gdb-multiarch {self.jsvm}') 395 print(f'gdb-server connect: target remote:123456') 396 os.system(cmd) 397 return 398 ret = self.run_cmd(cmd_map['abc']) 399 if ret[0]: 400 self.judge_test(file, ret) 401 return 402 if self.args.tool == 'aot': 403 ret = self.run_cmd(cmd_map['aot']) 404 if ret[0] and ret[2].find('aot compile success') < 0: 405 self.judge_test(file, ret) 406 return 407 ret = self.run_cmd(cmd_map['run']) 408 else: 409 ret = self.run_cmd(cmd_map[self.args.tool]) 410 self.judge_test(file, ret) 411 412 def run_test_on_device(self, file): 413 basename = os.path.basename(f'{file}') 414 name = os.path.splitext(basename)[0] 415 out_case_dir = '/data/test' 416 send_abc_file = f'{os.path.splitext(file)[0]}.abc'.replace('/', '\\') 417 abc_file = f'{out_case_dir}/{name}.abc' 418 cmd_map = {'abc': f'hdc file send {send_abc_file} {out_case_dir}/', 419 'aot': f'hdc shell ark_aot_compiler {self.aot_args} --aot-file={out_case_dir}/{name} {abc_file}', 420 'run': f'hdc shell ark_js_vm {self.jsvm_args} --aot-file={out_case_dir}/{name} --entry-point={name} {abc_file}', 421 'asmint': f'hdc shell ark_js_vm {self.jsvm_args} --entry-point={name} {abc_file}', 422 'int': f'hdc shell ark_js_vm {self.jsvm_args} --asm-interpreter=0 --entry-point={name} {abc_file}'} 423 if self.step != 'all': 424 run_and_print(cmd_map[self.step]) 425 return 426 run_and_print(cmd_map['abc']) 427 if self.args.tool == 'aot': 428 ret = self.run_cmd(cmd_map['aot']) 429 if ret[0] and ret[2].find('aot compile success') < 0: 430 self.judge_test(file, ret) 431 return 432 ret = self.run_cmd(cmd_map['run']) 433 else: 434 ret = self.run_cmd(cmd_map[self.args.tool]) 435 self.judge_test(file, ret) 436 437 def judge_test(self, file, out): 438 if out[0]: 439 self.fail_cases.append(file) 440 print_fail(f'FAIL: {file}') 441 return 442 expect_file = f'{os.path.dirname(file)}/{self.expect}' 443 if os.path.exists(expect_file): 444 with open(expect_file, mode='r') as infile: 445 expect = ''.join(infile.readlines()[13:]) 446 if out[1].replace('\r', '') != expect.replace('\r', ''): 447 self.fail_cases.append(file) 448 print(f'expect: [{expect}]\nbut got: [{out[1]}]') 449 print_fail(f'FAIL: {file}') 450 else: 451 print_pass(f'PASS: {file}') 452 else: 453 print_pass(f'PASS: {file}') 454 print(out[1]) 455 456 def report_test(self): 457 fail_count = len(self.fail_cases) 458 print(f'Ran tests: {self.test_count}') 459 print(f'Ran failed: {fail_count}') 460 if fail_count == 0: 461 print_pass('================================== All tests Run PASSED!') 462 return 463 print_fail('==================================') 464 for case in self.fail_cases: 465 print(case) 466 print_fail('==================================') 467 468 def find_file(self, dir, postfix_list): 469 result = [] 470 for root, lists, files in os.walk(dir): 471 for file in files: 472 for postfix in postfix_list: 473 path = os.path.join(root, file) 474 found = path.find(postfix) 475 if found == len(path) - len(postfix): 476 result.append(path) 477 if os.path.isfile(dir): 478 for postfix in postfix_list: 479 found = dir.find(postfix) 480 if found == len(dir) - len(postfix): 481 result.append(dir) 482 break 483 return result 484 485 def test_hap(self): 486 if self.step != 'all': 487 return 1 488 files = self.find_file(self.args.name, [self.hap_abc, '.hap']) 489 if len(files): 490 self.step = 'hap' 491 file = files[0] 492 type = os.path.splitext(file)[-1] 493 if type == '.hap': 494 hap_dir = f'{os.path.splitext(file)[0]}.aot' 495 os.system(f'mkdir -p {hap_dir} && unzip -o -q {file} -d {hap_dir}') 496 file = f'{hap_dir}/{self.hap_abc}' 497 self.run_test(file) 498 return 0 499 return 1 500 501 def sign_hap(self, hap_name): 502 name = os.path.splitext(hap_name)[0] 503 sign_dir = f'{name}.sign' 504 sign_tool_dir = f'{self.ohdir}/developtools/hapsigner/dist' 505 name = os.path.splitext(sign_dir)[0] 506 self_dir = os.path.abspath(sys.argv[0]) 507 os.system(f'mkdir -p {sign_dir} && unzip -o -q {hap_name} module.json -d {sign_dir}') 508 bundle_name = get_bundle_name(sign_dir) 509 if not self.args.sign or self.args.sign == 'system_core': 510 bundle_apl = 'system_core' 511 bundle_feature = 'hos_system_app' 512 elif self.args.sign == 'system_basic': 513 bundle_apl = self.args.sign 514 bundle_feature = 'hos_system_app' 515 elif self.args.sign == 'normal': 516 bundle_apl = self.args.sign 517 bundle_feature = 'hos_normal_app' 518 else: 519 print(f'sign not supported input: {self.args.sign}') 520 return 1 521 # modify sign config 522 data_load = [] 523 data_save = [] 524 sign_config = 'UnsgnedReleasedProfileTemplate.json' 525 with open(f'{sign_tool_dir}/{sign_config}') as f: 526 data_load = json.load(f) 527 data_load['bundle-info']['bundle-name'] = bundle_name 528 data_load['bundle-info']['apl'] = bundle_apl 529 data_load['bundle-info']['app-feature'] = bundle_feature 530 data_save = json.dumps(data_load) 531 with open(f'{sign_dir}/{sign_config}', 'w+') as f: 532 f.write(data_save) 533 # generate cert and sign 534 gen_cert = f'java -jar {sign_tool_dir}/hap-sign-tool.jar sign-profile -keyAlias "openharmony application profile release" -signAlg "SHA256withECDSA" -mode "localSign" -profileCertFile "{sign_tool_dir}/OpenHarmonyProfileRelease.pem" -inFile "{sign_dir}/{sign_config}" -keystoreFile "{sign_tool_dir}/OpenHarmony.p12" -outFile "{sign_dir}/openharmony.p7b" -keyPwd "123456" -keystorePwd "123456"' 535 sign_hap = f'java -jar {sign_tool_dir}/hap-sign-tool.jar sign-app -keyAlias "openharmony application release" -signAlg "SHA256withECDSA" -mode "localSign" -appCertFile "{sign_tool_dir}/OpenHarmonyApplication.pem" -profileFile "{sign_dir}/openharmony.p7b" -inFile "{hap_name}" -keystoreFile "{sign_tool_dir}/OpenHarmony.p12" -outFile "{name}.sign.hap" -keyPwd "123456" -keystorePwd "123456"' 536 print(gen_cert) 537 print(sign_hap) 538 os.system(gen_cert) 539 os.system(sign_hap) 540 print(f'signed of {bundle_apl} for hap: {name}.sign.hap') 541 542 def test(self): 543 # run single test by name 544 files = [] 545 if self.step not in self.types: 546 print(f'not supported step: {self.step}') 547 return 1 548 if not self.args.all: 549 files = self.find_file(self.args.name, self.types[self.step]) 550 if len(files): 551 self.run_test(files[0]) 552 elif self.test_hap(): 553 print(f'only support file type: {self.types[self.step]}') 554 print(f'input path no test case: {self.args.name}') 555 return 1 556 return 0 557 558 # run all test in path 559 if not os.path.isdir(self.args.name): 560 print(f'input path not exists or is file: {self.args.name}') 561 return 1 562 files = self.find_file(self.args.name, self.types[self.step]) 563 for test in files: 564 self.run_test(test) 565 566 if len(files) == 0: 567 self.test_hap() 568 569 if self.step == 'clean': 570 print('clean output files finished') 571 return 0 572 573 if self.test_count == 0: 574 print(f'input path no test case: {self.args.name}') 575 return 1 576 577 # output report 578 self.report_test() 579 return 0 580 581def print_pass(str): 582 print(f'\033[32;2m{str}\033[0m') 583 sys.stdout.flush() 584 585def print_fail(str): 586 print(f'\033[31;2m{str}\033[0m') 587 sys.stdout.flush() 588 589def main(): 590 args = parse_args() 591 arktest = ArkTest(args) 592 return arktest.test() 593 594if __name__ == '__main__': 595 sys.exit(main()) 596