From f250de4d7636966150abafc6d5cf5c678ced9cea Mon Sep 17 00:00:00 2001 From: Nejc Stebe Date: Tue, 31 Mar 2026 13:30:04 +0200 Subject: [PATCH 1/8] add unit test stdout (error details) to renderFailed state --- render_machine/actions/run_unit_tests.py | 2 +- render_machine/render_utils.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/render_machine/actions/run_unit_tests.py b/render_machine/actions/run_unit_tests.py index 08d1728..bbea953 100644 --- a/render_machine/actions/run_unit_tests.py +++ b/render_machine/actions/run_unit_tests.py @@ -34,7 +34,6 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | return self.SUCCESSFUL_OUTCOME, None elif exit_code in UNRECOVERABLE_ERROR_EXIT_CODES: - console.error(unittests_issue) return ( self.UNRECOVERABLE_ERROR_OUTCOME, RenderError.encode( @@ -42,6 +41,7 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | error_type="ENVIRONMENT_ERROR", exit_code=exit_code, script=render_context.unittests_script, + issue=unittests_issue, ).to_payload(), ) else: diff --git a/render_machine/render_utils.py b/render_machine/render_utils.py index f7d8dcb..46e3454 100644 --- a/render_machine/render_utils.py +++ b/render_machine/render_utils.py @@ -1,4 +1,5 @@ import os +import re import signal import subprocess import sys @@ -125,6 +126,10 @@ def execute_script( # noqa: C901 stdout = "" elapsed_time = time.time() - start_time + erase_display_pattern = re.compile(r"(?:\033\[[^a-zA-Z]*[a-zA-Z])*\033\[2J(?:\033\[[^a-zA-Z]*[a-zA-Z])*") + parts = erase_display_pattern.split(stdout) + stdout = parts[-1] if len(parts) > 1 else stdout + # Log the info about the script execution if verbose: with tempfile.NamedTemporaryFile( From 8f91bdf431de7dc8354dda37330b86b4eba442de Mon Sep 17 00:00:00 2001 From: Nejc Stebe Date: Tue, 31 Mar 2026 15:37:51 +0200 Subject: [PATCH 2/8] display multiple error message lines after unrecoverable error --- render_machine/actions/run_unit_tests.py | 1 - render_machine/render_types.py | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/render_machine/actions/run_unit_tests.py b/render_machine/actions/run_unit_tests.py index bbea953..4f1ab1a 100644 --- a/render_machine/actions/run_unit_tests.py +++ b/render_machine/actions/run_unit_tests.py @@ -39,7 +39,6 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | RenderError.encode( message="Unit tests script failed due to problems in the environment setup. Please check your environment or update the script for running unittests.", error_type="ENVIRONMENT_ERROR", - exit_code=exit_code, script=render_context.unittests_script, issue=unittests_issue, ).to_payload(), diff --git a/render_machine/render_types.py b/render_machine/render_types.py index 58ef1c9..91c17d5 100644 --- a/render_machine/render_types.py +++ b/render_machine/render_types.py @@ -133,7 +133,11 @@ def format_for_display(self) -> str: if self.details: lines.append("\nDetails:") for detail_name, detail_value in self.details.items(): - lines.append(f" {detail_name}: {detail_value}") + if detail_name == "issue": + detail_value_indented = "\n".join(" " + line for line in detail_value.splitlines()) + lines.append(detail_value_indented) + else: + lines.append(f" {detail_name.capitalize()}: {detail_value}") return "\n".join(lines) From d4162cb9f2294441096362b8b306219ba25678b1 Mon Sep 17 00:00:00 2001 From: Nejc Stebe Date: Tue, 31 Mar 2026 15:57:02 +0200 Subject: [PATCH 3/8] readd logging --- render_machine/actions/run_unit_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/render_machine/actions/run_unit_tests.py b/render_machine/actions/run_unit_tests.py index 4f1ab1a..8cfcaa7 100644 --- a/render_machine/actions/run_unit_tests.py +++ b/render_machine/actions/run_unit_tests.py @@ -34,6 +34,7 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | return self.SUCCESSFUL_OUTCOME, None elif exit_code in UNRECOVERABLE_ERROR_EXIT_CODES: + console.error(unittests_issue) return ( self.UNRECOVERABLE_ERROR_OUTCOME, RenderError.encode( From caba073a522791e08c5d3c6dec481533f2e166f4 Mon Sep 17 00:00:00 2001 From: Nejc Stebe Date: Wed, 1 Apr 2026 14:58:11 +0200 Subject: [PATCH 4/8] add stdout clearing examples to the examples --- test_scripts/run_unittests_golang.sh | 1 + test_scripts/run_unittests_python.sh | 1 + test_scripts/run_unittests_react.sh | 1 + 3 files changed, 3 insertions(+) diff --git a/test_scripts/run_unittests_golang.sh b/test_scripts/run_unittests_golang.sh index 56da7f1..87b6ffd 100755 --- a/test_scripts/run_unittests_golang.sh +++ b/test_scripts/run_unittests_golang.sh @@ -37,6 +37,7 @@ cp -R $1/* $GO_BUILD_SUBFOLDER cd "$GO_BUILD_SUBFOLDER" 2>/dev/null if [ $? -ne 0 ]; then + clear printf "Error: Go build folder '$GO_BUILD_SUBFOLDER' does not exist.\n" exit $UNRECOVERABLE_ERROR_EXIT_CODE fi diff --git a/test_scripts/run_unittests_python.sh b/test_scripts/run_unittests_python.sh index 56bfc5c..e2fe3b2 100755 --- a/test_scripts/run_unittests_python.sh +++ b/test_scripts/run_unittests_python.sh @@ -47,6 +47,7 @@ cp -R $1/* $PYTHON_BUILD_SUBFOLDER cd "$PYTHON_BUILD_SUBFOLDER" 2>/dev/null if [ $? -ne 0 ]; then + clear printf "Error: Python build folder '$PYTHON_BUILD_SUBFOLDER' does not exist.\n" exit $UNRECOVERABLE_ERROR_EXIT_CODE fi diff --git a/test_scripts/run_unittests_react.sh b/test_scripts/run_unittests_react.sh index 514bf15..eb93da3 100755 --- a/test_scripts/run_unittests_react.sh +++ b/test_scripts/run_unittests_react.sh @@ -45,6 +45,7 @@ cp -R $1/* $NODE_SUBFOLDER cd "$NODE_SUBFOLDER" 2>/dev/null if [ $? -ne 0 ]; then + clear echo "Error: Subfolder '$1' does not exist." exit $UNRECOVERABLE_ERROR_EXIT_CODE fi From 9383f14b679d77a096bd35ac3481b43fb08767da Mon Sep 17 00:00:00 2001 From: Nejc Stebe Date: Wed, 1 Apr 2026 15:24:25 +0200 Subject: [PATCH 5/8] move output sanitization to separate function --- render_machine/render_utils.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/render_machine/render_utils.py b/render_machine/render_utils.py index 46e3454..0f18e80 100644 --- a/render_machine/render_utils.py +++ b/render_machine/render_utils.py @@ -71,6 +71,17 @@ def _kill_process(proc: subprocess.Popen) -> None: proc.kill() +def sanitize_script_output(script_output: str) -> str: + # this function removes the escape codes that clear the console + clear_console_escape_codes_pattern = r"(?:\033\[[^a-zA-Z]*[a-zA-Z])*\033\[2J(?:\033\[[^a-zA-Z]*[a-zA-Z])*" + + pattern = re.compile(clear_console_escape_codes_pattern) + parts = pattern.split(script_output) + + # take only the part after the last clear console escape code + return parts[-1] if len(parts) > 1 else script_output + + def execute_script( # noqa: C901 script: str, scripts_args: list[str], @@ -126,9 +137,7 @@ def execute_script( # noqa: C901 stdout = "" elapsed_time = time.time() - start_time - erase_display_pattern = re.compile(r"(?:\033\[[^a-zA-Z]*[a-zA-Z])*\033\[2J(?:\033\[[^a-zA-Z]*[a-zA-Z])*") - parts = erase_display_pattern.split(stdout) - stdout = parts[-1] if len(parts) > 1 else stdout + sanitized_script_output = sanitize_script_output(stdout) # Log the info about the script execution if verbose: @@ -136,7 +145,7 @@ def execute_script( # noqa: C901 mode="w+", encoding="utf-8", delete=False, suffix=".script_output" ) as temp_file: temp_file.write(f"\n═════════════════════════ {script_type} Script Output ═════════════════════════\n") - temp_file.write(stdout) + temp_file.write(sanitized_script_output) temp_file.write("\n══════════════════════════════════════════════════════════════════════\n") temp_file_path = temp_file.name if proc.returncode != 0: @@ -164,7 +173,7 @@ def execute_script( # noqa: C901 else: console.info(f"[#79FC96]All {script_type} scripts have passed successfully.[/#79FC96]") - return proc.returncode, stdout, temp_file_path + return proc.returncode, sanitized_script_output, temp_file_path except RenderCancelledError: raise From d2331f6d075613876b4ddbdd6831c39b03d15a92 Mon Sep 17 00:00:00 2001 From: Nejc Stebe Date: Wed, 1 Apr 2026 15:42:02 +0200 Subject: [PATCH 6/8] take out ../ parent dir shorthands from the unit tests script path --- render_machine/actions/run_unit_tests.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/render_machine/actions/run_unit_tests.py b/render_machine/actions/run_unit_tests.py index 8cfcaa7..938d2d9 100644 --- a/render_machine/actions/run_unit_tests.py +++ b/render_machine/actions/run_unit_tests.py @@ -1,3 +1,4 @@ +import os from typing import Any import render_machine.render_utils as render_utils @@ -15,12 +16,14 @@ class RunUnitTests(BaseAction): UNRECOVERABLE_ERROR_OUTCOME = "unrecoverable_error_occurred" def execute(self, render_context: RenderContext, _previous_action_payload: Any | None): + unittests_script = os.path.normpath(render_context.unittests_script) + if render_context.verbose: console.info( - f"Running unit tests script {render_context.unittests_script}. (attempt: {render_context.unit_tests_running_context.fix_attempts + 1})" + f"Running unit tests script {unittests_script}. (attempt: {render_context.unit_tests_running_context.fix_attempts + 1})" ) exit_code, unittests_issue, unittests_temp_file_path = render_utils.execute_script( - render_context.unittests_script, + unittests_script, [render_context.build_folder], render_context.verbose, "Unit Tests", @@ -35,12 +38,13 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | elif exit_code in UNRECOVERABLE_ERROR_EXIT_CODES: console.error(unittests_issue) + return ( self.UNRECOVERABLE_ERROR_OUTCOME, RenderError.encode( message="Unit tests script failed due to problems in the environment setup. Please check your environment or update the script for running unittests.", error_type="ENVIRONMENT_ERROR", - script=render_context.unittests_script, + script=unittests_script, issue=unittests_issue, ).to_payload(), ) From cfcd99f77a278b2ea880bf3c08489888e7a00186 Mon Sep 17 00:00:00 2001 From: Nejc Stebe Date: Wed, 1 Apr 2026 16:00:17 +0200 Subject: [PATCH 7/8] improve error screen for failed conformance tests too --- render_machine/actions/run_conformance_tests.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/render_machine/actions/run_conformance_tests.py b/render_machine/actions/run_conformance_tests.py index 06402a4..d9f9d81 100644 --- a/render_machine/actions/run_conformance_tests.py +++ b/render_machine/actions/run_conformance_tests.py @@ -1,3 +1,4 @@ +import os from typing import Any import render_machine.render_utils as render_utils @@ -16,6 +17,8 @@ class RunConformanceTests(BaseAction): UNRECOVERABLE_ERROR_OUTCOME = "unrecoverable_error_occurred" def execute(self, render_context: RenderContext, _previous_action_payload: Any | None): + conformance_tests_script = os.path.normpath(render_context.conformance_tests_script) + if render_context.module_name == render_context.conformance_tests_running_context.current_testing_module_name: conformance_tests_folder_name = ( render_context.conformance_tests_running_context.get_current_conformance_test_folder_name() @@ -32,14 +35,14 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | if render_context.verbose: console.info( - f"Running conformance tests script {render_context.conformance_tests_script} " + f"Running conformance tests script {conformance_tests_script} " + f"for {conformance_tests_folder_name} (" + f"functionality {render_context.conformance_tests_running_context.current_testing_frid} " + f"in module {render_context.conformance_tests_running_context.current_testing_module_name}" + ")." ) exit_code, conformance_tests_issue, conformance_tests_temp_file_path = render_utils.execute_script( - render_context.conformance_tests_script, + conformance_tests_script, [render_context.build_folder, conformance_tests_folder_name], render_context.verbose, "Conformance Tests", @@ -72,9 +75,9 @@ def execute(self, render_context: RenderContext, _previous_action_payload: Any | RenderError.encode( message=conformance_tests_issue, error_type="ENVIRONMENT_ERROR", - exit_code=exit_code, - script=render_context.conformance_tests_script, + script=conformance_tests_script, frid=render_context.conformance_tests_running_context.current_testing_frid, + issue=conformance_tests_issue, ).to_payload(), ) From e347af003dffb05260b7ced8ed50238ba5a28cb1 Mon Sep 17 00:00:00 2001 From: Nejc Stebe Date: Thu, 2 Apr 2026 07:40:17 +0200 Subject: [PATCH 8/8] make function private --- render_machine/render_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/render_machine/render_utils.py b/render_machine/render_utils.py index 0f18e80..3404284 100644 --- a/render_machine/render_utils.py +++ b/render_machine/render_utils.py @@ -71,7 +71,7 @@ def _kill_process(proc: subprocess.Popen) -> None: proc.kill() -def sanitize_script_output(script_output: str) -> str: +def _sanitize_script_output(script_output: str) -> str: # this function removes the escape codes that clear the console clear_console_escape_codes_pattern = r"(?:\033\[[^a-zA-Z]*[a-zA-Z])*\033\[2J(?:\033\[[^a-zA-Z]*[a-zA-Z])*" @@ -137,7 +137,7 @@ def execute_script( # noqa: C901 stdout = "" elapsed_time = time.time() - start_time - sanitized_script_output = sanitize_script_output(stdout) + sanitized_script_output = _sanitize_script_output(stdout) # Log the info about the script execution if verbose: