From 7ea6632faf2997cb4595cd0b90779bd49b5aa294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E6=96=87=E6=B3=A2?= <1010589661@qq.com> Date: Mon, 3 Mar 2025 14:57:24 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E3=80=90=E5=BC=80=E5=8F=91=E8=87=AA?= =?UTF-8?q?=E6=8F=90=E3=80=91=E3=80=90=E7=BD=91=E7=BB=9C=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E3=80=91st/ut=E6=A1=86=E6=9E=B6=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../analysis_flight.py | 0 .../check_path.py | 0 .../flight_recoder.md | 0 flight_recoder/test/__init__.py | 0 flight_recoder/test/run_st.py | 94 +++++++++++++++++++ flight_recoder/test/run_ut.sh | 50 ++++++++++ flight_recoder/test/st/__init__.py | 0 flight_recoder/test/st/utils.py | 64 +++++++++++++ 8 files changed, 208 insertions(+) rename flight_recoder/{ => flight_recoder_analyze}/analysis_flight.py (100%) rename flight_recoder/{ => flight_recoder_analyze}/check_path.py (100%) rename flight_recoder/{ => flight_recoder_analyze}/flight_recoder.md (100%) create mode 100644 flight_recoder/test/__init__.py create mode 100644 flight_recoder/test/run_st.py create mode 100644 flight_recoder/test/run_ut.sh create mode 100644 flight_recoder/test/st/__init__.py create mode 100644 flight_recoder/test/st/utils.py diff --git a/flight_recoder/analysis_flight.py b/flight_recoder/flight_recoder_analyze/analysis_flight.py similarity index 100% rename from flight_recoder/analysis_flight.py rename to flight_recoder/flight_recoder_analyze/analysis_flight.py diff --git a/flight_recoder/check_path.py b/flight_recoder/flight_recoder_analyze/check_path.py similarity index 100% rename from flight_recoder/check_path.py rename to flight_recoder/flight_recoder_analyze/check_path.py diff --git a/flight_recoder/flight_recoder.md b/flight_recoder/flight_recoder_analyze/flight_recoder.md similarity index 100% rename from flight_recoder/flight_recoder.md rename to flight_recoder/flight_recoder_analyze/flight_recoder.md diff --git a/flight_recoder/test/__init__.py b/flight_recoder/test/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/flight_recoder/test/run_st.py b/flight_recoder/test/run_st.py new file mode 100644 index 0000000000..b8acfde729 --- /dev/null +++ b/flight_recoder/test/run_st.py @@ -0,0 +1,94 @@ +# Copyright (c) 2025-2025 Huawei Technologies Co., Ltd. + +import datetime +import logging +import os +import subprocess +import sys +import threading + +stop_print_thread = False + + +def print_stout(output): + while True: + line = output.readline().strip() + if line: + logging.info(line) + global stop_print_thread + if stop_print_thread: + break + + +def stop_stout_threads(thread_list): + global stop_print_thread + stop_print_thread = True + for stout_thread in thread_list: + if stout_thread.is_alive(): + stout_thread.join() + + +def start_st_process(module_name): + st_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "st", module_name) + cmd = ["python3", "-m", "pytest", "-s", st_path] + process = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + stout_thread = threading.Thread(target=print_stout, args=(process.stdout,)) + stout_thread.start() + return process, stout_thread + + +def stop_st_process(process_list): + for process in process_list: + if process.poll() is None: + process.terminate() + process.wait() + + +def run_st(module_choice): + timeout = 3600 + modules = ["flight_recoder_analyze"] + if module_choice != "all": + modules = [module_choice] + process_list = [] + thread_list = [] + for module in modules: + process, stout_thread = start_st_process(module) + process_list.append(process) + thread_list.append(stout_thread) + + success, failed = True, False + start_time = datetime.datetime.utcnow() + while process_list: + duration = datetime.datetime.utcnow() - start_time + if duration.total_seconds() >= timeout: + logging.error("run st use case timeout.") + stop_stout_threads(thread_list) + stop_st_process(process_list) + return failed + for process in process_list: + if process.poll() is None: + continue + if process.returncode == 0: + process_list.remove(process) + continue + stop_stout_threads(thread_list) + stop_st_process(process_list) + return failed + stop_stout_threads(thread_list) + return success + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') + if '--module' in sys.argv: + module_index = sys.argv.index("--module") + 1 + module = sys.argv[module_index] + else: + module = "all" + st_success = run_st(module) + if st_success: + logging.info("run st successfully.") + sys.exit(0) + else: + logging.error("run st failed.") + sys.exit(1) \ No newline at end of file diff --git a/flight_recoder/test/run_ut.sh b/flight_recoder/test/run_ut.sh new file mode 100644 index 0000000000..4f0d8caac3 --- /dev/null +++ b/flight_recoder/test/run_ut.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# This script is used to run ut and st testcase. +# Copyright Huawei Technologies Co., Ltd. 2021-2022. All rights reserved. +CUR_DIR=$(dirname $(readlink -f $0)) +TOP_DIR=$(readlink -f ${CUR_DIR}/..) +TEST_DIR=${TOP_DIR}/"test" +SRC_DIR=${TOP_DIR}/"src" +ret=0 + +clean() { + cd ${TEST_DIR} + if [ -e ${TEST_DIR}/coverage.xml ]; then + rm coverage.xml + echo "remove last coverage.xml success" + fi + cd - +} + +run_test_cpp() { + cd . +} + +run_test_python() { + python3 --version + #pip3 install pytest "pandas>=2.2" + export PYTHONPATH=${TOP_DIR}:${PYTHONPATH} + python3 -m coverage run --branch --source ${TOP_DIR}/'flight_recoder_analyze' -m pytest ${TEST_DIR}/ut + + if [ $? -ne 0 ]; then + echo "UT Failure" + exit 1 + fi + + python3 -m coverage report -m + python3 -m coverage xml -o ${TEST_DIR}/coverage.xml +} + +run_test() { + run_test_cpp + run_test_python +} + +main() { + cd ${TEST_DIR} + clean + run_test + echo "UT Success" +} + +main \ No newline at end of file diff --git a/flight_recoder/test/st/__init__.py b/flight_recoder/test/st/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/flight_recoder/test/st/utils.py b/flight_recoder/test/st/utils.py new file mode 100644 index 0000000000..3cc4eea180 --- /dev/null +++ b/flight_recoder/test/st/utils.py @@ -0,0 +1,64 @@ +# Copyright (c) 2025-2025 Huawei Technologies Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +import logging + +COMMAND_SUCCESS = 0 + + +def execute_cmd(cmd): + logging.info('Execute command:%s' % " ".join(cmd)) + completed_process = subprocess.run(cmd, shell=False, stderr=subprocess.PIPE) + if completed_process.returncode != COMMAND_SUCCESS: + logging.error(completed_process.stderr.decode()) + return completed_process.returncode + + +def check_column_actual(actual_columns, expected_columns, context): + """检查实际列名是否与预期列名一致""" + for col in expected_columns: + if col not in actual_columns: + logging.error(f"在 {context} 中未找到预期列名: {col}") + return False + return True + + +def check_row(df, expected_columns, numeric_columns): + """检查数据框中Metric列数据类型和指定列数据是否为数字""" + # 检查Metric列的数据类型是否为字符串 + for row_index in df.index: + try: + value = df.at[row_index, 'Metric'] + if not isinstance(value, str): + logging.error(f"在Metric列的第{row_index}行,值 '{value}' 不是字符串类型") + return False + except KeyError: + logging.error(f"数据框中不存在 'Metric' 列") + return False + + # 检查其他列的数据是否为数字 + for column in numeric_columns: + if column not in df.columns: + logging.error(f"数据框中不存在 {column} 列") + continue + for row_index in df.index: + try: + cell_value = df.at[row_index, column] + float(cell_value) + except (ValueError, KeyError): + logging.error( + f"在 {column} 列的第 {row_index} 行,值 {cell_value} 不是有效的数字") + return False + return True \ No newline at end of file -- Gitee From 23706741adc2626994f88c3c791c4baad1536256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E6=96=87=E6=B3=A2?= <1010589661@qq.com> Date: Mon, 3 Mar 2025 16:22:56 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E3=80=90=E5=BC=80=E5=8F=91=E8=87=AA?= =?UTF-8?q?=E6=8F=90=E3=80=91=E3=80=90=E7=BD=91=E7=BB=9C=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E3=80=91st/ut=E6=A1=86=E6=9E=B6=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flight_recorder_analyze}/analysis_flight.py | 0 .../flight_recorder_analyze}/check_path.py | 0 .../flight_recorder_analyze/flight_recorder.md | 0 {flight_recoder => flight_recorder}/test/__init__.py | 0 {flight_recoder => flight_recorder}/test/run_st.py | 0 {flight_recoder => flight_recorder}/test/run_ut.sh | 0 {flight_recoder => flight_recorder}/test/st/__init__.py | 0 {flight_recoder => flight_recorder}/test/st/utils.py | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename {flight_recoder/flight_recoder_analyze => flight_recorder/flight_recorder_analyze}/analysis_flight.py (100%) rename {flight_recoder/flight_recoder_analyze => flight_recorder/flight_recorder_analyze}/check_path.py (100%) rename flight_recoder/flight_recoder_analyze/flight_recoder.md => flight_recorder/flight_recorder_analyze/flight_recorder.md (100%) rename {flight_recoder => flight_recorder}/test/__init__.py (100%) rename {flight_recoder => flight_recorder}/test/run_st.py (100%) rename {flight_recoder => flight_recorder}/test/run_ut.sh (100%) rename {flight_recoder => flight_recorder}/test/st/__init__.py (100%) rename {flight_recoder => flight_recorder}/test/st/utils.py (100%) diff --git a/flight_recoder/flight_recoder_analyze/analysis_flight.py b/flight_recorder/flight_recorder_analyze/analysis_flight.py similarity index 100% rename from flight_recoder/flight_recoder_analyze/analysis_flight.py rename to flight_recorder/flight_recorder_analyze/analysis_flight.py diff --git a/flight_recoder/flight_recoder_analyze/check_path.py b/flight_recorder/flight_recorder_analyze/check_path.py similarity index 100% rename from flight_recoder/flight_recoder_analyze/check_path.py rename to flight_recorder/flight_recorder_analyze/check_path.py diff --git a/flight_recoder/flight_recoder_analyze/flight_recoder.md b/flight_recorder/flight_recorder_analyze/flight_recorder.md similarity index 100% rename from flight_recoder/flight_recoder_analyze/flight_recoder.md rename to flight_recorder/flight_recorder_analyze/flight_recorder.md diff --git a/flight_recoder/test/__init__.py b/flight_recorder/test/__init__.py similarity index 100% rename from flight_recoder/test/__init__.py rename to flight_recorder/test/__init__.py diff --git a/flight_recoder/test/run_st.py b/flight_recorder/test/run_st.py similarity index 100% rename from flight_recoder/test/run_st.py rename to flight_recorder/test/run_st.py diff --git a/flight_recoder/test/run_ut.sh b/flight_recorder/test/run_ut.sh similarity index 100% rename from flight_recoder/test/run_ut.sh rename to flight_recorder/test/run_ut.sh diff --git a/flight_recoder/test/st/__init__.py b/flight_recorder/test/st/__init__.py similarity index 100% rename from flight_recoder/test/st/__init__.py rename to flight_recorder/test/st/__init__.py diff --git a/flight_recoder/test/st/utils.py b/flight_recorder/test/st/utils.py similarity index 100% rename from flight_recoder/test/st/utils.py rename to flight_recorder/test/st/utils.py -- Gitee