1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4# Copyright (c) 2022-2024 Huawei Device Co., Ltd.
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import re
18import argparse
19import subprocess
20import time
21
22from enum import Enum
23
24
25class TestTypes(Enum):
26    NORMAL = 0
27    CLANGTIDY = 1
28    CLANGFORMAT = 2
29
30
31def print_summary(log_lines, searched_words, end_word=""):
32    was_any_log = False
33    should_print = False
34
35    for line in log_lines:
36        for word in searched_words:
37            if any(word in line for word in searched_words):
38                should_print = True
39                was_any_log = True
40
41        if end_word and end_word in line:
42            should_print=False
43
44        if should_print:
45            print(line.strip())
46
47    if not was_any_log:
48        print("Problem occourd: ", was_any_log)
49
50    print(f"\n")
51
52
53def print_progress_to_console(line, test_type, pattern_progress_bar, pattern_clang_tidy, pattern_clang_format):
54    match test_type:
55        case TestTypes.NORMAL:
56            match = pattern_progress_bar.search(line)
57            if match:
58                print(line, end='')
59        case TestTypes.CLANGTIDY:
60            match = re.match(pattern_clang_tidy, line)
61            if match:
62                print(f"[{match.group(1)}/{match.group(2)}] {match.group(3)}")
63        case TestTypes.CLANGFORMAT:
64            match = re.match(pattern_clang_format, line)
65            if match:
66                print(f"[{match.group(1)}/{match.group(2)}] Clang-format: {match.group(3)} \n")
67
68
69def test_process_runner(runtime_process, test_type):
70    pattern_progress_bar = re.compile(r'\b(\d{1,3}%)\|(.+?)\| (\d+)/(\d+) \[\d{2}:\d{2}<\d{2}:\d{2},\s*\d+\.\d+it/s\]$')
71    pattern_clang_tidy = re.compile(r"^\[(\d+)\/(\d+)\]\s+Done\s+clang-tidy:\s+.*?\/es2panda\/(.+\.cpp)$")
72    pattern_clang_format = re.compile(r"\[(\d+)/(\d+)\]\s+Running clang-format: (.+)")
73
74    should_print = False
75    log_lines = []
76
77    for line in runtime_process.stdout:
78        log_lines.append(line)
79        print_progress_to_console(line, test_type, pattern_progress_bar, pattern_clang_tidy, pattern_clang_format)
80
81    return log_lines
82
83
84def command_runner(command_to_run, test_type):
85    try:
86        process = subprocess.Popen(command_to_run, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
87        process_log = test_process_runner(process, test_type)
88
89    except subprocess.CalledProcessError as e:
90        process_log = str(e)
91        print("An error occurred during processing:", process_log)
92
93    except Exception as e:
94        process_log = str(e)
95        print("An error occurred during processing:", process_log)
96
97    return process_log
98
99def print_summary_to_file(log, file_name, word_for_success, word_for_fail, test_name):
100    has_to_write_out_the_log = False
101
102    for line in log:
103        if word_for_fail in line:
104            has_to_write_out_the_log = True
105        elif word_for_success in line:
106            print(line)
107
108    if has_to_write_out_the_log:
109        with open(file_name, "w") as file:
110            for line in log:
111                file.write(line)
112
113        print(f"{test_name} is faild. Please check the log file: {file_name}")
114
115
116def main():
117    parser = argparse.ArgumentParser(description="Program description.")
118    parser.add_argument("--working-dir", required=False, help="Path to the working dir")
119    parser.add_argument("--build-root", required=False, help="Path to the working dir")
120
121    args = parser.parse_args()
122    print(f"Argumentum: Working dir: {args.working_dir}")
123    print(f"Argumentum: Build root: {args.build_root}")
124
125    command_helper = ["python3", f"{args.working_dir}/tests/tests-u-runner/main.py", "--build-dir", f"{args.build_root}",
126                      "--processes", "all", "--show-progress", "--force-generate"
127                    ]
128
129    # Run Parser tests
130    parser_test_run_command = command_helper + ["--parser" ]
131
132    parser_log = command_runner(parser_test_run_command, TestTypes.NORMAL)
133
134    # Run Runtime tests
135    runtime_test_run_command = command_helper + ["--ets-runtime", "--timeout", "60"]
136
137    runtime_log = command_runner(runtime_test_run_command, TestTypes.NORMAL)
138
139    # Functional tests
140    functional_test_run_command = command_helper + ["--ets-func-tests"]
141
142    functional_log = command_runner(functional_test_run_command, TestTypes.NORMAL)
143
144    # Run Ets-cts test
145    ets_cts_test_run_command =  command_helper + ["--ets-cts"]
146
147    ets_cts_log = command_runner(ets_cts_test_run_command, TestTypes.NORMAL)
148
149    # Run Clang-format
150    clang_format_run_command = ["ninja", "-C", f"{args.build_root}", "code-style-check"]
151
152    clang_format_log = command_runner(clang_format_run_command, TestTypes.CLANGFORMAT)
153
154    # Run Clang-tidy
155    clang_tidy_run_command = [f"{args.working_dir}/scripts/clang-tidy/clang_tidy_check.py", "--filename-filter=ets2panda",
156                                    f"{args.working_dir}",  f"{args.build_root}"
157                            ]
158
159    clang_tidy_log = command_runner(clang_tidy_run_command,TestTypes.CLANGTIDY)
160
161    print("\n\nTest results: \n")
162
163    print(f"\nParser test results:")
164    print_summary(parser_log, ["New failures at", "Summary("])
165
166    print(f"\nRuntime test results:")
167    print_summary(runtime_log, ["New failures at", "Summary("])
168
169    print(f"\nFunctional test results:")
170    print_summary(functional_log, ["Summary("])
171
172    print(f"\nEts-cts test results:")
173    print_summary(ets_cts_log, ["New failures at", "Summary("])
174
175    print(f"\nClang-format results:")
176    print_summary_to_file(clang_format_log, "clang-format.log", "Clang-format was passed successfully!", "Failed:", "Clang-format")
177
178    print(f"\nClang-tidy results:")
179    print_summary(clang_tidy_log,["Clang-tidy was passed successfully!", "Failed:"], "Done clang-tidy:")
180
181
182if __name__ == "__main__":
183    start_time = time.perf_counter()
184    main()
185    end_time = time.perf_counter()
186    print("Runtime: ", (end_time - start_time)/60, " minute" )
187