From fb419de588ed23df1ee29e46181b92b099ec4d64 Mon Sep 17 00:00:00 2001 From: Bartosz Krystowski Date: Mon, 11 Aug 2025 10:31:11 +0200 Subject: [PATCH 1/8] Add dual host ffmpeg tests for various video formats and configurations --- tests/validation/mtl_engine/ffmpeg_app.py | 322 ++++++++++++++++++ .../validation/tests/dual/ffmpeg/__init__.py | 2 + .../dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg.py | 59 ++++ .../ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24.py | 55 +++ ...test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple.py | 64 ++++ .../dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp.py | 66 ++++ 6 files changed, 568 insertions(+) create mode 100755 tests/validation/tests/dual/ffmpeg/__init__.py create mode 100755 tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg.py create mode 100755 tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24.py create mode 100755 tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple.py create mode 100755 tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp.py diff --git a/tests/validation/mtl_engine/ffmpeg_app.py b/tests/validation/mtl_engine/ffmpeg_app.py index 9697fd134..c7fa7d57e 100755 --- a/tests/validation/mtl_engine/ffmpeg_app.py +++ b/tests/validation/mtl_engine/ffmpeg_app.py @@ -993,3 +993,325 @@ def decode_video_format_to_st20p(video_format: str) -> tuple: else: log_fail(f"Invalid video format: {video_format}") return None + + +def execute_dual_test( + test_time: int, + build: str, + tx_host, + rx_host, + type_: str, + video_format: str, + pg_format: str, + video_url: str, + output_format: str, + multiple_sessions: bool = False, + tx_is_ffmpeg: bool = True, + capture_cfg=None, +): + init_test_logging() + + case_id = os.environ.get("PYTEST_CURRENT_TEST", "ffmpeg_dual_test") + case_id = case_id[: case_id.rfind("(") - 1] if "(" in case_id else case_id + + tx_nic_port_list = tx_host.vfs + rx_nic_port_list = rx_host.vfs + video_size, fps = decode_video_format_16_9(video_format) + + match output_format: + case "yuv": + ffmpeg_rx_f_flag = "-f rawvideo" + case "h264": + ffmpeg_rx_f_flag = "-c:v libopenh264" + + if not multiple_sessions: + output_files = create_empty_output_files(output_format, 1, rx_host, build) + rx_cmd = ( + f"ffmpeg -p_port {rx_nic_port_list[0]} -p_sip {ip_dict['rx_interfaces']} " + f"-p_rx_ip {ip_dict['rx_sessions']} -udp_port 20000 -payload_type 112 " + f"-fps {fps} -pix_fmt yuv422p10le -video_size {video_size} " + f"-f mtl_st20p -i k {ffmpeg_rx_f_flag} {output_files[0]} -y" + ) + if tx_is_ffmpeg: + tx_cmd = ( + f"ffmpeg -stream_loop -1 -video_size {video_size} -f rawvideo -pix_fmt yuv422p10le " + f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[0]} " + f"-p_sip {ip_dict['tx_interfaces']} -p_tx_ip {ip_dict['tx_sessions']} " + f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" + ) + else: + tx_config_file = generate_rxtxapp_tx_config( + tx_nic_port_list[0], video_format, video_url, tx_host, build, multiple_sessions + ) + tx_cmd = f"{RXTXAPP_PATH} --config_file {tx_config_file} --test_time {test_time}" + else: # multiple sessions + output_files = create_empty_output_files(output_format, 2, rx_host, build) + # Implementation for multiple sessions would go here + + logger.info(f"TX Command (host {tx_host.name}): {tx_cmd}") + logger.info(f"RX Command (host {rx_host.name}): {rx_cmd}") + log_to_file(f"TX Command (host {tx_host.name}): {tx_cmd}", tx_host, build) + log_to_file(f"RX Command (host {rx_host.name}): {rx_cmd}", rx_host, build) + + rx_proc = None + tx_proc = None + tcpdump_tx = prepare_tcpdump(capture_cfg, tx_host) + tcpdump_rx = prepare_tcpdump(capture_cfg, rx_host) + + try: + # Start RX first + rx_proc = run(rx_cmd, background=True, host=rx_host) + time.sleep(2) + + # Start TX + tx_proc = run(tx_cmd, background=True, host=tx_host) + + # Wait for test completion + time.sleep(test_time + 5) + + except Exception as e: + logger.error(f"Error during dual test execution: {e}") + log_to_file(f"Error during dual test execution: {e}", tx_host, build) + log_to_file(f"Error during dual test execution: {e}", rx_host, build) + raise + finally: + # Stop processes + if tx_proc: + run(f"pkill -f '{tx_cmd.split()[0]}'", host=tx_host) + if rx_proc: + run(f"pkill -f '{rx_cmd.split()[0]}'", host=rx_host) + + # Stop tcpdump if running + if tcpdump_tx: + tcpdump_tx.stop() + if tcpdump_rx: + tcpdump_rx.stop() + + time.sleep(2) + + passed = False + match output_format: + case "yuv": + passed = check_output_video_yuv(output_files[0], rx_host, build, video_url) + case "h264": + passed = check_output_video_h264( + output_files[0], video_size, rx_host, build, video_url + ) + + # Clean up output files after validation + try: + for output_file in output_files: + run(f"rm -f {output_file}", host=rx_host) + except Exception as e: + logger.warning(f"Failed to clean up output files: {e}") + + if not passed: + log_fail(f"Dual ffmpeg test failed for {video_format}") + + return passed + + +def execute_dual_test_rgb24( + test_time: int, + build: str, + tx_host, + rx_host, + type_: str, + video_format: str, + pg_format: str, + video_url: str, + capture_cfg=None, +): + """Execute dual host RGB24 ffmpeg test""" + # Initialize logging for this test + init_test_logging() + + tx_nic_port_list = tx_host.vfs + rx_nic_port_list = rx_host.vfs + video_size, fps = decode_video_format_16_9(video_format) + + logger.info(f"Creating RX config for dual RGB24 test with video_format: {video_format}") + log_to_file( + f"Creating RX config for dual RGB24 test with video_format: {video_format}", + rx_host, + build, + ) + + try: + rx_config_file = generate_rxtxapp_rx_config( + rx_nic_port_list[0], video_format, rx_host, build + ) + except Exception as e: + logger.error(f"Failed to create RX config: {e}") + log_to_file(f"Failed to create RX config: {e}", rx_host, build) + raise + + rx_cmd = f"{RXTXAPP_PATH} --config_file {rx_config_file} --test_time {test_time}" + tx_cmd = ( + f"ffmpeg -stream_loop -1 -video_size {video_size} -f rawvideo -pix_fmt rgb24 " + f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[0]} " + f"-p_sip {ip_dict['tx_interfaces']} -p_tx_ip {ip_dict['tx_sessions']} " + f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" + ) + + logger.info(f"TX Command (host {tx_host.name}): {tx_cmd}") + logger.info(f"RX Command (host {rx_host.name}): {rx_cmd}") + log_to_file(f"TX Command (host {tx_host.name}): {tx_cmd}", tx_host, build) + log_to_file(f"RX Command (host {rx_host.name}): {rx_cmd}", rx_host, build) + + rx_proc = None + tx_proc = None + tcpdump_tx = prepare_tcpdump(capture_cfg, tx_host) + tcpdump_rx = prepare_tcpdump(capture_cfg, rx_host) + + try: + # Start RX first + rx_proc = run(rx_cmd, background=True, host=rx_host) + time.sleep(2) + + # Start TX + tx_proc = run(tx_cmd, background=True, host=tx_host) + + # Wait for test completion + time.sleep(test_time + 5) + + # Get RX output + rx_output = rx_proc.stdout_text if rx_proc else "" + + except Exception as e: + logger.error(f"Error during dual RGB24 test execution: {e}") + log_to_file(f"Error during dual RGB24 test execution: {e}", tx_host, build) + log_to_file(f"Error during dual RGB24 test execution: {e}", rx_host, build) + raise + finally: + # Stop processes + if tx_proc: + run(f"pkill -f '{tx_cmd.split()[0]}'", host=tx_host) + if rx_proc: + run(f"pkill -f '{rx_cmd.split()[0]}'", host=rx_host) + + # Stop tcpdump if running + if tcpdump_tx: + tcpdump_tx.stop() + if tcpdump_rx: + tcpdump_rx.stop() + + time.sleep(2) + + if not check_output_rgb24(rx_output, 1): + log_fail(f"Dual RGB24 ffmpeg test failed for {video_format}") + + time.sleep(5) + return True + + +def execute_dual_test_rgb24_multiple( + test_time: int, + build: str, + tx_host, + rx_host, + type_: str, + video_format_list: list, + pg_format: str, + video_url_list: list, + capture_cfg=None, +): + """Execute dual host RGB24 multiple sessions ffmpeg test""" + # Initialize logging for this test + init_test_logging() + + tx_nic_port_list = tx_host.vfs + rx_nic_port_list = rx_host.vfs + video_size_1, fps_1 = decode_video_format_16_9(video_format_list[0]) + video_size_2, fps_2 = decode_video_format_16_9(video_format_list[1]) + + logger.info( + f"Creating RX config for dual RGB24 multiple test with video_formats: {video_format_list}" + ) + log_to_file( + f"Creating RX config for dual RGB24 multiple test with video_formats: {video_format_list}", + rx_host, + build, + ) + + try: + rx_config_file = generate_rxtxapp_rx_config_multiple( + rx_nic_port_list[:2], video_format_list, rx_host, build, True + ) + except Exception as e: + logger.error(f"Failed to create RX config: {e}") + log_to_file(f"Failed to create RX config: {e}", rx_host, build) + raise + + rx_cmd = f"{RXTXAPP_PATH} --config_file {rx_config_file} --test_time {test_time}" + tx_1_cmd = ( + f"ffmpeg -stream_loop -1 -video_size {video_size_1} -f rawvideo -pix_fmt rgb24 " + f"-i {video_url_list[0]} -filter:v fps={fps_1} -p_port {tx_nic_port_list[0]} " + f"-p_sip {ip_dict_rgb24_multiple['p_sip_1']} " + f"-p_tx_ip {ip_dict_rgb24_multiple['p_tx_ip_1']} " + f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" + ) + tx_2_cmd = ( + f"ffmpeg -stream_loop -1 -video_size {video_size_2} -f rawvideo -pix_fmt rgb24 " + f"-i {video_url_list[1]} -filter:v fps={fps_2} -p_port {tx_nic_port_list[1]} " + f"-p_sip {ip_dict_rgb24_multiple['p_sip_2']} " + f"-p_tx_ip {ip_dict_rgb24_multiple['p_tx_ip_2']} " + f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" + ) + + logger.info(f"TX1 Command (host {tx_host.name}): {tx_1_cmd}") + logger.info(f"TX2 Command (host {tx_host.name}): {tx_2_cmd}") + logger.info(f"RX Command (host {rx_host.name}): {rx_cmd}") + log_to_file(f"TX1 Command (host {tx_host.name}): {tx_1_cmd}", tx_host, build) + log_to_file(f"TX2 Command (host {tx_host.name}): {tx_2_cmd}", tx_host, build) + log_to_file(f"RX Command (host {rx_host.name}): {rx_cmd}", rx_host, build) + + rx_proc = None + tx_1_proc = None + tx_2_proc = None + tcpdump_tx = prepare_tcpdump(capture_cfg, tx_host) + tcpdump_rx = prepare_tcpdump(capture_cfg, rx_host) + + try: + # Start RX first + rx_proc = run(rx_cmd, background=True, host=rx_host) + time.sleep(2) + + # Start TX processes + tx_1_proc = run(tx_1_cmd, background=True, host=tx_host) + time.sleep(1) + tx_2_proc = run(tx_2_cmd, background=True, host=tx_host) + + # Wait for test completion + time.sleep(test_time + 5) + + # Get RX output + rx_output = rx_proc.stdout_text if rx_proc else "" + + except Exception as e: + logger.error(f"Error during dual RGB24 multiple test execution: {e}") + log_to_file(f"Error during dual RGB24 multiple test execution: {e}", tx_host, build) + log_to_file(f"Error during dual RGB24 multiple test execution: {e}", rx_host, build) + raise + finally: + # Stop processes + if tx_1_proc: + run(f"pkill -f '{tx_1_cmd.split()[0]}'", host=tx_host) + if tx_2_proc: + run(f"pkill -f '{tx_2_cmd.split()[0]}'", host=tx_host) + if rx_proc: + run(f"pkill -f '{rx_cmd.split()[0]}'", host=rx_host) + + # Stop tcpdump if running + if tcpdump_tx: + tcpdump_tx.stop() + if tcpdump_rx: + tcpdump_rx.stop() + + time.sleep(2) + + if not check_output_rgb24(rx_output, 2): + log_fail(f"Dual RGB24 multiple ffmpeg test failed for {video_format_list}") + + time.sleep(5) + return True diff --git a/tests/validation/tests/dual/ffmpeg/__init__.py b/tests/validation/tests/dual/ffmpeg/__init__.py new file mode 100755 index 000000000..7aacd98ac --- /dev/null +++ b/tests/validation/tests/dual/ffmpeg/__init__.py @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024-2025 Intel Corporation diff --git a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg.py b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg.py new file mode 100755 index 000000000..283532cd0 --- /dev/null +++ b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg.py @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024-2025 Intel Corporation + +import os + +import pytest +from mtl_engine import ffmpeg_app +from mtl_engine.media_files import yuv_files + + +@pytest.mark.parametrize( + "video_format, test_time_multipler,", + [ + ("i1080p25", 2), + ("i1080p50", 2), + pytest.param("i1080p60", 4, marks=pytest.mark.smoke), + ("i2160p60", 6), + ], +) +@pytest.mark.parametrize("output_format", ["yuv", "h264"]) +def test_rx_ffmpeg_tx_ffmpeg_dual( + hosts, + test_time, + build, + media, + nic_port_list, + video_format, + test_time_multipler, + output_format, + test_config, + prepare_ramdisk, +): + # Get TX and RX hosts + host_list = list(hosts.values()) + if len(host_list) < 2: + pytest.skip("Dual tests require at least 2 hosts") + + tx_host = host_list[0] + rx_host = host_list[1] + + capture_cfg = dict(test_config.get("capture_cfg", {})) + capture_cfg["test_name"] = ( + f"test_rx_ffmpeg_tx_ffmpeg_dual_{video_format}_{output_format}" + ) + + video_file = yuv_files[video_format] + + ffmpeg_app.execute_dual_test( + test_time=test_time * test_time_multipler, + build=build, + tx_host=tx_host, + rx_host=rx_host, + type_="frame", + video_format=video_format, + pg_format=video_file["format"], + video_url=os.path.join(media, video_file["filename"]), + output_format=output_format, + capture_cfg=capture_cfg, + ) diff --git a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24.py b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24.py new file mode 100755 index 000000000..b00749ed5 --- /dev/null +++ b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24.py @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024-2025 Intel Corporation + +import os + +import pytest +from mtl_engine import ffmpeg_app +from mtl_engine.media_files import yuv_files + + +@pytest.mark.parametrize( + "video_format, test_time_mutlipler", + [ + ("i1080p25", 2), + ("i1080p30", 2), + ("i1080p60", 4), + ("i2160p30", 4), + ("i2160p60", 6), + ], +) +def test_rx_ffmpeg_tx_ffmpeg_rgb24_dual( + hosts, + test_time, + build, + media, + nic_port_list, + video_format, + test_time_mutlipler, + test_config, + prepare_ramdisk, +): + # Get TX and RX hosts + host_list = list(hosts.values()) + if len(host_list) < 2: + pytest.skip("Dual tests require at least 2 hosts") + + tx_host = host_list[0] + rx_host = host_list[1] + + capture_cfg = dict(test_config.get("capture_cfg", {})) + capture_cfg["test_name"] = f"test_rx_ffmpeg_tx_ffmpeg_rgb24_dual_{video_format}" + + video_file = yuv_files[video_format] + + ffmpeg_app.execute_dual_test_rgb24( + test_time=test_time * test_time_mutlipler, + build=build, + tx_host=tx_host, + rx_host=rx_host, + type_="frame", + video_format=video_format, + pg_format=video_file["format"], + video_url=os.path.join(media, video_file["filename"]), + capture_cfg=capture_cfg, + ) diff --git a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple.py b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple.py new file mode 100755 index 000000000..255fe1e06 --- /dev/null +++ b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple.py @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024-2025 Intel Corporation + +import os + +import pytest +from mtl_engine import ffmpeg_app +from mtl_engine.media_files import yuv_files + + +@pytest.mark.parametrize( + "video_format_1, video_format_2, test_time_mutlipler", + [ + ("i1080p25", "i1080p25", 4), + ("i1080p30", "i1080p30", 4), + ("i1080p60", "i1080p60", 8), + ("i1080p60", "i1080p50", 8), + ("i1080p50", "i1080p30", 6), + ("i1080p25", "i1080p50", 6), + ("i1080p25", "i1080p60", 6), + ], +) +def test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual( + hosts, + test_time, + build, + media, + nic_port_list, + video_format_1, + video_format_2, + test_time_mutlipler, + test_config, + prepare_ramdisk, +): + # Get TX and RX hosts + host_list = list(hosts.values()) + if len(host_list) < 2: + pytest.skip("Dual tests require at least 2 hosts") + + tx_host = host_list[0] + rx_host = host_list[1] + + capture_cfg = dict(test_config.get("capture_cfg", {})) + capture_cfg["test_name"] = ( + f"test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual_{video_format_1}_{video_format_2}" + ) + + video_file_1 = yuv_files[video_format_1] + video_file_2 = yuv_files[video_format_2] + + ffmpeg_app.execute_dual_test_rgb24_multiple( + test_time=test_time * test_time_mutlipler, + build=build, + tx_host=tx_host, + rx_host=rx_host, + type_="frame", + video_format_list=[video_format_1, video_format_2], + pg_format=video_file_1["format"], + video_url_list=[ + os.path.join(media, video_file_1["filename"]), + os.path.join(media, video_file_2["filename"]), + ], + capture_cfg=capture_cfg, + ) diff --git a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp.py b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp.py new file mode 100755 index 000000000..07a5de176 --- /dev/null +++ b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp.py @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024-2025 Intel Corporation + +import os + +import pytest +from mtl_engine import ffmpeg_app +from mtl_engine.media_files import yuv_files + + +@pytest.mark.parametrize( + "video_format, multiple_sessions, test_time_multipler", + [ + ("i1080p25", False, 1), + ("i1080p30", False, 1), + ("i1080p60", False, 2), + ("i2160p25", False, 2), + ("i2160p30", False, 2), + ("i2160p60", False, 2), + ("i1080p25", True, 3), + ("i1080p30", True, 3), + ], +) +@pytest.mark.parametrize("output_format", ["yuv", "h264"]) +def test_rx_ffmpeg_tx_rxtxapp_dual( + hosts, + test_time, + build, + media, + nic_port_list, + video_format, + multiple_sessions, + test_time_multipler, + output_format, + test_config, + prepare_ramdisk, +): + # Get TX and RX hosts + host_list = list(hosts.values()) + if len(host_list) < 2: + pytest.skip("Dual tests require at least 2 hosts") + + tx_host = host_list[0] + rx_host = host_list[1] + + capture_cfg = dict(test_config.get("capture_cfg", {})) + capture_cfg["test_name"] = ( + f"test_rx_ffmpeg_tx_rxtxapp_dual_{video_format}_{output_format}_{multiple_sessions}_{test_time_multipler}" + ) + + video_file = yuv_files[video_format] + + ffmpeg_app.execute_dual_test( + test_time=test_time * test_time_multipler, + build=build, + tx_host=tx_host, + rx_host=rx_host, + type_="frame", + video_format=video_format, + pg_format=video_file["format"], + video_url=os.path.join(media, video_file["filename"]), + output_format=output_format, + multiple_sessions=multiple_sessions, + tx_is_ffmpeg=False, # This test uses RxTxApp for TX + capture_cfg=capture_cfg, + ) From ef780d099b3adcf13d88dbb7b2e118aaeec148fe Mon Sep 17 00:00:00 2001 From: Bartosz Krystowski Date: Tue, 12 Aug 2025 14:00:02 +0200 Subject: [PATCH 2/8] Fix dual basic tests --- tests/validation/mtl_engine/RxTxApp.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/tests/validation/mtl_engine/RxTxApp.py b/tests/validation/mtl_engine/RxTxApp.py index 8524aabe2..423ebf7fc 100755 --- a/tests/validation/mtl_engine/RxTxApp.py +++ b/tests/validation/mtl_engine/RxTxApp.py @@ -1482,7 +1482,7 @@ def add_dual_interfaces( tx_config["interfaces"][0]["name"] = tx_nic_port_list[0] # Configure RX host interface only - rx_config["interfaces"][0]["name"] = rx_nic_port_list[1] + rx_config["interfaces"][0]["name"] = rx_nic_port_list[0] if test_mode == "unicast": tx_config["interfaces"][0]["ip"] = unicast_ip_dict["tx_interfaces"] @@ -1673,20 +1673,27 @@ def execute_dual_test( tx_config = config["tx_config"] rx_config = config["rx_config"] + tx_config_json = json.dumps(tx_config, indent=4) + rx_config_json = json.dumps(rx_config, indent=4) + # Log test start logger.info(f"Starting dual RxTxApp test: {get_case_id()}") log_to_file(f"Starting dual RxTxApp test: {get_case_id()}", tx_host, build) log_to_file(f"Starting dual RxTxApp test: {get_case_id()}", rx_host, build) - log_to_file(f"TX config: {json.dumps(tx_config, indent=4)}", tx_host, build) - log_to_file(f"RX config: {json.dumps(rx_config, indent=4)}", rx_host, build) + log_to_file(f"TX config: {tx_config_json}", tx_host, build) + log_to_file(f"RX config: {rx_config_json}", rx_host, build) # Prepare TX config + tx_config_file = f"{build}/tests/tx_config.json" tx_f = tx_host.connection.path(build, "tests", "tx_config.json") - tx_f.write_text(tx_config, encoding="utf-8") + tx_json_content = tx_config_json.replace('"', '\\"') + tx_f.write_text(tx_json_content) # Prepare RX config - rx_f = tx_host.connection.path(build, "tests", "rx_config.json") - rx_f.write_text(rx_config, encoding="utf-8") + rx_config_file = f"{build}/tests/rx_config.json" + rx_f = rx_host.connection.path(build, "tests", "rx_config.json") + rx_json_content = rx_config_json.replace('"', '\\"') + rx_f.write_text(rx_json_content) # Adjust test_time for high-res/fps/replicas if ( @@ -1710,8 +1717,8 @@ def execute_dual_test( if ptp: base_command += " --ptp" - tx_command = f"{base_command} --config_file {tx_config}" - rx_command = f"{base_command} --config_file {rx_config}" + tx_command = f"{base_command} --config_file {tx_config_file}" + rx_command = f"{base_command} --config_file {rx_config_file}" logger.info(f"TX Command: {tx_command}") logger.info(f"RX Command: {rx_command}") From 1e1cab7aa685d61068c90d7b188e351b479e2050 Mon Sep 17 00:00:00 2001 From: Bartosz Krystowski Date: Tue, 12 Aug 2025 21:31:02 +0200 Subject: [PATCH 3/8] Fix dual ffmpeg tests; Change test cases names; Adjust logging; --- tests/validation/mtl_engine/ffmpeg_app.py | 548 +++++++++++++----- .../validation/tests/dual/ffmpeg/__init__.py | 2 - ...eg.py => test_rx_ffmpeg_tx_ffmpeg_dual.py} | 8 +- ...=> test_rx_ffmpeg_tx_ffmpeg_rgb24_dual.py} | 10 +- ...x_ffmpeg_tx_ffmpeg_rgb24_multiple_dual.py} | 14 +- ...p.py => test_rx_ffmpeg_tx_rxtxapp_dual.py} | 0 6 files changed, 416 insertions(+), 166 deletions(-) rename tests/validation/tests/dual/ffmpeg/{test_rx_ffmpeg_tx_ffmpeg.py => test_rx_ffmpeg_tx_ffmpeg_dual.py} (90%) rename tests/validation/tests/dual/ffmpeg/{test_rx_ffmpeg_tx_ffmpeg_rgb24.py => test_rx_ffmpeg_tx_ffmpeg_rgb24_dual.py} (90%) rename tests/validation/tests/dual/ffmpeg/{test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple.py => test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual.py} (85%) rename tests/validation/tests/dual/ffmpeg/{test_rx_ffmpeg_tx_rxtxapp.py => test_rx_ffmpeg_tx_rxtxapp_dual.py} (100%) diff --git a/tests/validation/mtl_engine/ffmpeg_app.py b/tests/validation/mtl_engine/ffmpeg_app.py index c7fa7d57e..8ddbe9029 100755 --- a/tests/validation/mtl_engine/ffmpeg_app.py +++ b/tests/validation/mtl_engine/ffmpeg_app.py @@ -113,17 +113,21 @@ def execute_test( if not multiple_sessions: output_files = create_empty_output_files(output_format, 1, host, build) rx_cmd = ( - f"ffmpeg -p_port {nic_port_list[0]} -p_sip {ip_dict['rx_interfaces']} " - f"-p_rx_ip {ip_dict['rx_sessions']} -udp_port 20000 -payload_type 112 " - f"-fps {fps} -pix_fmt yuv422p10le -video_size {video_size} " - f"-f mtl_st20p -i k {ffmpeg_rx_f_flag} {output_files[0]} -y" + f"ffmpeg -p_port {nic_port_list[0]} " + f"-p_sip {ip_dict['rx_interfaces']} " + f"-p_rx_ip {ip_dict['rx_sessions']} -udp_port 20000 " + f"-payload_type 112 -fps {fps} -pix_fmt yuv422p10le " + f"-video_size {video_size} -f mtl_st20p -i k " + f"{ffmpeg_rx_f_flag} {output_files[0]} -y" ) if tx_is_ffmpeg: tx_cmd = ( - f"ffmpeg -video_size {video_size} -f rawvideo -pix_fmt yuv422p10le " - f"-i {video_url} -filter:v fps={fps} -p_port {nic_port_list[1]} " - f"-p_sip {ip_dict['tx_interfaces']} -p_tx_ip {ip_dict['tx_sessions']} " - f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" + f"ffmpeg -video_size {video_size} -f rawvideo " + f"-pix_fmt yuv422p10le -i {video_url} " + f"-filter:v fps={fps} -p_port {nic_port_list[1]} " + f"-p_sip {ip_dict['tx_interfaces']} " + f"-p_tx_ip {ip_dict['tx_sessions']} -udp_port 20000 " + f"-payload_type 112 -f mtl_st20p -" ) else: # tx is rxtxapp tx_config_file = generate_rxtxapp_tx_config( @@ -134,21 +138,25 @@ def execute_test( output_files = create_empty_output_files(output_format, 2, host, build) rx_cmd = ( f"ffmpeg -p_sip {ip_dict['rx_interfaces']} " - f"-p_port {nic_port_list[0]} -p_rx_ip {ip_dict['rx_sessions']} " - f"-udp_port 20000 -payload_type 112 -fps {fps} -pix_fmt yuv422p10le " + f"-p_port {nic_port_list[0]} " + f"-p_rx_ip {ip_dict['rx_sessions']} -udp_port 20000 " + f"-payload_type 112 -fps {fps} -pix_fmt yuv422p10le " f"-video_size {video_size} -f mtl_st20p -i 1 " - f"-p_port {nic_port_list[0]} -p_rx_ip {ip_dict['rx_sessions']} " - f"-udp_port 20002 -payload_type 112 -fps {fps} -pix_fmt yuv422p10le " + f"-p_port {nic_port_list[0]} " + f"-p_rx_ip {ip_dict['rx_sessions']} -udp_port 20002 " + f"-payload_type 112 -fps {fps} -pix_fmt yuv422p10le " f"-video_size {video_size} -f mtl_st20p -i 2 " f"-map 0:0 {ffmpeg_rx_f_flag} {output_files[0]} -y " f"-map 1:0 {ffmpeg_rx_f_flag} {output_files[1]} -y" ) if tx_is_ffmpeg: tx_cmd = ( - f"ffmpeg -video_size {video_size} -f rawvideo -pix_fmt yuv422p10le " - f"-i {video_url} -filter:v fps={fps} -p_port {nic_port_list[1]} " - f"-p_sip {ip_dict['tx_interfaces']} -p_tx_ip {ip_dict['tx_sessions']} " - f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" + f"ffmpeg -video_size {video_size} -f rawvideo " + f"-pix_fmt yuv422p10le -i {video_url} " + f"-filter:v fps={fps} -p_port {nic_port_list[1]} " + f"-p_sip {ip_dict['tx_interfaces']} " + f"-p_tx_ip {ip_dict['tx_sessions']} -udp_port 20000 " + f"-payload_type 112 -f mtl_st20p -" ) else: # tx is rxtxapp tx_config_file = generate_rxtxapp_tx_config( @@ -1009,21 +1017,20 @@ def execute_dual_test( tx_is_ffmpeg: bool = True, capture_cfg=None, ): + # Initialize logging for this test init_test_logging() - case_id = os.environ.get("PYTEST_CURRENT_TEST", "ffmpeg_dual_test") + case_id = os.environ.get("PYTEST_CURRENT_TEST", "ffmpeg_test") case_id = case_id[: case_id.rfind("(") - 1] if "(" in case_id else case_id tx_nic_port_list = tx_host.vfs rx_nic_port_list = rx_host.vfs video_size, fps = decode_video_format_16_9(video_format) - match output_format: case "yuv": ffmpeg_rx_f_flag = "-f rawvideo" case "h264": ffmpeg_rx_f_flag = "-c:v libopenh264" - if not multiple_sessions: output_files = create_empty_output_files(output_format, 1, rx_host, build) rx_cmd = ( @@ -1034,61 +1041,154 @@ def execute_dual_test( ) if tx_is_ffmpeg: tx_cmd = ( - f"ffmpeg -stream_loop -1 -video_size {video_size} -f rawvideo -pix_fmt yuv422p10le " + f"ffmpeg -video_size {video_size} -f rawvideo -pix_fmt yuv422p10le " f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[0]} " f"-p_sip {ip_dict['tx_interfaces']} -p_tx_ip {ip_dict['tx_sessions']} " f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) - else: + else: # tx is rxtxapp tx_config_file = generate_rxtxapp_tx_config( - tx_nic_port_list[0], video_format, video_url, tx_host, build, multiple_sessions + tx_nic_port_list[0], video_format, video_url, tx_host, build ) - tx_cmd = f"{RXTXAPP_PATH} --config_file {tx_config_file} --test_time {test_time}" + tx_cmd = f"{RXTXAPP_PATH} --config_file {tx_config_file}" else: # multiple sessions output_files = create_empty_output_files(output_format, 2, rx_host, build) - # Implementation for multiple sessions would go here + rx_cmd = ( + f"ffmpeg -p_sip {ip_dict['rx_interfaces']} " + f"-p_port {rx_nic_port_list[0]} -p_rx_ip {ip_dict['rx_sessions']} " + f"-udp_port 20000 -payload_type 112 -fps {fps} -pix_fmt yuv422p10le " + f"-video_size {video_size} -f mtl_st20p -i 1 " + f"-p_port {rx_nic_port_list[0]} -p_rx_ip {ip_dict['rx_sessions']} " + f"-udp_port 20002 -payload_type 112 -fps {fps} -pix_fmt yuv422p10le " + f"-video_size {video_size} -f mtl_st20p -i 2 " + f"-map 0:0 {ffmpeg_rx_f_flag} {output_files[0]} -y " + f"-map 1:0 {ffmpeg_rx_f_flag} {output_files[1]} -y" + ) + if tx_is_ffmpeg: + tx_cmd = ( + f"ffmpeg -video_size {video_size} -f rawvideo -pix_fmt yuv422p10le " + f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[0]} " + f"-p_sip {ip_dict['tx_interfaces']} -p_tx_ip {ip_dict['tx_sessions']} " + f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" + ) + else: # tx is rxtxapp + tx_config_file = generate_rxtxapp_tx_config( + tx_nic_port_list[0], video_format, video_url, tx_host, build, True + ) + tx_cmd = f"{RXTXAPP_PATH} --config_file {tx_config_file}" - logger.info(f"TX Command (host {tx_host.name}): {tx_cmd}") - logger.info(f"RX Command (host {rx_host.name}): {rx_cmd}") - log_to_file(f"TX Command (host {tx_host.name}): {tx_cmd}", tx_host, build) - log_to_file(f"RX Command (host {rx_host.name}): {rx_cmd}", rx_host, build) + logger.info(f"TX Host: {tx_host}") + logger.info(f"RX Host: {rx_host}") + logger.info(f"RX Command: {rx_cmd}") + logger.info(f"TX Command: {tx_cmd}") + log_to_file(f"TX Host: {tx_host}", rx_host, build) + log_to_file(f"RX Host: {rx_host}", rx_host, build) + log_to_file(f"RX Command: {rx_cmd}", rx_host, build) + log_to_file(f"TX Command: {tx_cmd}", tx_host, build) rx_proc = None tx_proc = None - tcpdump_tx = prepare_tcpdump(capture_cfg, tx_host) - tcpdump_rx = prepare_tcpdump(capture_cfg, rx_host) + # Use RX host for tcpdump capture + tcpdump = prepare_tcpdump(capture_cfg, rx_host) try: - # Start RX first - rx_proc = run(rx_cmd, background=True, host=rx_host) + # Start RX pipeline first on RX host + logger.info("Starting RX pipeline on RX host...") + rx_proc = run( + rx_cmd, + cwd=build, + timeout=test_time + 60, + testcmd=True, + host=rx_host, + background=True, + enable_sudo=True, + ) time.sleep(2) - - # Start TX - tx_proc = run(tx_cmd, background=True, host=tx_host) - - # Wait for test completion - time.sleep(test_time + 5) - + + # Start TX pipeline on TX host + logger.info("Starting TX pipeline on TX host...") + tx_proc = run( + tx_cmd, + cwd=build, + timeout=test_time + 60, + testcmd=True, + host=tx_host, + background=True, + enable_sudo=True, + ) + # Start tcpdump after pipelines are running + if tcpdump: + logger.info("Starting tcpdump capture...") + tcpdump.capture(capture_time=capture_cfg.get("capture_time", test_time)) + + # Let the test run for the specified duration + logger.info(f"Running test for {test_time} seconds...") + time.sleep(test_time) + + logger.info("Terminating processes...") + if tx_proc: + try: + tx_proc.terminate() + except Exception: + pass + if rx_proc: + try: + rx_proc.terminate() + except Exception: + pass + # Wait a bit for termination + time.sleep(2) + # Get output after processes have been terminated + try: + rx_output = f"RX Output:\n{rx_proc.stdout_text}" + log_to_file(rx_output, rx_host, build) + except Exception: + logger.info("Could not retrieve RX output") + try: + tx_output = f"TX Output:\n{tx_proc.stdout_text}" + log_to_file(tx_output, tx_host, build) + except Exception: + logger.info("Could not retrieve TX output") except Exception as e: - logger.error(f"Error during dual test execution: {e}") - log_to_file(f"Error during dual test execution: {e}", tx_host, build) - log_to_file(f"Error during dual test execution: {e}", rx_host, build) + log_fail(f"Error during test execution: {e}") + # Terminate processes immediately on error + if tx_proc: + try: + tx_proc.terminate() + except Exception: + pass + if rx_proc: + try: + rx_proc.terminate() + except Exception: + pass raise finally: - # Stop processes + # Ensure processes are terminated with force kill if needed if tx_proc: - run(f"pkill -f '{tx_cmd.split()[0]}'", host=tx_host) + try: + tx_proc.terminate() + tx_proc.wait(timeout=5) + except Exception: + try: + # Force kill if terminate didn't work + tx_proc.kill() + tx_proc.wait(timeout=5) + except Exception: + pass if rx_proc: - run(f"pkill -f '{rx_cmd.split()[0]}'", host=rx_host) - - # Stop tcpdump if running - if tcpdump_tx: - tcpdump_tx.stop() - if tcpdump_rx: - tcpdump_rx.stop() - - time.sleep(2) - + try: + rx_proc.terminate() + rx_proc.wait(timeout=5) + except Exception: + try: + # Force kill if terminate didn't work + rx_proc.kill() + rx_proc.wait(timeout=5) + except Exception: + pass + if tcpdump: + tcpdump.stop() passed = False match output_format: case "yuv": @@ -1097,17 +1197,15 @@ def execute_dual_test( passed = check_output_video_h264( output_files[0], video_size, rx_host, build, video_url ) - # Clean up output files after validation try: for output_file in output_files: run(f"rm -f {output_file}", host=rx_host) + logger.info(f"Removed output file: {output_file}") except Exception as e: - logger.warning(f"Failed to clean up output files: {e}") - + logger.info(f"Could not remove output files: {e}") if not passed: - log_fail(f"Dual ffmpeg test failed for {video_format}") - + log_fail("test failed") return passed @@ -1122,30 +1220,33 @@ def execute_dual_test_rgb24( video_url: str, capture_cfg=None, ): - """Execute dual host RGB24 ffmpeg test""" # Initialize logging for this test init_test_logging() + # Use separate NIC port lists for TX and RX hosts tx_nic_port_list = tx_host.vfs rx_nic_port_list = rx_host.vfs video_size, fps = decode_video_format_16_9(video_format) - logger.info(f"Creating RX config for dual RGB24 test with video_format: {video_format}") + logger.info(f"Creating RX config for RGB24 dual test with video_format: {video_format}") log_to_file( - f"Creating RX config for dual RGB24 test with video_format: {video_format}", + f"Creating RX config for RGB24 dual test with video_format: {video_format}", rx_host, build, ) - try: rx_config_file = generate_rxtxapp_rx_config( rx_nic_port_list[0], video_format, rx_host, build ) + logger.info(f"Successfully created RX config file: {rx_config_file}") + log_to_file( + f"Successfully created RX config file: {rx_config_file}", rx_host, build + ) except Exception as e: - logger.error(f"Failed to create RX config: {e}") - log_to_file(f"Failed to create RX config: {e}", rx_host, build) - raise - + log_fail(f"Failed to create RX config file: {e}") + log_to_file(f"Failed to create RX config file: {e}", rx_host, build) + return False + rx_cmd = f"{RXTXAPP_PATH} --config_file {rx_config_file} --test_time {test_time}" tx_cmd = ( f"ffmpeg -stream_loop -1 -video_size {video_size} -f rawvideo -pix_fmt rgb24 " @@ -1154,53 +1255,129 @@ def execute_dual_test_rgb24( f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) - logger.info(f"TX Command (host {tx_host.name}): {tx_cmd}") - logger.info(f"RX Command (host {rx_host.name}): {rx_cmd}") - log_to_file(f"TX Command (host {tx_host.name}): {tx_cmd}", tx_host, build) - log_to_file(f"RX Command (host {rx_host.name}): {rx_cmd}", rx_host, build) + logger.info(f"TX Host: {tx_host}") + logger.info(f"RX Host: {rx_host}") + logger.info(f"RX Command: {rx_cmd}") + logger.info(f"TX Command: {tx_cmd}") + log_to_file(f"TX Host: {tx_host}", rx_host, build) + log_to_file(f"RX Host: {rx_host}", rx_host, build) + log_to_file(f"RX Command: {rx_cmd}", rx_host, build) + log_to_file(f"TX Command: {tx_cmd}", tx_host, build) rx_proc = None tx_proc = None - tcpdump_tx = prepare_tcpdump(capture_cfg, tx_host) - tcpdump_rx = prepare_tcpdump(capture_cfg, rx_host) + # Use RX host for tcpdump capture + tcpdump = prepare_tcpdump(capture_cfg, rx_host) try: - # Start RX first - rx_proc = run(rx_cmd, background=True, host=rx_host) - time.sleep(2) + # Start RX pipeline first on RX host + logger.info("Starting RX pipeline on RX host...") + rx_proc = run( + rx_cmd, + cwd=build, + timeout=test_time + 60, + testcmd=True, + host=rx_host, + background=True, + enable_sudo=True, + ) + time.sleep(5) - # Start TX - tx_proc = run(tx_cmd, background=True, host=tx_host) + # Start TX pipeline on TX host + logger.info("Starting TX pipeline on TX host...") + tx_proc = run( + tx_cmd, + cwd=build, + timeout=test_time + 60, + testcmd=True, + host=tx_host, + background=True, + enable_sudo=True, + ) - # Wait for test completion - time.sleep(test_time + 5) + # Start tcpdump after pipelines are running + if tcpdump: + logger.info("Starting tcpdump capture...") + tcpdump.capture(capture_time=capture_cfg.get("capture_time", test_time)) + + logger.info( + f"Waiting for RX process to complete (test_time: {test_time} seconds)..." + ) + rx_proc.wait() + logger.info("RX process completed") + + # Terminate TX process after RX completes + logger.info("Terminating TX process...") + if tx_proc: + try: + tx_proc.terminate() + tx_proc.wait(timeout=5) + logger.info("TX process terminated successfully") + except Exception: + try: + tx_proc.kill() + tx_proc.wait(timeout=5) + logger.info("TX process killed") + except Exception: + logger.info("Could not terminate TX process") - # Get RX output - rx_output = rx_proc.stdout_text if rx_proc else "" + rx_output = "" + try: + rx_output = rx_proc.stdout_text + log_to_file(f"RX Output:\n{rx_output}", rx_host, build) + logger.info("RX output captured successfully") + except Exception as e: + logger.info(f"Error retrieving RX output: {e}") + log_to_file(f"Error retrieving RX output: {e}", rx_host, build) + + try: + log_to_file(f"TX Output:\n{tx_proc.stdout_text}", tx_host, build) + logger.info("TX output captured successfully") + except Exception as e: + log_to_file(f"Error retrieving TX output: {e}", tx_host, build) except Exception as e: - logger.error(f"Error during dual RGB24 test execution: {e}") - log_to_file(f"Error during dual RGB24 test execution: {e}", tx_host, build) - log_to_file(f"Error during dual RGB24 test execution: {e}", rx_host, build) + log_fail(f"Error during test execution: {e}") + # Terminate processes immediately on error + if tx_proc: + try: + tx_proc.terminate() + except Exception: + pass + if rx_proc: + try: + rx_proc.terminate() + except Exception: + pass raise finally: - # Stop processes + # Final cleanup - ensure processes are terminated if tx_proc: - run(f"pkill -f '{tx_cmd.split()[0]}'", host=tx_host) + try: + tx_proc.terminate() + tx_proc.wait(timeout=3) + except Exception: + try: + tx_proc.kill() + tx_proc.wait(timeout=3) + except Exception: + pass if rx_proc: - run(f"pkill -f '{rx_cmd.split()[0]}'", host=rx_host) - - # Stop tcpdump if running - if tcpdump_tx: - tcpdump_tx.stop() - if tcpdump_rx: - tcpdump_rx.stop() - - time.sleep(2) - + try: + rx_proc.terminate() + rx_proc.wait(timeout=3) + except Exception: + try: + rx_proc.kill() + rx_proc.wait(timeout=3) + except Exception: + pass + if tcpdump: + tcpdump.stop() + if not check_output_rgb24(rx_output, 1): - log_fail(f"Dual RGB24 ffmpeg test failed for {video_format}") - + log_fail("rx video sessions failed") + return False time.sleep(5) return True @@ -1216,33 +1393,36 @@ def execute_dual_test_rgb24_multiple( video_url_list: list, capture_cfg=None, ): - """Execute dual host RGB24 multiple sessions ffmpeg test""" # Initialize logging for this test init_test_logging() + # Use separate NIC port lists for TX and RX hosts tx_nic_port_list = tx_host.vfs rx_nic_port_list = rx_host.vfs video_size_1, fps_1 = decode_video_format_16_9(video_format_list[0]) video_size_2, fps_2 = decode_video_format_16_9(video_format_list[1]) logger.info( - f"Creating RX config for dual RGB24 multiple test with video_formats: {video_format_list}" + f"Creating RX config for RGB24 multiple dual test with video_formats: {video_format_list}" ) log_to_file( - f"Creating RX config for dual RGB24 multiple test with video_formats: {video_format_list}", + f"Creating RX config for RGB24 multiple dual test with video_formats: {video_format_list}", rx_host, build, ) - try: rx_config_file = generate_rxtxapp_rx_config_multiple( rx_nic_port_list[:2], video_format_list, rx_host, build, True ) + logger.info(f"Successfully created RX config file: {rx_config_file}") + log_to_file( + f"Successfully created RX config file: {rx_config_file}", rx_host, build + ) except Exception as e: - logger.error(f"Failed to create RX config: {e}") - log_to_file(f"Failed to create RX config: {e}", rx_host, build) - raise - + log_fail(f"Failed to create RX config file: {e}") + log_to_file(f"Failed to create RX config file: {e}", rx_host, build) + return False + rx_cmd = f"{RXTXAPP_PATH} --config_file {rx_config_file} --test_time {test_time}" tx_1_cmd = ( f"ffmpeg -stream_loop -1 -video_size {video_size_1} -f rawvideo -pix_fmt rgb24 " @@ -1259,59 +1439,131 @@ def execute_dual_test_rgb24_multiple( f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) - logger.info(f"TX1 Command (host {tx_host.name}): {tx_1_cmd}") - logger.info(f"TX2 Command (host {tx_host.name}): {tx_2_cmd}") - logger.info(f"RX Command (host {rx_host.name}): {rx_cmd}") - log_to_file(f"TX1 Command (host {tx_host.name}): {tx_1_cmd}", tx_host, build) - log_to_file(f"TX2 Command (host {tx_host.name}): {tx_2_cmd}", tx_host, build) - log_to_file(f"RX Command (host {rx_host.name}): {rx_cmd}", rx_host, build) + logger.info(f"TX Host: {tx_host}") + logger.info(f"RX Host: {rx_host}") + logger.info(f"RX Command: {rx_cmd}") + logger.info(f"TX1 Command: {tx_1_cmd}") + logger.info(f"TX2 Command: {tx_2_cmd}") + log_to_file(f"TX Host: {tx_host}", rx_host, build) + log_to_file(f"RX Host: {rx_host}", rx_host, build) + log_to_file(f"RX Command: {rx_cmd}", rx_host, build) + log_to_file(f"TX1 Command: {tx_1_cmd}", tx_host, build) + log_to_file(f"TX2 Command: {tx_2_cmd}", tx_host, build) rx_proc = None tx_1_proc = None tx_2_proc = None - tcpdump_tx = prepare_tcpdump(capture_cfg, tx_host) - tcpdump_rx = prepare_tcpdump(capture_cfg, rx_host) + # Use RX host for tcpdump capture + tcpdump = prepare_tcpdump(capture_cfg, rx_host) try: - # Start RX first - rx_proc = run(rx_cmd, background=True, host=rx_host) - time.sleep(2) + # Start RX pipeline first on RX host + logger.info("Starting RX pipeline on RX host...") + rx_proc = run( + rx_cmd, + cwd=build, + timeout=test_time + 60, + testcmd=True, + host=rx_host, + background=True, + enable_sudo=True, + ) + time.sleep(5) - # Start TX processes - tx_1_proc = run(tx_1_cmd, background=True, host=tx_host) - time.sleep(1) - tx_2_proc = run(tx_2_cmd, background=True, host=tx_host) + # Start TX pipelines on TX host + logger.info("Starting TX pipelines on TX host...") + tx_1_proc = run( + tx_1_cmd, + cwd=build, + timeout=test_time + 60, + testcmd=True, + host=tx_host, + background=True, + enable_sudo=True, + ) + tx_2_proc = run( + tx_2_cmd, + cwd=build, + timeout=test_time + 60, + testcmd=True, + host=tx_host, + background=True, + enable_sudo=True, + ) + + # Start tcpdump after pipelines are running + if tcpdump: + logger.info("Starting tcpdump capture...") + tcpdump.capture(capture_time=capture_cfg.get("capture_time", test_time)) + + logger.info(f"Waiting for RX process (test_time: {test_time} seconds)...") + rx_proc.wait() + logger.info("RX process completed") + + # Terminate TX processes after RX completes + logger.info("Terminating TX processes...") + for proc in [tx_1_proc, tx_2_proc]: + if proc: + try: + proc.terminate() + proc.wait(timeout=5) + logger.info("TX process terminated successfully") + except Exception: + try: + proc.kill() + proc.wait(timeout=5) + logger.info("TX process killed") + except Exception: + logger.info("Could not terminate TX process") - # Wait for test completion - time.sleep(test_time + 5) + rx_output = "" + try: + rx_output = rx_proc.stdout_text + log_to_file(f"RX Output:\n{rx_output}", rx_host, build) + logger.info("RX output captured successfully") + except Exception as e: + logger.info(f"Error retrieving RX output: {e}") + log_to_file(f"Error retrieving RX output: {e}", rx_host, build) - # Get RX output - rx_output = rx_proc.stdout_text if rx_proc else "" + try: + log_to_file(f"TX1 Output:\n{tx_1_proc.stdout_text}", tx_host, build) + logger.info("TX1 output captured successfully") + except Exception as e: + logger.info(f"Error retrieving TX1 output: {e}") + try: + log_to_file(f"TX2 Output:\n{tx_2_proc.stdout_text}", tx_host, build) + logger.info("TX2 output captured successfully") + except Exception as e: + logger.info(f"Error retrieving TX2 output: {e}") except Exception as e: - logger.error(f"Error during dual RGB24 multiple test execution: {e}") - log_to_file(f"Error during dual RGB24 multiple test execution: {e}", tx_host, build) - log_to_file(f"Error during dual RGB24 multiple test execution: {e}", rx_host, build) + log_fail(f"Error during test execution: {e}") + # Terminate processes immediately on error + for proc in [tx_1_proc, tx_2_proc, rx_proc]: + if proc: + try: + proc.terminate() + except Exception: + pass raise finally: - # Stop processes - if tx_1_proc: - run(f"pkill -f '{tx_1_cmd.split()[0]}'", host=tx_host) - if tx_2_proc: - run(f"pkill -f '{tx_2_cmd.split()[0]}'", host=tx_host) - if rx_proc: - run(f"pkill -f '{rx_cmd.split()[0]}'", host=rx_host) - - # Stop tcpdump if running - if tcpdump_tx: - tcpdump_tx.stop() - if tcpdump_rx: - tcpdump_rx.stop() - - time.sleep(2) - + # Final cleanup - ensure processes are terminated + for proc in [tx_1_proc, tx_2_proc, rx_proc]: + if proc: + try: + proc.terminate() + proc.wait(timeout=3) + except Exception: + try: + proc.kill() + proc.wait(timeout=3) + except Exception: + pass + if tcpdump: + tcpdump.stop() + if not check_output_rgb24(rx_output, 2): - log_fail(f"Dual RGB24 multiple ffmpeg test failed for {video_format_list}") - + log_fail("rx video session failed") + return False time.sleep(5) - return True + return True \ No newline at end of file diff --git a/tests/validation/tests/dual/ffmpeg/__init__.py b/tests/validation/tests/dual/ffmpeg/__init__.py index 7aacd98ac..e69de29bb 100755 --- a/tests/validation/tests/dual/ffmpeg/__init__.py +++ b/tests/validation/tests/dual/ffmpeg/__init__.py @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2024-2025 Intel Corporation diff --git a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg.py b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_dual.py similarity index 90% rename from tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg.py rename to tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_dual.py index 283532cd0..9c37d4a00 100755 --- a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg.py +++ b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_dual.py @@ -11,10 +11,10 @@ @pytest.mark.parametrize( "video_format, test_time_multipler,", [ - ("i1080p25", 2), - ("i1080p50", 2), - pytest.param("i1080p60", 4, marks=pytest.mark.smoke), - ("i2160p60", 6), + ("i1080p25", 1), + ("i1080p50", 1), + ("i1080p60", 2), + ("i2160p60", 3), ], ) @pytest.mark.parametrize("output_format", ["yuv", "h264"]) diff --git a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24.py b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_dual.py similarity index 90% rename from tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24.py rename to tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_dual.py index b00749ed5..278f0e018 100755 --- a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24.py +++ b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_dual.py @@ -11,11 +11,11 @@ @pytest.mark.parametrize( "video_format, test_time_mutlipler", [ - ("i1080p25", 2), - ("i1080p30", 2), - ("i1080p60", 4), - ("i2160p30", 4), - ("i2160p60", 6), + ("i1080p25", 1), + ("i1080p30", 1), + ("i1080p60", 2), + ("i2160p30", 2), + ("i2160p60", 3), ], ) def test_rx_ffmpeg_tx_ffmpeg_rgb24_dual( diff --git a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple.py b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual.py similarity index 85% rename from tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple.py rename to tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual.py index 255fe1e06..748a79296 100755 --- a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple.py +++ b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual.py @@ -11,13 +11,13 @@ @pytest.mark.parametrize( "video_format_1, video_format_2, test_time_mutlipler", [ - ("i1080p25", "i1080p25", 4), - ("i1080p30", "i1080p30", 4), - ("i1080p60", "i1080p60", 8), - ("i1080p60", "i1080p50", 8), - ("i1080p50", "i1080p30", 6), - ("i1080p25", "i1080p50", 6), - ("i1080p25", "i1080p60", 6), + ("i1080p25", "i1080p25", 2), + ("i1080p30", "i1080p30", 2), + ("i1080p60", "i1080p60", 4), + ("i1080p60", "i1080p50", 4), + ("i1080p50", "i1080p30", 3), + ("i1080p25", "i1080p50", 3), + ("i1080p25", "i1080p60", 3), ], ) def test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual( diff --git a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp.py b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp_dual.py similarity index 100% rename from tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp.py rename to tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp_dual.py From 9bac7a54993e77442bfd88e8c909ad4464678fa0 Mon Sep 17 00:00:00 2001 From: Bartosz Krystowski Date: Tue, 12 Aug 2025 21:55:40 +0200 Subject: [PATCH 4/8] Fix linter issues --- tests/validation/mtl_engine/ffmpeg_app.py | 42 ++++++++++--------- .../ffmpeg/test_rx_ffmpeg_tx_ffmpeg_dual.py | 2 +- .../test_rx_ffmpeg_tx_ffmpeg_rgb24_dual.py | 2 +- ...rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual.py | 2 +- .../ffmpeg/test_rx_ffmpeg_tx_rxtxapp_dual.py | 2 +- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/tests/validation/mtl_engine/ffmpeg_app.py b/tests/validation/mtl_engine/ffmpeg_app.py index 8ddbe9029..7d1b5d7e1 100755 --- a/tests/validation/mtl_engine/ffmpeg_app.py +++ b/tests/validation/mtl_engine/ffmpeg_app.py @@ -1222,13 +1222,15 @@ def execute_dual_test_rgb24( ): # Initialize logging for this test init_test_logging() - + # Use separate NIC port lists for TX and RX hosts tx_nic_port_list = tx_host.vfs rx_nic_port_list = rx_host.vfs video_size, fps = decode_video_format_16_9(video_format) - - logger.info(f"Creating RX config for RGB24 dual test with video_format: {video_format}") + + logger.info( + f"Creating RX config for RGB24 dual test with video_format: {video_format}" + ) log_to_file( f"Creating RX config for RGB24 dual test with video_format: {video_format}", rx_host, @@ -1246,7 +1248,7 @@ def execute_dual_test_rgb24( log_fail(f"Failed to create RX config file: {e}") log_to_file(f"Failed to create RX config file: {e}", rx_host, build) return False - + rx_cmd = f"{RXTXAPP_PATH} --config_file {rx_config_file} --test_time {test_time}" tx_cmd = ( f"ffmpeg -stream_loop -1 -video_size {video_size} -f rawvideo -pix_fmt rgb24 " @@ -1282,7 +1284,7 @@ def execute_dual_test_rgb24( enable_sudo=True, ) time.sleep(5) - + # Start TX pipeline on TX host logger.info("Starting TX pipeline on TX host...") tx_proc = run( @@ -1294,7 +1296,7 @@ def execute_dual_test_rgb24( background=True, enable_sudo=True, ) - + # Start tcpdump after pipelines are running if tcpdump: logger.info("Starting tcpdump capture...") @@ -1320,7 +1322,7 @@ def execute_dual_test_rgb24( logger.info("TX process killed") except Exception: logger.info("Could not terminate TX process") - + rx_output = "" try: rx_output = rx_proc.stdout_text @@ -1335,7 +1337,7 @@ def execute_dual_test_rgb24( logger.info("TX output captured successfully") except Exception as e: log_to_file(f"Error retrieving TX output: {e}", tx_host, build) - + except Exception as e: log_fail(f"Error during test execution: {e}") # Terminate processes immediately on error @@ -1374,7 +1376,7 @@ def execute_dual_test_rgb24( pass if tcpdump: tcpdump.stop() - + if not check_output_rgb24(rx_output, 1): log_fail("rx video sessions failed") return False @@ -1395,13 +1397,13 @@ def execute_dual_test_rgb24_multiple( ): # Initialize logging for this test init_test_logging() - - # Use separate NIC port lists for TX and RX hosts + + # Use separate NIC port lists for TX and RX hosts tx_nic_port_list = tx_host.vfs rx_nic_port_list = rx_host.vfs video_size_1, fps_1 = decode_video_format_16_9(video_format_list[0]) video_size_2, fps_2 = decode_video_format_16_9(video_format_list[1]) - + logger.info( f"Creating RX config for RGB24 multiple dual test with video_formats: {video_format_list}" ) @@ -1422,7 +1424,7 @@ def execute_dual_test_rgb24_multiple( log_fail(f"Failed to create RX config file: {e}") log_to_file(f"Failed to create RX config file: {e}", rx_host, build) return False - + rx_cmd = f"{RXTXAPP_PATH} --config_file {rx_config_file} --test_time {test_time}" tx_1_cmd = ( f"ffmpeg -stream_loop -1 -video_size {video_size_1} -f rawvideo -pix_fmt rgb24 " @@ -1469,7 +1471,7 @@ def execute_dual_test_rgb24_multiple( enable_sudo=True, ) time.sleep(5) - + # Start TX pipelines on TX host logger.info("Starting TX pipelines on TX host...") tx_1_proc = run( @@ -1490,7 +1492,7 @@ def execute_dual_test_rgb24_multiple( background=True, enable_sudo=True, ) - + # Start tcpdump after pipelines are running if tcpdump: logger.info("Starting tcpdump capture...") @@ -1515,7 +1517,7 @@ def execute_dual_test_rgb24_multiple( logger.info("TX process killed") except Exception: logger.info("Could not terminate TX process") - + rx_output = "" try: rx_output = rx_proc.stdout_text @@ -1524,13 +1526,13 @@ def execute_dual_test_rgb24_multiple( except Exception as e: logger.info(f"Error retrieving RX output: {e}") log_to_file(f"Error retrieving RX output: {e}", rx_host, build) - + try: log_to_file(f"TX1 Output:\n{tx_1_proc.stdout_text}", tx_host, build) logger.info("TX1 output captured successfully") except Exception as e: logger.info(f"Error retrieving TX1 output: {e}") - + try: log_to_file(f"TX2 Output:\n{tx_2_proc.stdout_text}", tx_host, build) logger.info("TX2 output captured successfully") @@ -1561,9 +1563,9 @@ def execute_dual_test_rgb24_multiple( pass if tcpdump: tcpdump.stop() - + if not check_output_rgb24(rx_output, 2): log_fail("rx video session failed") return False time.sleep(5) - return True \ No newline at end of file + return True diff --git a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_dual.py b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_dual.py index 9c37d4a00..95d96cd4a 100755 --- a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_dual.py +++ b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_dual.py @@ -37,7 +37,7 @@ def test_rx_ffmpeg_tx_ffmpeg_dual( tx_host = host_list[0] rx_host = host_list[1] - + capture_cfg = dict(test_config.get("capture_cfg", {})) capture_cfg["test_name"] = ( f"test_rx_ffmpeg_tx_ffmpeg_dual_{video_format}_{output_format}" diff --git a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_dual.py b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_dual.py index 278f0e018..56ebfe24d 100755 --- a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_dual.py +++ b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_dual.py @@ -36,7 +36,7 @@ def test_rx_ffmpeg_tx_ffmpeg_rgb24_dual( tx_host = host_list[0] rx_host = host_list[1] - + capture_cfg = dict(test_config.get("capture_cfg", {})) capture_cfg["test_name"] = f"test_rx_ffmpeg_tx_ffmpeg_rgb24_dual_{video_format}" diff --git a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual.py b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual.py index 748a79296..e831afd33 100755 --- a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual.py +++ b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual.py @@ -39,7 +39,7 @@ def test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual( tx_host = host_list[0] rx_host = host_list[1] - + capture_cfg = dict(test_config.get("capture_cfg", {})) capture_cfg["test_name"] = ( f"test_rx_ffmpeg_tx_ffmpeg_rgb24_multiple_dual_{video_format_1}_{video_format_2}" diff --git a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp_dual.py b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp_dual.py index 07a5de176..2ff984aae 100755 --- a/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp_dual.py +++ b/tests/validation/tests/dual/ffmpeg/test_rx_ffmpeg_tx_rxtxapp_dual.py @@ -42,7 +42,7 @@ def test_rx_ffmpeg_tx_rxtxapp_dual( tx_host = host_list[0] rx_host = host_list[1] - + capture_cfg = dict(test_config.get("capture_cfg", {})) capture_cfg["test_name"] = ( f"test_rx_ffmpeg_tx_rxtxapp_dual_{video_format}_{output_format}_{multiple_sessions}_{test_time_multipler}" From d8aae0ab092fd882cc0b52b63754ed62b071944f Mon Sep 17 00:00:00 2001 From: Bartosz Krystowski Date: Thu, 21 Aug 2025 10:17:41 +0200 Subject: [PATCH 5/8] Fix ffmpeg tests; Remove log to file loggin --- tests/validation/mtl_engine/RxTxApp.py | 262 +------------------ tests/validation/mtl_engine/ffmpeg_app.py | 189 ++----------- tests/validation/mtl_engine/media_creator.py | 2 +- 3 files changed, 35 insertions(+), 418 deletions(-) mode change 100755 => 100644 tests/validation/mtl_engine/RxTxApp.py diff --git a/tests/validation/mtl_engine/RxTxApp.py b/tests/validation/mtl_engine/RxTxApp.py old mode 100755 new mode 100644 index 423ebf7fc..85ff7507c --- a/tests/validation/mtl_engine/RxTxApp.py +++ b/tests/validation/mtl_engine/RxTxApp.py @@ -517,8 +517,6 @@ def execute_test( config_json = json.dumps(config, indent=4) logger.info(f"Starting RxTxApp test: {get_case_id()}") - log_to_file(f"Starting RxTxApp test: {get_case_id()}", host, build) - log_to_file(f"Test configuration: {config_json}", host, build) remote_host = host remote_conn = remote_host.connection @@ -528,7 +526,6 @@ def execute_test( config_json = config_json.replace('"', '\\"') f.write_text(config_json, encoding="utf-8") config_path = os.path.join(build, config_file) - log_to_file(f"Config file written to remote host: {config_path}", host, build) # Adjust test_time for high-res/fps/replicas if ( @@ -565,7 +562,7 @@ def execute_test( if ptp: command += " --ptp" - log_to_file(f"RxTxApp Command: {command}", host, build) + logger.info(f"RxTxApp Command: {command}") # Prepare tcpdump recorder if capture is enabled in the test configuration. tcpdump = prepare_tcpdump(capture_cfg, host) @@ -578,9 +575,6 @@ def execute_test( timeout = test_time + 120 logger.info(f"Running RxTxApp for {test_time} seconds with timeout {timeout}") - log_to_file( - f"Running RxTxApp for {test_time} seconds with timeout {timeout}", host, build - ) # Use run() for both local and remote cp = run( @@ -596,7 +590,6 @@ def execute_test( if tcpdump: tcpdump.capture(capture_time=capture_cfg.get("capture_time", 0.5)) logger.info(f"Started tcpdump capture on host {host.name}") - log_to_file("Started tcpdump capture", host, build) finally: cp.wait() @@ -604,24 +597,17 @@ def execute_test( bad_rc = {124: "timeout", 137: "SIGKILL", 143: "SIGTERM"} if cp.return_code != 0: if cp.return_code < 0: - log_to_file( - f"RxTxApp was killed with signal {-cp.return_code}", host, build - ) log_fail(f"RxTxApp was killed with signal {-cp.return_code}") return False for rc, reason in bad_rc.items(): if cp.return_code == rc: log_fail(f"RxTxApp stopped by reason: {reason}") - log_to_file(f"RxTxApp stopped by reason: {reason}", host, build) return False log_fail(f"RxTxApp returned non-zero exit code: {cp.return_code}") - log_to_file( - f"RxTxApp returned non-zero exit code: {cp.return_code}", host, build - ) return False output = cp.stdout_text.splitlines() - log_to_file(f"RxTxApp Output:\n{cp.stdout_text}", host, build) + logger.info(f"RxTxApp Output:\n{cp.stdout_text}") passed = True for session, check_output in zip( @@ -716,7 +702,7 @@ def execute_test( logger.info(f"RxTxApp test completed with result: {passed}") else: log_fail(f"RxTxApp test failed with result: {passed}") - log_to_file(f"RxTxApp test completed with result: {passed}", host, build) + logger.info(f"RxTxApp test completed with result: {passed}") return passed @@ -739,8 +725,7 @@ def execute_perf_test( config_json = json.dumps(config, indent=4) logger.info(f"Starting RxTxApp performance test: {get_case_id()}") - log_to_file(f"Starting RxTxApp performance test: {get_case_id()}", host, build) - log_to_file(f"Performance test configuration: {config_json}", host, build) + logger.info(f"Performance test configuration: {config_json}") remote_conn = host.connection config_file = f"{build}/tests/config.json" @@ -749,14 +734,10 @@ def execute_perf_test( config_json = config_json.replace('"', '\\"') f.write_text(config_json, encoding="utf-8") config_path = os.path.join(build, config_file) - log_to_file( - f"Performance config file written to remote host: {config_path}", host, build - ) command = f"sudo {RXTXAPP_PATH} --config_file {config_path} --test_time {test_time}" logger.info(f"Performance RxTxApp Command: {command}") - log_to_file(f"Performance RxTxApp Command: {command}", host, build) # Prepare tcpdump recorder if capture is enabled in the test configuration. tcpdump = prepare_tcpdump(capture_cfg, host) @@ -788,20 +769,10 @@ def execute_perf_test( logger.info( f"Scaling timeout for {total_replicas} replicas: +{additional_timeout}s" ) - log_to_file( - f"Scaling timeout for {total_replicas} replicas: +{additional_timeout}s", - host, - build, - ) logger.info( f"Running performance RxTxApp for {test_time} seconds with timeout {timeout}" ) - log_to_file( - f"Running performance RxTxApp for {test_time} seconds with timeout {timeout}", - host, - build, - ) cp = run( command, @@ -816,7 +787,7 @@ def execute_perf_test( try: if tcpdump: tcpdump.capture(capture_time=capture_cfg.get("capture_time", 0.5)) - log_to_file("Started performance test tcpdump capture", host, build) + logger.info("Started performance test tcpdump capture") finally: cp.wait() @@ -824,29 +795,20 @@ def execute_perf_test( logger.info( f"Performance RxTxApp process completed with return code: {cp.return_code}" ) - log_to_file( - f"Performance RxTxApp process completed with return code: {cp.return_code}", - host, - build, - ) # Check if process was killed or terminated unexpectedly if cp.return_code < 0: - log_to_file( - f"Performance RxTxApp was killed with signal {-cp.return_code}", host, build + logger.info( + f"Performance RxTxApp was killed with signal {-cp.return_code}" ) - logger.info(f"Performance RxTxApp was killed with signal {-cp.return_code}") return False elif cp.return_code == 124: # timeout return code - log_to_file("Performance RxTxApp timed out", host, build) logger.info("Performance RxTxApp timed out") return False elif cp.return_code == 137: # SIGKILL - log_to_file("Performance RxTxApp was killed (SIGKILL)", host, build) logger.info("Performance RxTxApp was killed (SIGKILL)") return False elif cp.return_code == 143: # SIGTERM - log_to_file("Performance RxTxApp was terminated (SIGTERM)", host, build) logger.info("Performance RxTxApp was terminated (SIGTERM)") return False @@ -856,16 +818,10 @@ def execute_perf_test( logger.info(line) if cp.return_code != 0: - log_to_file( - f"Performance RxTxApp returned non-zero exit code: {cp.return_code}", - host, - build, - ) logger.info( f"Performance RxTxApp returned non-zero exit code: {cp.return_code}" ) if cp.stderr_text: - log_to_file(f"Performance RxTxApp stderr: {cp.stderr_text}", host, build) logger.info(f"Performance RxTxApp stderr: {cp.stderr_text}") # For performance tests, non-zero exit code means test failed return False @@ -881,7 +837,7 @@ def execute_perf_test( session_type = "video" break - log_to_file(f"Performance test session type detected: {session_type}", host, build) + logger.info(f"Performance test session type detected: {session_type}", host, build) result = check_tx_output( config=config, @@ -893,9 +849,6 @@ def execute_perf_test( ) logger.info(f"Performance RxTxApp test completed with result: {result}") - log_to_file( - f"Performance RxTxApp test completed with result: {result}", host, build - ) return result @@ -975,15 +928,11 @@ def check_tx_output( # Regular check for OK results ok_cnt = 0 logger.info(f"Checking TX {session_type} output for OK results") - if host: - log_to_file(f"Checking TX {session_type} output for OK results", host, build) for line in output: if f"app_tx_{session_type}_result" in line and "OK" in line: ok_cnt += 1 logger.info(f"Found TX {session_type} OK result: {line}") - if host: - log_to_file(f"Found TX {session_type} OK result: {line}", host, build) replicas = 0 for session in config["tx_sessions"]: @@ -992,39 +941,15 @@ def check_tx_output( replicas += s["replicas"] logger.info(f"TX {session_type} check: {ok_cnt}/{replicas} OK results found") - if host: - log_to_file( - f"TX {session_type} check: {ok_cnt}/{replicas} OK results found", - host, - build, - ) if ok_cnt == replicas: logger.info(f"TX {session_type} check PASSED: all {replicas} sessions OK") - if host: - log_to_file( - f"TX {session_type} check PASSED: all {replicas} sessions OK", - host, - build, - ) return True if fail_on_error: log_fail(f"tx {session_type} session failed") - if host: - log_to_file( - f"TX {session_type} check FAILED: {ok_cnt}/{replicas} sessions OK", - host, - build, - ) else: logger.info(f"tx {session_type} session failed") - if host: - log_to_file( - f"TX {session_type} check FAILED (non-fatal): {ok_cnt}/{replicas} sessions OK", - host, - build, - ) return False @@ -1053,19 +978,11 @@ def check_tx_fps_performance( if expected_fps is None: logger.info("Could not determine expected FPS from config") - if host: - log_to_file("Could not determine expected FPS from config", host, build) return False logger.info( f"Checking TX FPS performance: expected {expected_fps} fps for {replicas} replicas" ) - if host: - log_to_file( - f"Checking TX FPS performance: expected {expected_fps} fps for {replicas} replicas", - host, - build, - ) # Look for TX_VIDEO_SESSION fps lines - check if any reading reaches target fps_pattern = re.compile( @@ -1092,42 +1009,18 @@ def check_tx_fps_performance( logger.info( f"TX FPS performance check: {successful_count}/{replicas} sessions achieved target" ) - if host: - log_to_file( - f"TX FPS performance check: {successful_count}/{replicas} sessions achieved target", - host, - build, - ) if successful_count == replicas: - if host: - log_to_file( - f"TX FPS performance check PASSED: all {replicas} sessions achieved target FPS", - host, - build, - ) return True if fail_on_error: log_fail( f"tx {session_type} fps performance failed: {successful_count}/{replicas} sessions" ) - if host: - log_to_file( - f"TX FPS performance check FAILED: {successful_count}/{replicas} sessions achieved target", - host, - build, - ) else: logger.info( f"tx {session_type} fps performance failed: {successful_count}/{replicas} sessions" ) - if host: - log_to_file( - f"TX FPS performance check FAILED (non-fatal): {successful_count}/{replicas} sessions achieved target", - host, - build, - ) return False @@ -1142,8 +1035,6 @@ def check_rx_output( ) -> bool: ok_cnt = 0 logger.info(f"Checking RX {session_type} output for OK results") - if host: - log_to_file(f"Checking RX {session_type} output for OK results", host, build) pattern = re.compile(r"app_rx_.*_result") if session_type == "anc": @@ -1168,45 +1059,19 @@ def check_rx_output( if pattern.search(line) and "OK" in line: ok_cnt += 1 logger.info(f"Found RX {session_type} OK result: {line}") - if host: - log_to_file(f"Found RX {session_type} OK result: {line}", host, build) replicas = config["rx_sessions"][0][session_type][0]["replicas"] logger.info(f"RX {session_type} check: {ok_cnt}/{replicas} OK results found") - if host: - log_to_file( - f"RX {session_type} check: {ok_cnt}/{replicas} OK results found", - host, - build, - ) if ok_cnt == replicas: logger.info(f"RX {session_type} check PASSED: all {replicas} sessions OK") - if host: - log_to_file( - f"RX {session_type} check PASSED: all {replicas} sessions OK", - host, - build, - ) return True if fail_on_error: log_fail(f"rx {session_type} session failed") - if host: - log_to_file( - f"RX {session_type} check FAILED: {ok_cnt}/{replicas} sessions OK", - host, - build, - ) else: logger.info(f"rx {session_type} session failed") - if host: - log_to_file( - f"RX {session_type} check FAILED (non-fatal): {ok_cnt}/{replicas} sessions OK", - host, - build, - ) return False @@ -1224,12 +1089,6 @@ def check_tx_converter_output( input_format = config["tx_sessions"][0]["st20p"][0]["input_format"] logger.info(f"Checking TX {session_type} converter output") - if host: - log_to_file( - f"Checking TX {session_type} converter output for format {transport_format}/{input_format}", - host, - build, - ) for line in output: if ( @@ -1238,8 +1097,6 @@ def check_tx_converter_output( ): ok_cnt += 1 logger.info(f"Found TX converter creation: {line}") - if host: - log_to_file(f"Found TX converter creation: {line}", host, build) if session_type == "anc": session_type = "ancillary" @@ -1248,39 +1105,15 @@ def check_tx_converter_output( logger.info( f"TX {session_type} converter check: {ok_cnt}/{replicas} converters created" ) - if host: - log_to_file( - f"TX {session_type} converter check: {ok_cnt}/{replicas} converters created", - host, - build, - ) if ok_cnt == replicas: logger.info(f"TX {session_type} converter check PASSED") - if host: - log_to_file( - f"TX {session_type} converter check PASSED: all {replicas} converters created", - host, - build, - ) return True if fail_on_error: log_fail(f"tx {session_type} session failed") - if host: - log_to_file( - f"TX {session_type} converter check FAILED: {ok_cnt}/{replicas} converters created", - host, - build, - ) else: logger.info(f"tx {session_type} session failed") - if host: - log_to_file( - f"TX {session_type} converter check FAILED (non-fatal): {ok_cnt}/{replicas} converters created", - host, - build, - ) return False @@ -1299,12 +1132,6 @@ def check_rx_converter_output( output_format = config["rx_sessions"][0]["st20p"][0]["output_format"] logger.info(f"Checking RX {session_type} converter output") - if host: - log_to_file( - f"Checking RX {session_type} converter output for format {transport_format}/{output_format}", - host, - build, - ) for line in output: if ( @@ -1313,8 +1140,6 @@ def check_rx_converter_output( ): ok_cnt += 1 logger.info(f"Found RX converter creation: {line}") - if host: - log_to_file(f"Found RX converter creation: {line}", host, build) if session_type == "anc": session_type = "ancillary" @@ -1323,39 +1148,15 @@ def check_rx_converter_output( logger.info( f"RX {session_type} converter check: {ok_cnt}/{replicas} converters created" ) - if host: - log_to_file( - f"RX {session_type} converter check: {ok_cnt}/{replicas} converters created", - host, - build, - ) if ok_cnt == replicas: logger.info(f"RX {session_type} converter check PASSED") - if host: - log_to_file( - f"RX {session_type} converter check PASSED: all {replicas} converters created", - host, - build, - ) return True if fail_on_error: log_fail(f"rx {session_type} session failed") - if host: - log_to_file( - f"RX {session_type} converter check FAILED: {ok_cnt}/{replicas} converters created", - host, - build, - ) else: logger.info(f"rx {session_type} session failed") - if host: - log_to_file( - f"RX {session_type} converter check FAILED (non-fatal): {ok_cnt}/{replicas} converters created", - host, - build, - ) return False @@ -1432,35 +1233,6 @@ def sanitize_filename(name: str) -> str: return re.sub(r"[^A-Za-z0-9_.-]", "_", name) -def log_to_file(message: str, host, build: str): - """Log message to a file on the remote host""" - global _log_timestamp - - # Initialize timestamp if not set - if _log_timestamp is None: - init_test_logging() - - test_name = sanitize_filename(get_case_id()) - log_file = f"{build}/tests/{test_name}_{_log_timestamp}_rxtxapp.log" - - remote_conn = host.connection - f = remote_conn.path(log_file) - - # Ensure parent directory exists - parent_dir = os.path.dirname(log_file) - run(f"mkdir -p {parent_dir}", host=host) - - # Append to file with timestamp - log_timestamp = time.strftime("%Y-%m-%d %H:%M:%S") - log_entry = f"[{log_timestamp}] {message}\n" - - if f.exists(): - current_content = f.read_text() - f.write_text(current_content + log_entry) - else: - f.write_text(log_entry) - - read_ip_addresses_from_json(json_filename) @@ -1482,7 +1254,7 @@ def add_dual_interfaces( tx_config["interfaces"][0]["name"] = tx_nic_port_list[0] # Configure RX host interface only - rx_config["interfaces"][0]["name"] = rx_nic_port_list[0] + rx_config["interfaces"][0]["name"] = rx_nic_port_list[1] if test_mode == "unicast": tx_config["interfaces"][0]["ip"] = unicast_ip_dict["tx_interfaces"] @@ -1678,10 +1450,6 @@ def execute_dual_test( # Log test start logger.info(f"Starting dual RxTxApp test: {get_case_id()}") - log_to_file(f"Starting dual RxTxApp test: {get_case_id()}", tx_host, build) - log_to_file(f"Starting dual RxTxApp test: {get_case_id()}", rx_host, build) - log_to_file(f"TX config: {tx_config_json}", tx_host, build) - log_to_file(f"RX config: {rx_config_json}", rx_host, build) # Prepare TX config tx_config_file = f"{build}/tests/tx_config.json" @@ -1722,8 +1490,6 @@ def execute_dual_test( logger.info(f"TX Command: {tx_command}") logger.info(f"RX Command: {rx_command}") - log_to_file(f"TX Command: {tx_command}", tx_host, build) - log_to_file(f"RX Command: {rx_command}", rx_host, build) # Start RX first rx_cp = run( @@ -1754,20 +1520,12 @@ def execute_dual_test( # Log outputs logger.info("=== TX OUTPUT ===") - log_to_file("=== TX OUTPUT ===", tx_host, build) for line in tx_output: logger.info(line) - log_to_file(line, tx_host, build) logger.info("=== RX OUTPUT ===") - log_to_file("=== RX OUTPUT ===", rx_host, build) for line in rx_output: logger.info(line) - log_to_file(line, rx_host, build) - - # Log the complete output to file - log_to_file(f"TX RxTxApp Output:\n{tx_cp.stdout_text}", tx_host, build) - log_to_file(f"RX RxTxApp Output:\n{rx_cp.stdout_text}", rx_host, build) # Check results passed = True @@ -1809,7 +1567,5 @@ def execute_dual_test( ) logger.info(f"Dual RxTxApp test completed with result: {passed}") - log_to_file(f"Dual RxTxApp test completed with result: {passed}", tx_host, build) - log_to_file(f"Dual RxTxApp test completed with result: {passed}", rx_host, build) return passed diff --git a/tests/validation/mtl_engine/ffmpeg_app.py b/tests/validation/mtl_engine/ffmpeg_app.py index 7d1b5d7e1..b0524c2cc 100755 --- a/tests/validation/mtl_engine/ffmpeg_app.py +++ b/tests/validation/mtl_engine/ffmpeg_app.py @@ -55,35 +55,6 @@ def sanitize_filename(name: str) -> str: return re.sub(r"[^A-Za-z0-9_.-]", "_", name) -def log_to_file(message: str, host, build: str): - """Log message to a file on the remote host""" - global _log_timestamp - - # Initialize timestamp if not set - if _log_timestamp is None: - init_test_logging() - - test_name = sanitize_filename(get_case_id()) - log_file = f"{build}/tests/{test_name}_{_log_timestamp}_ffmpeg.log" - - remote_conn = host.connection - f = remote_conn.path(log_file) - - # Ensure parent directory exists - parent_dir = os.path.dirname(log_file) - run(f"mkdir -p {parent_dir}", host=host) - - # Append to file with timestamp - log_timestamp = time.strftime("%Y-%m-%d %H:%M:%S") - log_entry = f"[{log_timestamp}] {message}\n" - - if f.exists(): - current_content = f.read_text() - f.write_text(current_content + log_entry, encoding="utf-8") - else: - f.write_text(log_entry, encoding="utf-8") - - def execute_test( test_time: int, build: str, @@ -166,8 +137,6 @@ def execute_test( logger.info(f"RX Command: {rx_cmd}") logger.info(f"TX Command: {tx_cmd}") - log_to_file(f"RX Command: {rx_cmd}", host, build) - log_to_file(f"TX Command: {tx_cmd}", host, build) rx_proc = None tx_proc = None @@ -183,7 +152,6 @@ def execute_test( testcmd=True, host=host, background=True, - enable_sudo=True, ) time.sleep(2) @@ -196,7 +164,6 @@ def execute_test( testcmd=True, host=host, background=True, - enable_sudo=True, ) # Start tcpdump after pipelines are running if tcpdump: @@ -223,12 +190,12 @@ def execute_test( # Get output after processes have been terminated try: if rx_proc and hasattr(rx_proc, "stdout_text"): - log_to_file(f"RX Output: {rx_proc.stdout_text}", host, build) + logger.info(f"RX Output: {rx_proc.stdout_text}", host, build) except Exception: logger.info("Could not retrieve RX output") try: if tx_proc and hasattr(tx_proc, "stdout_text"): - log_to_file(f"TX Output: {tx_proc.stdout_text}", host, build) + logger.info(f"TX Output: {tx_proc.stdout_text}", host, build) except Exception: logger.info("Could not retrieve TX output") except Exception as e: @@ -306,22 +273,14 @@ def execute_test_rgb24( nic_port_list = host.vfs video_size, fps = decode_video_format_16_9(video_format) logger.info(f"Creating RX config for RGB24 test with video_format: {video_format}") - log_to_file( - f"Creating RX config for RGB24 test with video_format: {video_format}", - host, - build, - ) try: rx_config_file = generate_rxtxapp_rx_config( nic_port_list[0], video_format, host, build ) logger.info(f"Successfully created RX config file: {rx_config_file}") - log_to_file( - f"Successfully created RX config file: {rx_config_file}", host, build - ) + except Exception as e: log_fail(f"Failed to create RX config file: {e}") - log_to_file(f"Failed to create RX config file: {e}", host, build) return False rx_cmd = f"{RXTXAPP_PATH} --config_file {rx_config_file} --test_time {test_time}" tx_cmd = ( @@ -333,8 +292,6 @@ def execute_test_rgb24( logger.info(f"RX Command: {rx_cmd}") logger.info(f"TX Command: {tx_cmd}") - log_to_file(f"RX Command: {rx_cmd}", host, build) - log_to_file(f"TX Command: {tx_cmd}", host, build) rx_proc = None tx_proc = None @@ -350,7 +307,6 @@ def execute_test_rgb24( testcmd=True, host=host, background=True, - enable_sudo=True, ) time.sleep(5) # Start TX pipeline @@ -362,7 +318,6 @@ def execute_test_rgb24( testcmd=True, host=host, background=True, - enable_sudo=True, ) # Start tcpdump after pipelines are running if tcpdump: @@ -393,17 +348,15 @@ def execute_test_rgb24( try: if rx_proc and hasattr(rx_proc, "stdout_text"): rx_output = rx_proc.stdout_text - log_to_file(f"RX Output: {rx_output}", host, build) + logger.info(f"RX Output: {rx_output}") logger.info("RX output captured successfully") else: logger.info("Could not retrieve RX output") - log_to_file("Could not retrieve RX output", host, build) except Exception as e: logger.info(f"Error retrieving RX output: {e}") - log_to_file(f"Error retrieving RX output: {e}", host, build) try: if tx_proc and hasattr(tx_proc, "stdout_text"): - log_to_file(f"TX Output: {tx_proc.stdout_text}", host, build) + logger.info(f"TX Output: {tx_proc.stdout_text}") logger.info("TX output captured successfully") except Exception as e: logger.info(f"Error retrieving TX output: {e}") @@ -470,22 +423,13 @@ def execute_test_rgb24_multiple( logger.info( f"Creating RX config for RGB24 multiple test with video_formats: {video_format_list}" ) - log_to_file( - f"Creating RX config for RGB24 multiple test with video_formats: {video_format_list}", - host, - build, - ) try: rx_config_file = generate_rxtxapp_rx_config_multiple( nic_port_list[:2], video_format_list, host, build, True ) logger.info(f"Successfully created RX config file: {rx_config_file}") - log_to_file( - f"Successfully created RX config file: {rx_config_file}", host, build - ) except Exception as e: log_fail(f"Failed to create RX config file: {e}") - log_to_file(f"Failed to create RX config file: {e}", host, build) return False rx_cmd = f"{RXTXAPP_PATH} --config_file {rx_config_file} --test_time {test_time}" tx_1_cmd = ( @@ -506,9 +450,6 @@ def execute_test_rgb24_multiple( logger.info(f"RX Command: {rx_cmd}") logger.info(f"TX1 Command: {tx_1_cmd}") logger.info(f"TX2 Command: {tx_2_cmd}") - log_to_file(f"RX Command: {rx_cmd}", host, build) - log_to_file(f"TX1 Command: {tx_1_cmd}", host, build) - log_to_file(f"TX2 Command: {tx_2_cmd}", host, build) rx_proc = None tx_1_proc = None @@ -523,7 +464,6 @@ def execute_test_rgb24_multiple( testcmd=True, host=host, background=True, - enable_sudo=True, ) time.sleep(5) # Start TX pipelines @@ -535,7 +475,6 @@ def execute_test_rgb24_multiple( testcmd=True, host=host, background=True, - enable_sudo=True, ) tx_2_proc = run( tx_2_cmd, @@ -544,7 +483,6 @@ def execute_test_rgb24_multiple( testcmd=True, host=host, background=True, - enable_sudo=True, ) # Start tcpdump after pipelines are running if tcpdump: @@ -574,23 +512,21 @@ def execute_test_rgb24_multiple( try: if rx_proc and hasattr(rx_proc, "stdout_text"): rx_output = rx_proc.stdout_text - log_to_file(f"RX Output: {rx_output}", host, build) + logger.info(f"RX Output: {rx_output}") logger.info("RX output captured successfully") else: logger.info("Could not retrieve RX output") - log_to_file("Could not retrieve RX output", host, build) except Exception as e: logger.info(f"Error retrieving RX output: {e}") - log_to_file(f"Error retrieving RX output: {e}", host, build) try: if tx_1_proc and hasattr(tx_1_proc, "stdout_text"): - log_to_file(f"TX1 Output: {tx_1_proc.stdout_text}", host, build) + logger.info(f"TX1 Output: {tx_1_proc.stdout_text}") logger.info("TX1 output captured successfully") except Exception as e: logger.info(f"Error retrieving TX1 output: {e}") try: if tx_2_proc and hasattr(tx_2_proc, "stdout_text"): - log_to_file(f"TX2 Output: {tx_2_proc.stdout_text}", host, build) + logger.info(f"TX2 Output: {tx_2_proc.stdout_text}") logger.info("TX2 output captured successfully") except Exception as e: logger.info(f"Error retrieving TX2 output: {e}") @@ -633,17 +569,10 @@ def check_output_video_yuv(output_file: str, host, build: str, input_file: str): if input_stat_proc.return_code == 0: input_file_size = int(input_stat_proc.stdout_text.strip()) logger.info(f"Input file size: {input_file_size} bytes for {input_file}") - log_to_file( - f"Input file size: {input_file_size} bytes for {input_file}", - host, - build, - ) else: logger.info(f"Could not get input file size for {input_file}") - log_to_file(f"Could not get input file size for {input_file}", host, build) except Exception as e: logger.info(f"Error checking input file size: {e}") - log_to_file(f"Error checking input file size: {e}", host, build) # Use run() to check output file size stat_proc = run(f"stat -c '%s' {output_file}", host=host) @@ -651,16 +580,11 @@ def check_output_video_yuv(output_file: str, host, build: str, input_file: str): if stat_proc.return_code == 0: output_file_size = int(stat_proc.stdout_text.strip()) logger.info(f"Output file size: {output_file_size} bytes for {output_file}") - log_to_file( - f"Output file size: {output_file_size} bytes for {output_file}", host, build - ) result = output_file_size > 0 logger.info(f"YUV check result: {result}") - log_to_file(f"YUV check result: {result}", host, build) return result else: logger.info(f"Could not get output file size for {output_file}") - log_to_file(f"Could not get output file size for {output_file}", host, build) return False @@ -673,17 +597,10 @@ def check_output_video_h264( if input_stat_proc.return_code == 0: input_file_size = int(input_stat_proc.stdout_text.strip()) logger.info(f"Input file size: {input_file_size} bytes for {input_file}") - log_to_file( - f"Input file size: {input_file_size} bytes for {input_file}", - host, - build, - ) else: logger.info(f"Could not get input file size for {input_file}") - log_to_file(f"Could not get input file size for {input_file}", host, build) except Exception as e: logger.info(f"Error checking input file size: {e}") - log_to_file(f"Error checking input file size: {e}", host, build) # Log output file size first try: @@ -691,19 +608,10 @@ def check_output_video_h264( if stat_proc.return_code == 0: output_file_size = int(stat_proc.stdout_text.strip()) logger.info(f"Output file size: {output_file_size} bytes for {output_file}") - log_to_file( - f"Output file size: {output_file_size} bytes for {output_file}", - host, - build, - ) else: logger.info(f"Could not get output file size for {output_file}") - log_to_file( - f"Could not get output file size for {output_file}", host, build - ) except Exception as e: logger.info(f"Error checking output file size: {e}") - log_to_file(f"Error checking output file size: {e}", host, build) code_name_pattern = r"codec_name=([^\n]+)" width_pattern = r"width=(\d+)" @@ -726,15 +634,9 @@ def check_output_video_h264( logger.info( f"H264 check result: {result} (codec: {codec_name}, size: {width}x{height})" ) - log_to_file( - f"H264 check result: {result} (codec: {codec_name}, size: {width}x{height})", - host, - build, - ) return result else: logger.info("H264 check failed") - log_to_file("H264 check failed", host, build) return False @@ -835,7 +737,6 @@ def generate_rxtxapp_rx_config( f.write_text(config_json, encoding="utf-8") logger.info("Config file written successfully") - log_to_file(f"Generated RX config file: {config_file}", host, build) return config_file @@ -902,7 +803,7 @@ def generate_rxtxapp_rx_config_multiple( f.write_text(config_json, encoding="utf-8") logger.info("Multiple config file written successfully") - log_to_file(f"Generated RX multiple config file: {config_file}", host, build) + logger.info(f"Generated RX multiple config file: {config_file}") return config_file @@ -966,7 +867,7 @@ def generate_rxtxapp_tx_config( f.write_text(config_json, encoding="utf-8") logger.info("TX Config file written successfully") - log_to_file(f"Generated TX config file: {config_file}", host, build) + logger.info(f"Generated TX config file: {config_file}") return config_file @@ -1042,13 +943,13 @@ def execute_dual_test( if tx_is_ffmpeg: tx_cmd = ( f"ffmpeg -video_size {video_size} -f rawvideo -pix_fmt yuv422p10le " - f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[0]} " + f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[1]} " f"-p_sip {ip_dict['tx_interfaces']} -p_tx_ip {ip_dict['tx_sessions']} " f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) else: # tx is rxtxapp tx_config_file = generate_rxtxapp_tx_config( - tx_nic_port_list[0], video_format, video_url, tx_host, build + tx_nic_port_list[1], video_format, video_url, tx_host, build ) tx_cmd = f"{RXTXAPP_PATH} --config_file {tx_config_file}" else: # multiple sessions @@ -1067,13 +968,13 @@ def execute_dual_test( if tx_is_ffmpeg: tx_cmd = ( f"ffmpeg -video_size {video_size} -f rawvideo -pix_fmt yuv422p10le " - f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[0]} " + f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[1]} " f"-p_sip {ip_dict['tx_interfaces']} -p_tx_ip {ip_dict['tx_sessions']} " f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) else: # tx is rxtxapp tx_config_file = generate_rxtxapp_tx_config( - tx_nic_port_list[0], video_format, video_url, tx_host, build, True + tx_nic_port_list[1], video_format, video_url, tx_host, build, True ) tx_cmd = f"{RXTXAPP_PATH} --config_file {tx_config_file}" @@ -1081,10 +982,6 @@ def execute_dual_test( logger.info(f"RX Host: {rx_host}") logger.info(f"RX Command: {rx_cmd}") logger.info(f"TX Command: {tx_cmd}") - log_to_file(f"TX Host: {tx_host}", rx_host, build) - log_to_file(f"RX Host: {rx_host}", rx_host, build) - log_to_file(f"RX Command: {rx_cmd}", rx_host, build) - log_to_file(f"TX Command: {tx_cmd}", tx_host, build) rx_proc = None tx_proc = None @@ -1101,7 +998,6 @@ def execute_dual_test( testcmd=True, host=rx_host, background=True, - enable_sudo=True, ) time.sleep(2) @@ -1114,7 +1010,6 @@ def execute_dual_test( testcmd=True, host=tx_host, background=True, - enable_sudo=True, ) # Start tcpdump after pipelines are running if tcpdump: @@ -1141,12 +1036,12 @@ def execute_dual_test( # Get output after processes have been terminated try: rx_output = f"RX Output:\n{rx_proc.stdout_text}" - log_to_file(rx_output, rx_host, build) + logger.info(rx_output) except Exception: logger.info("Could not retrieve RX output") try: tx_output = f"TX Output:\n{tx_proc.stdout_text}" - log_to_file(tx_output, tx_host, build) + logger.info(tx_output) except Exception: logger.info("Could not retrieve TX output") except Exception as e: @@ -1231,28 +1126,19 @@ def execute_dual_test_rgb24( logger.info( f"Creating RX config for RGB24 dual test with video_format: {video_format}" ) - log_to_file( - f"Creating RX config for RGB24 dual test with video_format: {video_format}", - rx_host, - build, - ) try: rx_config_file = generate_rxtxapp_rx_config( rx_nic_port_list[0], video_format, rx_host, build ) logger.info(f"Successfully created RX config file: {rx_config_file}") - log_to_file( - f"Successfully created RX config file: {rx_config_file}", rx_host, build - ) except Exception as e: log_fail(f"Failed to create RX config file: {e}") - log_to_file(f"Failed to create RX config file: {e}", rx_host, build) return False rx_cmd = f"{RXTXAPP_PATH} --config_file {rx_config_file} --test_time {test_time}" tx_cmd = ( f"ffmpeg -stream_loop -1 -video_size {video_size} -f rawvideo -pix_fmt rgb24 " - f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[0]} " + f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[1]} " f"-p_sip {ip_dict['tx_interfaces']} -p_tx_ip {ip_dict['tx_sessions']} " f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) @@ -1261,10 +1147,6 @@ def execute_dual_test_rgb24( logger.info(f"RX Host: {rx_host}") logger.info(f"RX Command: {rx_cmd}") logger.info(f"TX Command: {tx_cmd}") - log_to_file(f"TX Host: {tx_host}", rx_host, build) - log_to_file(f"RX Host: {rx_host}", rx_host, build) - log_to_file(f"RX Command: {rx_cmd}", rx_host, build) - log_to_file(f"TX Command: {tx_cmd}", tx_host, build) rx_proc = None tx_proc = None @@ -1281,7 +1163,6 @@ def execute_dual_test_rgb24( testcmd=True, host=rx_host, background=True, - enable_sudo=True, ) time.sleep(5) @@ -1294,7 +1175,6 @@ def execute_dual_test_rgb24( testcmd=True, host=tx_host, background=True, - enable_sudo=True, ) # Start tcpdump after pipelines are running @@ -1326,17 +1206,16 @@ def execute_dual_test_rgb24( rx_output = "" try: rx_output = rx_proc.stdout_text - log_to_file(f"RX Output:\n{rx_output}", rx_host, build) + logger.info(f"RX Output:\n{rx_output}") logger.info("RX output captured successfully") except Exception as e: logger.info(f"Error retrieving RX output: {e}") - log_to_file(f"Error retrieving RX output: {e}", rx_host, build) try: - log_to_file(f"TX Output:\n{tx_proc.stdout_text}", tx_host, build) + logger.info(f"TX Output:\n{tx_proc.stdout_text}") logger.info("TX output captured successfully") except Exception as e: - log_to_file(f"Error retrieving TX output: {e}", tx_host, build) + logger.info(f"Error retrieving TX output: {e}") except Exception as e: log_fail(f"Error during test execution: {e}") @@ -1407,35 +1286,26 @@ def execute_dual_test_rgb24_multiple( logger.info( f"Creating RX config for RGB24 multiple dual test with video_formats: {video_format_list}" ) - log_to_file( - f"Creating RX config for RGB24 multiple dual test with video_formats: {video_format_list}", - rx_host, - build, - ) try: rx_config_file = generate_rxtxapp_rx_config_multiple( rx_nic_port_list[:2], video_format_list, rx_host, build, True ) logger.info(f"Successfully created RX config file: {rx_config_file}") - log_to_file( - f"Successfully created RX config file: {rx_config_file}", rx_host, build - ) except Exception as e: log_fail(f"Failed to create RX config file: {e}") - log_to_file(f"Failed to create RX config file: {e}", rx_host, build) return False rx_cmd = f"{RXTXAPP_PATH} --config_file {rx_config_file} --test_time {test_time}" tx_1_cmd = ( f"ffmpeg -stream_loop -1 -video_size {video_size_1} -f rawvideo -pix_fmt rgb24 " - f"-i {video_url_list[0]} -filter:v fps={fps_1} -p_port {tx_nic_port_list[0]} " + f"-i {video_url_list[0]} -filter:v fps={fps_1} -p_port {tx_nic_port_list[1]} " f"-p_sip {ip_dict_rgb24_multiple['p_sip_1']} " f"-p_tx_ip {ip_dict_rgb24_multiple['p_tx_ip_1']} " f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) tx_2_cmd = ( f"ffmpeg -stream_loop -1 -video_size {video_size_2} -f rawvideo -pix_fmt rgb24 " - f"-i {video_url_list[1]} -filter:v fps={fps_2} -p_port {tx_nic_port_list[1]} " + f"-i {video_url_list[1]} -filter:v fps={fps_2} -p_port {tx_nic_port_list[2]} " f"-p_sip {ip_dict_rgb24_multiple['p_sip_2']} " f"-p_tx_ip {ip_dict_rgb24_multiple['p_tx_ip_2']} " f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" @@ -1446,11 +1316,6 @@ def execute_dual_test_rgb24_multiple( logger.info(f"RX Command: {rx_cmd}") logger.info(f"TX1 Command: {tx_1_cmd}") logger.info(f"TX2 Command: {tx_2_cmd}") - log_to_file(f"TX Host: {tx_host}", rx_host, build) - log_to_file(f"RX Host: {rx_host}", rx_host, build) - log_to_file(f"RX Command: {rx_cmd}", rx_host, build) - log_to_file(f"TX1 Command: {tx_1_cmd}", tx_host, build) - log_to_file(f"TX2 Command: {tx_2_cmd}", tx_host, build) rx_proc = None tx_1_proc = None @@ -1468,7 +1333,6 @@ def execute_dual_test_rgb24_multiple( testcmd=True, host=rx_host, background=True, - enable_sudo=True, ) time.sleep(5) @@ -1481,7 +1345,6 @@ def execute_dual_test_rgb24_multiple( testcmd=True, host=tx_host, background=True, - enable_sudo=True, ) tx_2_proc = run( tx_2_cmd, @@ -1490,7 +1353,6 @@ def execute_dual_test_rgb24_multiple( testcmd=True, host=tx_host, background=True, - enable_sudo=True, ) # Start tcpdump after pipelines are running @@ -1521,20 +1383,19 @@ def execute_dual_test_rgb24_multiple( rx_output = "" try: rx_output = rx_proc.stdout_text - log_to_file(f"RX Output:\n{rx_output}", rx_host, build) + logger.info(f"RX Output:\n{rx_output}") logger.info("RX output captured successfully") except Exception as e: logger.info(f"Error retrieving RX output: {e}") - log_to_file(f"Error retrieving RX output: {e}", rx_host, build) try: - log_to_file(f"TX1 Output:\n{tx_1_proc.stdout_text}", tx_host, build) + logger.info(f"TX1 Output:\n{tx_1_proc.stdout_text}") logger.info("TX1 output captured successfully") except Exception as e: logger.info(f"Error retrieving TX1 output: {e}") try: - log_to_file(f"TX2 Output:\n{tx_2_proc.stdout_text}", tx_host, build) + logger.info(f"TX2 Output:\n{tx_2_proc.stdout_text}") logger.info("TX2 output captured successfully") except Exception as e: logger.info(f"Error retrieving TX2 output: {e}") diff --git a/tests/validation/mtl_engine/media_creator.py b/tests/validation/mtl_engine/media_creator.py index 3dbf28c6a..77e0d6d5c 100755 --- a/tests/validation/mtl_engine/media_creator.py +++ b/tests/validation/mtl_engine/media_creator.py @@ -40,7 +40,7 @@ def create_video_file( media_path: str, output_path: str = "test_video.yuv", pattern: str = "ball", - duration: int = 10, + duration: int = 3, host=None, ): file_path = os.path.join(media_path, output_path) From 0693814dec8520694ff1219af3ab6d24c6a9e6d0 Mon Sep 17 00:00:00 2001 From: Bartosz Krystowski Date: Thu, 21 Aug 2025 10:41:35 +0200 Subject: [PATCH 6/8] Fix formatting --- tests/validation/mtl_engine/RxTxApp.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) mode change 100644 => 100755 tests/validation/mtl_engine/RxTxApp.py diff --git a/tests/validation/mtl_engine/RxTxApp.py b/tests/validation/mtl_engine/RxTxApp.py old mode 100644 new mode 100755 index 85ff7507c..25b7055d8 --- a/tests/validation/mtl_engine/RxTxApp.py +++ b/tests/validation/mtl_engine/RxTxApp.py @@ -792,15 +792,11 @@ def execute_perf_test( cp.wait() # Enhanced logging for process completion - logger.info( - f"Performance RxTxApp process completed with return code: {cp.return_code}" - ) + logger.info(f"Performance RxTxApp was killed with signal {-cp.return_code}") # Check if process was killed or terminated unexpectedly if cp.return_code < 0: - logger.info( - f"Performance RxTxApp was killed with signal {-cp.return_code}" - ) + logger.info(f"Performance RxTxApp was killed with signal {-cp.return_code}") return False elif cp.return_code == 124: # timeout return code logger.info("Performance RxTxApp timed out") From d1c205e72ac7428e1810c4ac368f483edfb12eec Mon Sep 17 00:00:00 2001 From: Bartosz Krystowski Date: Thu, 21 Aug 2025 18:17:39 +0200 Subject: [PATCH 7/8] Enhance logging in execute modules --- tests/validation/mtl_engine/RxTxApp.py | 54 +++- tests/validation/mtl_engine/execute.py | 1 - tests/validation/mtl_engine/ffmpeg_app.py | 371 +++++++--------------- 3 files changed, 150 insertions(+), 276 deletions(-) diff --git a/tests/validation/mtl_engine/RxTxApp.py b/tests/validation/mtl_engine/RxTxApp.py index 25b7055d8..d2c4ddd7f 100755 --- a/tests/validation/mtl_engine/RxTxApp.py +++ b/tests/validation/mtl_engine/RxTxApp.py @@ -42,6 +42,22 @@ ) +def capture_stdout(proc, proc_name: str): + """Capture and log stdout from a process""" + try: + if proc and hasattr(proc, "stdout_text"): + output = proc.stdout_text + if output and output.strip(): + logger.info(f"{proc_name} Output:\n{output}") + return output + else: + logger.debug(f"No stdout available for {proc_name}") + return "" + except Exception as e: + logger.warning(f"Failed to capture stdout for {proc_name}: {e}") + return "" + + def read_ip_addresses_from_json(filename: str): global unicast_ip_dict, multicast_ip_dict, kernel_ip_dict try: @@ -52,14 +68,14 @@ def read_ip_addresses_from_json(filename: str): multicast_ip_dict = ip_addresses["multicast_ip_dict"] kernel_ip_dict = ip_addresses["kernel_ip_dict"] except Exception: - print( + logger.warning( f"File {filename} does not contain proper input, check " "ip_addresses.json.example for a schema. It might have " "been loaded partially. Where not specified, " "default was set." ) except Exception: - print( + logger.warning( f"File {filename} could not be loaded properly! " "Default values are set for all IPs." ) @@ -593,6 +609,9 @@ def execute_test( finally: cp.wait() + # Capture stdout output for logging + capture_stdout(cp, "RxTxApp") + # Check if process was killed or terminated unexpectedly bad_rc = {124: "timeout", 137: "SIGKILL", 143: "SIGTERM"} if cp.return_code != 0: @@ -607,7 +626,6 @@ def execute_test( return False output = cp.stdout_text.splitlines() - logger.info(f"RxTxApp Output:\n{cp.stdout_text}") passed = True for session, check_output in zip( @@ -791,6 +809,9 @@ def execute_perf_test( finally: cp.wait() + # Capture stdout output for logging + capture_stdout(cp, "RxTxApp Performance") + # Enhanced logging for process completion logger.info(f"Performance RxTxApp was killed with signal {-cp.return_code}") @@ -810,8 +831,6 @@ def execute_perf_test( # Get output lines output = cp.stdout_text.splitlines() - for line in output: - logger.info(line) if cp.return_code != 0: logger.info( @@ -1250,7 +1269,7 @@ def add_dual_interfaces( tx_config["interfaces"][0]["name"] = tx_nic_port_list[0] # Configure RX host interface only - rx_config["interfaces"][0]["name"] = rx_nic_port_list[1] + rx_config["interfaces"][0]["name"] = rx_nic_port_list[0] if test_mode == "unicast": tx_config["interfaces"][0]["ip"] = unicast_ip_dict["tx_interfaces"] @@ -1506,23 +1525,28 @@ def execute_dual_test( host=tx_host, ) + # Start tcpdump capture if enabled + tcpdump = prepare_tcpdump(capture_cfg, rx_host) + if tcpdump: + tcpdump.capture(capture_time=capture_cfg.get("capture_time", 0.5)) + logger.info("Started dual test tcpdump capture") + # Wait for both processes tx_cp.wait() rx_cp.wait() + # Capture stdout output for logging + capture_stdout(tx_cp, "TX RxTxApp") + capture_stdout(rx_cp, "RX RxTxApp") + + # Stop tcpdump if it was started + if tcpdump: + tcpdump.stop() + # Get output from both hosts tx_output = tx_cp.stdout_text.splitlines() rx_output = rx_cp.stdout_text.splitlines() - # Log outputs - logger.info("=== TX OUTPUT ===") - for line in tx_output: - logger.info(line) - - logger.info("=== RX OUTPUT ===") - for line in rx_output: - logger.info(line) - # Check results passed = True diff --git a/tests/validation/mtl_engine/execute.py b/tests/validation/mtl_engine/execute.py index d2f5070b3..df0787d95 100755 --- a/tests/validation/mtl_engine/execute.py +++ b/tests/validation/mtl_engine/execute.py @@ -241,7 +241,6 @@ def run( ) if not background: process.wait(timeout=timeout) - logger.debug(process.stdout_text) logger.debug(f"RC: {process.return_code}") else: logger.debug("Process started in background mode.") diff --git a/tests/validation/mtl_engine/ffmpeg_app.py b/tests/validation/mtl_engine/ffmpeg_app.py index b0524c2cc..b5ae2a8e4 100755 --- a/tests/validation/mtl_engine/ffmpeg_app.py +++ b/tests/validation/mtl_engine/ffmpeg_app.py @@ -35,6 +35,22 @@ _log_timestamp = None +def capture_stdout(proc, proc_name: str): + """Capture and log stdout from a process""" + try: + if proc and hasattr(proc, "stdout_text"): + output = proc.stdout_text + if output and output.strip(): + logger.info(f"{proc_name} Output:\n{output}") + return output + else: + logger.debug(f"No stdout available for {proc_name}") + return "" + except Exception as e: + logger.warning(f"Failed to capture stdout for {proc_name}: {e}") + return "" + + def get_case_id() -> str: case_id = os.environ["PYTEST_CURRENT_TEST"] # Extract the test function name and parameters @@ -135,9 +151,6 @@ def execute_test( ) tx_cmd = f"{RXTXAPP_PATH} --config_file {tx_config_file}" - logger.info(f"RX Command: {rx_cmd}") - logger.info(f"TX Command: {tx_cmd}") - rx_proc = None tx_proc = None tcpdump = prepare_tcpdump(capture_cfg, host) @@ -177,65 +190,51 @@ def execute_test( logger.info("Terminating processes...") if tx_proc: try: - tx_proc.terminate() + tx_proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass if rx_proc: try: - rx_proc.terminate() + rx_proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass # Wait a bit for termination time.sleep(2) # Get output after processes have been terminated - try: - if rx_proc and hasattr(rx_proc, "stdout_text"): - logger.info(f"RX Output: {rx_proc.stdout_text}", host, build) - except Exception: - logger.info("Could not retrieve RX output") - try: - if tx_proc and hasattr(tx_proc, "stdout_text"): - logger.info(f"TX Output: {tx_proc.stdout_text}", host, build) - except Exception: - logger.info("Could not retrieve TX output") + capture_stdout(rx_proc, "RX") + capture_stdout(tx_proc, "TX") except Exception as e: log_fail(f"Error during test execution: {e}") # Terminate processes immediately on error if tx_proc: try: - tx_proc.terminate() + tx_proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass if rx_proc: try: - rx_proc.terminate() + rx_proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass raise finally: - # Ensure processes are terminated with force kill if needed + # Ensure processes are terminated if tx_proc: try: - tx_proc.terminate() - tx_proc.wait(timeout=5) + tx_proc.kill() except Exception: - try: - # Force kill if terminate didn't work - tx_proc.kill() - tx_proc.wait(timeout=5) - except Exception: - pass + # SSH process might already be terminated or unreachable - ignore + pass if rx_proc: try: - rx_proc.terminate() - rx_proc.wait(timeout=5) + rx_proc.kill() except Exception: - try: - # Force kill if terminate didn't work - rx_proc.kill() - rx_proc.wait(timeout=5) - except Exception: - pass + # SSH process might already be terminated or unreachable - ignore + pass if tcpdump: tcpdump.stop() passed = False @@ -250,7 +249,6 @@ def execute_test( try: for output_file in output_files: run(f"rm -f {output_file}", host=host) - logger.info(f"Removed output file: {output_file}") except Exception as e: logger.info(f"Could not remove output files: {e}") if not passed: @@ -277,8 +275,6 @@ def execute_test_rgb24( rx_config_file = generate_rxtxapp_rx_config( nic_port_list[0], video_format, host, build ) - logger.info(f"Successfully created RX config file: {rx_config_file}") - except Exception as e: log_fail(f"Failed to create RX config file: {e}") return False @@ -290,9 +286,6 @@ def execute_test_rgb24( f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) - logger.info(f"RX Command: {rx_cmd}") - logger.info(f"TX Command: {tx_cmd}") - rx_proc = None tx_proc = None tcpdump = prepare_tcpdump(capture_cfg, host) @@ -331,71 +324,45 @@ def execute_test_rgb24( logger.info("RX process completed") # Terminate TX process after RX completes - logger.info("Terminating TX process...") if tx_proc: try: - tx_proc.terminate() - tx_proc.wait(timeout=5) - logger.info("TX process terminated successfully") + tx_proc.kill() except Exception: - try: - tx_proc.kill() - tx_proc.wait(timeout=5) - logger.info("TX process killed") - except Exception: - logger.info("Could not terminate TX process") - rx_output = "" - try: - if rx_proc and hasattr(rx_proc, "stdout_text"): - rx_output = rx_proc.stdout_text - logger.info(f"RX Output: {rx_output}") - logger.info("RX output captured successfully") - else: - logger.info("Could not retrieve RX output") - except Exception as e: - logger.info(f"Error retrieving RX output: {e}") - try: - if tx_proc and hasattr(tx_proc, "stdout_text"): - logger.info(f"TX Output: {tx_proc.stdout_text}") - logger.info("TX output captured successfully") - except Exception as e: - logger.info(f"Error retrieving TX output: {e}") + # Process might already be terminated - ignore kill errors + pass + logger.info("TX process killed") + rx_output = capture_stdout(rx_proc, "RX") + capture_stdout(tx_proc, "TX") except Exception as e: log_fail(f"Error during test execution: {e}") # Terminate processes immediately on error if tx_proc: try: - tx_proc.terminate() + tx_proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass if rx_proc: try: - rx_proc.terminate() + rx_proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass raise finally: # Final cleanup - ensure processes are terminated if tx_proc: try: - tx_proc.terminate() - tx_proc.wait(timeout=3) + tx_proc.kill() except Exception: - try: - tx_proc.kill() - tx_proc.wait(timeout=3) - except Exception: - pass + # SSH process might already be terminated or unreachable - ignore + pass if rx_proc: try: - rx_proc.terminate() - rx_proc.wait(timeout=3) + rx_proc.kill() except Exception: - try: - rx_proc.kill() - rx_proc.wait(timeout=3) - except Exception: - pass + # SSH process might already be terminated or unreachable - ignore + pass if tcpdump: tcpdump.stop() if not check_output_rgb24(rx_output, 1): @@ -447,10 +414,6 @@ def execute_test_rgb24_multiple( f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) - logger.info(f"RX Command: {rx_cmd}") - logger.info(f"TX1 Command: {tx_1_cmd}") - logger.info(f"TX2 Command: {tx_2_cmd}") - rx_proc = None tx_1_proc = None tx_2_proc = None @@ -498,46 +461,22 @@ def execute_test_rgb24_multiple( for proc in [tx_1_proc, tx_2_proc]: if proc: try: - proc.terminate() - proc.wait(timeout=5) - logger.info("TX process terminated successfully") + proc.kill() + logger.info("TX process killed") except Exception: - try: - proc.kill() - proc.wait(timeout=5) - logger.info("TX process killed") - except Exception: - logger.info("Could not terminate TX process") - rx_output = "" - try: - if rx_proc and hasattr(rx_proc, "stdout_text"): - rx_output = rx_proc.stdout_text - logger.info(f"RX Output: {rx_output}") - logger.info("RX output captured successfully") - else: - logger.info("Could not retrieve RX output") - except Exception as e: - logger.info(f"Error retrieving RX output: {e}") - try: - if tx_1_proc and hasattr(tx_1_proc, "stdout_text"): - logger.info(f"TX1 Output: {tx_1_proc.stdout_text}") - logger.info("TX1 output captured successfully") - except Exception as e: - logger.info(f"Error retrieving TX1 output: {e}") - try: - if tx_2_proc and hasattr(tx_2_proc, "stdout_text"): - logger.info(f"TX2 Output: {tx_2_proc.stdout_text}") - logger.info("TX2 output captured successfully") - except Exception as e: - logger.info(f"Error retrieving TX2 output: {e}") + logger.info("Could not terminate TX process") + rx_output = capture_stdout(rx_proc, "RX") + capture_stdout(tx_1_proc, "TX1") + capture_stdout(tx_2_proc, "TX2") except Exception as e: log_fail(f"Error during test execution: {e}") # Terminate processes immediately on error for proc in [tx_1_proc, tx_2_proc, rx_proc]: if proc: try: - proc.terminate() + proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass raise finally: @@ -545,14 +484,10 @@ def execute_test_rgb24_multiple( for proc in [tx_1_proc, tx_2_proc, rx_proc]: if proc: try: - proc.terminate() - proc.wait(timeout=3) + proc.kill() except Exception: - try: - proc.kill() - proc.wait(timeout=3) - except Exception: - pass + # Process might already be terminated - ignore kill errors + pass if tcpdump: tcpdump.stop() if not check_output_rgb24(rx_output, 2): @@ -703,7 +638,6 @@ def generate_rxtxapp_rx_config( config["rx_sessions"][0]["ip"][0] = ip_dict["rx_sessions"] width, height, fps = decode_video_format_to_st20p(video_format) - logger.info(f"Decoded video format: width={width}, height={height}, fps={fps}") rx_session = copy.deepcopy(rxtxapp_config.config_rx_st20p_session) config["rx_sessions"][0]["st20p"].append(rx_session) @@ -736,8 +670,6 @@ def generate_rxtxapp_rx_config( config_json = config_json.replace('"', '\\"') f.write_text(config_json, encoding="utf-8") - logger.info("Config file written successfully") - return config_file except Exception as e: @@ -802,9 +734,6 @@ def generate_rxtxapp_rx_config_multiple( config_json = config_json.replace('"', '\\"') f.write_text(config_json, encoding="utf-8") - logger.info("Multiple config file written successfully") - logger.info(f"Generated RX multiple config file: {config_file}") - return config_file except Exception as e: @@ -831,7 +760,6 @@ def generate_rxtxapp_tx_config( config["tx_sessions"][0]["dip"][0] = ip_dict["tx_sessions"] width, height, fps = decode_video_format_to_st20p(video_format) - logger.info(f"Decoded video format: width={width}, height={height}, fps={fps}") tx_session = copy.deepcopy(rxtxapp_config.config_tx_st20p_session) config["tx_sessions"][0]["st20p"].append(tx_session) @@ -857,8 +785,6 @@ def generate_rxtxapp_tx_config( timestamp = time.strftime("%Y%m%d_%H%M%S") config_file = f"{build}/tests/{test_name}_{timestamp}_tx.json" - logger.info(f"Writing TX config file to: {config_file}") - config_json = json.dumps(config, indent=4) remote_conn = host.connection f = remote_conn.path(config_file) @@ -866,9 +792,6 @@ def generate_rxtxapp_tx_config( config_json = config_json.replace('"', '\\"') f.write_text(config_json, encoding="utf-8") - logger.info("TX Config file written successfully") - logger.info(f"Generated TX config file: {config_file}") - return config_file except Exception as e: @@ -878,8 +801,6 @@ def generate_rxtxapp_tx_config( def decode_video_format_to_st20p(video_format: str) -> tuple: """Convert video format string to st20p parameters (width, height, fps)""" - logger.info(f"Decoding video format: {video_format}") - pattern = r"i(\d+)([ip])(\d+)" match = re.search(pattern, video_format) @@ -943,13 +864,13 @@ def execute_dual_test( if tx_is_ffmpeg: tx_cmd = ( f"ffmpeg -video_size {video_size} -f rawvideo -pix_fmt yuv422p10le " - f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[1]} " + f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[0]} " f"-p_sip {ip_dict['tx_interfaces']} -p_tx_ip {ip_dict['tx_sessions']} " f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) else: # tx is rxtxapp tx_config_file = generate_rxtxapp_tx_config( - tx_nic_port_list[1], video_format, video_url, tx_host, build + tx_nic_port_list[0], video_format, video_url, tx_host, build ) tx_cmd = f"{RXTXAPP_PATH} --config_file {tx_config_file}" else: # multiple sessions @@ -968,20 +889,18 @@ def execute_dual_test( if tx_is_ffmpeg: tx_cmd = ( f"ffmpeg -video_size {video_size} -f rawvideo -pix_fmt yuv422p10le " - f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[1]} " + f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[0]} " f"-p_sip {ip_dict['tx_interfaces']} -p_tx_ip {ip_dict['tx_sessions']} " f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) else: # tx is rxtxapp tx_config_file = generate_rxtxapp_tx_config( - tx_nic_port_list[1], video_format, video_url, tx_host, build, True + tx_nic_port_list[0], video_format, video_url, tx_host, build, True ) tx_cmd = f"{RXTXAPP_PATH} --config_file {tx_config_file}" logger.info(f"TX Host: {tx_host}") logger.info(f"RX Host: {rx_host}") - logger.info(f"RX Command: {rx_cmd}") - logger.info(f"TX Command: {tx_cmd}") rx_proc = None tx_proc = None @@ -1023,65 +942,51 @@ def execute_dual_test( logger.info("Terminating processes...") if tx_proc: try: - tx_proc.terminate() + tx_proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass if rx_proc: try: - rx_proc.terminate() + rx_proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass # Wait a bit for termination time.sleep(2) # Get output after processes have been terminated - try: - rx_output = f"RX Output:\n{rx_proc.stdout_text}" - logger.info(rx_output) - except Exception: - logger.info("Could not retrieve RX output") - try: - tx_output = f"TX Output:\n{tx_proc.stdout_text}" - logger.info(tx_output) - except Exception: - logger.info("Could not retrieve TX output") + capture_stdout(rx_proc, "RX") + capture_stdout(tx_proc, "TX") except Exception as e: log_fail(f"Error during test execution: {e}") # Terminate processes immediately on error if tx_proc: try: - tx_proc.terminate() + tx_proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass if rx_proc: try: - rx_proc.terminate() + rx_proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass raise finally: - # Ensure processes are terminated with force kill if needed + # Ensure processes are terminated if tx_proc: try: - tx_proc.terminate() - tx_proc.wait(timeout=5) + tx_proc.kill() except Exception: - try: - # Force kill if terminate didn't work - tx_proc.kill() - tx_proc.wait(timeout=5) - except Exception: - pass + # Process might already be terminated - ignore kill errors + pass if rx_proc: try: - rx_proc.terminate() - rx_proc.wait(timeout=5) + rx_proc.kill() except Exception: - try: - # Force kill if terminate didn't work - rx_proc.kill() - rx_proc.wait(timeout=5) - except Exception: - pass + # Process might already be terminated - ignore kill errors + pass if tcpdump: tcpdump.stop() passed = False @@ -1096,7 +1001,6 @@ def execute_dual_test( try: for output_file in output_files: run(f"rm -f {output_file}", host=rx_host) - logger.info(f"Removed output file: {output_file}") except Exception as e: logger.info(f"Could not remove output files: {e}") if not passed: @@ -1138,15 +1042,13 @@ def execute_dual_test_rgb24( rx_cmd = f"{RXTXAPP_PATH} --config_file {rx_config_file} --test_time {test_time}" tx_cmd = ( f"ffmpeg -stream_loop -1 -video_size {video_size} -f rawvideo -pix_fmt rgb24 " - f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[1]} " + f"-i {video_url} -filter:v fps={fps} -p_port {tx_nic_port_list[0]} " f"-p_sip {ip_dict['tx_interfaces']} -p_tx_ip {ip_dict['tx_sessions']} " f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) logger.info(f"TX Host: {tx_host}") logger.info(f"RX Host: {rx_host}") - logger.info(f"RX Command: {rx_cmd}") - logger.info(f"TX Command: {tx_cmd}") rx_proc = None tx_proc = None @@ -1192,67 +1094,44 @@ def execute_dual_test_rgb24( logger.info("Terminating TX process...") if tx_proc: try: - tx_proc.terminate() - tx_proc.wait(timeout=5) - logger.info("TX process terminated successfully") + tx_proc.kill() + logger.info("TX process killed") except Exception: - try: - tx_proc.kill() - tx_proc.wait(timeout=5) - logger.info("TX process killed") - except Exception: - logger.info("Could not terminate TX process") - - rx_output = "" - try: - rx_output = rx_proc.stdout_text - logger.info(f"RX Output:\n{rx_output}") - logger.info("RX output captured successfully") - except Exception as e: - logger.info(f"Error retrieving RX output: {e}") + logger.info("Could not terminate TX process") - try: - logger.info(f"TX Output:\n{tx_proc.stdout_text}") - logger.info("TX output captured successfully") - except Exception as e: - logger.info(f"Error retrieving TX output: {e}") + rx_output = capture_stdout(rx_proc, "RX") + capture_stdout(tx_proc, "TX") except Exception as e: log_fail(f"Error during test execution: {e}") # Terminate processes immediately on error if tx_proc: try: - tx_proc.terminate() + tx_proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass if rx_proc: try: - rx_proc.terminate() + rx_proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass raise finally: # Final cleanup - ensure processes are terminated if tx_proc: try: - tx_proc.terminate() - tx_proc.wait(timeout=3) + tx_proc.kill() except Exception: - try: - tx_proc.kill() - tx_proc.wait(timeout=3) - except Exception: - pass + # Process might already be terminated - ignore kill errors + pass if rx_proc: try: - rx_proc.terminate() - rx_proc.wait(timeout=3) + rx_proc.kill() except Exception: - try: - rx_proc.kill() - rx_proc.wait(timeout=3) - except Exception: - pass + # Process might already be terminated - ignore kill errors + pass if tcpdump: tcpdump.stop() @@ -1298,14 +1177,14 @@ def execute_dual_test_rgb24_multiple( rx_cmd = f"{RXTXAPP_PATH} --config_file {rx_config_file} --test_time {test_time}" tx_1_cmd = ( f"ffmpeg -stream_loop -1 -video_size {video_size_1} -f rawvideo -pix_fmt rgb24 " - f"-i {video_url_list[0]} -filter:v fps={fps_1} -p_port {tx_nic_port_list[1]} " + f"-i {video_url_list[0]} -filter:v fps={fps_1} -p_port {tx_nic_port_list[0]} " f"-p_sip {ip_dict_rgb24_multiple['p_sip_1']} " f"-p_tx_ip {ip_dict_rgb24_multiple['p_tx_ip_1']} " f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" ) tx_2_cmd = ( f"ffmpeg -stream_loop -1 -video_size {video_size_2} -f rawvideo -pix_fmt rgb24 " - f"-i {video_url_list[1]} -filter:v fps={fps_2} -p_port {tx_nic_port_list[2]} " + f"-i {video_url_list[1]} -filter:v fps={fps_2} -p_port {tx_nic_port_list[1]} " f"-p_sip {ip_dict_rgb24_multiple['p_sip_2']} " f"-p_tx_ip {ip_dict_rgb24_multiple['p_tx_ip_2']} " f"-udp_port 20000 -payload_type 112 -f mtl_st20p -" @@ -1313,9 +1192,6 @@ def execute_dual_test_rgb24_multiple( logger.info(f"TX Host: {tx_host}") logger.info(f"RX Host: {rx_host}") - logger.info(f"RX Command: {rx_cmd}") - logger.info(f"TX1 Command: {tx_1_cmd}") - logger.info(f"TX2 Command: {tx_2_cmd}") rx_proc = None tx_1_proc = None @@ -1369,44 +1245,23 @@ def execute_dual_test_rgb24_multiple( for proc in [tx_1_proc, tx_2_proc]: if proc: try: - proc.terminate() - proc.wait(timeout=5) - logger.info("TX process terminated successfully") + proc.kill() + logger.info("TX process killed") except Exception: - try: - proc.kill() - proc.wait(timeout=5) - logger.info("TX process killed") - except Exception: - logger.info("Could not terminate TX process") - - rx_output = "" - try: - rx_output = rx_proc.stdout_text - logger.info(f"RX Output:\n{rx_output}") - logger.info("RX output captured successfully") - except Exception as e: - logger.info(f"Error retrieving RX output: {e}") - - try: - logger.info(f"TX1 Output:\n{tx_1_proc.stdout_text}") - logger.info("TX1 output captured successfully") - except Exception as e: - logger.info(f"Error retrieving TX1 output: {e}") - - try: - logger.info(f"TX2 Output:\n{tx_2_proc.stdout_text}") - logger.info("TX2 output captured successfully") - except Exception as e: - logger.info(f"Error retrieving TX2 output: {e}") + logger.info("Could not terminate TX process") + + rx_output = capture_stdout(rx_proc, "RX") + capture_stdout(tx_1_proc, "TX1") + capture_stdout(tx_2_proc, "TX2") except Exception as e: log_fail(f"Error during test execution: {e}") # Terminate processes immediately on error for proc in [tx_1_proc, tx_2_proc, rx_proc]: if proc: try: - proc.terminate() + proc.kill() except Exception: + # Process might already be terminated - ignore kill errors pass raise finally: @@ -1414,14 +1269,10 @@ def execute_dual_test_rgb24_multiple( for proc in [tx_1_proc, tx_2_proc, rx_proc]: if proc: try: - proc.terminate() - proc.wait(timeout=3) + proc.kill() except Exception: - try: - proc.kill() - proc.wait(timeout=3) - except Exception: - pass + # Process might already be terminated - ignore kill errors + pass if tcpdump: tcpdump.stop() From e27f58468f2b9ac55443f9e458be1e4578158c8b Mon Sep 17 00:00:00 2001 From: Bartosz Krystowski Date: Tue, 26 Aug 2025 15:27:16 +0200 Subject: [PATCH 8/8] remove unnecessary exception catchers --- tests/validation/mtl_engine/ffmpeg_app.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/tests/validation/mtl_engine/ffmpeg_app.py b/tests/validation/mtl_engine/ffmpeg_app.py index b5ae2a8e4..12ae2237f 100755 --- a/tests/validation/mtl_engine/ffmpeg_app.py +++ b/tests/validation/mtl_engine/ffmpeg_app.py @@ -37,17 +37,13 @@ def capture_stdout(proc, proc_name: str): """Capture and log stdout from a process""" - try: - if proc and hasattr(proc, "stdout_text"): - output = proc.stdout_text - if output and output.strip(): - logger.info(f"{proc_name} Output:\n{output}") - return output - else: - logger.debug(f"No stdout available for {proc_name}") - return "" - except Exception as e: - logger.warning(f"Failed to capture stdout for {proc_name}: {e}") + if hasattr(proc, "stdout_text"): + output = proc.stdout_text + if output and output.strip(): + logger.info(f"{proc_name} Output:\n{output}") + return output + else: + logger.debug(f"No stdout available for {proc_name}") return ""