1#!/usr/bin/env python3 2#coding: utf-8 3 4""" 5Copyright (c) 2021-2022 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: run script 19 expect_output will get run result, 20 expect_sub_output will catch pivotal sub output, 21 expect_file will get print string 22""" 23 24import argparse 25import os 26import subprocess 27import sys 28import time 29 30 31def get_env_path_from_rsp(script_file: str) -> list: 32 """get env path from response file recursively.""" 33 rsp_file = "{0}{1}".format(script_file, ".rsp") 34 if not os.path.exists(rsp_file): 35 print( 36 "File \"{}\" does not exist!\n" \ 37 "This indicates that its related shared_library is not compiled by this project, but there is an " \ 38 "executable or shared_library depend on its related shared_library!".format(rsp_file)) 39 sys.exit(1) 40 41 rsp_info_list = [] 42 with open(rsp_file, "r") as fi: 43 rsp_info_str = fi.read() 44 rsp_info_list = rsp_info_str.split(" ") 45 46 env_path_list = [] 47 for element in rsp_info_list: 48 if element.endswith(".so") or element.endswith(".dll"): 49 env_path_list.extend(get_env_path_from_rsp(element)) 50 env_path_list.append(os.path.dirname(element)) 51 return env_path_list 52 53 54def get_command_and_env_path(args: object) -> [str, str]: 55 """get command and environment path from args for running excutable.""" 56 env_path_list = list(set(get_env_path_from_rsp(args.script_file))) 57 env_path_list.append(args.clang_lib_path) 58 env_path = ":".join(env_path_list) 59 if args.qemu_binary_path: 60 if not os.path.exists(args.qemu_binary_path): 61 print("Have you set up environment for running executables with qemu?\n" \ 62 "If not, get set-up steps from https://gitee.com/ark_standalone_build/docs ," \ 63 " append your build command of ark.py with option \"--clean-continue\"," \ 64 " and execute the appended command after setting up the environment.\n" \ 65 "If yes, the environment settings for qemu on your host machine may be different from what the link" \ 66 " above shows, it is suggested to match your local environment settings with what the link shows.") 67 sys.exit(1) 68 cmd = \ 69 "{}".format(args.qemu_binary_path) + \ 70 " -L {}".format(args.qemu_ld_prefix) + \ 71 " -E LD_LIBRARY_PATH={}".format(env_path) + \ 72 " {}".format(args.script_file) 73 else: 74 cmd = "{}".format(args.script_file) 75 cmd += " {}".format(args.script_options) if args.script_options else "" 76 cmd += " {}".format(args.script_args) if args.script_args else "" 77 return [cmd, env_path] 78 79 80def parse_args() -> object: 81 """parse arguments.""" 82 parser = argparse.ArgumentParser() 83 parser.add_argument('--script-file', help='execute script file') 84 parser.add_argument('--script-options', help='execute script options') 85 parser.add_argument('--script-args', help='args of script') 86 parser.add_argument('--expect-output', help='expect output') 87 parser.add_argument('--expect-sub-output', help='expect sub output') 88 parser.add_argument('--expect-file', help='expect file') 89 parser.add_argument('--env-path', help='LD_LIBRARY_PATH env') 90 parser.add_argument('--timeout-limit', help='timeout limit') 91 parser.add_argument('--clang-lib-path', help='part for LD_LIBRARY_PATH, it is not in .rsp file') 92 parser.add_argument('--qemu-binary-path', help='path to qemu binary, run executable with qemu if assigned') 93 parser.add_argument('--qemu-ld-prefix', help='elf interpreter prefix') 94 args = parser.parse_args() 95 return args 96 97 98def process_open(args: object) -> [str, object]: 99 """get command and open subprocess.""" 100 if args.env_path: 101 # use the given env-path 102 cmd = args.script_file 103 cmd += " {}".format(args.script_options) if args.script_options else "" 104 cmd += " {}".format(args.script_args) if args.script_args else "" 105 # process for running executable directly 106 subp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, 107 env={'LD_LIBRARY_PATH': str(args.env_path)}) 108 else: 109 # get env-path from response file recursively 110 [cmd, env_path] = get_command_and_env_path(args) 111 if args.qemu_binary_path: 112 # process for running executable with qemu 113 subp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 114 else: 115 # process for running executable directly 116 subp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, 117 env={'LD_LIBRARY_PATH': str(env_path)}) 118 return [cmd, subp] 119 120 121def judge_output(args: object): 122 """run executable and judge is success or not.""" 123 start_time = time.time() 124 [cmd, subp] = process_open(args) 125 timeout_limit = int(args.timeout_limit) if args.timeout_limit else 150 # units: s 126 127 try: 128 out, err = subp.communicate(timeout=timeout_limit) 129 except subprocess.TimeoutExpired: 130 raise RuntimeError('Run [', cmd, '] timeout, timeout_limit = ', timeout_limit, 's') 131 132 if args.expect_output: 133 returncode = str(subp.returncode) 134 if returncode != args.expect_output: 135 out_str = out.decode('UTF-8') 136 err_str = err.decode('UTF-8') 137 print(out_str) 138 print(err_str) 139 print(">>>>> Expect return: [" + args.expect_output \ 140 + "]\n>>>>> But got: [" + returncode + "]") 141 raise RuntimeError("Run [" + cmd + "] failed!") 142 elif args.expect_sub_output: 143 out_str = out.decode('UTF-8') 144 if out_str.find(args.expect_sub_output) == -1: 145 out_str = out.decode('UTF-8') 146 print(out_str) 147 print(">>>>> Expect contain: [" + args.expect_sub_output \ 148 + "]\n>>>>> But got: [" + out_str + "]") 149 raise RuntimeError("Run [" + cmd + "] failed!") 150 elif args.expect_file: 151 with open(args.expect_file, mode='r') as file: 152 # skip license header 153 expect_output = ''.join(file.readlines()[13:]) 154 file.close() 155 out_str = out.decode('UTF-8') 156 if out_str != expect_output: 157 err_str = err.decode('UTF-8') 158 print(err_str) 159 print(">>>>> Expect : [" + expect_output \ 160 + "]\n>>>>> But got: [" + out_str + "]") 161 raise RuntimeError("Run [" + cmd + "] failed!") 162 else: 163 raise RuntimeError("Run [" + cmd + "] with no expect !") 164 165 print("Run [" + cmd + "] success!") 166 print("used: %.5f seconds" % (time.time() - start_time)) 167 168 169if __name__ == '__main__': 170 input_args = parse_args() 171 judge_output(input_args) 172