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