Files
2026-08-27 11:12:22 +02:00

513 lines
15 KiB
Bash
Executable File

#!/usr/bin/env bash
set -u
set -o pipefail
readonly DEFAULT_DURATION_SECONDS="8"
readonly TEST_OVERRIDE_ACK_VALUE="YES"
CAPTURE=""
STATUS_DIR=""
LAUNCH_ACTIVE="NO"
INTERRUPT_PENDING="NO"
SELECTED_SCENARIO=""
DISPLAY_SCENARIO=""
SELECTED_PROFILE="N/A"
SELECTED_DURATION=""
LAST_LAUNCHER_RC="NOT_AVAILABLE"
LAST_RUN_DIR="NOT_AVAILABLE"
LAST_RUN_DIR_STATUS="NOT_AVAILABLE"
cleanup_temporary_files() {
if [ -n "$CAPTURE" ]; then
rm -f -- "$CAPTURE"
CAPTURE=""
fi
if [ -n "$STATUS_DIR" ]; then
rm -f -- \
"$STATUS_DIR/launcher_rc" \
"$STATUS_DIR/tee_rc"
rmdir -- "$STATUS_DIR" 2>/dev/null || true
STATUS_DIR=""
fi
}
fatal_wrapper_error() {
local exit_code="$1"
local status="$2"
local message="$3"
printf 'ERRORE S03-H3: %s\n' "$message" >&2
if [ "$exit_code" -eq 70 ]; then
printf 'S03_H3_STARTUP_STATUS=%s\n' "$status" >&2
else
printf 'S03_H3_MENU_LIFECYCLE_STATUS=%s\n' "$status" >&2
fi
exit "$exit_code"
}
handle_int() {
if [ "$LAUNCH_ACTIVE" = "YES" ]; then
INTERRUPT_PENDING="YES"
return 0
fi
printf '\nInterruzione richiesta: nessun nuovo benchmark verra avviato.\n' >&2
printf 'LAUNCHER_EXECUTED=NO\n' >&2
exit 130
}
handle_hup() {
printf '\nS03-H3 terminato da SIGHUP.\n' >&2
exit 129
}
handle_term() {
printf '\nS03-H3 terminato da SIGTERM.\n' >&2
exit 143
}
trap cleanup_temporary_files EXIT
trap handle_hup HUP
trap handle_int INT
trap handle_term TERM
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
if [ -z "$SCRIPT_DIR" ]; then
fatal_wrapper_error 70 "FAIL_SUITE_ROOT" \
"impossibile determinare la directory del menu"
fi
INSTALLED_SUITE="$(cd -- "$SCRIPT_DIR/.." && pwd -P)"
if [ -z "$INSTALLED_SUITE" ]; then
fatal_wrapper_error 70 "FAIL_SUITE_ROOT" \
"impossibile determinare la radice della suite"
fi
readonly -a COMPLETE_OVERRIDE_PATHS=(
"launcher/marte_benchmark_launcher.sh"
"configurations/generated/S00/smoke_s0_core.marte"
"configurations/generated/S01/from_patcher/smoke_s1_timing_from_s00.marte"
"configurations/generated/S02/from_patcher/smoke_s2_binary_recording_from_s01.marte"
"configurations/generated/S03/from_patcher/smoke_s3_semantic_sentinels_from_s02.marte"
"patchers/configuration/build_s01_from_s00.sh"
"patchers/configuration/build_s02_from_s01.sh"
"patchers/configuration/build_s03_from_s02.sh"
"scenarios/S02_binary_recording/validate.sh"
"scenarios/S03_semantic_sentinels/validate.sh"
"scenarios/S03_semantic_sentinels/parse_s03_binary.py"
"common/marte_runner.sh"
"common/paths.sh"
"common/environment.sh"
"launcher/marte_benchmark_launcher_s03h1.sh"
"patchers/configuration/build_s03h1_from_s02.sh"
"scenarios/S03H1_execution_profiles/validate.sh"
"scenarios/S03H1_execution_profiles/verify_s03h1_config.py"
"scenarios/S03H1_execution_profiles/export_s03_csv.py"
"configurations/generated/S03H1/from_patcher/smoke_s03h1_execution_profiles_test_from_s02.marte"
"configurations/generated/S03H1/from_patcher/smoke_s03h1_execution_profiles_diagnostic_from_s02.marte"
"launcher/marte_benchmark_launcher_s03h3.sh"
"patchers/configuration/build_s03h3_minimal_from_s03h1_test.sh"
"scenarios/S03H3_execution_profiles/validate.sh"
"scenarios/S03H3_execution_profiles/verify_s03h3_minimal_structure.py"
"configurations/generated/S03H3/from_patcher/smoke_s03h3_execution_profiles_minimal_from_s03h1_test.marte"
"launcher/marte_benchmark_menu.sh"
)
verify_complete_override_root() {
local relative_path
local missing_count=0
for relative_path in "${COMPLETE_OVERRIDE_PATHS[@]}"; do
if [ ! -f "$SUITE/$relative_path" ]; then
printf 'ERRORE S03-H3: fixture incompleta, manca %s\n' \
"$relative_path" >&2
missing_count=$((missing_count + 1))
fi
done
[ "$missing_count" -eq 0 ]
}
OVERRIDE_ACTIVE="NO"
if [ -n "${MARTE_BENCHMARK_SUITE_ROOT:-}" ]; then
if [ "${S03H3_TEST_ONLY_OVERRIDE:-NO}" != "$TEST_OVERRIDE_ACK_VALUE" ]; then
fatal_wrapper_error 70 "FAIL_TEST_OVERRIDE_NOT_ACKNOWLEDGED" \
"MARTE_BENCHMARK_SUITE_ROOT richiede S03H3_TEST_ONLY_OVERRIDE=YES"
fi
if [[ "$MARTE_BENCHMARK_SUITE_ROOT" != /* ]]; then
fatal_wrapper_error 70 "FAIL_TEST_OVERRIDE_NOT_ABSOLUTE" \
"la radice di override deve essere un percorso assoluto"
fi
if [ ! -d "$MARTE_BENCHMARK_SUITE_ROOT" ]; then
fatal_wrapper_error 70 "FAIL_TEST_OVERRIDE_ROOT" \
"la radice di override non esiste"
fi
SUITE="$(cd -- "$MARTE_BENCHMARK_SUITE_ROOT" && pwd -P)"
if [ -z "$SUITE" ] || [ "$SUITE" = "/" ]; then
fatal_wrapper_error 70 "FAIL_TEST_OVERRIDE_ROOT" \
"la radice di override non e sicura"
fi
OVERRIDE_ACTIVE="YES"
if ! verify_complete_override_root; then
fatal_wrapper_error 70 "FAIL_INCOMPLETE_TEST_SUITE" \
"l'override e ammesso soltanto per una suite completa di 27 elementi"
fi
elif [ "${S03H3_TEST_ONLY_OVERRIDE:-NO}" = "$TEST_OVERRIDE_ACK_VALUE" ]; then
fatal_wrapper_error 70 "FAIL_TEST_OVERRIDE_ROOT_MISSING" \
"S03H3_TEST_ONLY_OVERRIDE=YES richiede MARTE_BENCHMARK_SUITE_ROOT"
else
SUITE="$INSTALLED_SUITE"
fi
readonly SUITE
readonly OVERRIDE_ACTIVE
STANDARD_LAUNCHER="$SUITE/launcher/marte_benchmark_launcher.sh"
S03H3_LAUNCHER="$SUITE/launcher/marte_benchmark_launcher_s03h3.sh"
readonly STANDARD_LAUNCHER
readonly S03H3_LAUNCHER
if [ ! -x "$STANDARD_LAUNCHER" ]; then
fatal_wrapper_error 70 "FAIL_REQUIRED_LAUNCHER" \
"launcher standard assente o non eseguibile: $STANDARD_LAUNCHER"
fi
if [ ! -x "$S03H3_LAUNCHER" ]; then
fatal_wrapper_error 70 "FAIL_REQUIRED_LAUNCHER" \
"launcher S03-H3 assente o non eseguibile: $S03H3_LAUNCHER"
fi
export MARTE_BENCHMARK_SUITE_ROOT="$SUITE"
is_positive_decimal() {
local value="$1"
[[ "$value" =~ ^[0-9]+$ ]] && [[ "$value" =~ [1-9] ]]
}
normalize_decimal() {
local value="$1"
while [ "${#value}" -gt 1 ] && [ "${value:0:1}" = "0" ]; do
value="${value#0}"
done
printf '%s' "$value"
}
print_main_menu() {
printf '\n============================================================\n'
printf 'MARTe2 Benchmark Suite — menu S03-H3\n'
printf '============================================================\n'
printf '1) S01\n'
printf '2) S02\n'
printf '3) S03\n'
printf '4) S03-H3\n'
printf '0) Exit\n'
printf 'Selection: '
}
read_duration() {
local value
printf 'Simulation duration [seconds] (default: %s): ' \
"$DEFAULT_DURATION_SECONDS"
if ! IFS= read -r value; then
return 1
fi
if [ -z "$value" ]; then
SELECTED_DURATION="$DEFAULT_DURATION_SECONDS"
return 0
fi
if ! is_positive_decimal "$value"; then
printf 'Durata non valida: usare solo un intero decimale positivo.\n' >&2
printf 'LAUNCHER_EXECUTED=NO\n'
return 2
fi
SELECTED_DURATION="$(normalize_decimal "$value")"
return 0
}
read_s03h3_profile() {
local value
printf '1) MINIMAL\n'
printf '2) TEST\n'
printf '3) DIAGNOSTIC\n'
printf 'Profile: '
if ! IFS= read -r value; then
return 1
fi
case "$value" in
1)
SELECTED_PROFILE="MINIMAL"
;;
2)
SELECTED_PROFILE="TEST"
;;
3)
SELECTED_PROFILE="DIAGNOSTIC"
;;
*)
printf 'Profilo non valido. Nessun launcher eseguito.\n' >&2
printf 'LAUNCHER_EXECUTED=NO\n'
return 2
;;
esac
return 0
}
confirm_execution() {
local answer
printf '\nScenario: %s\n' "$DISPLAY_SCENARIO"
printf 'Profile: %s\n' "$SELECTED_PROFILE"
printf 'Duration: %s s\n\n' "$SELECTED_DURATION"
printf 'Start execution? [y/N]: '
if ! IFS= read -r answer; then
return 1
fi
case "$answer" in
y|Y)
return 0
;;
*)
printf 'Esecuzione annullata.\n'
printf 'LAUNCHER_EXECUTED=NO\n'
return 2
;;
esac
}
delegate_launcher() {
case "$SELECTED_SCENARIO" in
S01)
"$STANDARD_LAUNCHER" S01 "$SELECTED_DURATION"
;;
S02)
"$STANDARD_LAUNCHER" S02 "$SELECTED_DURATION"
;;
S03)
"$STANDARD_LAUNCHER" S03 "$SELECTED_DURATION"
;;
S03H3)
"$S03H3_LAUNCHER" S03H3 "$SELECTED_DURATION" "$SELECTED_PROFILE"
;;
*)
return 125
;;
esac
}
read_recorded_status() {
local status_file="$1"
local fallback="$2"
local value=""
if [ -s "$status_file" ]; then
IFS= read -r value <"$status_file" || value=""
fi
if [[ "$value" =~ ^[0-9]+$ ]]; then
printf '%s' "$value"
else
printf '%s' "$fallback"
fi
}
observe_run_dir() {
local observed=""
local observed_resolved=""
local observed_parent=""
local observed_name=""
observed="$(sed -n 's/^RUN_DIR=//p' "$CAPTURE" | tail -n 1)"
if [ -z "$observed" ]; then
LAST_RUN_DIR="NOT_AVAILABLE"
LAST_RUN_DIR_STATUS="NOT_AVAILABLE"
elif [[ "$observed" != /* ]]; then
LAST_RUN_DIR="$observed"
LAST_RUN_DIR_STATUS="REPORTED_BUT_INVALID"
elif [ ! -d "$observed" ]; then
LAST_RUN_DIR="$observed"
LAST_RUN_DIR_STATUS="REPORTED_BUT_NOT_FOUND"
elif [ "$SELECTED_SCENARIO" = "S03H3" ]; then
observed_resolved="$(cd -- "$observed" && pwd -P)" || observed_resolved=""
observed_parent="$(dirname -- "$observed_resolved")"
observed_name="$(basename -- "$observed_resolved")"
if [ "$observed_parent" = "$SUITE/runs" ] &&
[[ "$observed_name" = *_S03H3_${SELECTED_PROFILE}_launcher ]]; then
LAST_RUN_DIR="$observed_resolved"
LAST_RUN_DIR_STATUS="FOUND"
else
LAST_RUN_DIR="$observed"
LAST_RUN_DIR_STATUS="REPORTED_BUT_INVALID"
fi
else
LAST_RUN_DIR="$observed"
LAST_RUN_DIR_STATUS="FOUND"
fi
}
print_execution_summary() {
printf '\n============================================================\n'
printf 'Riepilogo esecuzione S03-H3\n'
printf '============================================================\n'
printf 'Scenario: %s\n' "$DISPLAY_SCENARIO"
printf 'Profile: %s\n' "$SELECTED_PROFILE"
printf 'Duration: %s s\n' "$SELECTED_DURATION"
printf 'Launcher RC: %s\n' "$LAST_LAUNCHER_RC"
printf 'RUN_DIR: %s\n' "$LAST_RUN_DIR"
printf 'RUN_DIR status: %s\n' "$LAST_RUN_DIR_STATUS"
printf 'LAST_LAUNCHER_RC=%s\n' "$LAST_LAUNCHER_RC"
printf 'RUN_DIR_STATUS=%s\n' "$LAST_RUN_DIR_STATUS"
printf 'RUN_DIR=%s\n' "$LAST_RUN_DIR"
printf 'MENU_RECLASSIFIES_LAUNCHER_RESULT=NO\n'
}
invoke_selected_launcher() {
local -a pipeline_status
local launcher_rc
local tee_rc
cleanup_temporary_files
CAPTURE="$(mktemp "${TMPDIR:-/tmp}/marte_benchmark_menu.capture.XXXXXX")" ||
fatal_wrapper_error 71 "FAIL_CAPTURE_CREATION" \
"impossibile creare il file temporaneo di cattura"
STATUS_DIR="$(mktemp -d "${TMPDIR:-/tmp}/marte_benchmark_menu.status.XXXXXX")" || {
cleanup_temporary_files
fatal_wrapper_error 71 "FAIL_CAPTURE_CREATION" \
"impossibile creare lo stato temporaneo della cattura"
}
INTERRUPT_PENDING="NO"
LAUNCH_ACTIVE="YES"
(
delegate_launcher
launcher_rc=$?
printf '%s\n' "$launcher_rc" >"$STATUS_DIR/launcher_rc"
exit "$launcher_rc"
) 2>&1 | (
tee "$CAPTURE"
tee_rc=$?
printf '%s\n' "$tee_rc" >"$STATUS_DIR/tee_rc"
exit "$tee_rc"
)
pipeline_status=("${PIPESTATUS[@]}")
LAUNCH_ACTIVE="NO"
launcher_rc="$(read_recorded_status \
"$STATUS_DIR/launcher_rc" "${pipeline_status[0]:-125}")"
tee_rc="$(read_recorded_status \
"$STATUS_DIR/tee_rc" "${pipeline_status[1]:-125}")"
LAST_LAUNCHER_RC="$launcher_rc"
observe_run_dir
print_execution_summary
if [ "$INTERRUPT_PENDING" = "YES" ]; then
printf 'S03_H3_MENU_LIFECYCLE_STATUS=INTERRUPTED\n' >&2
printf 'LAUNCHER_RC_RECLASSIFIED=NO\n' >&2
cleanup_temporary_files
exit 130
fi
if [ "$tee_rc" -ne 0 ]; then
printf 'CAPTURE_TEE_STATUS=FAIL\n' >&2
printf 'CAPTURE_TEE_RC=%s\n' "$tee_rc" >&2
printf 'S03_H3_MENU_LIFECYCLE_STATUS=FAIL_CAPTURE_TEE\n' >&2
cleanup_temporary_files
exit 72
fi
printf 'CAPTURE_TEE_STATUS=PASS\n'
printf 'S03_H3_MENU_LIFECYCLE_STATUS=CONTINUE\n'
cleanup_temporary_files
}
printf 'S03_H3_STARTUP_STATUS=PASS\n'
printf 'S03_H3_SUITE_ROOT=%s\n' "$SUITE"
printf 'S03_H3_TEST_OVERRIDE_ACTIVE=%s\n' "$OVERRIDE_ACTIVE"
while true; do
print_main_menu
if ! IFS= read -r menu_choice; then
printf '\nEOF: uscita pulita dal menu.\n'
printf 'S03_H3_MENU_LIFECYCLE_STATUS=EXIT_EOF\n'
exit 0
fi
SELECTED_PROFILE="N/A"
case "$menu_choice" in
0)
printf 'Uscita dal menu S03-H3.\n'
printf 'S03_H3_MENU_LIFECYCLE_STATUS=EXIT_USER\n'
exit 0
;;
1)
SELECTED_SCENARIO="S01"
DISPLAY_SCENARIO="S01"
;;
2)
SELECTED_SCENARIO="S02"
DISPLAY_SCENARIO="S02"
;;
3)
SELECTED_SCENARIO="S03"
DISPLAY_SCENARIO="S03"
;;
4)
SELECTED_SCENARIO="S03H3"
DISPLAY_SCENARIO="S03-H3"
;;
*)
printf 'Selezione non valida. Nessun launcher eseguito.\n' >&2
printf 'LAUNCHER_EXECUTED=NO\n'
continue
;;
esac
read_duration
duration_status=$?
if [ "$duration_status" -eq 1 ]; then
printf '\nEOF prima dell esecuzione: azione annullata.\n'
printf 'LAUNCHER_EXECUTED=NO\n'
printf 'S03_H3_MENU_LIFECYCLE_STATUS=EXIT_EOF\n'
exit 0
elif [ "$duration_status" -ne 0 ]; then
continue
fi
if [ "$SELECTED_SCENARIO" = "S03H3" ]; then
read_s03h3_profile
profile_status=$?
if [ "$profile_status" -eq 1 ]; then
printf '\nEOF prima dell esecuzione: azione annullata.\n'
printf 'LAUNCHER_EXECUTED=NO\n'
printf 'S03_H3_MENU_LIFECYCLE_STATUS=EXIT_EOF\n'
exit 0
elif [ "$profile_status" -ne 0 ]; then
continue
fi
fi
confirm_execution
confirmation_status=$?
if [ "$confirmation_status" -eq 1 ]; then
printf '\nEOF prima della conferma: azione annullata.\n'
printf 'LAUNCHER_EXECUTED=NO\n'
printf 'S03_H3_MENU_LIFECYCLE_STATUS=EXIT_EOF\n'
exit 0
elif [ "$confirmation_status" -ne 0 ]; then
continue
fi
printf 'LAUNCHER_EXECUTED=YES\n'
invoke_selected_launcher
done