513 lines
15 KiB
Bash
Executable File
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
|