• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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