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
20import subprocess
21import time
22import re
23
24__all__ = ["get_time_stamp", "print_success", "print_failure", "compare_target_files", "exec_command", "file_exists",
25           "make_binary_file", "clean_binary_file", "get_all_idl_files", "get_idl", "get_subclasses",
26           "dump_ast_compare", "hdi_gen_fail_check_ignore_line"]
27
28def get_time_stamp():
29    return int(round(time.time() * 1000))
30
31
32def print_success(info):
33    print("\033[32m{}\033[0m".format(info))
34
35
36def print_failure(info):
37    print("\033[31m{}\033[0m".format(info))
38
39
40def is_subsequence(first_file, second_file):
41    first_info = first_file.read()
42    second_info = second_file.readline()
43    while second_info:
44        if first_info.find(second_info) == -1:
45            print("line\n", second_info, "is not in output file")
46            return False
47        second_info = second_file.readline()
48    return True
49
50
51def dump_ast_compare(line_lhd:str, line_rhd:str):
52    if line_lhd == line_rhd:
53        return True
54    if not line_lhd.startswith("AST") or not line_rhd.startswith("AST"):
55        return False
56    ast_templage = r"AST\[name:\s(.*)\sfile:\s(.*)\]"
57    obj_lhd = re.search(ast_templage, line_lhd)
58    obj_rhd = re.search(ast_templage, line_rhd)
59    if not obj_lhd or not obj_rhd:
60        return False
61    ast_name_lhd = obj_lhd.group(1)
62    ast_name_rhd = obj_rhd.group(1)
63    if ast_name_lhd.strip() != ast_name_rhd.strip():
64        return False
65    ast_path_lhd = obj_lhd.group(2)
66    ast_path_rhd = obj_rhd.group(2)
67    lhd_index = ast_path_lhd.find("foo")
68    rhd_index = ast_path_rhd.find("foo")
69    if ast_path_lhd[lhd_index:].strip() != ast_path_rhd[rhd_index:].strip():
70        return False
71    return True
72
73
74def content_compare(file1, file2, lhd, rhd, special_proc_func=None):
75    if len(lhd) != len(rhd):
76        print_failure(f"{file1} line num({len(lhd)}) != {file2} line num({len(rhd)}))")
77        return False
78    line_num = 0
79    for line1, line2 in zip(lhd, rhd):
80        line_num += 1
81        if ((special_proc_func is None and line1 != line2) or
82            (special_proc_func is not None and not special_proc_func(line1, line2))):
83            print_failure(f"{file1}:{line_num}:{line1}")
84            print_failure(f"{file2}:{line_num}:{line2}")
85            return False
86    return True
87
88
89def compare_file(first_file_path, second_file_path, special_proc_func=None):
90    with open(first_file_path, 'r') as first_file:
91        with open(second_file_path, 'r') as second_file:
92            return content_compare(first_file_path,
93                                   second_file_path,
94                                   first_file.readlines(),
95                                   second_file.readlines(),
96                                   special_proc_func)
97
98
99def check_c_cpp_file(file_list):
100    for filename in file_list:
101        if filename.endswith(".h") or filename.endswith(".c") or filename.endswith(".cpp"):
102            return True
103    return False
104
105
106def compare_target_files(first_file_path, second_file_path, special_proc_func=None):
107    first_files_list = get_all_files(first_file_path)
108    second_files_list = get_all_files(second_file_path)
109
110    first_files = set([file[len(first_file_path):] for file in first_files_list])
111    if_c_cpp = check_c_cpp_file(first_files)
112    if if_c_cpp:
113        # 去除末尾.txt符号
114        second_files = set([file[len(second_file_path):-4] for file in second_files_list])
115    else:
116        second_files = set([file[len(second_file_path):] for file in second_files_list])
117
118    if len(first_files) != len(second_files):
119        print_failure(f"[ERROR] file num not compile({len(first_files)}, {len(second_files)})")
120        return False
121
122    common_files = first_files & second_files
123
124    if len(common_files) == 0:
125        print_failure("[ERROR] not compile target")
126        return False
127
128    if if_c_cpp:
129        check_file_name_format = "{}{}.txt"
130    else:
131        check_file_name_format = "{}{}"
132
133    for files in common_files:
134        if not compare_file("{}{}".format(first_file_path, files),
135                            check_file_name_format.format(second_file_path, files), special_proc_func):
136            print("file ", "{}{}".format(first_file_path, files), "{}{}".format(second_file_path, files), \
137                "is different")
138            return False
139    return True
140
141
142def exec_command(command):
143    return subprocess.getstatusoutput(command)
144
145
146def file_exists(file_path):
147    return os.path.isfile(file_path)
148
149
150def make_binary_file(file_path):
151    print("making idl-gen...")
152    return exec_command("make --directory={} --jobs=4".format(file_path))
153
154
155def clean_binary_file(file_path):
156    return exec_command("make --directory={} clean".format(file_path))
157
158
159def get_all_files(path):
160    file_list = []
161    items = os.listdir(path)
162    for item in items:
163        item_path = os.path.join(path, item)
164        if not os.path.isdir(item_path):
165            file_list.append(item_path)
166        else:
167            file_list += get_all_files(item_path)
168    return file_list
169
170
171def get_all_idl_files(idl_path):
172    file_list = get_all_files(idl_path)
173    idl_file_list = []
174    for file in file_list:
175        if os.path.splitext(file)[-1] == ".idl":
176            idl_file_list.append(file)
177    return idl_file_list
178
179
180def get_idl():
181    current_path = os.path.dirname(os.path.abspath(__file__))
182    relative_path = os.path.join(current_path, "..", "..", "..", "idl_tool_2", "idl-gen")
183    return os.path.realpath(relative_path)
184
185
186def get_subclasses(cls):
187    return cls.__subclasses__()
188
189
190def hdi_gen_fail_check_ignore_line(result: str, target: str):
191    fail_template = r"(.*): \[(\S+):\d+\] \[?(.*)error:(.*)"
192    result_lines = result.split("\n")
193    target_lines = target.split("\n")
194    if len(result_lines) != len(target_lines):
195        print_failure(f"[ERROR] result line(len(result_lines)) != target line(len(target_lines))")
196        return False
197
198    for result_line, target_line in zip(result_lines, target_lines):
199        lhd_obj = re.search(fail_template, result_line)
200        rhd_obj = re.search(fail_template, target_line)
201        if not lhd_obj and not rhd_obj:
202            if result_line == target_line:
203                continue
204            else:
205                print_failure(f"[ERROR] actual: {result_line}")
206                print_failure(f"[ERROR] expect: {target_line}")
207                return False
208        elif not lhd_obj or not rhd_obj:
209            print_failure(f"[ERROR] actual: {result_line}")
210            print_failure(f"[ERROR] expect: {target_line}")
211            return False
212        lhd_start_check_content = lhd_obj.group(1)
213        rhd_start_check_content = rhd_obj.group(1)
214        lhd_err_func_check_content = lhd_obj.group(2)
215        rhd_err_func_check_content = rhd_obj.group(2)
216        lhd_median_check_content = lhd_obj.group(3)
217        rhd_median_check_content = rhd_obj.group(3)
218        lhd_end_check_content = lhd_obj.group(4)
219        rhd_end_check_content = rhd_obj.group(4)
220        if lhd_start_check_content != rhd_start_check_content or \
221            lhd_err_func_check_content != rhd_err_func_check_content or \
222            lhd_median_check_content != rhd_median_check_content or \
223            lhd_end_check_content != rhd_end_check_content:
224            print_failure(f"[ERROR] actual: {result_line}")
225            print_failure(f"[ERROR] expect: {target_line}")
226            return False
227
228    return True
229