#!/usr/bin/env bash set -u set -o pipefail readonly MINIMUM_SAMPLES="50" readonly EXPECTED_PARSER_SHA256="91c4d66770197e1986ed91eb6a4870e7da7df5a522ffdf4329b6d9250f238307" readonly EXPECTED_H1_VERIFIER_SHA256="2f1c41b186bd2e79a9fb51fab0461a7a0dce104bf0852c0ec1ade2c55a017443" readonly EXPECTED_TEST_CONFIG_SHA256="d037561b32760fbd0e2aec9f1eefc5efda27b1918eca4742c89092a8a2f7e92e" readonly EXPECTED_DIAGNOSTIC_CONFIG_SHA256="cd999ff249452298d650a22c8fe5b0b03bf48c0735f4630befdec8209cbb13a3" SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" SUITE="$(cd -- "$SCRIPT_DIR/../.." && pwd -P)" PARSER="$SUITE/scenarios/S03_semantic_sentinels/parse_s03_binary.py" H1_VERIFIER="$SUITE/scenarios/S03H1_execution_profiles/verify_s03h1_config.py" MINIMAL_VERIFIER="$SCRIPT_DIR/verify_s03h3_minimal_structure.py" TEST_CONFIG="$SUITE/configurations/generated/S03H1/from_patcher/smoke_s03h1_execution_profiles_test_from_s02.marte" DIAGNOSTIC_CONFIG="$SUITE/configurations/generated/S03H1/from_patcher/smoke_s03h1_execution_profiles_diagnostic_from_s02.marte" MINIMAL_CONFIG="$SUITE/configurations/generated/S03H3/from_patcher/smoke_s03h3_execution_profiles_minimal_from_s03h1_test.marte" MODE="NOT_PROVIDED" MODE_STATUS="NOT_DEMONSTRATED" PROFILE_CONFIG_STATUS="NOT_DEMONSTRATED" PROFILE_RUNTIME_STATUS="NOT_DEMONSTRATED" OBSERVABILITY_STATUS="NOT_DEMONSTRATED" OBSERVABILITY_REASON="NOT_EVALUATED" FUNCTIONAL_STATUS="NOT_DEMONSTRATED" SEMANTIC_STATUS="NOT_DEMONSTRATED" TIMING_STATUS="NOT_EVALUATED" MEASUREMENT_ELIGIBILITY="NO" COMPLETE_SAMPLE_COUNT="NOT_DEMONSTRATED" CONFIG_REPORT="" RUNTIME_CONFIG_REPORT="" BINARY_REPORT="" HASH_REPORT="" cleanup() { rm -f -- \ "${CONFIG_REPORT:-}" \ "${RUNTIME_CONFIG_REPORT:-}" \ "${BINARY_REPORT:-}" \ "${HASH_REPORT:-}" 2>/dev/null || true } trap cleanup EXIT HUP INT TERM emit_contract() { printf 'MODE=%s\n' "$MODE" printf 'MODE_STATUS=%s\n' "$MODE_STATUS" printf 'PROFILE_CONFIG_STATUS=%s\n' "$PROFILE_CONFIG_STATUS" printf 'PROFILE_RUNTIME_STATUS=%s\n' "$PROFILE_RUNTIME_STATUS" printf 'OBSERVABILITY_STATUS=%s\n' "$OBSERVABILITY_STATUS" printf 'OBSERVABILITY_REASON=%s\n' "$OBSERVABILITY_REASON" printf 'FUNCTIONAL_STATUS=%s\n' "$FUNCTIONAL_STATUS" printf 'SEMANTIC_STATUS=%s\n' "$SEMANTIC_STATUS" printf 'TIMING_STATUS=%s\n' "$TIMING_STATUS" printf 'MEASUREMENT_ELIGIBILITY=%s\n' "$MEASUREMENT_ELIGIBILITY" printf 'COMPLETE_SAMPLE_COUNT=%s\n' "$COMPLETE_SAMPLE_COUNT" } fail_early() { local code="$1" local reason="$2" printf '[NON DIMOSTRATO] %s\n' "$reason" >&2 OBSERVABILITY_REASON="$reason" emit_contract printf 'VALIDATION_RESULT=FAIL_REQUIRED_INPUT\n' exit "$code" } count_lines() { local pattern="$1" local file="$2" grep -Ec "$pattern" "$file" || true } report_value_exact() { local key="$1" local file="$2" local count count="$(grep -Ec "^${key}=" "$file" || true)" if [ "$count" -ne 1 ]; then return 1 fi sed -n "s/^${key}=//p" "$file" } verify_identity() { local file="$1" local expected="$2" [ -f "$file" ] || return 1 [ "$(sha256sum -- "$file" | awk '{print $1}')" = "$expected" ] } if [ "$#" -ne 2 ]; then printf 'Uso: %s MINIMAL|TEST|DIAGNOSTIC \n' "$0" >&2 emit_contract printf 'VALIDATION_RESULT=FAIL_INVALID_USAGE\n' exit 2 fi MODE="$1" case "$MODE" in MINIMAL) SELECTED_CONFIG="$MINIMAL_CONFIG" ;; TEST) SELECTED_CONFIG="$TEST_CONFIG" EXPECTED_SELECTED_CONFIG_SHA256="$EXPECTED_TEST_CONFIG_SHA256" ;; DIAGNOSTIC) SELECTED_CONFIG="$DIAGNOSTIC_CONFIG" EXPECTED_SELECTED_CONFIG_SHA256="$EXPECTED_DIAGNOSTIC_CONFIG_SHA256" ;; *) MODE_STATUS="FAIL" PROFILE_CONFIG_STATUS="FAIL" PROFILE_RUNTIME_STATUS="FAIL" OBSERVABILITY_STATUS="FAIL" OBSERVABILITY_REASON="UNKNOWN_MODE" emit_contract printf 'VALIDATION_RESULT=FAIL_UNKNOWN_MODE\n' exit 2 ;; esac INPUT_PATH="$2" if [ -d "$INPUT_PATH" ]; then RUN_DIR="$(cd -- "$INPUT_PATH" && pwd -P)" RUN_LOG="$RUN_DIR/run.log" elif [ -f "$INPUT_PATH" ]; then RUN_LOG="$(cd -- "$(dirname -- "$INPUT_PATH")" && pwd -P)/$(basename -- "$INPUT_PATH")" RUN_DIR="$(dirname -- "$RUN_LOG")" else fail_early 21 "INPUT_PATH_NOT_FOUND" fi RUN_CONFIG="$RUN_DIR/configuration.marte" OUTPUT_FILE="$RUN_DIR/s03_output.bin" RUNNER_SUMMARY="$RUN_DIR/runner_summary.txt" RUN_HASHES="$RUN_DIR/hashes.sha256" MODE_FILE="$RUN_DIR/s03h3_mode.txt" verify_identity "$PARSER" "$EXPECTED_PARSER_SHA256" || \ fail_early 21 "PARSER_IDENTITY_NOT_DEMONSTRATED" verify_identity "$H1_VERIFIER" "$EXPECTED_H1_VERIFIER_SHA256" || \ fail_early 21 "H1_VERIFIER_IDENTITY_NOT_DEMONSTRATED" [ -x "$MINIMAL_VERIFIER" ] || fail_early 21 "MINIMAL_VERIFIER_NOT_EXECUTABLE" for required_file in \ "$RUN_LOG" \ "$RUN_CONFIG" \ "$OUTPUT_FILE" \ "$RUNNER_SUMMARY" \ "$RUN_HASHES" \ "$MODE_FILE" \ "$SELECTED_CONFIG" do [ -f "$required_file" ] || fail_early 21 "REQUIRED_FILE_MISSING" done [ -s "$RUN_LOG" ] || fail_early 21 "RUN_LOG_EMPTY" [ -s "$RUN_HASHES" ] || fail_early 21 "RUN_HASH_MANIFEST_EMPTY" SELECTED_CONFIG_SHA256="$(sha256sum -- "$SELECTED_CONFIG" | awk '{print $1}')" if [ "$MODE" = "MINIMAL" ]; then EXPECTED_SELECTED_CONFIG_SHA256="$SELECTED_CONFIG_SHA256" fi CANONICAL_CONFIG_IDENTITY_STATUS="PASS" if [ "$SELECTED_CONFIG_SHA256" != "$EXPECTED_SELECTED_CONFIG_SHA256" ]; then CANONICAL_CONFIG_IDENTITY_STATUS="FAIL" fi MODE_FILE_CONTENT_STATUS="PASS" MODE_DECLARATION_COUNT=0 SCENARIO_DECLARATION_COUNT=0 CONFIG_HASH_DECLARATION_COUNT=0 while IFS= read -r metadata_line || [ -n "$metadata_line" ]; do case "$metadata_line" in '') ;; SCENARIO=S03H3) SCENARIO_DECLARATION_COUNT=$((SCENARIO_DECLARATION_COUNT + 1)) ;; MODE=MINIMAL|MODE=TEST|MODE=DIAGNOSTIC) MODE_DECLARATION_COUNT=$((MODE_DECLARATION_COUNT + 1)) [ "${metadata_line#MODE=}" = "$MODE" ] || MODE_FILE_CONTENT_STATUS="FAIL" ;; SELECTED_CONFIG_SHA256=*) CONFIG_HASH_DECLARATION_COUNT=$((CONFIG_HASH_DECLARATION_COUNT + 1)) declared_config_sha256="${metadata_line#SELECTED_CONFIG_SHA256=}" if [[ ! "$declared_config_sha256" =~ ^[0-9a-f]{64}$ ]] || [ "$declared_config_sha256" != "$EXPECTED_SELECTED_CONFIG_SHA256" ] || [ "$declared_config_sha256" != "$SELECTED_CONFIG_SHA256" ]; then MODE_FILE_CONTENT_STATUS="FAIL" fi ;; *) MODE_FILE_CONTENT_STATUS="FAIL" ;; esac done <"$MODE_FILE" if [ "$MODE_FILE_CONTENT_STATUS" = "PASS" ] && [ "$CANONICAL_CONFIG_IDENTITY_STATUS" = "PASS" ] && [ "$MODE_DECLARATION_COUNT" -eq 1 ] && [ "$SCENARIO_DECLARATION_COUNT" -eq 1 ] && [ "$CONFIG_HASH_DECLARATION_COUNT" -eq 1 ]; then MODE_STATUS="PASS" else MODE_STATUS="FAIL" fi CONFIG_REPORT="$(mktemp "${TMPDIR:-/tmp}/s03h3_config.XXXXXX")" || \ fail_early 21 "CONFIG_REPORT_CREATION_FAILED" RUNTIME_CONFIG_REPORT="$(mktemp "${TMPDIR:-/tmp}/s03h3_runtime.XXXXXX")" || \ fail_early 21 "RUNTIME_REPORT_CREATION_FAILED" BINARY_REPORT="$(mktemp "${TMPDIR:-/tmp}/s03h3_binary.XXXXXX")" || \ fail_early 21 "BINARY_REPORT_CREATION_FAILED" HASH_REPORT="$(mktemp "${TMPDIR:-/tmp}/s03h3_hashes.XXXXXX")" || \ fail_early 21 "HASH_REPORT_CREATION_FAILED" EXPECTED_FILENAME="$RUN_DIR/s03_output.bin" CONFIG_RC=1 RUNTIME_CONFIG_RC=1 CANONICAL_STRUCTURAL_COMPLETENESS_STATUS="NOT_APPLICABLE" MINIMAL_RUNTIME_CONFIG_STATUS="NOT_APPLICABLE" if [ "$MODE" = "MINIMAL" ]; then PYTHONHASHSEED=0 python3 "$MINIMAL_VERIFIER" \ CANONICAL "$TEST_CONFIG" "$MINIMAL_CONFIG" \ >"$CONFIG_REPORT" 2>&1 CONFIG_RC=$? PYTHONHASHSEED=0 python3 "$MINIMAL_VERIFIER" \ RUNTIME "$MINIMAL_CONFIG" "$RUN_CONFIG" "$RUN_DIR" \ >"$RUNTIME_CONFIG_REPORT" 2>&1 RUNTIME_CONFIG_RC=$? CANONICAL_STRUCTURAL_COMPLETENESS_STATUS="$( report_value_exact CANONICAL_STRUCTURAL_COMPLETENESS_STATUS "$CONFIG_REPORT" || printf FAIL )" MINIMAL_RUNTIME_CONFIG_STATUS="$( report_value_exact MINIMAL_RUNTIME_CONFIG_STATUS "$RUNTIME_CONFIG_REPORT" || printf FAIL )" if [ "$CONFIG_RC" -eq 0 ] && [ "$RUNTIME_CONFIG_RC" -eq 0 ] && [ "$CANONICAL_STRUCTURAL_COMPLETENESS_STATUS" = "PASS" ] && [ "$MINIMAL_RUNTIME_CONFIG_STATUS" = "PASS" ]; then PROFILE_CONFIG_STATUS="PASS" else PROFILE_CONFIG_STATUS="FAIL" fi else PYTHONHASHSEED=0 python3 "$H1_VERIFIER" \ "$MODE" "$RUN_CONFIG" "$EXPECTED_FILENAME" \ >"$CONFIG_REPORT" 2>&1 CONFIG_RC=$? RUNTIME_CONFIG_RC=0 PROFILE_CONFIG_STATUS="$( report_value_exact CONFIG_PROFILE_VERIFICATION_STATUS "$CONFIG_REPORT" || printf FAIL )" fi GAMTIMER_RUNTIME_LINES="$(count_lines '^\[Information - RealTimeApplicationConfigurationBuilder\.cpp:[0-9]+\]: Resolving for function GAMTimer \[idx: 0\][[:space:]]*$' "$RUN_LOG")" SENTINEL_RUNTIME_LINES="$(count_lines '^\[Information - RealTimeApplicationConfigurationBuilder\.cpp:[0-9]+\]: Resolving for function SentinelProducer \[idx: 1\][[:space:]]*$' "$RUN_LOG")" GAMDISPLAY_IDX2_LINES="$(count_lines '^\[Information - RealTimeApplicationConfigurationBuilder\.cpp:[0-9]+\]: Resolving for function GAMDisplay \[idx: 2\][[:space:]]*$' "$RUN_LOG")" IOGAM_IDX2_LINES="$(count_lines '^\[Information - RealTimeApplicationConfigurationBuilder\.cpp:[0-9]+\]: Resolving for function IOGAM_Writer \[idx: 2\][[:space:]]*$' "$RUN_LOG")" IOGAM_IDX3_LINES="$(count_lines '^\[Information - RealTimeApplicationConfigurationBuilder\.cpp:[0-9]+\]: Resolving for function IOGAM_Writer \[idx: 3\][[:space:]]*$' "$RUN_LOG")" FUNCTION_RESOLUTION_LINES="$(count_lines '^\[Information - RealTimeApplicationConfigurationBuilder\.cpp:[0-9]+\]: Resolving for function .* \[idx: [0-9]+\][[:space:]]*$' "$RUN_LOG")" GAMTIMER_OBJECT_RESOLUTION_LINES="$(count_lines '^\[Information - RealTimeApplicationConfigurationBuilder\.cpp:[0-9]+\]: Resolving GAMTimer[[:space:]]*$' "$RUN_LOG")" SENTINEL_OBJECT_RESOLUTION_LINES="$(count_lines '^\[Information - RealTimeApplicationConfigurationBuilder\.cpp:[0-9]+\]: Resolving SentinelProducer[[:space:]]*$' "$RUN_LOG")" GAMDISPLAY_OBJECT_RESOLUTION_LINES="$(count_lines '^\[Information - RealTimeApplicationConfigurationBuilder\.cpp:[0-9]+\]: Resolving GAMDisplay[[:space:]]*$' "$RUN_LOG")" IOGAM_OBJECT_RESOLUTION_LINES="$(count_lines '^\[Information - RealTimeApplicationConfigurationBuilder\.cpp:[0-9]+\]: Resolving IOGAM_Writer[[:space:]]*$' "$RUN_LOG")" case "$MODE" in MINIMAL) if [ "$GAMTIMER_RUNTIME_LINES" -eq 1 ] && [ "$SENTINEL_RUNTIME_LINES" -eq 1 ] && [ "$GAMDISPLAY_IDX2_LINES" -eq 0 ] && [ "$IOGAM_IDX2_LINES" -eq 1 ] && [ "$IOGAM_IDX3_LINES" -eq 0 ] && [ "$GAMTIMER_OBJECT_RESOLUTION_LINES" -eq 1 ] && [ "$SENTINEL_OBJECT_RESOLUTION_LINES" -eq 1 ] && [ "$GAMDISPLAY_OBJECT_RESOLUTION_LINES" -eq 0 ] && [ "$IOGAM_OBJECT_RESOLUTION_LINES" -eq 1 ] && [ "$FUNCTION_RESOLUTION_LINES" -eq 3 ]; then PROFILE_RUNTIME_STATUS="PASS" else PROFILE_RUNTIME_STATUS="FAIL" fi ;; TEST|DIAGNOSTIC) if [ "$GAMTIMER_RUNTIME_LINES" -eq 1 ] && [ "$SENTINEL_RUNTIME_LINES" -eq 1 ] && [ "$GAMDISPLAY_IDX2_LINES" -eq 1 ] && [ "$IOGAM_IDX2_LINES" -eq 0 ] && [ "$IOGAM_IDX3_LINES" -eq 1 ] && [ "$GAMTIMER_OBJECT_RESOLUTION_LINES" -eq 1 ] && [ "$SENTINEL_OBJECT_RESOLUTION_LINES" -eq 1 ] && [ "$GAMDISPLAY_OBJECT_RESOLUTION_LINES" -eq 1 ] && [ "$IOGAM_OBJECT_RESOLUTION_LINES" -eq 1 ] && [ "$FUNCTION_RESOLUTION_LINES" -eq 4 ]; then PROFILE_RUNTIME_STATUS="PASS" else PROFILE_RUNTIME_STATUS="FAIL" fi ;; esac PYTHONHASHSEED=0 python3 "$PARSER" "$OUTPUT_FILE" --min-samples "$MINIMUM_SAMPLES" \ >"$BINARY_REPORT" 2>&1 PARSER_RC=$? sha256sum -c --strict "$RUN_HASHES" >"$HASH_REPORT" 2>&1 HASH_RC=$? FUNCTIONAL_BINARY_STATUS="$(report_value_exact FUNCTIONAL_BINARY_STATUS "$BINARY_REPORT" || printf FAIL)" SEMANTIC_BINARY_STATUS="$(report_value_exact SEMANTIC_BINARY_STATUS "$BINARY_REPORT" || printf FAIL)" BINARY_STATUS="$(report_value_exact BINARY_STATUS "$BINARY_REPORT" || printf FAIL)" PARSER_PAYLOAD_ALIGNMENT_STATUS="$(report_value_exact PAYLOAD_ALIGNMENT_STATUS "$BINARY_REPORT" || printf FAIL)" COMPLETE_SAMPLE_COUNT="$(report_value_exact COMPLETE_SAMPLE_COUNT "$BINARY_REPORT" || printf NOT_DEMONSTRATED)" COMPLETE_SAMPLE_COUNT_STATUS="FAIL" case "$COMPLETE_SAMPLE_COUNT" in ''|*[!0-9]*) ;; *) if [ "$PARSER_RC" -eq 0 ] && [ "$FUNCTIONAL_BINARY_STATUS" = "PASS" ] && [ "$SEMANTIC_BINARY_STATUS" = "PASS" ] && [ "$BINARY_STATUS" = "PASS" ] && [ "$PARSER_PAYLOAD_ALIGNMENT_STATUS" = "PASS" ]; then COMPLETE_SAMPLE_COUNT_STATUS="PASS" fi ;; esac LOGGER_SIGNAL_LINES="$(count_lines '^\[Information - LoggerBroker\.cpp:[0-9]+\]: (Counter|Time|State1_Thread1_CycleTime|SentinelScalarA|SentinelScalarB|SentinelVector) \[[0-9]+:[0-9]+\]:' "$RUN_LOG")" LOGGER_COUNTER_LINES="$(count_lines '^\[Information - LoggerBroker\.cpp:[0-9]+\]: Counter \[0:0\]:' "$RUN_LOG")" LOGGER_TIME_LINES="$(count_lines '^\[Information - LoggerBroker\.cpp:[0-9]+\]: Time \[0:0\]:' "$RUN_LOG")" LOGGER_CYCLE_TIME_LINES="$(count_lines '^\[Information - LoggerBroker\.cpp:[0-9]+\]: State1_Thread1_CycleTime \[0:0\]:' "$RUN_LOG")" LOGGER_SCALAR_A_LINES="$(count_lines '^\[Information - LoggerBroker\.cpp:[0-9]+\]: SentinelScalarA \[0:0\]:' "$RUN_LOG")" LOGGER_SCALAR_B_LINES="$(count_lines '^\[Information - LoggerBroker\.cpp:[0-9]+\]: SentinelScalarB \[0:0\]:' "$RUN_LOG")" LOGGER_VECTOR_LINES="$(count_lines '^\[Information - LoggerBroker\.cpp:[0-9]+\]: SentinelVector \[0:2\]:' "$RUN_LOG")" if [ "$COMPLETE_SAMPLE_COUNT_STATUS" != "PASS" ]; then OBSERVABILITY_STATUS="NOT_DEMONSTRATED" OBSERVABILITY_REASON="COMPLETE_SAMPLE_COUNT_NOT_AUTHORITATIVE" elif [ "$MODE" = "MINIMAL" ] || [ "$MODE" = "TEST" ]; then if [ "$LOGGER_SIGNAL_LINES" -eq 0 ] && [ "$LOGGER_COUNTER_LINES" -eq 0 ] && [ "$LOGGER_TIME_LINES" -eq 0 ] && [ "$LOGGER_CYCLE_TIME_LINES" -eq 0 ] && [ "$LOGGER_SCALAR_A_LINES" -eq 0 ] && [ "$LOGGER_SCALAR_B_LINES" -eq 0 ] && [ "$LOGGER_VECTOR_LINES" -eq 0 ]; then OBSERVABILITY_STATUS="PASS" OBSERVABILITY_REASON="NONE" else OBSERVABILITY_STATUS="FAIL" OBSERVABILITY_REASON="UNEXPECTED_LOGGER_SIGNAL_LINES" fi else if [ "$LOGGER_COUNTER_LINES" -eq "$COMPLETE_SAMPLE_COUNT" ] && [ "$LOGGER_TIME_LINES" -eq "$COMPLETE_SAMPLE_COUNT" ] && [ "$LOGGER_CYCLE_TIME_LINES" -eq "$COMPLETE_SAMPLE_COUNT" ] && [ "$LOGGER_SCALAR_A_LINES" -eq "$COMPLETE_SAMPLE_COUNT" ] && [ "$LOGGER_SCALAR_B_LINES" -eq "$COMPLETE_SAMPLE_COUNT" ] && [ "$LOGGER_VECTOR_LINES" -eq "$COMPLETE_SAMPLE_COUNT" ] && [ "$LOGGER_SIGNAL_LINES" -eq $((6 * COMPLETE_SAMPLE_COUNT)) ]; then OBSERVABILITY_STATUS="PASS" OBSERVABILITY_REASON="NONE" elif [ "$LOGGER_COUNTER_LINES" -eq "$LOGGER_TIME_LINES" ] && [ "$LOGGER_COUNTER_LINES" -eq "$LOGGER_CYCLE_TIME_LINES" ] && [ "$LOGGER_COUNTER_LINES" -eq "$LOGGER_SCALAR_A_LINES" ] && [ "$LOGGER_COUNTER_LINES" -eq "$LOGGER_SCALAR_B_LINES" ] && [ "$LOGGER_COUNTER_LINES" -eq "$LOGGER_VECTOR_LINES" ]; then OBSERVABILITY_STATUS="NOT_DEMONSTRATED" OBSERVABILITY_REASON="SHUTDOWN_SKEW" else OBSERVABILITY_STATUS="FAIL" OBSERVABILITY_REASON="LOGGER_BINARY_COUNT_MISMATCH" fi fi START_LINES="$(count_lines '^\[Information - RealTimeLoader\.cpp:[0-9]+\]: Started application in state State1[[:space:]]*$' "$RUN_LOG")" APPLICATION_START_LINES="$(count_lines '^\[Information - MARTeApp\.cpp:[0-9]+\]: Application starting[[:space:]]*$' "$RUN_LOG")" FILE_OPEN_LINES="$(count_lines '^\[Information - FileWriter\.cpp:[0-9]+\]: Going to open file with name ' "$RUN_LOG")" SIGINT_LINES="$(count_lines '^\[Information - Bootstrap\.cpp:[0-9]+\]: Application recieved SIGINT\.[[:space:]]*$' "$RUN_LOG")" STOP_OK_LINES="$(count_lines '^\[Information - Bootstrap\.cpp:[0-9]+\]: Application successfully stopped\.[[:space:]]*$' "$RUN_LOG")" TERMINATED_LINES="$(count_lines '^\[NoError - MARTeApp\.cpp:[0-9]+\]: Application terminated[[:space:]]*$' "$RUN_LOG")" STARTUP_ERROR_LINES="$(count_lines 'Failed dlopen|Failed CreateByName|Failed to Initialise object|Failed to initialise the ObjectRegistryDatabase|Could not Initialise the loader' "$RUN_LOG")" FATAL_ERROR_LINES="$(count_lines '^\[FatalError ' "$RUN_LOG")" OS_ERROR_LINES="$(count_lines '^\[OSError ' "$RUN_LOG")" ERROR_LINES="$(count_lines '^\[Error ' "$RUN_LOG")" INITIALISATION_ERROR_LINES="$(count_lines '^\[InitialisationEr ' "$RUN_LOG")" PRIORITY_FAIL_LINES="$(count_lines '^\[Warning - Threads\.cpp:[0-9]+\]: Failed to change the thread priority' "$RUN_LOG")" DOUBLE_STOP_LINES="$(count_lines '^\[FatalError - RealTimeApplication\.cpp:[0-9]+\]: Could not stop the RealTimeApplication\. Was it ever started\?[[:space:]]*$' "$RUN_LOG")" ASYNC_CLOSE_LINES="$(count_lines '^\[FatalError - MemoryMapAsyncOutputBroker\.cpp:[0-9]+\]: Could not Close the EventSem\.[[:space:]]*$' "$RUN_LOG")" MUTEX_DESTROY_LINES="$(count_lines '^\[OSError - EventSem\.cpp:[0-9]+\]: Error: pthread_mutex_destroy\(\)[[:space:]]*$' "$RUN_LOG")" UNCLASSIFIED_FATAL_LINES=$((FATAL_ERROR_LINES - DOUBLE_STOP_LINES - ASYNC_CLOSE_LINES)) UNCLASSIFIED_OS_ERROR_LINES=$((OS_ERROR_LINES - MUTEX_DESTROY_LINES)) [ "$UNCLASSIFIED_FATAL_LINES" -ge 0 ] || UNCLASSIFIED_FATAL_LINES=0 [ "$UNCLASSIFIED_OS_ERROR_LINES" -ge 0 ] || UNCLASSIFIED_OS_ERROR_LINES=0 MARTE_EXIT_CODE="$(sed -n 's/^Exit code MARTe:[[:space:]]*//p' "$RUNNER_SUMMARY" | tail -n 1)" TEE_EXIT_CODE="$(sed -n 's/^Exit code tee:[[:space:]]*//p' "$RUNNER_SUMMARY" | tail -n 1)" [ -n "$MARTE_EXIT_CODE" ] || MARTE_EXIT_CODE="NOT_AVAILABLE" [ -n "$TEE_EXIT_CODE" ] || TEE_EXIT_CODE="NOT_AVAILABLE" case "$MARTE_EXIT_CODE" in 137) TIMING_STATUS="NOT_VALID_EXIT_137_SIGKILL" ;; *) if [ "$PRIORITY_FAIL_LINES" -ge 1 ]; then TIMING_STATUS="NOT_VALID_PRIORITY_NOT_APPLIED" else TIMING_STATUS="UNASSESSED_DT_SEMANTICS" fi ;; esac if [ "$MODE_STATUS" = "PASS" ] && [ "$PROFILE_CONFIG_STATUS" = "PASS" ] && [ "$PROFILE_RUNTIME_STATUS" = "PASS" ] && [ "$OBSERVABILITY_STATUS" = "PASS" ] && [ "$FUNCTIONAL_BINARY_STATUS" = "PASS" ] && [ "$START_LINES" -eq 1 ] && [ "$APPLICATION_START_LINES" -eq 1 ] && [ "$FILE_OPEN_LINES" -eq 1 ] && [ "$STARTUP_ERROR_LINES" -eq 0 ] && [ "$HASH_RC" -eq 0 ] && [ "$TEE_EXIT_CODE" = "0" ] && [ "$UNCLASSIFIED_FATAL_LINES" -eq 0 ] && [ "$UNCLASSIFIED_OS_ERROR_LINES" -eq 0 ] && [ "$ERROR_LINES" -eq 0 ] && [ "$INITIALISATION_ERROR_LINES" -eq 0 ]; then FUNCTIONAL_STATUS="PASS" else FUNCTIONAL_STATUS="NOT_DEMONSTRATED" fi if [ "$MODE_STATUS" = "PASS" ] && [ "$PROFILE_CONFIG_STATUS" = "PASS" ] && [ "$SEMANTIC_BINARY_STATUS" = "PASS" ]; then SEMANTIC_STATUS="PASS" elif [ "$SEMANTIC_BINARY_STATUS" = "FAIL" ]; then SEMANTIC_STATUS="FAIL" else SEMANTIC_STATUS="NOT_DEMONSTRATED" fi printf '============================================================\n' printf 'VALIDAZIONE S03-H3 - MINIMAL / TEST / DIAGNOSTIC\n' printf '============================================================\n' printf 'Run directory: %s\n' "$RUN_DIR" printf 'CANONICAL_STRUCTURAL_COMPLETENESS_STATUS=%s\n' "$CANONICAL_STRUCTURAL_COMPLETENESS_STATUS" printf 'MINIMAL_RUNTIME_CONFIG_STATUS=%s\n' "$MINIMAL_RUNTIME_CONFIG_STATUS" printf 'FUNCTION_RESOLUTION_LINES=%s\n' "$FUNCTION_RESOLUTION_LINES" printf 'LOGGER_SIGNAL_LINES=%s\n' "$LOGGER_SIGNAL_LINES" printf 'LOGGER_COUNTER_LINES=%s\n' "$LOGGER_COUNTER_LINES" printf 'LOGGER_TIME_LINES=%s\n' "$LOGGER_TIME_LINES" printf 'LOGGER_CYCLE_TIME_LINES=%s\n' "$LOGGER_CYCLE_TIME_LINES" printf 'LOGGER_SCALAR_A_LINES=%s\n' "$LOGGER_SCALAR_A_LINES" printf 'LOGGER_SCALAR_B_LINES=%s\n' "$LOGGER_SCALAR_B_LINES" printf 'LOGGER_VECTOR_LINES=%s\n' "$LOGGER_VECTOR_LINES" printf 'PARSER_RC=%s\n' "$PARSER_RC" printf 'HASH_VERIFICATION_STATUS=%s\n' "$( [ "$HASH_RC" -eq 0 ] && printf PASS || printf FAIL )" printf '\n--- CONFIGURATION VERIFIER DETAIL ---\n' if [ "$MODE" = "MINIMAL" ]; then sed 's/^/MINIMAL_CANONICAL_VERIFIER_/' "$CONFIG_REPORT" sed 's/^/MINIMAL_RUNTIME_VERIFIER_/' "$RUNTIME_CONFIG_REPORT" else cat -- "$CONFIG_REPORT" fi printf '\n--- BINARY PARSER DETAIL ---\n' sed 's/^/BINARY_PARSER_/' "$BINARY_REPORT" printf '\n--- HASH DETAIL ---\n' cat -- "$HASH_REPORT" printf '\n--- CONTRATTO S03-H3 ---\n' emit_contract if [ "$FUNCTIONAL_STATUS" != "PASS" ] || [ "$SEMANTIC_STATUS" != "PASS" ]; then printf 'VALIDATION_RESULT=FUNCTIONAL_OR_SEMANTIC_NOT_DEMONSTRATED\n' exit 20 fi if [ "$SIGINT_LINES" -ge 1 ] && [ "$STOP_OK_LINES" -ge 1 ] && [ "$TERMINATED_LINES" -ge 1 ] && [ "$FATAL_ERROR_LINES" -eq 0 ] && [ "$OS_ERROR_LINES" -eq 0 ] && [ "$ERROR_LINES" -eq 0 ] && [ "$INITIALISATION_ERROR_LINES" -eq 0 ]; then printf 'VALIDATION_RESULT=PASS_CLEAN_SHUTDOWN\n' exit 0 fi KNOWN_SHUTDOWN_TOTAL=$((DOUBLE_STOP_LINES + ASYNC_CLOSE_LINES + MUTEX_DESTROY_LINES)) if [ "$SIGINT_LINES" -ge 1 ] && [ "$STOP_OK_LINES" -ge 1 ] && [ "$TERMINATED_LINES" -ge 1 ] && [ "$KNOWN_SHUTDOWN_TOTAL" -ge 1 ] && [ "$UNCLASSIFIED_FATAL_LINES" -eq 0 ] && [ "$UNCLASSIFIED_OS_ERROR_LINES" -eq 0 ] && [ "$ERROR_LINES" -eq 0 ] && [ "$INITIALISATION_ERROR_LINES" -eq 0 ]; then printf 'VALIDATION_RESULT=PASS_KNOWN_SHUTDOWN_ANOMALY\n' exit 10 fi printf 'VALIDATION_RESULT=PASS_UNCLASSIFIED_SHUTDOWN_ANOMALY\n' exit 11