• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3"""
4Copyright (c) 2023 Huawei Device Co., Ltd.
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9    http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16
17Description: Use ark to execute workload test suite
18"""
19
20import argparse
21import datetime
22import json
23import logging
24import os
25import shutil
26import stat
27import subprocess
28from collections import namedtuple
29from openpyxl import Workbook, load_workbook
30from openpyxl.styles import PatternFill
31
32
33def get_logger(logger_name, log_file_path, level=logging.INFO):
34    formatter = logging.Formatter(fmt='[%(asctime)s]  [%(levelname)s]   %(message)s',
35                                  datefmt='%Y-%m-%d  %H:%M:%S')
36
37    fh = logging.FileHandler(encoding='utf-8', mode='a', filename=log_file_path)
38    fh.setFormatter(formatter)
39    fh.setLevel(logging.DEBUG)
40    # console output
41    ch = logging.StreamHandler()
42    ch.setFormatter(formatter)
43    ch.setLevel(logging.DEBUG)
44    log = logging.getLogger(logger_name)
45    log.addHandler(fh)
46    log.addHandler(ch)
47    log.setLevel(level)
48
49    return log
50
51
52class Constants:
53    logger = None
54    CUR_PATH = os.path.abspath(os.path.dirname(__file__))
55    TMP_PATH = os.path.join(os.getcwd(), "tmp")
56    REPORT_NAME_HEAD_FIX = "js_perf_test_result"
57    RET_OK = 0
58    RET_FAILED = 1
59    BINARY_PATH = ""
60    OUTPUT_PATH = ""
61    LOG_PATH = ""
62    TODAY_EXCEL_PATH = ""
63    YESTERDAY_EXCEL_PATH = ""
64    DETERIORATION_BOUNDARY_VALUE = 0.05
65    TODAY_EXCUTE_INFO = {}
66    YESTERDAY_EXCUTE_TIME_DICT = {}
67    V_8_EXCUTE_TIME_DICT = {}
68    V_8_JITLESS_EXCUTE_TIME_DICT = {}
69    JS_FILE_SUPER_LINK_DICT = {}
70    HYPERLINK_HEAD = "https://gitee.com/dov1s/arkjs-perf-test/tree/builtins_test1110/js-perf-test"
71    PASS = 'pass'
72    FAIL = 'fail'
73    SOLID = 'solid'
74    NA_FIX = 'NA'
75    # 1e-6 s
76    COMPARISON_ACCURACY = 0.001
77    ICU_DATA_PATH = ""
78    FIX_STR = "8/d"
79    V_8_ENGINED_PATH = '/usr/bin/v{}8'.format(FIX_STR)
80    VER_PLATFORM = "full_x86_64"
81    ES2ABC_PATH = ""
82    ARK_JS_VM_PATH = ""
83    CaseTestDataType = namedtuple('test', ['exec_status', 'exec_time'])
84
85
86def get_js_file_class_api_scenes(js_file_path):
87    scenes = []
88    with open(js_file_path, 'r') as f:
89        for line in f:
90            if "scene_output" in line:
91                str_array = line.split(':')
92                mid_str = str_array[1].strip()
93                elements = mid_str.split(' ')
94                main_key = '/'.join([elements[0], elements[1] + '.js', elements[2]]).lower()
95                scenes.append(main_key)
96    return scenes
97
98
99def degraded_str(yesterday_excute_time, exec_time):
100    is_degraded_str = Constants.NA_FIX
101    if len(str(yesterday_excute_time).strip()) != 0:
102        if abs(float(yesterday_excute_time)) <= Constants.COMPARISON_ACCURACY:
103            is_degraded_str = str(True) if abs(float(exec_time)) >= DETERIORATION_BOUNDARY_VALUE else str(False)
104        else:
105            is_degraded_tmp = float(exec_time) / float(yesterday_excute_time) >= (1 + DETERIORATION_BOUNDARY_VALUE)
106            is_degraded_str = str(True) if is_degraded_tmp else str(False)
107
108    return is_degraded_str
109
110
111def v_8_excute_time_compute(main_key):
112    v_8_excute_time_str = ''
113    if len(Constants.V_8_EXCUTE_TIME_DICT) > 0 and main_key in Constants.V_8_EXCUTE_TIME_DICT.keys():
114        v_8_excute_time_str = Constants.V_8_EXCUTE_TIME_DICT[main_key].strip()
115
116    if len(v_8_excute_time_str) == 0:
117        v_8_excute_time = ' '
118    else:
119        v_8_excute_time = v_8_excute_time_str
120
121    return v_8_excute_time
122
123
124def v_8_gitless_excute_time_compute(main_key):
125    v_8_jitless_excute_time_str = ''
126    if len(Constants.V_8_JITLESS_EXCUTE_TIME_DICT) > 0 and main_key in Constants.V_8_JITLESS_EXCUTE_TIME_DICT.keys():
127        v_8_jitless_excute_time_str = Constants.V_8_JITLESS_EXCUTE_TIME_DICT[main_key].strip()
128
129    if len(v_8_jitless_excute_time_str) == 0:
130        v_8_jitless_excute_time = ' '
131    else:
132        v_8_jitless_excute_time = v_8_jitless_excute_time_str
133
134    return v_8_jitless_excute_time
135
136
137def ark_divide_v_8_compute(exec_time, v_8_excute_time):
138    if len(exec_time) == 0 or len(v_8_excute_time.strip()) == 0:
139        ark_divide_v_8 = Constants.NA_FIX
140    elif abs(float(exec_time)) <= Constants.COMPARISON_ACCURACY:
141        if abs(float(v_8_excute_time)) <= Constants.COMPARISON_ACCURACY:
142            ark_divide_v_8 = '1'
143        else:
144            ark_divide_v_8 = '0'
145    else:
146        v_8_excute_time = v_8_excute_time.strip()
147        if len(v_8_excute_time) == 0 or abs(float(v_8_excute_time)) <= Constants.COMPARISON_ACCURACY:
148            ark_divide_v_8 = Constants.NA_FIX
149        else:
150            ark_divide_v_8 = str("{:.2f}".format(float(exec_time) / float(v_8_excute_time)))
151
152    return ark_divide_v_8
153
154
155def append_row_data(report_file, case_test_data):
156    wb = load_workbook(report_file)
157    ws = wb.worksheets[0]
158    for main_key in case_test_data.keys():
159        str_arr = main_key.split('/')
160        class_name = str_arr[0]
161        api_name = str_arr[1]
162        scene = str_arr[2]
163        js_case_name = '/'.join([class_name, api_name])
164        excute_status = case_test_data[main_key].exec_status
165        exec_time = case_test_data[main_key].exec_time.strip()
166        yesterday_excute_time = ''
167        if (len(Constants.YESTERDAY_EXCUTE_TIME_DICT) > 0 and
168                Constants.YESTERDAY_EXCUTE_TIME_DICT.get(main_key) is not None):
169            yesterday_excute_time = str(Constants.YESTERDAY_EXCUTE_TIME_DICT[main_key])
170        is_degraded_str = degraded_str(yesterday_excute_time, exec_time)
171        v_8_excute_time = v_8_excute_time_compute(main_key)
172        v_8_jitless_excute_time = v_8_gitless_excute_time_compute(main_key)
173        ark_divide_v_8 = ark_divide_v_8_compute(exec_time, v_8_excute_time)
174        if len(exec_time) == 0 or len(v_8_jitless_excute_time.strip()) == 0:
175            ark_divide_v_8_with_jitless = Constants.NA_FIX
176        elif abs(float(exec_time)) <= Constants.COMPARISON_ACCURACY:
177            if abs(float(v_8_jitless_excute_time)) <= Constants.COMPARISON_ACCURACY:
178                ark_divide_v_8_with_jitless = '1'
179            else:
180                ark_divide_v_8_with_jitless = '0'
181        else:
182            v_8_jitless_excute_time = v_8_jitless_excute_time.strip()
183            if (len(v_8_jitless_excute_time) == 0 or
184                    abs(float(v_8_jitless_excute_time)) <= Constants.COMPARISON_ACCURACY):
185                ark_divide_v_8_with_jitless = Constants.NA_FIX
186            else:
187                ark_divide_v_8_with_jitless = str("{:.2f}".format(float(exec_time) / float(v_8_jitless_excute_time)))
188        jis_case_file_name_with_class = Constants.JS_FILE_SUPER_LINK_DICT['/'.join([class_name, api_name])]
189        js_file_super_link = '/'.join([Constants.HYPERLINK_HEAD, jis_case_file_name_with_class])
190        new_row = [js_case_name, scene, excute_status, exec_time, yesterday_excute_time,
191                   is_degraded_str, v_8_excute_time, v_8_jitless_excute_time, ark_divide_v_8,
192                   ark_divide_v_8_with_jitless, js_file_super_link, ' ']
193        ws.append(new_row)
194        if is_degraded_str is str(True):
195            ws.cell(row=ws.max_row, column=6).fill = PatternFill(start_color='FF0000', end_color='FF0000',
196                                                                 fill_type=Constants.SOLID)
197        if (ark_divide_v_8 != Constants.NA_FIX and
198            (float(ark_divide_v_8) > 2 or
199             abs(float(ark_divide_v_8) - 2) <= Constants.COMPARISON_ACCURACY)):
200            ws.cell(row=ws.max_row, column=9).fill = PatternFill(start_color='FFFF00', end_color='FFFF00',
201                                                                 fill_type=Constants.SOLID)
202        if (ark_divide_v_8_with_jitless != Constants.NA_FIX and
203            (float(ark_divide_v_8_with_jitless) > 2 or
204             abs(float(ark_divide_v_8_with_jitless) - 2) <= Constants.COMPARISON_ACCURACY)):
205            ws.cell(row=ws.max_row, column=10).fill = PatternFill(start_color='FF00FF', end_color='FF00FF',
206                                                                  fill_type=Constants.SOLID)
207    wb.save(report_file)
208    return Constants.RET_OK
209
210
211def run_js_case_via_ark(binary_path, js_file_path, class_name, api_name, report_file):
212    composite_scenes = get_js_file_class_api_scenes(js_file_path)
213    case_test_data = {}
214    execute_status = Constants.FAIL
215    execute_time = ' '
216
217    for _, composite_scene in enumerate(composite_scenes):
218        case_test_data[composite_scene] = Constants.CaseTestDataType(execute_status, execute_time)
219
220    js_file_name = class_name + '/' + api_name + '.js'
221    fangzhou_test_path = os.path.join(Constants.TMP_PATH, "fangzhou_test")  # for abc file
222    if os.path.exists(fangzhou_test_path):
223        shutil.rmtree(fangzhou_test_path)
224    os.makedirs(fangzhou_test_path)
225
226    class_folder_path = os.path.join(fangzhou_test_path, class_name)
227    api_path = os.path.join(class_folder_path, api_name)
228    if not os.path.exists(class_folder_path):
229        os.makedirs(class_folder_path)
230    abc_file_path = api_path + ".abc"
231    cur_abc_file = os.path.join(Constants.CUR_PATH, api_name + ".abc")
232    api_log_path = os.path.join(class_folder_path, api_name + ".log")
233
234    es2abc_path = Constants.ES2ABC_PATH
235    # tranmit abc
236    cmd = [es2abc_path, js_file_path]
237
238    logger.info("run cmd: %s", cmd)
239    ret = subprocess.run(cmd)
240    if ret.returncode != 0:
241        logger.error("ret = %s, %s generate abc file failed. cmd: %s", str(ret), js_file_name, cmd)
242        append_row_data(report_file, case_test_data)
243        return case_test_data
244
245    cmd2 = ["cp", cur_abc_file, abc_file_path]
246    ret = subprocess.run(cmd2)
247    if ret.returncode != 0:
248        logger.error("ret.returncode = %s, %s generate abc file failed. cmd: %s", str(ret.returncode), js_file_name,
249                     cmd2)
250        append_row_data(report_file, case_test_data)
251        return case_test_data
252    # execute abc
253    ark_js_vm_path = Constants.ARK_JS_VM_PATH
254    cmd = [ark_js_vm_path, "--log-level=info", "--enable-runtime-stat=true", "--icu-data-path",
255           ICU_DATA_PATH, cur_abc_file]
256
257    logger.info("run cmd: %s", cmd)
258    flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
259    modes = stat.S_IWUSR | stat.S_IRUSR
260    if os.path.exists(api_log_path):
261        os.remove(api_log_path)
262    with os.fdopen(os.open(api_log_path, flags, modes), 'wb') as outfile:
263        ret = subprocess.run(cmd, stdout=outfile)
264
265    if ret.returncode != 0:
266        logger.error("%s execute abc file failed. cmd: %s", js_file_name, cmd)
267        append_row_data(report_file, case_test_data)
268        return case_test_data
269    else:
270        case_test_data.clear()
271        if os.path.exists(api_log_path):
272            with open(api_log_path, 'r') as f:
273                for line in f:
274                    if "scene_output" not in line:
275                        continue
276
277                    mid_str = line.split(':')[1].strip()
278                    scene = mid_str.split()[2]
279                    main_key = '/'.join([js_file_name, scene]).lower()
280                    execute_time = line.split(':')[2]
281                    execute_status = Constants.PASS
282                    case_test_data[main_key] = Constants.CaseTestDataType(execute_status, execute_time)
283
284        append_row_data(report_file, case_test_data)
285        logger.info("%s execute abc file successfully. cmd: %s case_test_data: %s", js_file_name, cmd, case_test_data)
286
287    os.remove(cur_abc_file)
288    return case_test_data
289
290
291def run_via_ark(jspath, report_file):
292    if not os.path.exists(jspath):
293        logger.error("js perf cases path is not exist. jspath: %s", jspath)
294    logger.info("begin to run js perf test via ark. js perf cases path: %s", jspath)
295    for root, _, files in os.walk(jspath):
296        if "TestCaseError" in root:
297            continue
298        for file in files:
299            if not file.endswith('.js'):
300                continue
301
302            file_path = os.path.join(root, file)
303            results = file_path.split("/")
304            class_name = results[-2]
305            api_name = results[-1].split(".")[0]
306            js_case_name = '/'.join([class_name, results[-1]])
307            logger.info("begin to execute %s.", js_case_name)
308            test_data = run_js_case_via_ark(BINARY_PATH, file_path, class_name, api_name, report_file)
309            for _, key in enumerate(test_data.keys()):
310                Constants.TODAY_EXCUTE_INFO[key] = test_data.get(key)
311            logger.info("finish executing %s. executing info: %s.", js_case_name, Constants.TODAY_EXCUTE_INFO)
312
313
314def get_js_case_super_link_data(jspath):
315    logger.info("get js case super link data")
316    for root, _, files in os.walk(jspath):
317        for file in files:
318            if not file.endswith('.js'):
319                continue
320
321            file_path = os.path.join(root, file)
322            results = file_path.split("/")
323            class_name = results[-2]
324            js_case_name = '/'.join([class_name, results[-1]])
325            key = js_case_name.lower()
326            Constants.JS_FILE_SUPER_LINK_DICT[key] = js_case_name
327
328
329def export_sumary_info_for_notifying_email(json_path, total_cases_num, ark_divide_v_8_num, ark_divide_v_8_jitless_num):
330    data = {}
331    data['kind'] = 'V 8 js-perf-test'
332    data['Total'] = total_cases_num
333    data['Ark劣化v 8'] = ark_divide_v_8_num
334    data['Ark劣化v 8 jitless'] = ark_divide_v_8_jitless_num
335    flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
336    modes = stat.S_IWUSR | stat.S_IRUSR
337    if os.path.exists(json_path):
338        os.remove(json_path)
339    with os.fdopen(os.open(json_path, flags, modes), 'w', encoding='utf-8') as f:
340        json.dump(data, f, indent=4, ensure_ascii=False)
341        logger.info("export summary info to json file successfully.")
342
343
344def get_umary_info_json_file_path(daily_report_file_path):
345    dir_path = os.path.dirname(daily_report_file_path)
346    json_file_name = 'jsperftest_notifying_info_in_email.json'
347    json_file_path = os.path.join(dir_path, json_file_name)
348    return json_file_path
349
350
351def append_summary_info(report_file, total_cost_time):
352    """
353        summary info:
354            pass count:
355            fail count:
356            totle count:
357            degraded count:
358            total excute time is(s) :
359            degraded percentage upper limit:
360            ark/v 8 degraded count:
361            ark/v 8 jitless degraded count:
362    """
363    wb = load_workbook(report_file)
364    ws = wb.worksheets[0]
365
366    totle_num = 0
367    degraded_upper_limit = DETERIORATION_BOUNDARY_VALUE
368    pass_num = 0
369    failed_num = 0
370    degraded_num = 0
371    ark_divide_v_8_degraded_count = 0
372    ark_divide_v_8_jitless_degraded_count = 0
373
374    for row_num in range(2, ws.max_row + 1):
375        excu_status = str(ws.cell(row=row_num, column=3).value)
376        is_degraded = str(ws.cell(row=row_num, column=6).value)
377        if is_degraded == str(True):
378            degraded_num += 1
379
380        if excu_status == Constants.PASS:
381            pass_num += 1
382            totle_num += 1
383        elif excu_status == Constants.FAIL:
384            failed_num += 1
385            totle_num += 1
386
387        obj = ws.cell(row=row_num, column=9).value
388        if obj is None:
389            obj = 0
390        ark_divide_v_8 = obj
391        if ark_divide_v_8 != Constants.NA_FIX and float(ark_divide_v_8) > 1:
392            ark_divide_v_8_degraded_count += 1
393        obj = ws.cell(row=row_num, column=10).value
394        if obj is None:
395            obj = 0
396        ark_divide_v_8_jitless = obj
397        if ark_divide_v_8_jitless != Constants.NA_FIX and float(ark_divide_v_8_jitless) > 1:
398            ark_divide_v_8_jitless_degraded_count += 1
399
400    count = 3
401    for _ in range(count):
402        new_row = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
403        ws.append(new_row)
404    new_row = ['劣化判定比率上限', degraded_upper_limit, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
405    ws.append(new_row)
406    new_row = ['js 用例总数', totle_num, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
407    ws.append(new_row)
408    new_row = ['Pass 数量', pass_num, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
409    ws.append(new_row)
410    new_row = ['Fail 数量', failed_num, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
411    ws.append(new_row)
412    new_row = ['ark今日劣化数量', degraded_num, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
413    ws.append(new_row)
414    new_row = ['Total excute time(时:分:秒.微妙)', total_cost_time, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
415    ws.append(new_row)
416    new_row = ['ark/v 8 劣化数量', ark_divide_v_8_degraded_count, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
417    ws.append(new_row)
418    new_row = ['ark/v 8 jitless 劣化数量', ark_divide_v_8_jitless_degraded_count, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
419               ' ', ' ']
420    ws.append(new_row)
421
422    ws.column_dimensions.group('E', hidden=True)
423    wb.save(report_file)
424
425    json_file_path = get_umary_info_json_file_path(report_file)
426    export_sumary_info_for_notifying_email(json_file_path, totle_num, ark_divide_v_8_degraded_count,
427                                           ark_divide_v_8_jitless_degraded_count)
428    return Constants.RET_OK
429
430
431def get_args():
432    parser = argparse.ArgumentParser()
433    parser.add_argument(
434        "--binarypath",
435        "-bp",
436        required=True,
437        help="path of binary folder. refer to harmony root folder path",
438    )
439    parser.add_argument(
440        "--jspath",
441        "-p",
442        required=True,
443        help="path of js scripts, support folder and file",
444    )
445    parser.add_argument(
446        "--deterioration_boundary_value",
447        "-d",
448        default=0.05,
449        help="deterioration boundary value, default 0.05",
450    )
451    parser.add_argument(
452        "--output_folder_path",
453        "-o",
454        default=None,
455        help="output folder for executing js cases, default current folder",
456    )
457    parser.add_argument(
458        "--d_8_binary_path",
459        "-v",
460        default=None,
461        help="v 8 engine d 8 binary path",
462    )
463    parser.add_argument(
464        "--ver_platform",
465        "-e",
466        default="full_x86_64",
467        help="Code repository version and platform",
468    )
469    args = parser.parse_args()
470
471    if not os.path.exists(args.binarypath):
472        logger.error("parameter --binarypath is not exist. Please check it! binary path: %s", args.binarypath)
473        raise RuntimeError("error bad  parameters  --binarypath")
474
475    if args.output_folder_path is None:
476        args.output_folder_path = os.getcwd()
477
478    if not os.path.isabs(args.output_folder_path):
479        args.output_folder_path = os.path.abspath(args.output_folder_path)
480
481    if not os.path.exists(args.d_8_binary_path):
482        logger.error("parameter --d_8_binary_path is not exist. Please check it! d 8  binary path: %s",
483                     args.d_8_binary_path)
484        raise RuntimeError("error bad  parameters  --d_8_binary_path: {}".format(args.d_8_binary_path))
485
486    return args
487
488
489def init_report(report_file):
490    try:
491        today_wb = load_workbook(report_file)
492        today_ws = today_wb.worksheets[0]
493    except FileNotFoundError:
494        headers_row = ['用例名称', '场景', '执行状态', 'ark用例执行耗时(ms)', '昨日ark用例执行耗时(ms)', '是否劣化',
495                       'v 8(ms)', 'v 8 --jitless(ms)', 'ark/v 8', 'ark/v 8 jitless', 'hyperlink', '备注']
496        today_wb = Workbook()
497        today_ws = today_wb.active
498
499        today_ws.column_dimensions['A'].width = 35.0
500        today_ws.column_dimensions['B'].width = 15.0
501        today_ws.column_dimensions['C'].width = 15.0
502        today_ws.column_dimensions['D'].width = 15.0
503        today_ws.column_dimensions['E'].width = 25.0
504        today_ws.column_dimensions['F'].width = 15.0
505        today_ws.column_dimensions['G'].width = 15.0
506        today_ws.column_dimensions['H'].width = 15.0
507        today_ws.column_dimensions['I'].width = 15.0
508        today_ws.column_dimensions['J'].width = 15.0
509        today_ws.column_dimensions['K'].width = 50.0
510        today_ws.column_dimensions['L'].width = 15.0
511        today_ws.append(headers_row)
512        today_ws.freeze_panes = 'A2'
513        today_wb.save(report_file)
514
515
516def append_date_label(target_str, date_input):
517    formatted_date = date_input.strftime('%Y%m%d')
518    new_str = target_str + "_{}".format(formatted_date)
519
520    return new_str
521
522
523def get_v_8_benchmark_daily_report_path():
524    '''
525        get v 8 based data. v 8 based data obtained on 1,11,21 day for dayevery month.that is to say, in 1,11,21,
526        v 8 executes js cases.
527    '''
528    now = datetime.datetime.now(tz=datetime.timezone.utc)
529    today_str = now.strftime("%Y.%m.%d")
530    str_list = today_str.split('.')
531    year_str = str_list[0]
532    month_str = str_list[1]
533    day = int(str_list[2])
534    based_day = 0
535    if day > 21:
536        based_day = 21
537    elif day > 11:
538        based_day = 11
539    else:
540        based_day = 1
541
542    based_date = year_str + month_str + str(based_day)
543    base_date_file = based_date + '.xlsx'
544    based_report_name = '_'.join([Constants.REPORT_NAME_HEAD_FIX, base_date_file])
545    report_file_path = os.path.join(OUTPUT_PATH, based_report_name)
546    return report_file_path
547
548
549def get_given_date_report_name(date_input):
550    report_name_head = append_date_label(Constants.REPORT_NAME_HEAD_FIX, date_input)
551    return report_name_head + ".xlsx"
552
553
554def get_given_date_report_path(date_input):
555    report_file_name = get_given_date_report_name(date_input)
556    report_file_path = os.path.join(OUTPUT_PATH, report_file_name)
557    return report_file_path
558
559
560def get_yesterday_excute_times(yesterday_report):
561    if not os.path.exists(yesterday_report) or not os.path.isfile(yesterday_report):
562        return
563
564    wb = load_workbook(yesterday_report)
565    ws = wb.worksheets[0]
566    for row_num in range(2, ws.max_row + 1):
567        js_case = ws.cell(row=row_num, column=1).value
568        scene = ws.cell(row=row_num, column=2).value
569        exec_status = ws.cell(row=row_num, column=3).value
570        if exec_status == Constants.PASS or exec_status == Constants.FAIL:
571            main_key = '/'.join([js_case, scene]).lower()
572            excute_time = ws.cell(row=row_num, column=4).value
573            Constants.YESTERDAY_EXCUTE_TIME_DICT[main_key] = excute_time
574
575
576def run_v_8_single_js_case(js_file_path, cmd_para, js_case_name):
577    v_8_exec_time_dict = {}
578    scenes = get_js_file_class_api_scenes(js_file_path)
579
580    v_8_log_path = os.path.join(Constants.CUR_PATH, "v_8.log")
581    if os.path.exists(v_8_log_path):
582        os.remove(v_8_log_path)
583
584    flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
585    modes = stat.S_IWUSR | stat.S_IRUSR
586    with os.fdopen(os.open(v_8_log_path, flags, modes), 'wb') as outfile:
587        if len(cmd_para) == 0:
588            cmd = [Constants.V_8_ENGINED_PATH, js_file_path]
589        else:
590            cmd = [Constants.V_8_ENGINED_PATH, cmd_para, js_file_path]
591        logger.info("run cmd:%s", cmd)
592        ret = subprocess.run(cmd, stdout=outfile)
593
594        if ret.returncode != 0:
595            for elem in enumerate(scenes):
596                v_8_exec_time_dict[elem] = 0
597            logger.error("execute cmd failed. cmd: %s", cmd)
598            return v_8_exec_time_dict
599
600    logger.info("v 8 excute %s successfully. cmd: %s", js_file_path, cmd)
601
602    with open(v_8_log_path, 'r') as f:
603        for line in f:
604            if "scene_output" not in line:
605                continue
606            str_array = line.split(':')
607            mid_str = str_array[1].strip()
608            scene = mid_str.split()[2]
609            exec_time = str_array[2]
610            key_str = '/'.join([js_case_name + '.js', scene]).lower()
611            v_8_exec_time_dict[key_str] = exec_time
612
613    os.remove(v_8_log_path)
614    return v_8_exec_time_dict
615
616
617def get_given_column_data(report_file, column_index):
618    column_data = {}
619    if os.path.exists(report_file) and report_file.endswith('.xlsx'):
620        wb = load_workbook(report_file)
621        ws = wb.worksheets[0]
622
623        for row_num in range(2, ws.max_row + 1):
624            js_case_name = str(ws.cell(row=row_num, column=1).value)
625            scene = str(ws.cell(row=row_num, column=2).value)
626            exec_status = str(ws.cell(row=row_num, column=3).value)
627            time = str(ws.cell(row=row_num, column=column_index).value)
628            if exec_status == Constants.PASS or exec_status == Constants.FAIL:
629                main_key = '/'.join([js_case_name, scene])
630                column_data[main_key] = time
631
632    return column_data
633
634
635def get_v_8_excute_times(jspath, v_8_based_report_file):
636    if os.path.exists(v_8_based_report_file) and os.path.isfile(v_8_based_report_file):
637        # Generate v 8 benchmark data on the 1st, 11th, and 21st of each month.The testing at other times refers to
638        # these V 8 benchmark data
639        v_8_exec_time_dict = get_given_column_data(v_8_based_report_file, 7)
640        for key in v_8_exec_time_dict.keys():
641            Constants.V_8_EXCUTE_TIME_DICT[key] = v_8_exec_time_dict[key]
642        return Constants.RET_OK
643
644    file_list = []
645    for root, _, files in os.walk(jspath):
646        for file in files:
647            if not file.endswith('.js'):
648                continue
649            file_path = os.path.join(root, file)
650            file_list.append(file_path)
651    for _, file_path in enumerate(file_list):
652        results = file_path.split("/")
653        class_name = results[-2]
654        api_name = results[-1].split(".")[0]
655        js_case_name = '/'.join([class_name, api_name])
656
657        v_8_exec_time_dict = run_v_8_single_js_case(file_path, '', js_case_name)
658        for key in v_8_exec_time_dict.keys():
659            Constants.V_8_EXCUTE_TIME_DICT[key] = v_8_exec_time_dict[key]
660
661    return Constants.RET_OK
662
663
664def get_v_8_jitless_excute_times(jspath, v_8_based_report_file_path):
665    if os.path.exists(v_8_based_report_file_path) and os.path.isfile(v_8_based_report_file_path):
666        # Generate v 8 benchmark data on the 1st, 11th, and 21st of each month.The testing at other times refers to
667        # these V 8 benchmark data
668        v_8_exec_time_dict = get_given_column_data(v_8_based_report_file_path, 8)
669        for key in v_8_exec_time_dict.keys():
670            Constants.V_8_JITLESS_EXCUTE_TIME_DICT[key] = v_8_exec_time_dict[key]
671        return Constants.RET_OK
672
673    file_list = []
674    for root, _, files in os.walk(jspath):
675        for file in files:
676            if not file.endswith('.js'):
677                continue
678            file_path = os.path.join(root, file)
679            file_list.append(file_path)
680
681    for _, file_path in enumerate(file_list):
682        results = file_path.split("/")
683        class_name = results[-2]
684        api_name = results[-1].split(".")[0]
685        js_case_name = '/'.join([class_name, api_name])
686
687        v_8_exec_time_dict = run_v_8_single_js_case(file_path, '--jitless', js_case_name)
688        for key in v_8_exec_time_dict.keys():
689            Constants.V_8_JITLESS_EXCUTE_TIME_DICT[key] = v_8_exec_time_dict[key]
690
691    return Constants.RET_OK
692
693
694def get_config():
695    config_json_path = os.path.join(Constants.CUR_PATH, "config.json")
696    with open(config_json_path, 'r', encoding='UTF-8') as f:
697        json_data = json.load(f)
698
699    Constants.ES2ABC_PATH = os.path.join(BINARY_PATH, json_data[Constants.VER_PLATFORM]["ES2ABC"])
700    Constants.ARK_JS_VM_PATH = os.path.join(BINARY_PATH, json_data[Constants.VER_PLATFORM]["ETS_RUNTIME_PATH"],
701                                            "ark_js_vm")
702    ETS_RUNTIME_PATH = os.path.join(BINARY_PATH, json_data[Constants.VER_PLATFORM]["ETS_RUNTIME_PATH"])
703    ICU_PATH = os.path.join(BINARY_PATH, json_data[Constants.VER_PLATFORM]["ICU_PATH"])
704    ZLIB_PATH = os.path.join(BINARY_PATH, json_data[Constants.VER_PLATFORM]["ZLIB_PATH"])
705    LIB_PATH = os.path.join(BINARY_PATH, json_data[Constants.VER_PLATFORM]["LIB_PATH"])
706    old_ld_library_path = os.environ.get('LD_LIBRARY_PATH', '')
707    os.environ['LD_LIBRARY_PATH'] = f'{ETS_RUNTIME_PATH}:' + f'{ICU_PATH}:' + f'{ZLIB_PATH}:' + f'{LIB_PATH}:'\
708                                    + old_ld_library_path
709
710
711if __name__ == "__main__":
712    """
713        command format: python3  run_js_test.py  -bp /home/out -p /home/arkjs-perf-test/js-perf-test -o output_path
714            -v d_8_binary_path -e ver_platform
715        notes: all paths must be absolute path
716    """
717    LOG_PATH = os.path.join(Constants.TMP_PATH, "test.log")
718    if os.path.exists(LOG_PATH):
719        os.remove(LOG_PATH)
720    logger = get_logger("jstest", LOG_PATH)
721
722    paras = get_args()
723    logger.info("execute arguments: %s", paras)
724
725    DETERIORATION_BOUNDARY_VALUE = paras.deterioration_boundary_value
726    BINARY_PATH = paras.binarypath
727    ICU_DATA_PATH = os.path.join(BINARY_PATH, "third_party/icu/ohos_icu4j/data/")
728    OUTPUT_PATH = Constants.CUR_PATH
729    Constants.V_8_ENGINED_PATH = paras.d_8_binary_path
730    Constants.VER_PLATFORM = paras.ver_platform
731    get_config()
732
733    if paras.output_folder_path is not None:
734        OUTPUT_PATH = paras.output_folder_path
735
736    if not os.path.exists(OUTPUT_PATH):
737        os.makedirs(OUTPUT_PATH)
738
739    today = datetime.date.today()
740    yesterday = today - datetime.timedelta(days=1)
741    TODAY_EXCEL_PATH = get_given_date_report_path(today)
742    YESTERDAY_EXCEL_PATH = get_given_date_report_path(yesterday)
743
744    if os.path.exists(TODAY_EXCEL_PATH):
745        os.remove(TODAY_EXCEL_PATH)
746
747    get_js_case_super_link_data(paras.jspath)
748    start_time = datetime.datetime.now(tz=datetime.timezone.utc)
749    init_report(TODAY_EXCEL_PATH)
750    get_yesterday_excute_times(YESTERDAY_EXCEL_PATH)
751    v_8_based_report_path = get_v_8_benchmark_daily_report_path()
752    get_v_8_excute_times(paras.jspath, v_8_based_report_path)
753    get_v_8_jitless_excute_times(paras.jspath, v_8_based_report_path)
754
755    run_via_ark(paras.jspath, TODAY_EXCEL_PATH)
756    end_time = datetime.datetime.now(tz=datetime.timezone.utc)
757
758    totol_time = u"%s" % (end_time - start_time)
759    append_summary_info(TODAY_EXCEL_PATH, totol_time)
760
761    logger.info("run js perf test finished. Please check details in report.")
762    shutil.rmtree(Constants.TMP_PATH)
763