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 if args.builtin: 129 self.builtin = f'{self.ohdir}/arkcompiler/ets_runtime/ecmascript/ts_types/lib_ark_builtins.d' 130 self.arm64 = False 131 if args.step == 'hap': 132 self.arm64 = True 133 if args.arm64: 134 self.product = PRODUCT_LIST[TARGET_PRODUCT_MAP['arm64']] 135 self.arm64 = True 136 if args.product: 137 self.product = match_list_name(PRODUCT_LIST, args.product) 138 self.step = 'all' 139 if args.step: 140 self.step = args.step 141 if args.clean: 142 self.step = 'clean' 143 self.expect = 'expect_output.txt' 144 search_type_list = ['.ts', '.js', '.abc'] 145 self.types = {'all': ['.ts', '.js'], 146 'abc': ['.ts', '.js'], 147 'pack': ['.an'], 148 'aot': search_type_list, 149 'aotd': search_type_list, 150 'run': search_type_list, 151 'rund': search_type_list, 152 'asmint': search_type_list, 153 'asmintd': search_type_list, 154 'int': search_type_list, 155 'intd': search_type_list, 156 'clean': search_type_list} 157 158 product_dir = f'{self.ohdir}/out/{self.product}' 159 libs_dir_x64_release = (f'{self.ohdir}/prebuilts/clang/ohos/linux-x86_64/llvm/lib:' 160 f'{product_dir}/clang_x64/arkcompiler/ets_runtime:' 161 f'{product_dir}/clang_x64/thirdparty/icu:' 162 f'{product_dir}/clang_x64/thirdparty/zlib') 163 libs_dir_x64_debug = (f'{self.ohdir}/prebuilts/clang/ohos/linux-x86_64/llvm/lib:' 164 f'{product_dir}/clang_x64/exe.unstripped/clang_x64/arkcompiler/ets_runtime:' 165 f'{product_dir}/clang_x64/lib.unstripped/clang_x64/arkcompiler/ets_runtime:' 166 f'{product_dir}/clang_x64/lib.unstripped/clang_x64/test/test:' 167 f'{product_dir}/clang_x64/lib.unstripped/clang_x64/thirdparty/icu:' 168 f'{product_dir}/clang_x64/lib.unstripped/clang_x64/thirdparty/zlib') 169 libs_dir_arm64_release = (f'{self.ohdir}/prebuilts/clang/ohos/linux-x86_64/llvm/lib/aarch64-linux-ohos/c++/:' 170 f'{product_dir}/arkcompiler/ets_runtime/:' 171 f'{product_dir}/utils/utils_base/:' 172 f'{product_dir}/thirdparty/icu:' 173 f'{product_dir}/thirdparty/zlib:' 174 f'{product_dir}/common/dsoftbus/:' 175 f'{product_dir}/commonlibrary/c_utils:' 176 f'{product_dir}/systemabilitymgr/samgr:' 177 f'{product_dir}/hiviewdfx/hisysevent_native:' 178 f'{product_dir}/common/common:' 179 f'{product_dir}/securec/thirdparty_bounds_checking_function:' 180 f'{product_dir}/hiviewdfx/faultloggerd:' 181 f'{product_dir}/thirdparty/bounds_checking_function:' 182 f'{product_dir}/hiviewdfx/hilog_native:' 183 f'{product_dir}/startup/init:' 184 f'{product_dir}/thirdparty/cjson:' 185 f'{product_dir}/lib.unstripped/common/dsoftbus:' 186 f'{product_dir}/security/selinux:' 187 f'{product_dir}/hiviewdfx/hitrace_native/:' 188 f'{product_dir}/communication/ipc/:' 189 f'{product_dir}/distributedschedule/samgr_standard:' 190 f'{product_dir}/security/access_token:' 191 f'{product_dir}/communication/dsoftbus:' 192 f'{product_dir}/startup/startup_l2/:' 193 f'{product_dir}/security/huks/:' 194 f'{product_dir}/clang_x64/thirdparty/icu:' 195 f'{product_dir}/clang_x64/thirdparty/zlib:' 196 f'{product_dir}/clang_x64/arkcompiler/ets_runtime') 197 libs_dir_arm64_debug = (f'{self.ohdir}/prebuilts/clang/ohos/linux-x86_64/llvm/lib/aarch64-linux-ohos/c++/:' 198 f'{product_dir}/lib.unstripped/arkcompiler/ets_runtime/:' 199 f'{product_dir}/utils/utils_base/:' 200 f'{product_dir}/thirdparty/icu:' 201 f'{product_dir}/thirdparty/zlib:' 202 f'{product_dir}/common/dsoftbus/:' 203 f'{product_dir}/commonlibrary/c_utils:' 204 f'{product_dir}/systemabilitymgr/samgr:' 205 f'{product_dir}/hiviewdfx/hisysevent_native:' 206 f'{product_dir}/common/common:' 207 f'{product_dir}/securec/thirdparty_bounds_checking_function:' 208 f'{product_dir}/hiviewdfx/faultloggerd:' 209 f'{product_dir}/thirdparty/bounds_checking_function:' 210 f'{product_dir}/hiviewdfx/hilog_native:' 211 f'{product_dir}/startup/init:' 212 f'{product_dir}/thirdparty/cjson:' 213 f'{product_dir}/security/selinux:' 214 f'{product_dir}/hiviewdfx/hitrace_native/:' 215 f'{product_dir}/communication/ipc/:' 216 f'{product_dir}/distributedschedule/samgr_standard:' 217 f'{product_dir}/security/access_token:' 218 f'{product_dir}/communication/dsoftbus:' 219 f'{product_dir}/startup/startup_l2/:' 220 f'{product_dir}/security/huks/:' 221 f'{product_dir}/clang_x64/thirdparty/icu/:' 222 f'{product_dir}/clang_x64/thirdparty/zlib/:' 223 f'{product_dir}/clang_x64/arkcompiler/ets_runtime') 224 libs_dir = [[libs_dir_x64_release, libs_dir_x64_debug], [libs_dir_arm64_release, libs_dir_arm64_debug]] 225 bins_dir = [['clang_x64/arkcompiler', 'clang_x64/exe.unstripped/clang_x64/arkcompiler'], 226 ['arkcompiler', 'exe.unstripped/arkcompiler']] 227 icu_arg = f'--icu-data-path={self.ohdir}/third_party/icu/ohos_icu4j/data' 228 self.libs_dir = libs_dir[self.arm64][args.debug] 229 self.compiler = f'{product_dir}/{bins_dir[0][args.debug]}/ets_runtime/ark_aot_compiler' 230 self.jsvm = f'{product_dir}/{bins_dir[self.arm64][args.debug]}/ets_runtime/ark_js_vm' 231 self.ts2abc = f'node --expose-gc {product_dir}/clang_x64/arkcompiler/ets_frontend/build/src/index.js' 232 self.es2abc = f'{product_dir}/clang_x64/arkcompiler/ets_frontend/es2abc' 233 self.frontend = self.ts2abc 234 if not args.frontend: 235 args.frontend = 'ts2abc' 236 if args.frontend not in ['ts2abc', 'es2abc']: 237 print(f'not supported frontend: {args.frontend}') 238 sys.exit(1) 239 if args.frontend == 'es2abc': 240 self.frontend = self.es2abc 241 abcmode = {'ts2abc': ['--merge-abc', '--merge-abc -m'], 242 'es2abc': ['--merge-abc', '--merge-abc --module']} 243 self.abcmode = abcmode[args.frontend][args.module] 244 self.frontend_args = '' 245 self.aot_args = '' 246 self.jsvm_args = icu_arg 247 if args.device: 248 self.jsvm_args = '' 249 if self.builtin: 250 self.aot_args = f'{self.aot_args} --builtins-dts={self.builtin}.abc' 251 self.pgo = False 252 if args.pgo: 253 self.pgo = True 254 self.aot_args = (f'{self.aot_args} --enable-pgo-profiler=true --compiler-pgo-hotness-threshold={args.pgo_th}' 255 f' --compiler-pgo-profiler-path=pgo_file_name.ap') 256 if args.frontend_args: 257 self.frontend_args = f'{self.frontend_args} {args.frontend_args}' 258 if args.aot_args: 259 self.aot_args = f'{self.aot_args} {args.aot_args}' 260 if args.jsvm_args: 261 self.jsvm_args = f'{self.jsvm_args} {args.jsvm_args}' 262 if args.info: 263 self.aot_args = f'{self.aot_args} --log-level=info' 264 self.jsvm_args = f'{self.jsvm_args} --log-level=info' 265 self.runner = '' 266 self.runnerd = 'gdb --args' 267 if self.arm64 or args.device: 268 if self.step[:3] != 'aot': 269 self.runner = 'qemu-aarch64' 270 self.runnerd = 'qemu-aarch64 -cpu max,sve=off -g 123456' 271 self.aot_args = f'{self.aot_args} --compiler-target-triple=aarch64-unknown-linux-gnu' 272 self.test_count = 0 273 self.fail_cases = [] 274 os.environ['LD_LIBRARY_PATH'] = self.libs_dir 275 if args.env: 276 print(f'export LD_LIBRARY_PATH={self.libs_dir}') 277 sys.exit(0) 278 if args.copy_path: 279 run_and_print(f'hdc shell mount -o remount,rw /') 280 run_and_print(f'hdc file send {args.copy_path}\\ark_aot_compiler /system/bin/') 281 run_and_print(f'hdc shell chmod a+x /system/bin/ark_aot_compiler') 282 run_and_print(f'hdc file send {args.copy_path}\\ark_js_vm /system/bin/') 283 run_and_print(f'hdc shell chmod a+x /system/bin/ark_js_vm') 284 sys.exit(0) 285 if args.npm: 286 index_dir = f'{product_dir}/clang_x64/arkcompiler/ets_frontend/build/src' 287 os.system(f'cd {index_dir}/.. && npm install') 288 sys.exit(0) 289 if args.sign: 290 self.sign_hap(self.args.name) 291 sys.exit(0) 292 293 def run_cmd(self, cmd): 294 print(cmd) 295 ret = run_command(cmd, self.args.timeout) 296 if ret[0]: 297 print(ret[2]) 298 return ret 299 300 def run_test(self, file): 301 self.test_count += 1 302 basename = os.path.basename(f'{file}') 303 type = os.path.splitext(basename)[-1] 304 name = os.path.splitext(basename)[0] 305 dir = os.path.dirname(file) 306 out_case_dir = f'{dir}' 307 hap_dir = 'null' 308 hap_name = 'null' 309 module_name = 'null' 310 if self.step == 'hap' or self.step == 'pack': 311 hap_dir = os.path.abspath(f'{out_case_dir}/..') 312 hap_name = os.path.basename(hap_dir) 313 module_name = get_module_name(hap_dir) 314 abc_file = f'{os.path.splitext(file)[0]}.abc' 315 if self.pgo: 316 pgo_file = f'{hap_dir}/ap/{module_name}' 317 self.aot_args = self.aot_args.replace('pgo_file_name', pgo_file) 318 cmd_map = { 319 'node': f'node {self.frontend_args} {file}', 320 'qjs': f'qjs {self.frontend_args} {file}', 321 'hermes': f'hermes {self.frontend_args} {file}', 322 'abc': f'{self.frontend} {self.frontend_args} {self.abcmode} --output {abc_file} {file}', 323 'pack': [f'mkdir -p {out_case_dir}/../an/arm64-v8a', 324 f'mv {out_case_dir}/{name}.an {hap_dir}/an/arm64-v8a/{module_name}.an', 325 f'mv {out_case_dir}/{name}.ai {hap_dir}/an/arm64-v8a/{module_name}.ai', 326 f'cd {out_case_dir}/.. && rm -f ../{hap_name}.hap && zip -r -q ../{hap_name}.hap *', 327 f'mv {hap_dir}/an/arm64-v8a/{module_name}.an {out_case_dir}/{name}.an', 328 f'mv {hap_dir}/an/arm64-v8a/{module_name}.ai {out_case_dir}/{name}.ai', 329 f'rm -rf {hap_dir}/an'], 330 'aot': f'{self.compiler} {self.aot_args} --aot-file={out_case_dir}/{name} {abc_file}', 331 'aotd': f'{self.runnerd} {self.compiler} {self.aot_args} --aot-file={out_case_dir}/{name} {abc_file}', 332 'run': f'{self.runner} {self.jsvm} {self.jsvm_args} --aot-file={out_case_dir}/{name} --entry-point={name} {abc_file}', 333 'rund': f'{self.runnerd} {self.jsvm} {self.jsvm_args} --aot-file={out_case_dir}/{name} --entry-point={name} {abc_file}', 334 'asmint': f'{self.runner} {self.jsvm} {self.jsvm_args} --entry-point={name} {abc_file}', 335 'asmintd': f'{self.runnerd} {self.jsvm} {self.jsvm_args} --entry-point={name} {abc_file}', 336 'int': f'{self.runner} {self.jsvm} {self.jsvm_args} --asm-interpreter=0 --entry-point={name} {abc_file}', 337 'intd': f'{self.runnerd} {self.jsvm} {self.jsvm_args} --asm-interpreter=0 --entry-point={name} {abc_file}', 338 'clean': f'rm -f {out_case_dir}/{name}.abc {out_case_dir}/{name}.an {out_case_dir}/{name}.ai', 339 'cleanhap': f'rm -rf {hap_dir}/an {out_case_dir}/{name}.an {out_case_dir}/{name}.ai'} 340 if self.builtin: 341 if self.frontend == self.ts2abc: 342 cmd = f'{self.ts2abc} {self.builtin}.ts -m --merge-abc -q -b' 343 elif self.frontend == self.es2abc: 344 cmd = (f'{self.es2abc} --module --merge-abc --extension=ts --type-extractor --type-dts-builtin ' 345 f'--output={self.builtin}.abc {self.builtin}.ts') 346 print(cmd) 347 os.system(cmd) 348 if self.step == 'hap': 349 self.step = 'aot' 350 perf_start = time.perf_counter() 351 cmd = cmd_map[self.step] 352 print(cmd) 353 os.system(cmd) 354 perf_end = time.perf_counter() 355 abc_size = os.path.getsize(file) / 1024 / 1024 356 an_size = os.path.getsize(f'{out_case_dir}/{name}.an') / 1024 / 1024 357 print(f'test: {file} abc_size: {abc_size: .1f}MB an_size: {an_size:.1f}MB ' 358 f'expand: {an_size / abc_size: .1f} time: {perf_end - perf_start: .1f}s') 359 self.step = 'pack' 360 if self.step == 'pack': 361 for cmd in cmd_map[self.step]: 362 print(cmd) 363 os.system(cmd) 364 print(f'packed hap: {hap_name}.hap') 365 print(f'sign --------------------------------------------') 366 self.sign_hap(f'{hap_name}.hap') 367 return 368 if self.step == 'clean': 369 if os.path.isfile(f'{hap_dir}/{self.hap_abc}'): 370 self.step = 'cleanhap' 371 if self.args.tool == 'node': 372 ret = self.run_cmd(cmd_map['node']) 373 self.judge_test(file, ret) 374 return 375 if self.args.tool == 'qjs': 376 ret = self.run_cmd(cmd_map['qjs']) 377 self.judge_test(file, ret) 378 return 379 if self.args.tool == 'hermes': 380 ret = self.run_cmd(cmd_map['hermes']) 381 self.judge_test(file, ret) 382 return 383 if not self.args.tool: 384 self.args.tool = 'aot' 385 if self.args.tool not in ['aot', 'asmint', 'int']: 386 print(f'not supported tool: {self.args.tool}') 387 sys.exit(1) 388 if self.args.device: 389 ret = self.run_test_on_device(file) 390 return 391 if self.step != 'all': 392 # gdb should use the os.system 393 cmd = cmd_map[self.step] 394 print(cmd) 395 if self.arm64 and self.step[-1:] == 'd' and self.step[:3] != 'aot': 396 print(f'gdb-client start: gdb-multiarch {self.jsvm}') 397 print(f'gdb-server connect: target remote:123456') 398 os.system(cmd) 399 return 400 ret = self.run_cmd(cmd_map['abc']) 401 if ret[0]: 402 self.judge_test(file, ret) 403 return 404 if self.args.tool == 'aot': 405 ret = self.run_cmd(cmd_map['aot']) 406 if ret[0] and ret[2].find('aot compile success') < 0: 407 self.judge_test(file, ret) 408 return 409 ret = self.run_cmd(cmd_map['run']) 410 else: 411 ret = self.run_cmd(cmd_map[self.args.tool]) 412 self.judge_test(file, ret) 413 414 def run_test_on_device(self, file): 415 basename = os.path.basename(f'{file}') 416 name = os.path.splitext(basename)[0] 417 out_case_dir = '/data/test' 418 send_abc_file = f'{os.path.splitext(file)[0]}.abc'.replace('/', '\\') 419 abc_file = f'{out_case_dir}/{name}.abc' 420 cmd_map = {'abc': f'hdc file send {send_abc_file} {out_case_dir}/', 421 'aot': f'hdc shell ark_aot_compiler {self.aot_args} --aot-file={out_case_dir}/{name} {abc_file}', 422 'run': f'hdc shell ark_js_vm {self.jsvm_args} --aot-file={out_case_dir}/{name} --entry-point={name} {abc_file}', 423 'asmint': f'hdc shell ark_js_vm {self.jsvm_args} --entry-point={name} {abc_file}', 424 'int': f'hdc shell ark_js_vm {self.jsvm_args} --asm-interpreter=0 --entry-point={name} {abc_file}'} 425 if self.step != 'all': 426 run_and_print(cmd_map[self.step]) 427 return 428 run_and_print(cmd_map['abc']) 429 if self.args.tool == 'aot': 430 ret = self.run_cmd(cmd_map['aot']) 431 if ret[0] and ret[2].find('aot compile success') < 0: 432 self.judge_test(file, ret) 433 return 434 ret = self.run_cmd(cmd_map['run']) 435 else: 436 ret = self.run_cmd(cmd_map[self.args.tool]) 437 self.judge_test(file, ret) 438 439 def judge_test(self, file, out): 440 if out[0]: 441 self.fail_cases.append(file) 442 print_fail(f'FAIL: {file}') 443 return 444 expect_file = f'{os.path.dirname(file)}/{self.expect}' 445 if os.path.exists(expect_file): 446 with open(expect_file, mode='r') as infile: 447 expect = ''.join(infile.readlines()[13:]) 448 if out[1].replace('\r', '') != expect.replace('\r', ''): 449 self.fail_cases.append(file) 450 print(f'expect: [{expect}]\nbut got: [{out[1]}]') 451 print_fail(f'FAIL: {file}') 452 else: 453 print_pass(f'PASS: {file}') 454 else: 455 print_pass(f'PASS: {file}') 456 print(out[1]) 457 458 def report_test(self): 459 fail_count = len(self.fail_cases) 460 print(f'Ran tests: {self.test_count}') 461 print(f'Ran failed: {fail_count}') 462 if fail_count == 0: 463 print_pass('================================== All tests Run PASSED!') 464 return 465 print_fail('==================================') 466 for case in self.fail_cases: 467 print(case) 468 print_fail('==================================') 469 470 def find_file(self, dir, postfix_list): 471 result = [] 472 for root, lists, files in os.walk(dir): 473 for file in files: 474 for postfix in postfix_list: 475 path = os.path.join(root, file) 476 found = path.find(postfix) 477 if found == len(path) - len(postfix): 478 result.append(path) 479 if os.path.isfile(dir): 480 for postfix in postfix_list: 481 found = dir.find(postfix) 482 if found == len(dir) - len(postfix): 483 result.append(dir) 484 break 485 return result 486 487 def test_hap(self): 488 if self.step != 'all': 489 return 1 490 files = self.find_file(self.args.name, [self.hap_abc, '.hap']) 491 if len(files): 492 self.step = 'hap' 493 file = files[0] 494 type = os.path.splitext(file)[-1] 495 if type == '.hap': 496 hap_dir = f'{os.path.splitext(file)[0]}.aot' 497 os.system(f'mkdir -p {hap_dir} && unzip -o -q {file} -d {hap_dir}') 498 file = f'{hap_dir}/{self.hap_abc}' 499 self.run_test(file) 500 return 0 501 return 1 502 503 def sign_hap(self, hap_name): 504 name = os.path.splitext(hap_name)[0] 505 sign_dir = f'{name}.sign' 506 sign_tool_dir = f'{self.ohdir}/developtools/hapsigner/dist' 507 name = os.path.splitext(sign_dir)[0] 508 self_dir = os.path.abspath(sys.argv[0]) 509 os.system(f'mkdir -p {sign_dir} && unzip -o -q {hap_name} module.json -d {sign_dir}') 510 bundle_name = get_bundle_name(sign_dir) 511 if not self.args.sign or self.args.sign == 'system_core': 512 bundle_apl = 'system_core' 513 bundle_feature = 'hos_system_app' 514 elif self.args.sign == 'system_basic': 515 bundle_apl = self.args.sign 516 bundle_feature = 'hos_system_app' 517 elif self.args.sign == 'normal': 518 bundle_apl = self.args.sign 519 bundle_feature = 'hos_normal_app' 520 else: 521 print(f'sign not supported input: {self.args.sign}') 522 return 1 523 # modify sign config 524 data_load = [] 525 data_save = [] 526 sign_config = 'UnsgnedReleasedProfileTemplate.json' 527 with open(f'{sign_tool_dir}/{sign_config}') as f: 528 data_load = json.load(f) 529 data_load['bundle-info']['bundle-name'] = bundle_name 530 data_load['bundle-info']['apl'] = bundle_apl 531 data_load['bundle-info']['app-feature'] = bundle_feature 532 data_save = json.dumps(data_load) 533 with open(f'{sign_dir}/{sign_config}', 'w+') as f: 534 f.write(data_save) 535 # generate cert and sign 536 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"' 537 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"' 538 print(gen_cert) 539 print(sign_hap) 540 os.system(gen_cert) 541 os.system(sign_hap) 542 print(f'signed of {bundle_apl} for hap: {name}.sign.hap') 543 544 def test(self): 545 # run single test by name 546 files = [] 547 if self.step not in self.types: 548 print(f'not supported step: {self.step}') 549 return 1 550 if not self.args.all: 551 files = self.find_file(self.args.name, self.types[self.step]) 552 if len(files): 553 self.run_test(files[0]) 554 elif self.test_hap(): 555 print(f'only support file type: {self.types[self.step]}') 556 print(f'input path no test case: {self.args.name}') 557 return 1 558 return 0 559 560 # run all test in path 561 if not os.path.isdir(self.args.name): 562 print(f'input path not exists or is file: {self.args.name}') 563 return 1 564 files = self.find_file(self.args.name, self.types[self.step]) 565 for test in files: 566 self.run_test(test) 567 568 if len(files) == 0: 569 self.test_hap() 570 571 if self.step == 'clean': 572 print('clean output files finished') 573 return 0 574 575 if self.test_count == 0: 576 print(f'input path no test case: {self.args.name}') 577 return 1 578 579 # output report 580 self.report_test() 581 return 0 582 583def print_pass(str): 584 print(f'\033[32;2m{str}\033[0m') 585 sys.stdout.flush() 586 587def print_fail(str): 588 print(f'\033[31;2m{str}\033[0m') 589 sys.stdout.flush() 590 591def main(): 592 args = parse_args() 593 arktest = ArkTest(args) 594 return arktest.test() 595 596if __name__ == '__main__': 597 sys.exit(main()) 598