1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4#
5# Copyright (c) 2024 Huawei Device Co., Ltd.
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19import os
20from .util import exec_command, compare_target_files, get_all_idl_files
21from .util import get_time_stamp, print_success, print_failure, dump_ast_compare
22from .util import get_idl, hdi_gen_fail_check_ignore_line
23
24
25__all__ = ["Test"]
26
27class Test:
28    def __init__(self):
29        self.name = self.__class__.__name__
30        self._file_name = self.get_file_name()
31        self.working_dir = self.get_working_dir()
32        self._package_path = self.working_dir
33        self.idl_dir = os.path.join(self.working_dir, "foo")
34        self.output_dir = os.path.join(self.working_dir, "out")
35        self.target_dir = os.path.join(self.working_dir, "target")
36        self._system_attr = "full"
37        self._mode_attr = "ipc"
38        self._command_attr = ""
39        self._command_ext_attr = ""
40        self._gen_langauge = "--gen-cpp"
41        self._idl = get_idl()
42        self._command_format = "{} --intf-type hdi --system {} -m {} {} {} {} -r ohos.hdi:{} -d {}"
43        self.command = self._command_format.format(self._idl, self._system_attr, self._mode_attr,
44                                                   self._command_attr, self._command_ext_attr,
45                                                   self._gen_langauge, self._package_path, self.output_dir)
46        self._not_use_default_add_idl_file = False
47        self._output_path = None
48        self._hash_command_format = "{} --intf-type hdi --hash -r ohos.hdi:{} {} -o {}"
49        self._dump_ast_command_format = "{} --intf-type hdi --dump-ast -r ohos.hdi:{} {} {} -o {}"
50        self._dump_ast_check = False
51        self._check_fail_ignore_line = False
52
53    def get_file_name(self):
54        # 子类继承实现
55        return ""
56
57    def set_check_fail_ignore_line(self, attr):
58        self._check_fail_ignore_line = attr
59
60    def get_working_dir(self):
61        current_path = os.path.dirname(os.path.abspath(__file__))
62        return os.path.realpath(os.path.join(current_path,
63                                             "..", os.path.splitext(os.path.basename(self._file_name))[0]))
64
65    def set_command_attr(self, attr):
66        self._command_attr = attr
67
68    def set_command_ext_attr(self, attr):
69        self._command_ext_attr = attr
70
71    def set_command_gen_langauge(self, langauge):
72        self._gen_langauge = langauge
73
74    def set_output_dir(self, output_dir):
75        self.output_dir = os.path.join(self.working_dir, output_dir)
76
77    def set_target_dir(self, target_dir):
78       self.target_dir = os.path.join(self.working_dir, target_dir)
79
80    def set_system_attr(self, attr):
81        self._system_attr = attr
82
83    def set_mode_attr(self, attr):
84        self._mode_attr = attr
85
86    def set_package_path(self, package_path):
87        self._package_path = package_path
88
89    def set_idl_dir(self, path):
90        self.idl_dir = path
91
92    def set_not_use_default_add_idl_file(self, opt):
93        self._not_use_default_add_idl_file = opt
94
95    def update_command(self):
96        self.command = self._command_format.format(self._idl, self._system_attr, self._mode_attr,
97                                                   self._command_attr, self._command_ext_attr,
98                                                   self._gen_langauge, self._package_path, self.output_dir)
99
100    def set_output_path(self, output_path):
101        self._output_path = output_path
102
103    def hash_command_update(self):
104        hash_command = self._hash_command_format.format(self._idl, self._package_path,
105                                                        self._command_attr, self._output_path)
106        self.set_command(hash_command)
107
108    def dump_ast_command_update(self, use_tee=True):
109        dump_ast_command = self._dump_ast_command_format.format(self._idl, self._package_path, self._command_attr,
110                                                                self._command_ext_attr, self._output_path)
111        if use_tee:
112            dump_ast_command += f" | tee {self._output_path}"
113        self.set_command(dump_ast_command)
114
115    def set_hash_param(self, package_path, command_attr):
116        self.set_package_path(package_path)
117        self.set_command_attr(f"-D {command_attr}")
118        output_path = os.path.join(self.working_dir, "hash_out")
119        if not os.path.exists(output_path):
120            os.makedirs(output_path)
121        self.set_output_path(os.path.join(output_path, "hash.txt"))
122        self.set_output_dir(output_path)
123        self.set_target_dir(os.path.join(self.working_dir, "hash_target"))
124        self.set_not_use_default_add_idl_file(True)
125        self.hash_command_update()
126
127    def set_dump_ast_check(self, if_check):
128        self._dump_ast_check = if_check
129
130    def set_dump_ast_param(self, package_path, command_attr, use_tee=True):
131        self.set_package_path(package_path)
132        self.set_command_attr(f"-D {command_attr}")
133        output_path = os.path.join(self.working_dir, "dump_ast_out")
134        if not os.path.exists(output_path):
135            os.makedirs(output_path)
136        self.set_output_path(os.path.join(output_path, "dump.txt"))
137        self.set_output_dir(output_path)
138        self.set_target_dir(os.path.join(self.working_dir, "dump_ast_target"))
139        self.set_not_use_default_add_idl_file(True)
140        self.set_dump_ast_check(True)
141        self.dump_ast_command_update(use_tee)
142
143    def set_command(self, command):
144        self.command = command
145
146    def set_gen_c_env(self):
147        self.set_command_gen_langauge("--gen-c")
148        self.set_output_dir("c_out")
149        self.set_target_dir("c_target")
150        self.update_command()
151
152    def set_gen_cpp_env(self):
153        self.set_command_gen_langauge("--gen-cpp")
154        self.set_output_dir("cpp_out")
155        self.set_target_dir("cpp_target")
156        self.update_command()
157
158    def set_gen_java_env(self):
159        self.set_command_gen_langauge("--gen-java")
160        self.set_output_dir("java_out")
161        self.set_target_dir("java_target")
162        self.update_command()
163
164    def run(self):
165        # please add test code here
166        return False
167
168    def run_choose(self, choose):
169        if choose:
170            return self.run_success()
171        return self.run_fail()
172
173    def run_success(self):
174        if not self._not_use_default_add_idl_file:
175            self.add_idl_files()
176        status, ret = exec_command(self.command)
177        if status != 0:
178            print_failure(f"[ERROR] command:{self.command} run err")
179            print_failure(f"[ERROR] {ret}")
180            return False
181        special_proc_func = None
182        if self._dump_ast_check:
183            special_proc_func = dump_ast_compare
184        if compare_target_files(self.output_dir, self.target_dir, special_proc_func):
185            return True
186        return False
187
188    def run_fail(self):
189        if not self._not_use_default_add_idl_file:
190            self.add_idl_files()
191        status, result = exec_command(self.command)
192
193        if status == 0:
194            print_failure(f"[ERROR] ret({status}) run cmd: {self.command}")
195            return False
196
197        expected_fail_output = ""
198        with open(os.path.join(self.target_dir, "fail_output.txt"), 'r') as target_output:
199            expected_fail_output = target_output.read()
200
201        if self._check_fail_ignore_line:
202            ret = hdi_gen_fail_check_ignore_line(result, expected_fail_output)
203            if not ret:
204                print_failure(f"[ERROR] Expect ret: {expected_fail_output}")
205                print_failure(f"[ERROR] Actual ret: {result}")
206            return ret
207
208        if expected_fail_output != result:
209            print_failure(f"[ERROR] Expect ret: {expected_fail_output}")
210            print_failure(f"[ERROR] Actual ret: {result}")
211            return False
212        return True
213
214    def remove_output(self):
215        exec_command("rm -rf {}".format(self.output_dir))
216        return True
217
218    def add_idl_files(self):
219        idl_list = get_all_idl_files(self.idl_dir)
220        for idl in idl_list:
221            self.command = "".join((self.command, " -c {}".format(idl)))
222
223    def test(self):
224        print_success("[ RUN       ] {}".format(self.name))
225        start_time = get_time_stamp()
226        result = self.run()
227        end_time = get_time_stamp()
228
229        if result:
230            print_success("[        OK ] {} ({}ms)".format(self.name, end_time - start_time))
231        else:
232            print_failure("[    FAILED ] {} ({}ms)".format(self.name, end_time - start_time))
233        return result
234