97 lines
3.2 KiB
Bash
Executable File
97 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
echo "usage: $0 <init|mark|check> <cases|arms> <expected-set> <state-root> <run-id> [name]" >&2
|
|
}
|
|
|
|
[[ "$#" -ge 5 ]] || { usage; exit 2; }
|
|
mode="$1"
|
|
dimension="$2"
|
|
expected_set="$3"
|
|
state_root="$4"
|
|
run_id="$5"
|
|
name="${6:-}"
|
|
|
|
[[ "$dimension" == cases || "$dimension" == arms ]] \
|
|
|| { echo "[fixture-suite] invalid coverage dimension: $dimension" >&2; exit 2; }
|
|
[[ -s "$expected_set" ]] \
|
|
|| { echo "[fixture-suite] expected set missing or empty: $expected_set" >&2; exit 2; }
|
|
[[ -n "$state_root" && "$state_root" != / ]] \
|
|
|| { echo "[fixture-suite] unsafe state root" >&2; exit 2; }
|
|
[[ "$run_id" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]] \
|
|
|| { echo "[fixture-suite] invalid run id: $run_id" >&2; exit 2; }
|
|
|
|
singular="${dimension%s}"
|
|
run_dir="$state_root/$run_id/$dimension"
|
|
|
|
expected_names() {
|
|
awk -F '\t' 'NF && $0 !~ /^[[:space:]]*#/ && !seen[$1]++ { sub(/\r$/, "", $1); print $1 }' \
|
|
"$expected_set" | LC_ALL=C sort
|
|
}
|
|
|
|
validate_expected_names() {
|
|
local found=0 expected
|
|
while IFS= read -r expected; do
|
|
[[ -n "$expected" ]] || continue
|
|
found=1
|
|
[[ "$expected" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]] \
|
|
|| { echo "[fixture-suite] invalid expected $singular name: $expected" >&2; return 1; }
|
|
done < <(expected_names)
|
|
[[ "$found" -eq 1 ]] \
|
|
|| { echo "[fixture-suite] expected set defines no $dimension" >&2; return 1; }
|
|
}
|
|
|
|
validate_expected_names
|
|
|
|
case "$mode" in
|
|
init)
|
|
[[ "$#" -eq 5 ]] || { usage; exit 2; }
|
|
mkdir -p "$run_dir"
|
|
find "$run_dir" -mindepth 1 -delete
|
|
;;
|
|
mark)
|
|
[[ "$#" -eq 6 ]] || { usage; exit 2; }
|
|
[[ "$name" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]] \
|
|
|| { echo "[fixture-suite] invalid $singular marker name: $name" >&2; exit 2; }
|
|
[[ -d "$run_dir" ]] \
|
|
|| { echo "[fixture-suite] $dimension state was not initialized: $run_id" >&2; exit 1; }
|
|
expected_names | grep -Fxq -- "$name" \
|
|
|| { echo "[fixture-suite] $singular is not in the expected set: $name" >&2; exit 1; }
|
|
: > "$run_dir/$name.ran"
|
|
;;
|
|
check)
|
|
[[ "$#" -eq 5 ]] || { usage; exit 2; }
|
|
mkdir -p "$run_dir"
|
|
expected_file="$(mktemp "$run_dir/.expected.XXXXXX")"
|
|
actual_file="$(mktemp "$run_dir/.actual.XXXXXX")"
|
|
cleanup() { rm -f "$expected_file" "$actual_file"; }
|
|
trap cleanup EXIT
|
|
|
|
expected_names > "$expected_file"
|
|
find "$run_dir" -mindepth 1 -maxdepth 1 -type f -name '*.ran' -printf '%f\n' \
|
|
| sed 's/\.ran$//' | LC_ALL=C sort -u > "$actual_file"
|
|
|
|
defined="$(wc -l < "$expected_file" | tr -d ' ')"
|
|
executed="$(wc -l < "$actual_file" | tr -d ' ')"
|
|
printf '[fixture-suite] %s_defined=%s %s_executed=%s\n' \
|
|
"$dimension" "$defined" "$dimension" "$executed"
|
|
|
|
if ! cmp -s "$expected_file" "$actual_file"; then
|
|
while IFS= read -r missing; do
|
|
[[ -n "$missing" ]] \
|
|
&& printf '[fixture-suite] missing_%s=%s\n' "$singular" "$missing" >&2
|
|
done < <(comm -23 "$expected_file" "$actual_file")
|
|
while IFS= read -r unexpected; do
|
|
[[ -n "$unexpected" ]] \
|
|
&& printf '[fixture-suite] unexpected_%s=%s\n' "$singular" "$unexpected" >&2
|
|
done < <(comm -13 "$expected_file" "$actual_file")
|
|
exit 1
|
|
fi
|
|
;;
|
|
*)
|
|
usage
|
|
exit 2
|
|
;;
|
|
esac
|