#!/bin/bash # Shared contract and execution helpers for maint scenario transports. # Extract one declared variable from a scenario file in a clean subshell. _scenario_var() { # bash -c 'set -eu; source "$1" || exit 9; eval "printf %s \"\${$2-}\""' \ _probe "$1" "$2" 2>/dev/null } _validate_scenario() { # -> fatal on contract violation local f="$1" base probe_err base=$(basename "$f") probe_err=$(bash -c 'set -eu; source "$1" : "${SCENARIO_DESC:?missing SCENARIO_DESC}" : "${SCENARIO_GROUP:?missing SCENARIO_GROUP}" : "${SCENARIO_PROFILES:?missing SCENARIO_PROFILES}" for p in $SCENARIO_PROFILES; do case "$p" in btrfs|zfs|any) ;; *) echo "bad profile token: $p" >&2; exit 1 ;; esac done declare -f scenario_break scenario_fix scenario_assert >/dev/null \ || { echo "missing scenario_break/fix/assert" >&2; exit 1; }' \ _probe "$f" 2>&1 >/dev/null) \ || fatal "scenario contract violation in $base: $probe_err" } run_scenario() { # local i="$1" name="${S_NAMES[$1]}" f="${S_FILES[$1]}" section "Scenario: $name — ${S_DESCS[$1]}" # shellcheck disable=SC1090 source "$f" local ok=true step "break" if ! scenario_break; then error "$name: break step failed" ok=false fi if [ "$ok" = "true" ]; then step "fix" if ! scenario_fix; then error "$name: fix step failed" ok=false fi fi if [ "$ok" = "true" ]; then step "assert" if ! scenario_assert; then error "$name: post-state assertion failed" ok=false fi fi unset -f scenario_break scenario_fix scenario_assert unset SCENARIO_DESC SCENARIO_GROUP SCENARIO_PROFILES if [ "$ok" = "true" ]; then success "PASS: $name" PASS+=("$name") else error "FAIL: $name" FAIL+=("$name") fi }