• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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