1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright (c) 2023 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16 17import os 18import re 19import yaml 20import platform 21import subprocess 22from tool.test_helper import read_declaration 23 24STRICT_OFF = ['--strict', 'false'] 25STRICT_ON = ['--strict', 'true'] 26MODULE = ['--module'] 27DECORATOR = ['--experimentalDecorators'] 28STRICTNULLCHECKS = ['--strictNullChecks'] 29 30 31def get_error_message(strs, filename): 32 if len(re.findall(filename + r':(\d+)', strs)) > 0: 33 line_number = re.findall(filename + r':(\d+)', strs) 34 else: 35 line_number = 0 36 err_message = strs 37 return err_message, line_number 38 39 40class TestCase: 41 temp_path = "" 42 ld_library_path = "" 43 js_runtime_path = "" 44 es2abc = "" 45 tsc = "" 46 47 def __init__(self, path): 48 self.path = path 49 self.target_js_path = "" 50 try: 51 data = yaml.safe_load(read_declaration(path)) 52 except: 53 data = {} 54 self.declaration = data 55 self.fail = False 56 self.is_test_case = False if data is None else True 57 self.detail_result = "" 58 self.err_line = 0 59 self.abc_file_path = "" 60 self.abc_file_path_temp = "" 61 62 def execute(self, ark_runtime=False): 63 if not self.is_test_case: 64 return 65 if ark_runtime: 66 with open(self.path, 'a') as file_added: 67 file_added.write('\rprint("TESTCASE SUCCESS");') 68 self.__test_es2abc() 69 if os.path.exists(self.abc_file_path): 70 os.remove(self.abc_file_path) 71 else: 72 self.__tsc_test() 73 74 def is_negative(self): 75 if 'error' in self.declaration: 76 return True 77 return False 78 79 def is_current(self): 80 if 'isCurrent' in self.declaration: 81 return True 82 return False 83 84 def experimental_decorators(self): 85 if 'experimentalDecorators' in self.declaration: 86 return True 87 return False 88 89 def null_checks(self): 90 if 'strictNullChecks' in self.declaration: 91 return True 92 return False 93 94 def is_set_module(self): 95 if 'module' in self.declaration: 96 return True 97 return False 98 99 def check_declaration(self): 100 if self.declaration == {}: 101 self.detail_result = "parse test case declaration failed, maybe bad format." 102 return False 103 if 'error' in self.declaration: 104 if self.declaration['error'] is None or 'code' not in self.declaration['error'] and 'type' not in \ 105 self.declaration['error']: 106 self.detail_result = "neither error code nor error type are defined in negative case." 107 return False 108 return True 109 110 def __error_code(self): 111 if 'code' in self.declaration['error']: 112 return self.declaration['error']['code'] 113 return None 114 115 def __error_type(self): 116 if 'type' in self.declaration['error']: 117 return self.declaration['error']['type'] 118 return None 119 120 def __get_tsc_cmd(self): 121 if platform.system().lower() == 'windows': 122 cmd = ['cmd', '/c', 'tsc', '--target', 'es2020'] 123 else: 124 cmd = [TestCase.tsc, '--target', 'es2020'] 125 if self.__is_strict(): 126 cmd.extend(STRICT_ON) 127 else: 128 cmd.extend(STRICT_OFF) 129 if self.is_set_module(): 130 cmd.extend(MODULE) 131 cmd.append('es2020') 132 if self.experimental_decorators(): 133 cmd.extend(DECORATOR) 134 cmd.append('true') 135 if self.null_checks(): 136 cmd.extend(STRICTNULLCHECKS) 137 cmd.append('false') 138 if self.is_current(): 139 cmd.append(self.path) 140 cmd.append('--outDir') 141 cmd.append(TestCase.temp_path) 142 self.target_js_path = TestCase.temp_path + self.__get_js_basename() 143 return cmd 144 145 def __get_node_cmd(self): 146 cmd = ['node'] 147 if self.is_current(): 148 cmd.append(self.target_js_path) 149 else: 150 cmd.append(TestCase.temp_path + self.__get_js_basename()) 151 return cmd 152 153 # get es2abc --merge-abc 154 def __get_es2abc_cmd(self, file_path): 155 abc_file_path = ("%s.abc" % (os.path.splitext(file_path)[0])) 156 self.abc_file_path_temp = abc_file_path 157 cmd = [TestCase.es2abc + 'es2abc'] 158 cmd.extend(['--module', '--output', abc_file_path, file_path]) 159 return cmd 160 161 # create abc files 162 def create_abc(self, filename): 163 process = subprocess.Popen(self.__get_es2abc_cmd(filename), stdin=subprocess.PIPE, stdout=subprocess.PIPE, 164 stderr=subprocess.PIPE) 165 out, err = process.communicate(timeout=5000) 166 return_code = process.returncode 167 if return_code != 0: 168 err_msg, line = get_error_message( 169 out.decode("utf-8", errors="ignore") + err.decode("utf-8", errors="ignore"), filename) 170 self.detail_result = err_msg 171 self.err_line = line 172 self.fail = True 173 return 174 if "TESTCASE SUCCESS" not in out.decode("utf-8", errors="ignore"): 175 self.detail_result = "check stdout failed!" 176 self.fail = True 177 return 178 179 # get es2abc file commands 180 def _get_ark_js_cmd(self): 181 os.environ.setdefault("LD_LIBRARY_PATH", TestCase.ld_library_path) 182 run_abc_cmd = [os.path.join(TestCase.js_runtime_path, 'ark_js_vm'), self.abc_file_path_temp] 183 return run_abc_cmd 184 pass 185 186 def __get_js_basename(self): 187 sp = '/' 188 return "test_ts_cases" + sp + self.path.split(sp + "test_ts_cases" + sp)[1].replace('.ts', '.js') 189 190 def __is_strict(self): 191 if 'strict' in self.declaration: 192 return bool(self.declaration['strict']) 193 return True 194 195 def __tsc_test(self): 196 process = subprocess.Popen(self.__get_tsc_cmd(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, 197 stderr=subprocess.PIPE) 198 out, err = process.communicate(timeout=5000) 199 return_code = process.returncode 200 if self.is_negative(): 201 if return_code == 0: 202 self.fail = True 203 self.detail_result = "No error found in negative case." 204 return 205 if self.__error_code() in out.decode("utf-8", errors="ignore") + err.decode("utf-8", errors="ignore"): 206 return 207 self.fail = True 208 self.detail_result = "Error code not as expected." 209 return 210 # positive case 211 if return_code != 0: 212 self.detail_result = out.decode("utf-8", errors="ignore") + err.decode("utf-8", errors="ignore") 213 self.fail = True 214 return 215 if self.is_current(): 216 with open(self.target_js_path, 'a') as fileAdded: 217 fileAdded.write('console.log("TESTCASE SUCCESS");') 218 # run node command 219 process = subprocess.Popen(self.__get_node_cmd(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, 220 stderr=subprocess.PIPE) 221 out, err = process.communicate(timeout=5000) 222 return_code = process.returncode 223 if self.is_current(): 224 if os.path.exists(self.target_js_path): 225 os.remove(self.target_js_path) 226 if return_code != 0: 227 err_msg, line = get_error_message( 228 out.decode("utf-8", errors="ignore") + err.decode("utf-8", errors="ignore"), self.__get_js_basename()) 229 self.detail_result = err_msg 230 self.err_line = line 231 self.fail = True 232 return 233 # check std out 234 if "TESTCASE SUCCESS" not in out.decode("utf-8", errors="ignore"): 235 self.detail_result = "check stdout failed!" 236 self.fail = True 237 return 238 239 def __test_es2abc(self): 240 # compiler to abc 241 process = subprocess.Popen(self.__get_es2abc_cmd(self.path), stdin=subprocess.PIPE, stdout=subprocess.PIPE, 242 stderr=subprocess.PIPE) 243 out, err = process.communicate(timeout=5000) 244 return_code = process.returncode 245 if self.is_negative(): 246 if return_code == 0: 247 self.fail = True 248 return 249 if self.__error_type() in out.decode("utf-8", errors="ignore") + err.decode("utf-8", errors="ignore"): 250 return 251 self.fail = True 252 self.detail_result = "Error type not as expected." 253 return 254 # positive case 255 if return_code != 0: 256 self.detail_result = out.decode("utf-8", errors="ignore") + err.decode("utf-8", errors="ignore") 257 self.fail = True 258 return 259 # execute ark_js_vm 260 process = subprocess.Popen(self._get_ark_js_cmd(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, 261 stderr=subprocess.PIPE) 262 out, err = process.communicate(timeout=5000) 263 return_code = process.returncode 264 if return_code != 0: 265 err_msg, line = get_error_message( 266 out.decode("utf-8", errors="ignore") + err.decode("utf-8", errors="ignore"), 267 os.path.basename(self.abc_file_path)) 268 self.detail_result = err_msg 269 self.err_line = line 270 self.fail = True 271 return 272 # check std out 273 if "TESTCASE SUCCESS" not in out.decode("utf-8", errors="ignore"): 274 self.detail_result = "check stdout failed!" 275 self.fail = True 276 return 277