keiro-dsl-0.21.0.0: test/history-dependent-holes-mutation-test.sh
#!/usr/bin/env bash
# BUG-10: each invalid witness must fail the initial-hole harness by name.
set -euo pipefail
WITNESSES=keiro-dsl/test/conformance-history-dependent-holes/HistoryDependentHoles/Assignment/BehaviorHoles.hs
HARNESS=keiro-dsl/test/conformance-history-dependent-holes/Generated/HistoryDependentHoles/Assignment/Harness.hs
BACKUP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/keiro-initial-hole.XXXXXX")"
cp "$WITNESSES" "$BACKUP_DIR/BehaviorHoles.hs"
cleanup() {
cp "$BACKUP_DIR/BehaviorHoles.hs" "$WITNESSES"
rm -f "$BACKUP_DIR/BehaviorHoles.hs" "$BACKUP_DIR/mutation.log"
rmdir "$BACKUP_DIR"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
run_fixture() {
cabal test -v0 keiro-dsl-conformance-history-dependent-holes --test-show-details=direct
}
run_fixture >"$BACKUP_DIR/mutation.log" 2>&1
grep -Fq 'case step assignmentTransducer (AssignmentActive, initialAssignmentRegs) (Touch' "$HARNESS"
echo 'ok: baseline and generated-owned Touch probe'
mutate() {
python3 - "$BACKUP_DIR/BehaviorHoles.hs" "$WITNESSES" "$1" <<'PY'
from pathlib import Path
import sys
source, target, mutation = sys.argv[1:]
text = Path(source).read_text()
live = 'behavior-v1-fe7277b756f0ff4b'
replay = 'behavior-v1-afe574346545beaa'
set_key = 'behavior-v1-73b7455c36956c2b'
line = next(row for row in text.splitlines(keepends=True) if live in row)
if mutation == 'missing':
text = text.replace(line, '')
elif mutation == 'duplicate':
text = text.replace(line, line + line)
elif mutation == 'pending':
text = text.replace(line, ' , Pending (BehaviorKey "' + live + '")\n')
elif mutation == 'stale':
text = text.replace(live, live[:-1] + 'c')
elif mutation in ('replay sibling', 'wrong edge'):
other = replay if mutation == 'replay sibling' else set_key
text = text.replace(live, 'fe7277b756f0ff4b-KEY').replace(other, live).replace('fe7277b756f0ff4b-KEY', other)
elif mutation == 'inadequate history':
text = text.replace(line, line.replace('[PropertySet (PropertySetData "colour" "blue")]', '[]'))
elif mutation == 'lying emissions':
text = text.replace(line, line.replace('PropertyClearedData "colour"', 'PropertyClearedData "other"'))
else:
raise ValueError(mutation)
assert text != Path(source).read_text(), mutation
Path(target).write_text(text)
PY
}
expect_red() {
local mutation="$1" row="$2" diagnostic="${3:-}"
mutate "$mutation"
local status=0
run_fixture >"$BACKUP_DIR/mutation.log" 2>&1 || status=$?
if [[ "$status" == 0 ]] ||
! grep -Fq 'FAIL accepts ClearProperty from AssignmentActive' "$BACKUP_DIR/mutation.log" ||
! grep -Fq "FAIL forward/replay equality: ClearProperty from AssignmentActive -- hole witness $row" "$BACKUP_DIR/mutation.log" ||
{ [[ -n "$diagnostic" ]] && ! grep -Fq "$diagnostic" "$BACKUP_DIR/mutation.log"; }; then
cat "$BACKUP_DIR/mutation.log"
echo "FAIL: $mutation did not fail through the expected harness rows ($row, $diagnostic)"
exit 1
fi
cp "$BACKUP_DIR/BehaviorHoles.hs" "$WITNESSES"
echo "ok: $mutation -> hole witness $row ${diagnostic}"
}
expect_red missing filled
expect_red duplicate filled
expect_red pending filled
expect_red stale filled 'stale: 1'
expect_red 'replay sibling' verified '[witness-kind]'
expect_red 'inadequate history' verified '[unexpected-rejection]'
expect_red 'lying emissions' verified '[event-value-mismatch]'
expect_red 'wrong edge' verified '[command-mismatch]'
run_fixture >"$BACKUP_DIR/mutation.log" 2>&1
git diff --check
echo 'PASS: all eight initial-hole mutations failed by name; witnesses restored'