S03-H3 CLOSED baseline
This commit is contained in:
Executable
+149
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
|
||||
SUITE="/home/dariodf/Scrivania/MARTE/marte-benchmark-suite"
|
||||
|
||||
DEFAULT_SOURCE="$SUITE/configurations/generated/S00/smoke_s0_core.marte"
|
||||
DEFAULT_OUTPUT="$SUITE/configurations/generated/S01/from_patcher/smoke_s1_timing_from_s00.marte"
|
||||
|
||||
SOURCE="${1:-$DEFAULT_SOURCE}"
|
||||
OUTPUT="${2:-$DEFAULT_OUTPUT}"
|
||||
|
||||
EXPECTED_SOURCE_SHA256="49a9b48595aab88cd8fd11d1e58ace4ab11d7d0a649e9b143bdc25c8866253d5"
|
||||
EXPECTED_OUTPUT_SHA256="1513e1ca72eba56d53079ac7328908f12ddc72772456e2d75bcbacb6465d2427"
|
||||
|
||||
fail() {
|
||||
code="$1"
|
||||
shift
|
||||
printf "ERRORE: %s\n" "$*" >&2
|
||||
exit "$code"
|
||||
}
|
||||
|
||||
if [ ! -f "$SOURCE" ]; then
|
||||
fail 2 "configurazione sorgente non trovata: $SOURCE"
|
||||
fi
|
||||
|
||||
SOURCE_SHA256="$(sha256sum "$SOURCE" | awk '{print $1}')"
|
||||
|
||||
if [ "$SOURCE_SHA256" != "$EXPECTED_SOURCE_SHA256" ]; then
|
||||
fail 3 "hash della configurazione sorgente non riconosciuto: $SOURCE_SHA256"
|
||||
fi
|
||||
|
||||
if grep -q 'State1_Thread1_CycleTime' "$SOURCE"; then
|
||||
fail 4 "la configurazione sorgente contiene già il segnale S01"
|
||||
fi
|
||||
|
||||
OUTPUT_DIR="$(dirname "$OUTPUT")"
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
if [ -e "$OUTPUT" ]; then
|
||||
if [ ! -f "$OUTPUT" ]; then
|
||||
fail 5 "il percorso di output esiste ma non è un file regolare: $OUTPUT"
|
||||
fi
|
||||
|
||||
OUTPUT_SHA256="$(sha256sum "$OUTPUT" | awk '{print $1}')"
|
||||
|
||||
if [ "$OUTPUT_SHA256" = "$EXPECTED_OUTPUT_SHA256" ]; then
|
||||
printf "RISULTATO GIÀ PRESENTE E CORRETTO\n"
|
||||
printf "Output: %s\n" "$OUTPUT"
|
||||
printf "SHA-256: %s\n" "$OUTPUT_SHA256"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
fail 6 "il file di output esiste ma ha un contenuto inatteso: $OUTPUT"
|
||||
fi
|
||||
|
||||
TMP="${OUTPUT}.tmp.$$"
|
||||
|
||||
cleanup() {
|
||||
if [ -f "$TMP" ]; then
|
||||
rm -f "$TMP"
|
||||
fi
|
||||
}
|
||||
|
||||
trap cleanup EXIT HUP INT TERM
|
||||
|
||||
set +e
|
||||
awk '
|
||||
BEGIN {
|
||||
inGamDisplay = 0
|
||||
inInputSignals = 0
|
||||
inOutputSignals = 0
|
||||
inputInsertions = 0
|
||||
outputInsertions = 0
|
||||
}
|
||||
|
||||
{
|
||||
if ($0 ~ /^ \+GAMDisplay[[:space:]]*=[[:space:]]*\{[[:space:]]*$/) {
|
||||
inGamDisplay = 1
|
||||
}
|
||||
|
||||
if (inGamDisplay &&
|
||||
$0 ~ /^ InputSignals[[:space:]]*=[[:space:]]*\{[[:space:]]*$/) {
|
||||
inInputSignals = 1
|
||||
}
|
||||
|
||||
if (inGamDisplay &&
|
||||
$0 ~ /^ OutputSignals[[:space:]]*=[[:space:]]*\{[[:space:]]*$/) {
|
||||
inOutputSignals = 1
|
||||
}
|
||||
|
||||
if (inInputSignals &&
|
||||
$0 ~ /^ \}[[:space:]]*$/) {
|
||||
print " State1_Thread1_CycleTime = {"
|
||||
print " Alias = State1.Thread1_CycleTime"
|
||||
print " DataSource = Timings"
|
||||
print " Type = uint32"
|
||||
print " }"
|
||||
inputInsertions++
|
||||
inInputSignals = 0
|
||||
}
|
||||
|
||||
if (inOutputSignals &&
|
||||
$0 ~ /^ \}[[:space:]]*$/) {
|
||||
print " State1_Thread1_CycleTime = {"
|
||||
print " DataSource = Display"
|
||||
print " Type = uint32"
|
||||
print " }"
|
||||
print " } "
|
||||
outputInsertions++
|
||||
inOutputSignals = 0
|
||||
next
|
||||
}
|
||||
|
||||
print
|
||||
|
||||
if (inGamDisplay &&
|
||||
$0 ~ /^ \}[[:space:]]*$/) {
|
||||
inGamDisplay = 0
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
if (inputInsertions != 1 || outputInsertions != 1) {
|
||||
exit 42
|
||||
}
|
||||
}
|
||||
' "$SOURCE" > "$TMP"
|
||||
|
||||
AWK_RC=$?
|
||||
set -e
|
||||
|
||||
if [ "$AWK_RC" -ne 0 ]; then
|
||||
fail 7 "trasformazione non applicata in modo univoco; codice awk: $AWK_RC"
|
||||
fi
|
||||
|
||||
GENERATED_SHA256="$(sha256sum "$TMP" | awk '{print $1}')"
|
||||
|
||||
if [ "$GENERATED_SHA256" != "$EXPECTED_OUTPUT_SHA256" ]; then
|
||||
fail 8 "output generato differente dalla S01 manuale: $GENERATED_SHA256"
|
||||
fi
|
||||
|
||||
mv "$TMP" "$OUTPUT"
|
||||
trap - EXIT HUP INT TERM
|
||||
|
||||
printf "PATCH S00 -> S01 COMPLETATA\n"
|
||||
printf "Sorgente: %s\n" "$SOURCE"
|
||||
printf "Output: %s\n" "$OUTPUT"
|
||||
printf "SHA-256 sorgente: %s\n" "$SOURCE_SHA256"
|
||||
printf "SHA-256 output: %s\n" "$GENERATED_SHA256"
|
||||
Executable
+224
@@ -0,0 +1,224 @@
|
||||
#!/usr/bin/env bash
|
||||
set -u
|
||||
|
||||
SUITE="/home/dariodf/Scrivania/MARTE/marte-benchmark-suite"
|
||||
|
||||
SOURCE_CONFIG="$SUITE/configurations/generated/S01/from_patcher/smoke_s1_timing_from_s00.marte"
|
||||
OUTPUT_DIR="$SUITE/configurations/generated/S02/from_patcher"
|
||||
OUTPUT_CONFIG="$OUTPUT_DIR/smoke_s2_binary_recording_from_s01.marte"
|
||||
|
||||
EXPECTED_SOURCE_SHA256="1513e1ca72eba56d53079ac7328908f12ddc72772456e2d75bcbacb6465d2427"
|
||||
|
||||
if [ ! -f "$SOURCE_CONFIG" ]; then
|
||||
printf "SOURCE_STATUS=NOT_FOUND\n"
|
||||
printf "SOURCE_CONFIG=%s\n" "$SOURCE_CONFIG"
|
||||
exit 20
|
||||
fi
|
||||
|
||||
ACTUAL_SOURCE_SHA256="$(sha256sum -- "$SOURCE_CONFIG" | awk '{print $1}')"
|
||||
|
||||
printf "SOURCE_CONFIG=%s\n" "$SOURCE_CONFIG"
|
||||
printf "EXPECTED_SOURCE_SHA256=%s\n" "$EXPECTED_SOURCE_SHA256"
|
||||
printf "ACTUAL_SOURCE_SHA256=%s\n" "$ACTUAL_SOURCE_SHA256"
|
||||
|
||||
if [ "$ACTUAL_SOURCE_SHA256" != "$EXPECTED_SOURCE_SHA256" ]; then
|
||||
printf "SOURCE_HASH_STATUS=MISMATCH\n"
|
||||
exit 21
|
||||
fi
|
||||
|
||||
printf "SOURCE_HASH_STATUS=MATCH\n"
|
||||
|
||||
mkdir -p -- "$OUTPUT_DIR"
|
||||
|
||||
TEMP_CONFIG="$(mktemp "$OUTPUT_DIR/.s02_candidate_XXXXXX.marte")"
|
||||
|
||||
if [ -z "$TEMP_CONFIG" ]; then
|
||||
printf "TEMPORARY_FILE_STATUS=FAIL\n"
|
||||
exit 22
|
||||
fi
|
||||
|
||||
trap 'rm -f -- "$TEMP_CONFIG"' EXIT
|
||||
|
||||
python3 - "$SOURCE_CONFIG" "$TEMP_CONFIG" <<'PY'
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
source = Path(sys.argv[1])
|
||||
destination = Path(sys.argv[2])
|
||||
|
||||
text = source.read_text(encoding="utf-8")
|
||||
|
||||
for forbidden in (
|
||||
"+IOGAM_Writer =",
|
||||
"+FileWriter =",
|
||||
"__MARTE_RUN_DIR__",
|
||||
):
|
||||
if forbidden in text:
|
||||
print("SOURCE_ALREADY_CONTAINS_S02_CONTENT=" + forbidden)
|
||||
sys.exit(30)
|
||||
|
||||
writer_gam = """ +IOGAM_Writer = {
|
||||
Class = IOGAM
|
||||
InputSignals = {
|
||||
Counter = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
}
|
||||
Time = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
}
|
||||
State1_Thread1_CycleTime = {
|
||||
Alias = State1.Thread1_CycleTime
|
||||
DataSource = Timings
|
||||
Type = uint32
|
||||
}
|
||||
}
|
||||
OutputSignals = {
|
||||
Counter = {
|
||||
DataSource = FileWriter
|
||||
Type = uint32
|
||||
}
|
||||
Time = {
|
||||
DataSource = FileWriter
|
||||
Type = uint32
|
||||
}
|
||||
State1_Thread1_CycleTime = {
|
||||
DataSource = FileWriter
|
||||
Type = uint32
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
file_writer = """ +FileWriter = {
|
||||
Class = FileDataSource::FileWriter
|
||||
NumberOfBuffers = 100
|
||||
CPUMask = 0x1
|
||||
StackSize = 10000000
|
||||
Filename = "__MARTE_RUN_DIR__/s02_output.bin"
|
||||
Overwrite = "yes"
|
||||
FileFormat = "binary"
|
||||
StoreOnTrigger = 0
|
||||
RefreshContent = 0
|
||||
Signals = {
|
||||
Counter = {
|
||||
Type = uint32
|
||||
}
|
||||
Time = {
|
||||
Type = uint32
|
||||
}
|
||||
State1_Thread1_CycleTime = {
|
||||
Type = uint32
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
patched, functions_count = re.subn(
|
||||
r"(?m)^ }\n \+Data = \{\n",
|
||||
writer_gam + " }\n +Data = {\n",
|
||||
text,
|
||||
count=1,
|
||||
)
|
||||
|
||||
patched, data_count = re.subn(
|
||||
r"(?m)^ }\n \+States = \{\n",
|
||||
file_writer + " }\n +States = {\n",
|
||||
patched,
|
||||
count=1,
|
||||
)
|
||||
|
||||
patched, thread_count = re.subn(
|
||||
r"Functions = \{GAMTimer GAMDisplay\}",
|
||||
"Functions = {GAMTimer GAMDisplay IOGAM_Writer}",
|
||||
patched,
|
||||
count=1,
|
||||
)
|
||||
|
||||
print("FUNCTIONS_TRANSFORM_COUNT=" + str(functions_count))
|
||||
print("DATA_TRANSFORM_COUNT=" + str(data_count))
|
||||
print("THREAD_TRANSFORM_COUNT=" + str(thread_count))
|
||||
|
||||
if (functions_count, data_count, thread_count) != (1, 1, 1):
|
||||
print("TRANSFORM_STATUS=FAIL")
|
||||
sys.exit(31)
|
||||
|
||||
checks = {
|
||||
"IOGAM_WRITER_COUNT": patched.count("+IOGAM_Writer ="),
|
||||
"FILE_WRITER_COUNT": patched.count("+FileWriter ="),
|
||||
"FILE_WRITER_CLASS_COUNT": patched.count("Class = FileDataSource::FileWriter"),
|
||||
"PLAIN_FILE_WRITER_CLASS_COUNT": patched.count("Class = FileWriter"),
|
||||
"FILEWRITER_OUTPUT_COUNT": patched.count("DataSource = FileWriter"),
|
||||
"RUN_DIR_PLACEHOLDER_COUNT": patched.count("__MARTE_RUN_DIR__"),
|
||||
"BINARY_FORMAT_COUNT": patched.count('FileFormat = "binary"'),
|
||||
"OVERWRITE_YES_COUNT": patched.count('Overwrite = "yes"'),
|
||||
"CONTINUOUS_MODE_COUNT": patched.count("StoreOnTrigger = 0"),
|
||||
}
|
||||
|
||||
for name, value in checks.items():
|
||||
print(name + "=" + str(value))
|
||||
|
||||
expected = {
|
||||
"IOGAM_WRITER_COUNT": 1,
|
||||
"FILE_WRITER_COUNT": 1,
|
||||
"FILE_WRITER_CLASS_COUNT": 1,
|
||||
"PLAIN_FILE_WRITER_CLASS_COUNT": 0,
|
||||
"FILEWRITER_OUTPUT_COUNT": 3,
|
||||
"RUN_DIR_PLACEHOLDER_COUNT": 1,
|
||||
"BINARY_FORMAT_COUNT": 1,
|
||||
"OVERWRITE_YES_COUNT": 1,
|
||||
"CONTINUOUS_MODE_COUNT": 1,
|
||||
}
|
||||
|
||||
if checks != expected:
|
||||
print("STRUCTURAL_CHECK_STATUS=FAIL")
|
||||
sys.exit(32)
|
||||
|
||||
required_thread = "Functions = {GAMTimer GAMDisplay IOGAM_Writer}"
|
||||
|
||||
if patched.count(required_thread) != 1:
|
||||
print("THREAD_FUNCTION_LIST_STATUS=FAIL")
|
||||
sys.exit(33)
|
||||
|
||||
destination.write_text(patched, encoding="utf-8")
|
||||
|
||||
print("STRUCTURAL_CHECK_STATUS=PASS")
|
||||
print("TRANSFORM_STATUS=PASS")
|
||||
PY
|
||||
|
||||
PYTHON_RC=$?
|
||||
|
||||
if [ "$PYTHON_RC" -ne 0 ]; then
|
||||
printf "PYTHON_TRANSFORM_EXIT_CODE=%s\n" "$PYTHON_RC"
|
||||
exit 23
|
||||
fi
|
||||
|
||||
if [ -f "$OUTPUT_CONFIG" ]; then
|
||||
if cmp -s -- "$TEMP_CONFIG" "$OUTPUT_CONFIG"; then
|
||||
printf "OUTPUT_STATUS=ALREADY_VALID\n"
|
||||
printf "OUTPUT_CONFIG=%s\n" "$OUTPUT_CONFIG"
|
||||
printf "OUTPUT_SHA256=%s\n" \
|
||||
"$(sha256sum -- "$OUTPUT_CONFIG" | awk '{print $1}')"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf "OUTPUT_STATUS=EXISTS_BUT_DIFFERS\n"
|
||||
printf "OUTPUT_CONFIG=%s\n" "$OUTPUT_CONFIG"
|
||||
exit 24
|
||||
fi
|
||||
|
||||
chmod 0644 "$TEMP_CONFIG"
|
||||
|
||||
if ! mv -- "$TEMP_CONFIG" "$OUTPUT_CONFIG"; then
|
||||
printf "OUTPUT_STATUS=PUBLISH_FAILED\n"
|
||||
exit 25
|
||||
fi
|
||||
|
||||
trap - EXIT
|
||||
|
||||
printf "OUTPUT_STATUS=CREATED\n"
|
||||
printf "OUTPUT_CONFIG=%s\n" "$OUTPUT_CONFIG"
|
||||
printf "OUTPUT_SHA256=%s\n" \
|
||||
"$(sha256sum -- "$OUTPUT_CONFIG" | awk '{print $1}')"
|
||||
Executable
+317
@@ -0,0 +1,317 @@
|
||||
#!/usr/bin/env bash
|
||||
set -u
|
||||
|
||||
SCRIPT_DIR="$(
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")" &&
|
||||
pwd
|
||||
)"
|
||||
SUITE="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
DEFAULT_SOURCE="$SUITE/configurations/generated/S02/from_patcher/smoke_s2_binary_recording_from_s01.marte"
|
||||
DEFAULT_OUTPUT="$SUITE/configurations/generated/S03/from_patcher/smoke_s3_semantic_sentinels_from_s02.marte"
|
||||
|
||||
SOURCE_CONFIG="${1:-$DEFAULT_SOURCE}"
|
||||
OUTPUT_CONFIG="${2:-$DEFAULT_OUTPUT}"
|
||||
|
||||
EXPECTED_SOURCE_SHA256="8ecc8ba55e46e9f6fb8f304404d4070ff4c2ea5b9c783a69113bc08b457859d1"
|
||||
EXPECTED_OUTPUT_SHA256="0f8916735ff67a9be2b167b52f147687fe131a063f410a81bfbf3bf9ff65f1e4"
|
||||
|
||||
fail() {
|
||||
code="$1"
|
||||
shift
|
||||
printf "S03_BUILD_STATUS=FAIL\n" >&2
|
||||
printf "S03_BUILD_ERROR=%s\n" "$*" >&2
|
||||
exit "$code"
|
||||
}
|
||||
|
||||
if [ ! -f "$SOURCE_CONFIG" ]; then
|
||||
fail 20 "SOURCE_NOT_FOUND:$SOURCE_CONFIG"
|
||||
fi
|
||||
|
||||
SOURCE_SHA256="$(sha256sum -- "$SOURCE_CONFIG" | awk '{print $1}')"
|
||||
|
||||
printf "SOURCE_CONFIG=%s\n" "$SOURCE_CONFIG"
|
||||
printf "EXPECTED_SOURCE_SHA256=%s\n" "$EXPECTED_SOURCE_SHA256"
|
||||
printf "ACTUAL_SOURCE_SHA256=%s\n" "$SOURCE_SHA256"
|
||||
|
||||
if [ "$SOURCE_SHA256" != "$EXPECTED_SOURCE_SHA256" ]; then
|
||||
fail 21 "SOURCE_HASH_MISMATCH:$SOURCE_SHA256"
|
||||
fi
|
||||
|
||||
OUTPUT_DIR="$(dirname "$OUTPUT_CONFIG")"
|
||||
if ! mkdir -p -- "$OUTPUT_DIR"; then
|
||||
fail 22 "OUTPUT_DIRECTORY_CREATE_FAILED:$OUTPUT_DIR"
|
||||
fi
|
||||
|
||||
if [ -e "$OUTPUT_CONFIG" ] && [ ! -f "$OUTPUT_CONFIG" ]; then
|
||||
fail 23 "OUTPUT_EXISTS_NOT_REGULAR_FILE:$OUTPUT_CONFIG"
|
||||
fi
|
||||
|
||||
TEMP_CONFIG="$(mktemp "$OUTPUT_DIR/.s03_candidate_XXXXXX.marte")" ||
|
||||
fail 24 "TEMPORARY_FILE_CREATE_FAILED:$OUTPUT_DIR"
|
||||
|
||||
cleanup() {
|
||||
rm -f -- "$TEMP_CONFIG"
|
||||
}
|
||||
trap cleanup EXIT HUP INT TERM
|
||||
|
||||
PYTHONHASHSEED=0 python3 - "$SOURCE_CONFIG" "$TEMP_CONFIG" <<'PY_S03_PATCHER'
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
source = Path(sys.argv[1])
|
||||
destination = Path(sys.argv[2])
|
||||
text = source.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def require_count(haystack, needle, expected, label):
|
||||
observed = haystack.count(needle)
|
||||
print(f"{label}_COUNT={observed}")
|
||||
if observed != expected:
|
||||
raise RuntimeError(f"{label}_COUNT_EXPECTED_{expected}_OBSERVED_{observed}")
|
||||
|
||||
|
||||
def replace_once(haystack, old, new, label):
|
||||
require_count(haystack, old, 1, label)
|
||||
return haystack.replace(old, new, 1)
|
||||
|
||||
|
||||
for forbidden in (
|
||||
"+SentinelProducer =",
|
||||
"SentinelScalarA",
|
||||
"SentinelScalarB",
|
||||
"SentinelVector",
|
||||
"s03_output.bin",
|
||||
):
|
||||
if forbidden in text:
|
||||
raise RuntimeError("SOURCE_ALREADY_CONTAINS_S03_CONTENT:" + forbidden)
|
||||
|
||||
constant_gam = """ +SentinelProducer = {
|
||||
Class = ConstantGAM
|
||||
OutputSignals = {
|
||||
SentinelScalarA = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
Default = 324508639
|
||||
}
|
||||
SentinelScalarB = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
Default = 610839776
|
||||
}
|
||||
SentinelVector = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfDimensions = 1
|
||||
NumberOfElements = 3
|
||||
Default = {16909060 286397204 555885348}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
sentinel_signals = """ SentinelScalarA = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
}
|
||||
SentinelScalarB = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
}
|
||||
SentinelVector = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfDimensions = 1
|
||||
NumberOfElements = 3
|
||||
}
|
||||
"""
|
||||
|
||||
filewriter_signals = """ SentinelScalarA = {
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
}
|
||||
SentinelScalarB = {
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
}
|
||||
SentinelVector = {
|
||||
Type = uint32
|
||||
NumberOfDimensions = 1
|
||||
NumberOfElements = 3
|
||||
}
|
||||
"""
|
||||
|
||||
text = replace_once(
|
||||
text,
|
||||
" +GAMDisplay = {\n",
|
||||
constant_gam + " +GAMDisplay = {\n",
|
||||
"SENTINEL_PRODUCER_ANCHOR",
|
||||
)
|
||||
|
||||
writer_start = text.index(" +IOGAM_Writer = {\n")
|
||||
writer_end = text.index(" }\n +Data = {\n", writer_start)
|
||||
writer = text[writer_start:writer_end]
|
||||
|
||||
writer = replace_once(
|
||||
writer,
|
||||
""" State1_Thread1_CycleTime = {
|
||||
Alias = State1.Thread1_CycleTime
|
||||
DataSource = Timings
|
||||
Type = uint32
|
||||
}
|
||||
}
|
||||
OutputSignals = {
|
||||
""",
|
||||
""" State1_Thread1_CycleTime = {
|
||||
Alias = State1.Thread1_CycleTime
|
||||
DataSource = Timings
|
||||
Type = uint32
|
||||
}
|
||||
""" + sentinel_signals + """ }
|
||||
OutputSignals = {
|
||||
""",
|
||||
"WRITER_INPUT_ANCHOR",
|
||||
)
|
||||
|
||||
writer_output_signals = sentinel_signals.replace("DataSource = DDB1", "DataSource = FileWriter")
|
||||
writer = replace_once(
|
||||
writer,
|
||||
""" State1_Thread1_CycleTime = {
|
||||
DataSource = FileWriter
|
||||
Type = uint32
|
||||
}
|
||||
}
|
||||
}
|
||||
""",
|
||||
""" State1_Thread1_CycleTime = {
|
||||
DataSource = FileWriter
|
||||
Type = uint32
|
||||
}
|
||||
""" + writer_output_signals + """ }
|
||||
}
|
||||
""",
|
||||
"WRITER_OUTPUT_ANCHOR",
|
||||
)
|
||||
|
||||
text = text[:writer_start] + writer + text[writer_end:]
|
||||
|
||||
filewriter_start = text.index(" +FileWriter = {\n")
|
||||
filewriter_end = text.index(" }\n +States = {\n", filewriter_start)
|
||||
filewriter = text[filewriter_start:filewriter_end]
|
||||
|
||||
filewriter = replace_once(
|
||||
filewriter,
|
||||
' Filename = "__MARTE_RUN_DIR__/s02_output.bin"\n',
|
||||
' Filename = "__MARTE_RUN_DIR__/s03_output.bin"\n',
|
||||
"OUTPUT_FILENAME_ANCHOR",
|
||||
)
|
||||
|
||||
filewriter = replace_once(
|
||||
filewriter,
|
||||
""" State1_Thread1_CycleTime = {
|
||||
Type = uint32
|
||||
}
|
||||
}
|
||||
}
|
||||
""",
|
||||
""" State1_Thread1_CycleTime = {
|
||||
Type = uint32
|
||||
}
|
||||
""" + filewriter_signals + """ }
|
||||
}
|
||||
""",
|
||||
"FILEWRITER_SIGNAL_ANCHOR",
|
||||
)
|
||||
|
||||
text = text[:filewriter_start] + filewriter + text[filewriter_end:]
|
||||
|
||||
text = replace_once(
|
||||
text,
|
||||
"Functions = {GAMTimer GAMDisplay IOGAM_Writer}",
|
||||
"Functions = {GAMTimer SentinelProducer GAMDisplay IOGAM_Writer}",
|
||||
"THREAD_FUNCTION_LIST_ANCHOR",
|
||||
)
|
||||
|
||||
# Canonicalise the historical trailing blank line so the generated candidate
|
||||
# is byte-stable across copies and archive extraction tools.
|
||||
text = text.rstrip("\n") + "\n"
|
||||
|
||||
checks = {
|
||||
"SENTINEL_PRODUCER": text.count("+SentinelProducer ="),
|
||||
"CONSTANT_GAM_CLASS": text.count("Class = ConstantGAM"),
|
||||
"SENTINEL_SCALAR_A_DECLARATIONS": text.count("SentinelScalarA ="),
|
||||
"SENTINEL_SCALAR_B_DECLARATIONS": text.count("SentinelScalarB ="),
|
||||
"SENTINEL_VECTOR_DECLARATIONS": text.count("SentinelVector ="),
|
||||
"VECTOR_DIMENSION_DECLARATIONS": text.count("NumberOfDimensions = 1"),
|
||||
"VECTOR_CARDINALITY_DECLARATIONS": text.count("NumberOfElements = 3"),
|
||||
"S03_OUTPUT_FILENAME": text.count("__MARTE_RUN_DIR__/s03_output.bin"),
|
||||
"S02_OUTPUT_FILENAME": text.count("s02_output.bin"),
|
||||
"RUN_DIR_PLACEHOLDER": text.count("__MARTE_RUN_DIR__"),
|
||||
"FILEWRITER_CLASS": text.count("Class = FileDataSource::FileWriter"),
|
||||
"THREAD_FUNCTION_LIST": text.count(
|
||||
"Functions = {GAMTimer SentinelProducer GAMDisplay IOGAM_Writer}"
|
||||
),
|
||||
}
|
||||
|
||||
expected = {
|
||||
"SENTINEL_PRODUCER": 1,
|
||||
"CONSTANT_GAM_CLASS": 1,
|
||||
"SENTINEL_SCALAR_A_DECLARATIONS": 4,
|
||||
"SENTINEL_SCALAR_B_DECLARATIONS": 4,
|
||||
"SENTINEL_VECTOR_DECLARATIONS": 4,
|
||||
"VECTOR_DIMENSION_DECLARATIONS": 4,
|
||||
"VECTOR_CARDINALITY_DECLARATIONS": 4,
|
||||
"S03_OUTPUT_FILENAME": 1,
|
||||
"S02_OUTPUT_FILENAME": 0,
|
||||
"RUN_DIR_PLACEHOLDER": 1,
|
||||
"FILEWRITER_CLASS": 1,
|
||||
"THREAD_FUNCTION_LIST": 1,
|
||||
}
|
||||
|
||||
for name in sorted(checks):
|
||||
print(f"{name}_COUNT={checks[name]}")
|
||||
|
||||
if checks != expected:
|
||||
raise RuntimeError(f"STRUCTURAL_CHECK_MISMATCH:{checks!r}")
|
||||
|
||||
destination.write_text(text, encoding="utf-8")
|
||||
print("TRANSFORM_STATUS=PASS")
|
||||
print("STRUCTURAL_CHECK_STATUS=PASS")
|
||||
PY_S03_PATCHER
|
||||
|
||||
PYTHON_RC=$?
|
||||
if [ "$PYTHON_RC" -ne 0 ]; then
|
||||
fail 25 "TRANSFORM_FAILED_RC_$PYTHON_RC"
|
||||
fi
|
||||
|
||||
GENERATED_SHA256="$(sha256sum -- "$TEMP_CONFIG" | awk '{print $1}')"
|
||||
printf "GENERATED_SHA256=%s\n" "$GENERATED_SHA256"
|
||||
|
||||
if [ "$GENERATED_SHA256" != "$EXPECTED_OUTPUT_SHA256" ]; then
|
||||
fail 26 "OUTPUT_HASH_MISMATCH:$GENERATED_SHA256"
|
||||
fi
|
||||
|
||||
if [ -f "$OUTPUT_CONFIG" ]; then
|
||||
if cmp -s -- "$TEMP_CONFIG" "$OUTPUT_CONFIG"; then
|
||||
printf "S03_BUILD_STATUS=ALREADY_VALID\n"
|
||||
printf "OUTPUT_CONFIG=%s\n" "$OUTPUT_CONFIG"
|
||||
printf "OUTPUT_SHA256=%s\n" "$GENERATED_SHA256"
|
||||
exit 0
|
||||
fi
|
||||
fail 27 "OUTPUT_EXISTS_BUT_DIFFERS:$OUTPUT_CONFIG"
|
||||
fi
|
||||
|
||||
chmod 0644 "$TEMP_CONFIG" || fail 28 "OUTPUT_CHMOD_FAILED:$TEMP_CONFIG"
|
||||
if ! mv -- "$TEMP_CONFIG" "$OUTPUT_CONFIG"; then
|
||||
fail 29 "ATOMIC_PUBLISH_FAILED:$OUTPUT_CONFIG"
|
||||
fi
|
||||
trap - EXIT HUP INT TERM
|
||||
|
||||
printf "S03_BUILD_STATUS=CREATED\n"
|
||||
printf "OUTPUT_CONFIG=%s\n" "$OUTPUT_CONFIG"
|
||||
printf "OUTPUT_SHA256=%s\n" "$GENERATED_SHA256"
|
||||
+458
@@ -0,0 +1,458 @@
|
||||
#!/usr/bin/env bash
|
||||
set -u
|
||||
|
||||
SCRIPT_DIR="$(
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")" &&
|
||||
pwd
|
||||
)"
|
||||
PACKAGE_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
DEFAULT_SOURCE="$PACKAGE_ROOT/baseline/smoke_s2_binary_recording_from_s01.marte"
|
||||
DEFAULT_OUTPUT_ROOT="$PACKAGE_ROOT/configurations/generated/S03H1/from_patcher"
|
||||
|
||||
EXPECTED_SOURCE_SHA256="8ecc8ba55e46e9f6fb8f304404d4070ff4c2ea5b9c783a69113bc08b457859d1"
|
||||
EXPECTED_TEST_SHA256="d037561b32760fbd0e2aec9f1eefc5efda27b1918eca4742c89092a8a2f7e92e"
|
||||
EXPECTED_DIAGNOSTIC_SHA256="cd999ff249452298d650a22c8fe5b0b03bf48c0735f4630befdec8209cbb13a3"
|
||||
|
||||
fail() {
|
||||
code="$1"
|
||||
shift
|
||||
printf "S03_H1_BUILD_STATUS=FAIL\n" >&2
|
||||
printf "S03_H1_BUILD_ERROR=%s\n" "$*" >&2
|
||||
exit "$code"
|
||||
}
|
||||
|
||||
usage() {
|
||||
printf "Uso:\n" >&2
|
||||
printf " %s TEST|DIAGNOSTIC\n" "$0" >&2
|
||||
printf " %s <source-S02> <output-config> TEST|DIAGNOSTIC\n" "$0" >&2
|
||||
}
|
||||
|
||||
case "$#" in
|
||||
1)
|
||||
SOURCE_CONFIG="$DEFAULT_SOURCE"
|
||||
MODE="$1"
|
||||
case "$MODE" in
|
||||
TEST)
|
||||
OUTPUT_CONFIG="$DEFAULT_OUTPUT_ROOT/smoke_s03h1_execution_profiles_test_from_s02.marte"
|
||||
;;
|
||||
DIAGNOSTIC)
|
||||
OUTPUT_CONFIG="$DEFAULT_OUTPUT_ROOT/smoke_s03h1_execution_profiles_diagnostic_from_s02.marte"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
fail 20 "UNKNOWN_MODE:$MODE"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
3)
|
||||
SOURCE_CONFIG="$1"
|
||||
OUTPUT_CONFIG="$2"
|
||||
MODE="$3"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
fail 20 "INVALID_ARGUMENT_COUNT:$#"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$MODE" in
|
||||
TEST)
|
||||
EXPECTED_OUTPUT_SHA256="$EXPECTED_TEST_SHA256"
|
||||
DISPLAY_CLASS="GAMDataSource"
|
||||
;;
|
||||
DIAGNOSTIC)
|
||||
EXPECTED_OUTPUT_SHA256="$EXPECTED_DIAGNOSTIC_SHA256"
|
||||
DISPLAY_CLASS="LoggerDataSource"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
fail 20 "UNKNOWN_MODE:$MODE"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ! -f "$SOURCE_CONFIG" ]; then
|
||||
fail 21 "SOURCE_NOT_FOUND:$SOURCE_CONFIG"
|
||||
fi
|
||||
|
||||
SOURCE_SHA256="$(sha256sum -- "$SOURCE_CONFIG" | awk '{print $1}')"
|
||||
printf "MODE=%s\n" "$MODE"
|
||||
printf "SOURCE_CONFIG=%s\n" "$SOURCE_CONFIG"
|
||||
printf "EXPECTED_SOURCE_SHA256=%s\n" "$EXPECTED_SOURCE_SHA256"
|
||||
printf "ACTUAL_SOURCE_SHA256=%s\n" "$SOURCE_SHA256"
|
||||
|
||||
if [ "$SOURCE_SHA256" != "$EXPECTED_SOURCE_SHA256" ]; then
|
||||
fail 22 "SOURCE_HASH_MISMATCH:$SOURCE_SHA256"
|
||||
fi
|
||||
|
||||
OUTPUT_DIR="$(dirname "$OUTPUT_CONFIG")"
|
||||
if ! mkdir -p -- "$OUTPUT_DIR"; then
|
||||
fail 23 "OUTPUT_DIRECTORY_CREATE_FAILED:$OUTPUT_DIR"
|
||||
fi
|
||||
|
||||
if [ -e "$OUTPUT_CONFIG" ] && [ ! -f "$OUTPUT_CONFIG" ]; then
|
||||
fail 24 "OUTPUT_EXISTS_NOT_REGULAR_FILE:$OUTPUT_CONFIG"
|
||||
fi
|
||||
|
||||
TEMP_CONFIG="$(mktemp "$OUTPUT_DIR/.s03h1_candidate_XXXXXX.marte")" ||
|
||||
fail 25 "TEMPORARY_FILE_CREATE_FAILED:$OUTPUT_DIR"
|
||||
|
||||
cleanup() {
|
||||
rm -f -- "$TEMP_CONFIG"
|
||||
}
|
||||
trap cleanup EXIT HUP INT TERM
|
||||
|
||||
PYTHONHASHSEED=0 python3 - \
|
||||
"$SOURCE_CONFIG" \
|
||||
"$TEMP_CONFIG" \
|
||||
"$MODE" \
|
||||
"$DISPLAY_CLASS" <<'PY_S03H1_PATCHER'
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
source = Path(sys.argv[1])
|
||||
destination = Path(sys.argv[2])
|
||||
mode = sys.argv[3]
|
||||
display_class = sys.argv[4]
|
||||
text = source.read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def require_count(haystack, needle, expected, label):
|
||||
observed = haystack.count(needle)
|
||||
print(f"{label}_COUNT={observed}")
|
||||
if observed != expected:
|
||||
raise RuntimeError(
|
||||
f"{label}_COUNT_EXPECTED_{expected}_OBSERVED_{observed}"
|
||||
)
|
||||
|
||||
|
||||
def replace_once(haystack, old, new, label):
|
||||
require_count(haystack, old, 1, label)
|
||||
return haystack.replace(old, new, 1)
|
||||
|
||||
|
||||
for forbidden in (
|
||||
"+SentinelProducer =",
|
||||
"SentinelScalarA",
|
||||
"SentinelScalarB",
|
||||
"SentinelVector",
|
||||
"s03_output.bin",
|
||||
):
|
||||
if forbidden in text:
|
||||
raise RuntimeError("SOURCE_ALREADY_CONTAINS_S03_CONTENT:" + forbidden)
|
||||
|
||||
if mode not in {"TEST", "DIAGNOSTIC"}:
|
||||
raise RuntimeError("UNKNOWN_MODE:" + mode)
|
||||
if display_class not in {"GAMDataSource", "LoggerDataSource"}:
|
||||
raise RuntimeError("UNKNOWN_DISPLAY_CLASS:" + display_class)
|
||||
|
||||
constant_gam = """ +SentinelProducer = {
|
||||
Class = ConstantGAM
|
||||
OutputSignals = {
|
||||
SentinelScalarA = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
Default = 324508639
|
||||
}
|
||||
SentinelScalarB = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
Default = 610839776
|
||||
}
|
||||
SentinelVector = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfDimensions = 1
|
||||
NumberOfElements = 3
|
||||
Default = {16909060 286397204 555885348}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
gam_display = f""" +GAMDisplay = {{
|
||||
Class = IOGAM
|
||||
InputSignals = {{
|
||||
Counter = {{
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
}}
|
||||
Time = {{
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
}}
|
||||
State1_Thread1_CycleTime = {{
|
||||
Alias = State1.Thread1_CycleTime
|
||||
DataSource = Timings
|
||||
Type = uint32
|
||||
}}
|
||||
SentinelScalarA = {{
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
}}
|
||||
SentinelScalarB = {{
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
}}
|
||||
SentinelVector = {{
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfDimensions = 1
|
||||
NumberOfElements = 3
|
||||
}}
|
||||
}}
|
||||
OutputSignals = {{
|
||||
Counter = {{
|
||||
DataSource = Display
|
||||
Type = uint32
|
||||
}}
|
||||
Time = {{
|
||||
DataSource = Display
|
||||
Type = uint32
|
||||
}}
|
||||
State1_Thread1_CycleTime = {{
|
||||
DataSource = Display
|
||||
Type = uint32
|
||||
}}
|
||||
SentinelScalarA = {{
|
||||
DataSource = Display
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
}}
|
||||
SentinelScalarB = {{
|
||||
DataSource = Display
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
}}
|
||||
SentinelVector = {{
|
||||
DataSource = Display
|
||||
Type = uint32
|
||||
NumberOfDimensions = 1
|
||||
NumberOfElements = 3
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
|
||||
sentinel_signals = """ SentinelScalarA = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
}
|
||||
SentinelScalarB = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
}
|
||||
SentinelVector = {
|
||||
DataSource = DDB1
|
||||
Type = uint32
|
||||
NumberOfDimensions = 1
|
||||
NumberOfElements = 3
|
||||
}
|
||||
"""
|
||||
|
||||
filewriter_signals = """ SentinelScalarA = {
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
}
|
||||
SentinelScalarB = {
|
||||
Type = uint32
|
||||
NumberOfElements = 1
|
||||
}
|
||||
SentinelVector = {
|
||||
Type = uint32
|
||||
NumberOfDimensions = 1
|
||||
NumberOfElements = 3
|
||||
}
|
||||
"""
|
||||
|
||||
require_count(text, " +GAMDisplay = {\n", 1, "GAMDISPLAY_START_ANCHOR")
|
||||
require_count(text, " +IOGAM_Writer = {\n", 1, "IOGAM_WRITER_START_ANCHOR")
|
||||
display_start = text.index(" +GAMDisplay = {\n")
|
||||
writer_start = text.index(" +IOGAM_Writer = {\n", display_start)
|
||||
text = text[:display_start] + constant_gam + gam_display + text[writer_start:]
|
||||
|
||||
writer_start = text.index(" +IOGAM_Writer = {\n")
|
||||
writer_end = text.index(" }\n +Data = {\n", writer_start)
|
||||
writer = text[writer_start:writer_end]
|
||||
|
||||
writer = replace_once(
|
||||
writer,
|
||||
""" State1_Thread1_CycleTime = {
|
||||
Alias = State1.Thread1_CycleTime
|
||||
DataSource = Timings
|
||||
Type = uint32
|
||||
}
|
||||
}
|
||||
OutputSignals = {
|
||||
""",
|
||||
""" State1_Thread1_CycleTime = {
|
||||
Alias = State1.Thread1_CycleTime
|
||||
DataSource = Timings
|
||||
Type = uint32
|
||||
}
|
||||
""" + sentinel_signals + """ }
|
||||
OutputSignals = {
|
||||
""",
|
||||
"WRITER_INPUT_ANCHOR",
|
||||
)
|
||||
|
||||
writer_output_signals = sentinel_signals.replace(
|
||||
"DataSource = DDB1", "DataSource = FileWriter"
|
||||
)
|
||||
writer = replace_once(
|
||||
writer,
|
||||
""" State1_Thread1_CycleTime = {
|
||||
DataSource = FileWriter
|
||||
Type = uint32
|
||||
}
|
||||
}
|
||||
}
|
||||
""",
|
||||
""" State1_Thread1_CycleTime = {
|
||||
DataSource = FileWriter
|
||||
Type = uint32
|
||||
}
|
||||
""" + writer_output_signals + """ }
|
||||
}
|
||||
""",
|
||||
"WRITER_OUTPUT_ANCHOR",
|
||||
)
|
||||
text = text[:writer_start] + writer + text[writer_end:]
|
||||
|
||||
text = replace_once(
|
||||
text,
|
||||
""" +Display = {
|
||||
Class = LoggerDataSource
|
||||
}
|
||||
""",
|
||||
f""" +Display = {{
|
||||
Class = {display_class}
|
||||
}}
|
||||
""",
|
||||
"DISPLAY_DATASOURCE_ANCHOR",
|
||||
)
|
||||
|
||||
filewriter_start = text.index(" +FileWriter = {\n")
|
||||
filewriter_end = text.index(" }\n +States = {\n", filewriter_start)
|
||||
filewriter = text[filewriter_start:filewriter_end]
|
||||
filewriter = replace_once(
|
||||
filewriter,
|
||||
' Filename = "__MARTE_RUN_DIR__/s02_output.bin"\n',
|
||||
' Filename = "__MARTE_RUN_DIR__/s03_output.bin"\n',
|
||||
"OUTPUT_FILENAME_ANCHOR",
|
||||
)
|
||||
filewriter = replace_once(
|
||||
filewriter,
|
||||
""" State1_Thread1_CycleTime = {
|
||||
Type = uint32
|
||||
}
|
||||
}
|
||||
}
|
||||
""",
|
||||
""" State1_Thread1_CycleTime = {
|
||||
Type = uint32
|
||||
}
|
||||
""" + filewriter_signals + """ }
|
||||
}
|
||||
""",
|
||||
"FILEWRITER_SIGNAL_ANCHOR",
|
||||
)
|
||||
text = text[:filewriter_start] + filewriter + text[filewriter_end:]
|
||||
|
||||
text = replace_once(
|
||||
text,
|
||||
"Functions = {GAMTimer GAMDisplay IOGAM_Writer}",
|
||||
"Functions = {GAMTimer SentinelProducer GAMDisplay IOGAM_Writer}",
|
||||
"THREAD_FUNCTION_LIST_ANCHOR",
|
||||
)
|
||||
|
||||
text = text.rstrip("\n") + "\n"
|
||||
|
||||
checks = {
|
||||
"SENTINEL_PRODUCER": text.count("+SentinelProducer ="),
|
||||
"CONSTANT_GAM_CLASS": text.count("Class = ConstantGAM"),
|
||||
"GAMDISPLAY_OBJECT": text.count("+GAMDisplay ="),
|
||||
"SENTINEL_SCALAR_A_DECLARATIONS": text.count("SentinelScalarA ="),
|
||||
"SENTINEL_SCALAR_B_DECLARATIONS": text.count("SentinelScalarB ="),
|
||||
"SENTINEL_VECTOR_DECLARATIONS": text.count("SentinelVector ="),
|
||||
"VECTOR_DIMENSION_DECLARATIONS": text.count("NumberOfDimensions = 1"),
|
||||
"VECTOR_CARDINALITY_DECLARATIONS": text.count("NumberOfElements = 3"),
|
||||
"S03_OUTPUT_FILENAME": text.count("__MARTE_RUN_DIR__/s03_output.bin"),
|
||||
"S02_OUTPUT_FILENAME": text.count("s02_output.bin"),
|
||||
"RUN_DIR_PLACEHOLDER": text.count("__MARTE_RUN_DIR__"),
|
||||
"FILEWRITER_CLASS": text.count("Class = FileDataSource::FileWriter"),
|
||||
"THREAD_FUNCTION_LIST": text.count(
|
||||
"Functions = {GAMTimer SentinelProducer GAMDisplay IOGAM_Writer}"
|
||||
),
|
||||
"DISPLAY_DATASOURCE_BLOCK": text.count(
|
||||
f" +Display = {{\n Class = {display_class}\n }}\n"
|
||||
),
|
||||
}
|
||||
expected = {
|
||||
"SENTINEL_PRODUCER": 1,
|
||||
"CONSTANT_GAM_CLASS": 1,
|
||||
"GAMDISPLAY_OBJECT": 1,
|
||||
"SENTINEL_SCALAR_A_DECLARATIONS": 6,
|
||||
"SENTINEL_SCALAR_B_DECLARATIONS": 6,
|
||||
"SENTINEL_VECTOR_DECLARATIONS": 6,
|
||||
"VECTOR_DIMENSION_DECLARATIONS": 6,
|
||||
"VECTOR_CARDINALITY_DECLARATIONS": 6,
|
||||
"S03_OUTPUT_FILENAME": 1,
|
||||
"S02_OUTPUT_FILENAME": 0,
|
||||
"RUN_DIR_PLACEHOLDER": 1,
|
||||
"FILEWRITER_CLASS": 1,
|
||||
"THREAD_FUNCTION_LIST": 1,
|
||||
"DISPLAY_DATASOURCE_BLOCK": 1,
|
||||
}
|
||||
|
||||
for name in sorted(checks):
|
||||
print(f"{name}_COUNT={checks[name]}")
|
||||
if checks != expected:
|
||||
raise RuntimeError(f"STRUCTURAL_CHECK_MISMATCH:{checks!r}")
|
||||
|
||||
destination.write_text(text, encoding="utf-8")
|
||||
print("TRANSFORM_STATUS=PASS")
|
||||
print("STRUCTURAL_CHECK_STATUS=PASS")
|
||||
PY_S03H1_PATCHER
|
||||
PYTHON_RC=$?
|
||||
|
||||
if [ "$PYTHON_RC" -ne 0 ]; then
|
||||
fail 26 "TRANSFORM_FAILED_RC_$PYTHON_RC"
|
||||
fi
|
||||
|
||||
GENERATED_SHA256="$(sha256sum -- "$TEMP_CONFIG" | awk '{print $1}')"
|
||||
printf "GENERATED_SHA256=%s\n" "$GENERATED_SHA256"
|
||||
printf "EXPECTED_OUTPUT_SHA256=%s\n" "$EXPECTED_OUTPUT_SHA256"
|
||||
|
||||
if [ "$GENERATED_SHA256" != "$EXPECTED_OUTPUT_SHA256" ]; then
|
||||
fail 27 "OUTPUT_HASH_MISMATCH:$GENERATED_SHA256"
|
||||
fi
|
||||
|
||||
if [ -f "$OUTPUT_CONFIG" ]; then
|
||||
if cmp -s -- "$TEMP_CONFIG" "$OUTPUT_CONFIG"; then
|
||||
printf "S03_H1_BUILD_STATUS=ALREADY_VALID\n"
|
||||
printf "MODE=%s\n" "$MODE"
|
||||
printf "OUTPUT_CONFIG=%s\n" "$OUTPUT_CONFIG"
|
||||
printf "OUTPUT_SHA256=%s\n" "$GENERATED_SHA256"
|
||||
exit 0
|
||||
fi
|
||||
fail 28 "OUTPUT_EXISTS_BUT_DIFFERS:$OUTPUT_CONFIG"
|
||||
fi
|
||||
|
||||
chmod 0644 "$TEMP_CONFIG" || fail 29 "OUTPUT_CHMOD_FAILED:$TEMP_CONFIG"
|
||||
if ! mv -- "$TEMP_CONFIG" "$OUTPUT_CONFIG"; then
|
||||
fail 30 "ATOMIC_PUBLISH_FAILED:$OUTPUT_CONFIG"
|
||||
fi
|
||||
trap - EXIT HUP INT TERM
|
||||
|
||||
printf "S03_H1_BUILD_STATUS=CREATED\n"
|
||||
printf "MODE=%s\n" "$MODE"
|
||||
printf "OUTPUT_CONFIG=%s\n" "$OUTPUT_CONFIG"
|
||||
printf "OUTPUT_SHA256=%s\n" "$GENERATED_SHA256"
|
||||
@@ -0,0 +1,151 @@
|
||||
#!/usr/bin/env bash
|
||||
set -u
|
||||
set -o pipefail
|
||||
|
||||
PATCHER_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
SUITE="$(cd -- "$PATCHER_DIR/../.." && pwd -P)"
|
||||
|
||||
PARENT="$SUITE/configurations/generated/S03H1/from_patcher/smoke_s03h1_execution_profiles_test_from_s02.marte"
|
||||
OUTPUT_DIR="$SUITE/configurations/generated/S03H3/from_patcher"
|
||||
OUTPUT="$OUTPUT_DIR/smoke_s03h3_execution_profiles_minimal_from_s03h1_test.marte"
|
||||
VERIFIER="$SUITE/scenarios/S03H3_execution_profiles/verify_s03h3_minimal_structure.py"
|
||||
EXPECTED_PARENT_SHA256="d037561b32760fbd0e2aec9f1eefc5efda27b1918eca4742c89092a8a2f7e92e"
|
||||
|
||||
TEMP_OUTPUT=""
|
||||
|
||||
cleanup() {
|
||||
if [ -n "$TEMP_OUTPUT" ]; then
|
||||
rm -f -- "$TEMP_OUTPUT"
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT HUP INT TERM
|
||||
|
||||
fail() {
|
||||
local code="$1"
|
||||
local reason="$2"
|
||||
printf 'PATCHER_STATUS=FAIL\n' >&2
|
||||
printf 'PATCHER_ERROR=%s\n' "$reason" >&2
|
||||
printf 'SOURCE_MODIFIED_IN_PLACE=NO\n' >&2
|
||||
exit "$code"
|
||||
}
|
||||
|
||||
if [ "$#" -ne 0 ]; then
|
||||
printf 'Uso: %s\n' "$0" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ ! -f "$PARENT" ]; then
|
||||
fail 10 "CANONICAL_TEST_PARENT_MISSING"
|
||||
fi
|
||||
if [ ! -f "$VERIFIER" ]; then
|
||||
fail 11 "MINIMAL_VERIFIER_MISSING"
|
||||
fi
|
||||
|
||||
PARENT_SHA256_BEFORE="$(sha256sum -- "$PARENT" | awk '{print $1}')" || \
|
||||
fail 12 "PARENT_HASH_UNAVAILABLE"
|
||||
if [ "$PARENT_SHA256_BEFORE" != "$EXPECTED_PARENT_SHA256" ]; then
|
||||
fail 13 "CANONICAL_TEST_PARENT_SHA256_MISMATCH"
|
||||
fi
|
||||
|
||||
if ! mkdir -p -- "$OUTPUT_DIR"; then
|
||||
fail 14 "OUTPUT_DIRECTORY_CREATION_FAILED"
|
||||
fi
|
||||
TEMP_OUTPUT="$(mktemp "$OUTPUT_DIR/.s03h3_minimal.XXXXXX")" || \
|
||||
fail 15 "TEMPORARY_OUTPUT_CREATION_FAILED"
|
||||
|
||||
if ! python3 - "$PARENT" "$TEMP_OUTPUT" <<'PY'
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
parent = Path(sys.argv[1])
|
||||
target = Path(sys.argv[2])
|
||||
text = parent.read_bytes().decode("utf-8")
|
||||
|
||||
gamdisplay_start = " +GAMDisplay = {\n"
|
||||
writer_start = " +IOGAM_Writer = {\n"
|
||||
display_block = (
|
||||
" +Display = {\n"
|
||||
" Class = GAMDataSource\n"
|
||||
" }\n"
|
||||
)
|
||||
old_functions = (
|
||||
" Functions = "
|
||||
"{GAMTimer SentinelProducer GAMDisplay IOGAM_Writer}"
|
||||
)
|
||||
new_functions = (
|
||||
" Functions = "
|
||||
"{GAMTimer SentinelProducer IOGAM_Writer}"
|
||||
)
|
||||
|
||||
checks = {
|
||||
"GAMDISPLAY_ANCHOR": text.count(gamdisplay_start),
|
||||
"WRITER_ANCHOR": text.count(writer_start),
|
||||
"DISPLAY_BLOCK": text.count(display_block),
|
||||
"FUNCTIONS_ANCHOR": text.count(old_functions),
|
||||
"MINIMAL_FUNCTIONS_PREEXISTING": text.count(new_functions),
|
||||
}
|
||||
if checks != {
|
||||
"GAMDISPLAY_ANCHOR": 1,
|
||||
"WRITER_ANCHOR": 1,
|
||||
"DISPLAY_BLOCK": 1,
|
||||
"FUNCTIONS_ANCHOR": 1,
|
||||
"MINIMAL_FUNCTIONS_PREEXISTING": 0,
|
||||
}:
|
||||
for name, value in checks.items():
|
||||
print(f"{name}_COUNT={value}", file=sys.stderr)
|
||||
raise SystemExit(20)
|
||||
|
||||
start = text.index(gamdisplay_start)
|
||||
end = text.index(writer_start, start)
|
||||
if end <= start:
|
||||
raise SystemExit(21)
|
||||
|
||||
result = text[:start] + text[end:]
|
||||
result = result.replace(display_block, "", 1)
|
||||
result = result.replace(old_functions, new_functions, 1)
|
||||
target.write_bytes(result.encode("utf-8"))
|
||||
PY
|
||||
then
|
||||
fail 16 "STRUCTURAL_TRANSFORMATION_FAILED"
|
||||
fi
|
||||
|
||||
PARENT_SHA256_AFTER="$(sha256sum -- "$PARENT" | awk '{print $1}')" || \
|
||||
fail 17 "PARENT_POST_HASH_UNAVAILABLE"
|
||||
if [ "$PARENT_SHA256_AFTER" != "$PARENT_SHA256_BEFORE" ]; then
|
||||
fail 18 "SOURCE_MODIFIED_IN_PLACE"
|
||||
fi
|
||||
|
||||
if ! python3 "$VERIFIER" CANONICAL "$PARENT" "$TEMP_OUTPUT"; then
|
||||
fail 19 "CANONICAL_STRUCTURAL_COMPLETENESS_FAILED"
|
||||
fi
|
||||
|
||||
if [ -e "$OUTPUT" ]; then
|
||||
if [ ! -f "$OUTPUT" ]; then
|
||||
fail 20 "OUTPUT_EXISTS_NOT_REGULAR_FILE"
|
||||
fi
|
||||
if ! cmp -s -- "$TEMP_OUTPUT" "$OUTPUT"; then
|
||||
fail 21 "EXISTING_OUTPUT_DIFFERS_FROM_DETERMINISTIC_RESULT"
|
||||
fi
|
||||
if ! python3 "$VERIFIER" CANONICAL "$PARENT" "$OUTPUT" >/dev/null; then
|
||||
fail 22 "EXISTING_OUTPUT_COMPLETENESS_FAILED"
|
||||
fi
|
||||
printf 'PATCHER_RESULT=ALREADY_VALID\n'
|
||||
else
|
||||
chmod 0644 -- "$TEMP_OUTPUT" || fail 23 "OUTPUT_MODE_SET_FAILED"
|
||||
mv -- "$TEMP_OUTPUT" "$OUTPUT" || fail 24 "OUTPUT_PUBLICATION_FAILED"
|
||||
TEMP_OUTPUT=""
|
||||
if ! python3 "$VERIFIER" CANONICAL "$PARENT" "$OUTPUT" >/dev/null; then
|
||||
fail 25 "PUBLISHED_OUTPUT_COMPLETENESS_FAILED"
|
||||
fi
|
||||
printf 'PATCHER_RESULT=CREATED\n'
|
||||
fi
|
||||
|
||||
OUTPUT_SHA256="$(sha256sum -- "$OUTPUT" | awk '{print $1}')" || \
|
||||
fail 26 "OUTPUT_HASH_UNAVAILABLE"
|
||||
printf 'PATCHER_STATUS=PASS\n'
|
||||
printf 'PATCHER_DETERMINISM=PASS\n'
|
||||
printf 'PATCHER_PARENT_HASH_MATCH=PASS\n'
|
||||
printf 'CANONICAL_STRUCTURAL_COMPLETENESS_STATUS=PASS\n'
|
||||
printf 'SOURCE_MODIFIED_IN_PLACE=NO\n'
|
||||
printf 'MINIMAL_CONFIG=%s\n' "$OUTPUT"
|
||||
printf 'MINIMAL_CONFIG_SHA256=%s\n' "$OUTPUT_SHA256"
|
||||
Reference in New Issue
Block a user