14514f5e3Sopenharmony_ci#!/usr/bin/env python3 24514f5e3Sopenharmony_ci#coding: utf-8 34514f5e3Sopenharmony_ci 44514f5e3Sopenharmony_ci""" 54514f5e3Sopenharmony_ciCopyright (c) 2021-2022 Huawei Device Co., Ltd. 64514f5e3Sopenharmony_ciLicensed under the Apache License, Version 2.0 (the "License"); 74514f5e3Sopenharmony_ciyou may not use this file except in compliance with the License. 84514f5e3Sopenharmony_ciYou may obtain a copy of the License at 94514f5e3Sopenharmony_ci 104514f5e3Sopenharmony_ci http://www.apache.org/licenses/LICENSE-2.0 114514f5e3Sopenharmony_ci 124514f5e3Sopenharmony_ciUnless required by applicable law or agreed to in writing, software 134514f5e3Sopenharmony_cidistributed under the License is distributed on an "AS IS" BASIS, 144514f5e3Sopenharmony_ciWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 154514f5e3Sopenharmony_ciSee the License for the specific language governing permissions and 164514f5e3Sopenharmony_cilimitations under the License. 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ciDescription: run script 194514f5e3Sopenharmony_ci expect_output will get run result, 204514f5e3Sopenharmony_ci expect_sub_output will catch pivotal sub output, 214514f5e3Sopenharmony_ci expect_file will get print string 224514f5e3Sopenharmony_ci""" 234514f5e3Sopenharmony_ci 244514f5e3Sopenharmony_ciimport argparse 254514f5e3Sopenharmony_ciimport os 264514f5e3Sopenharmony_ciimport stat 274514f5e3Sopenharmony_ciimport subprocess 284514f5e3Sopenharmony_ciimport sys 294514f5e3Sopenharmony_ciimport time 304514f5e3Sopenharmony_ci 314514f5e3Sopenharmony_ci 324514f5e3Sopenharmony_cidef get_env_path_from_rsp(script_file: str) -> list: 334514f5e3Sopenharmony_ci """get env path from response file recursively.""" 344514f5e3Sopenharmony_ci rsp_file = "{0}{1}".format(script_file, ".rsp") 354514f5e3Sopenharmony_ci if not os.path.exists(rsp_file): 364514f5e3Sopenharmony_ci print( 374514f5e3Sopenharmony_ci "File \"{}\" does not exist!\n" \ 384514f5e3Sopenharmony_ci "This indicates that its related shared_library is not compiled by this project, but there is an " \ 394514f5e3Sopenharmony_ci "executable or shared_library depend on its related shared_library!".format(rsp_file)) 404514f5e3Sopenharmony_ci sys.exit(1) 414514f5e3Sopenharmony_ci 424514f5e3Sopenharmony_ci rsp_info_list = [] 434514f5e3Sopenharmony_ci with open(rsp_file, "r") as fi: 444514f5e3Sopenharmony_ci rsp_info_str = fi.read() 454514f5e3Sopenharmony_ci rsp_info_list = rsp_info_str.split(" ") 464514f5e3Sopenharmony_ci 474514f5e3Sopenharmony_ci env_path_list = [] 484514f5e3Sopenharmony_ci for element in rsp_info_list: 494514f5e3Sopenharmony_ci if element.endswith(".so") or element.endswith(".dll"): 504514f5e3Sopenharmony_ci env_path_list.extend(get_env_path_from_rsp(element)) 514514f5e3Sopenharmony_ci env_path_list.append(os.path.dirname(element)) 524514f5e3Sopenharmony_ci return env_path_list 534514f5e3Sopenharmony_ci 544514f5e3Sopenharmony_ci 554514f5e3Sopenharmony_cidef get_command_and_env_path(args: object) -> [str, str]: 564514f5e3Sopenharmony_ci """get command and environment path from args for running excutable.""" 574514f5e3Sopenharmony_ci env_path_list = list(set(get_env_path_from_rsp(args.script_file))) 584514f5e3Sopenharmony_ci env_path_list.append(args.clang_lib_path) 594514f5e3Sopenharmony_ci env_path = ":".join(env_path_list) 604514f5e3Sopenharmony_ci if args.qemu_binary_path: 614514f5e3Sopenharmony_ci if not os.path.exists(args.qemu_binary_path): 624514f5e3Sopenharmony_ci print("Have you set up environment for running executables with qemu?\n" \ 634514f5e3Sopenharmony_ci "If not, get set-up steps from https://gitee.com/ark_standalone_build/docs ," \ 644514f5e3Sopenharmony_ci " append your build command of ark.py with option \"--clean-continue\"," \ 654514f5e3Sopenharmony_ci " and execute the appended command after setting up the environment.\n" \ 664514f5e3Sopenharmony_ci "If yes, the environment settings for qemu on your host machine may be different from what the link" \ 674514f5e3Sopenharmony_ci " above shows, it is suggested to match your local environment settings with what the link shows.") 684514f5e3Sopenharmony_ci sys.exit(1) 694514f5e3Sopenharmony_ci cmd = \ 704514f5e3Sopenharmony_ci "{}".format(args.qemu_binary_path) + \ 714514f5e3Sopenharmony_ci " -L {}".format(args.qemu_ld_prefix) + \ 724514f5e3Sopenharmony_ci " -E LD_LIBRARY_PATH={}".format(env_path) + \ 734514f5e3Sopenharmony_ci " {}".format(args.script_file) 744514f5e3Sopenharmony_ci else: 754514f5e3Sopenharmony_ci cmd = "{}".format(args.script_file) 764514f5e3Sopenharmony_ci cmd += " {}".format(args.script_options) if args.script_options else "" 774514f5e3Sopenharmony_ci cmd += " {}".format(args.script_args) if args.script_args else "" 784514f5e3Sopenharmony_ci return [cmd, env_path] 794514f5e3Sopenharmony_ci 804514f5e3Sopenharmony_ci 814514f5e3Sopenharmony_cidef parse_args() -> object: 824514f5e3Sopenharmony_ci """parse arguments.""" 834514f5e3Sopenharmony_ci parser = argparse.ArgumentParser() 844514f5e3Sopenharmony_ci parser.add_argument('--script-file', help='execute script file') 854514f5e3Sopenharmony_ci parser.add_argument('--script-options', help='execute script options') 864514f5e3Sopenharmony_ci parser.add_argument('--script-args', help='args of script') 874514f5e3Sopenharmony_ci parser.add_argument('--expect-output', help='expect output') 884514f5e3Sopenharmony_ci parser.add_argument('--expect-sub-output', help='expect sub output') 894514f5e3Sopenharmony_ci parser.add_argument('--expect-file', help='expect file') 904514f5e3Sopenharmony_ci parser.add_argument('--env-path', help='LD_LIBRARY_PATH env') 914514f5e3Sopenharmony_ci parser.add_argument('--timeout-limit', help='timeout limit') 924514f5e3Sopenharmony_ci parser.add_argument('--clang-lib-path', help='part for LD_LIBRARY_PATH, it is not in .rsp file') 934514f5e3Sopenharmony_ci parser.add_argument('--qemu-binary-path', help='path to qemu binary, run executable with qemu if assigned') 944514f5e3Sopenharmony_ci parser.add_argument('--qemu-ld-prefix', help='elf interpreter prefix') 954514f5e3Sopenharmony_ci args = parser.parse_args() 964514f5e3Sopenharmony_ci return args 974514f5e3Sopenharmony_ci 984514f5e3Sopenharmony_ci 994514f5e3Sopenharmony_cidef process_open(args: object) -> [str, object]: 1004514f5e3Sopenharmony_ci """get command and open subprocess.""" 1014514f5e3Sopenharmony_ci if args.env_path: 1024514f5e3Sopenharmony_ci # use the given env-path 1034514f5e3Sopenharmony_ci cmd = args.script_file 1044514f5e3Sopenharmony_ci cmd += " {}".format(args.script_options) if args.script_options else "" 1054514f5e3Sopenharmony_ci cmd += " {}".format(args.script_args) if args.script_args else "" 1064514f5e3Sopenharmony_ci # process for running executable directly 1074514f5e3Sopenharmony_ci subp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, 1084514f5e3Sopenharmony_ci env={'LD_LIBRARY_PATH': str(args.env_path)}) 1094514f5e3Sopenharmony_ci else: 1104514f5e3Sopenharmony_ci # get env-path from response file recursively 1114514f5e3Sopenharmony_ci [cmd, env_path] = get_command_and_env_path(args) 1124514f5e3Sopenharmony_ci if args.qemu_binary_path: 1134514f5e3Sopenharmony_ci # process for running executable with qemu 1144514f5e3Sopenharmony_ci subp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 1154514f5e3Sopenharmony_ci else: 1164514f5e3Sopenharmony_ci # process for running executable directly 1174514f5e3Sopenharmony_ci subp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, 1184514f5e3Sopenharmony_ci env={'LD_LIBRARY_PATH': str(env_path)}) 1194514f5e3Sopenharmony_ci return [cmd, subp] 1204514f5e3Sopenharmony_ci 1214514f5e3Sopenharmony_ci 1224514f5e3Sopenharmony_cidef generate_stub_code_comment(out_str:str): 1234514f5e3Sopenharmony_ci flags = os.O_WRONLY | os.O_CREAT 1244514f5e3Sopenharmony_ci mode = stat.S_IWUSR | stat.S_IRUSR 1254514f5e3Sopenharmony_ci dir_path = './gen/arkcompiler/ets_runtime/' 1264514f5e3Sopenharmony_ci if not os.path.exists(dir_path): 1274514f5e3Sopenharmony_ci return 1284514f5e3Sopenharmony_ci file_path = dir_path + 'stub_code_comment.txt' 1294514f5e3Sopenharmony_ci fd = os.open(file_path, flags, mode) 1304514f5e3Sopenharmony_ci with os.fdopen(fd, "w") as code_comment_file: 1314514f5e3Sopenharmony_ci code_comment_file.write(out_str) 1324514f5e3Sopenharmony_ci 1334514f5e3Sopenharmony_ci 1344514f5e3Sopenharmony_cidef judge_output(args: object): 1354514f5e3Sopenharmony_ci """run executable and judge is success or not.""" 1364514f5e3Sopenharmony_ci start_time = time.time() 1374514f5e3Sopenharmony_ci [cmd, subp] = process_open(args) 1384514f5e3Sopenharmony_ci timeout_limit = int(args.timeout_limit) if args.timeout_limit else 1200 # units: s 1394514f5e3Sopenharmony_ci 1404514f5e3Sopenharmony_ci try: 1414514f5e3Sopenharmony_ci out, err = subp.communicate(timeout=timeout_limit) 1424514f5e3Sopenharmony_ci except subprocess.TimeoutExpired: 1434514f5e3Sopenharmony_ci raise RuntimeError('Run [', cmd, '] timeout, timeout_limit = ', timeout_limit, 's') 1444514f5e3Sopenharmony_ci 1454514f5e3Sopenharmony_ci out_str = out.decode('UTF-8', errors="ignore") 1464514f5e3Sopenharmony_ci err_str = err.decode('UTF-8', errors="ignore") 1474514f5e3Sopenharmony_ci generate_stub_code_comment(out_str) 1484514f5e3Sopenharmony_ci returncode = str(subp.returncode) 1494514f5e3Sopenharmony_ci if args.expect_output: 1504514f5e3Sopenharmony_ci if returncode != args.expect_output: 1514514f5e3Sopenharmony_ci print(">>>>> ret <<<<<") 1524514f5e3Sopenharmony_ci print(returncode) 1534514f5e3Sopenharmony_ci print(">>>>> out <<<<<") 1544514f5e3Sopenharmony_ci print(out_str) 1554514f5e3Sopenharmony_ci print(">>>>> err <<<<<") 1564514f5e3Sopenharmony_ci print(err_str) 1574514f5e3Sopenharmony_ci print(">>>>> Expect return: [" + args.expect_output \ 1584514f5e3Sopenharmony_ci + "]\n>>>>> But got: [" + returncode + "]") 1594514f5e3Sopenharmony_ci raise RuntimeError("Run [" + cmd + "] failed!") 1604514f5e3Sopenharmony_ci elif args.expect_sub_output: 1614514f5e3Sopenharmony_ci if out_str.find(args.expect_sub_output) == -1 or returncode != "0": 1624514f5e3Sopenharmony_ci print(">>>>> ret <<<<<") 1634514f5e3Sopenharmony_ci print(returncode) 1644514f5e3Sopenharmony_ci print(">>>>> err <<<<<") 1654514f5e3Sopenharmony_ci print(err_str) 1664514f5e3Sopenharmony_ci print(">>>>> Expect contain: [" + args.expect_sub_output \ 1674514f5e3Sopenharmony_ci + "]\n>>>>> But got: [" + out_str + "]") 1684514f5e3Sopenharmony_ci raise RuntimeError("Run [" + cmd + "] failed!") 1694514f5e3Sopenharmony_ci elif args.expect_file: 1704514f5e3Sopenharmony_ci with open(args.expect_file, mode='r') as file: 1714514f5e3Sopenharmony_ci # skip license header 1724514f5e3Sopenharmony_ci expect_output = ''.join(file.readlines()[13:]) 1734514f5e3Sopenharmony_ci file.close() 1744514f5e3Sopenharmony_ci result_cmp = compare_line_by_line(expect_output, out_str) 1754514f5e3Sopenharmony_ci if result_cmp or returncode != "0": 1764514f5e3Sopenharmony_ci print(">>>>> ret <<<<<") 1774514f5e3Sopenharmony_ci print(returncode) 1784514f5e3Sopenharmony_ci print(">>>>> err <<<<<") 1794514f5e3Sopenharmony_ci print(err_str) 1804514f5e3Sopenharmony_ci print(">>>>> Expect {} lines: [{}]\n>>>>> But got {} lines: [{}]".format( 1814514f5e3Sopenharmony_ci expect_output.count('\n'), expect_output, out_str.count('\n'), out_str 1824514f5e3Sopenharmony_ci )) 1834514f5e3Sopenharmony_ci raise RuntimeError("Run [" + cmd + "] failed!") 1844514f5e3Sopenharmony_ci else: 1854514f5e3Sopenharmony_ci raise RuntimeError("Run [" + cmd + "] with no expect !") 1864514f5e3Sopenharmony_ci 1874514f5e3Sopenharmony_ci print("Run [" + cmd + "] success!") 1884514f5e3Sopenharmony_ci print("used: %.5f seconds" % (time.time() - start_time)) 1894514f5e3Sopenharmony_ci 1904514f5e3Sopenharmony_cidef compare_line_by_line(expect_output:str, got_output:str): 1914514f5e3Sopenharmony_ci expect_output_list = expect_output.split("\n") 1924514f5e3Sopenharmony_ci got_output_list = got_output.split("\n") 1934514f5e3Sopenharmony_ci for index, (expect_line, got_line) in enumerate(zip(expect_output_list, got_output_list)): 1944514f5e3Sopenharmony_ci if expect_line == got_line: 1954514f5e3Sopenharmony_ci continue 1964514f5e3Sopenharmony_ci error_msg = "" 1974514f5e3Sopenharmony_ci 1984514f5e3Sopenharmony_ci if "__INT_MORE_PREV__" in expect_line: 1994514f5e3Sopenharmony_ci prev_got_value = reverse_find_first_not_trace_line(got_output_list, index-1) 2004514f5e3Sopenharmony_ci if got_line.isdigit() and prev_got_value.isdigit() and int(prev_got_value) < int(got_line): 2014514f5e3Sopenharmony_ci continue 2024514f5e3Sopenharmony_ci error_msg = "Got integer result is not more than previous integer result" 2034514f5e3Sopenharmony_ci 2044514f5e3Sopenharmony_ci if "__INT__" in expect_line: 2054514f5e3Sopenharmony_ci if got_line.isdigit(): 2064514f5e3Sopenharmony_ci continue 2074514f5e3Sopenharmony_ci error_msg = "Got not integer" 2084514f5e3Sopenharmony_ci 2094514f5e3Sopenharmony_ci print(">>>>> diff <<<<<") 2104514f5e3Sopenharmony_ci if error_msg: 2114514f5e3Sopenharmony_ci print(error_msg) 2124514f5e3Sopenharmony_ci print("Difference in line {}:\nExcepted: [{}]\nBut got: [{}]".format(index+1, expect_line, got_line)) 2134514f5e3Sopenharmony_ci return True 2144514f5e3Sopenharmony_ci return False 2154514f5e3Sopenharmony_ci 2164514f5e3Sopenharmony_cidef reverse_find_first_not_trace_line(output_list: list, init_index: int) -> str: 2174514f5e3Sopenharmony_ci for i in range(init_index, -1, -1): 2184514f5e3Sopenharmony_ci if "[trace]" not in output_list[i]: 2194514f5e3Sopenharmony_ci return output_list[i] 2204514f5e3Sopenharmony_ci return "" 2214514f5e3Sopenharmony_ci 2224514f5e3Sopenharmony_ciif __name__ == '__main__': 2234514f5e3Sopenharmony_ci input_args = parse_args() 2244514f5e3Sopenharmony_ci judge_output(input_args) 225