#!/usr/bin/env bash # 0009 — the mutation check. # # Copies your crate to a temp dir, plants ONE deliberate bug in the copy, and # runs YOUR tests against it. Your own files are never touched. # # killed = your tests noticed the bug. Good. # SURVIVED = the bug is invisible to your suite. Write the missing test. # SKIP = the pattern is not in your source, so nothing was planted. # # Usage: bash 0009-mutants.sh ~/learn-rust/tasks set -u crate=$(cd "${1:-.}" && pwd) work=$(mktemp -d) export CARGO_TARGET_DIR=$work/target killed=0 survived=0 skipped=0 # name file sed expression mutants=$(cat <<'EOF' stats-order src/cli.rs s/Priority::High, Priority::Medium, Priority::Low/Priority::Low, Priority::Medium, Priority::High/ stats-zero src/cli.rs s/unwrap_or(0)/unwrap_or(1)/ clear-count src/cli.rs s/remove_completed()/remove_completed() + 1/ list-format src/task.rs s/({})"/{}"/ status-parse src/task.rs s/"in-progress" =>/"inprogress" =>/ command-case src/command.rs s/to_lowercase()/to_string()/ EOF ) echo "crate: $crate" while IFS=$'\t' read -r name file expr; do d=$(mktemp -d) cp -r "$crate/src" "$crate/tests" "$crate/Cargo.toml" "$crate/Cargo.lock" "$d/" if [ ! -f "$d/$file" ]; then printf ' SKIP %-13s %s does not exist yet\n' "$name" "$file" skipped=$((skipped + 1)) continue fi before=$(md5sum <"$d/$file") sed -i "$expr" "$d/$file" if [ "$before" = "$(md5sum <"$d/$file")" ]; then printf ' SKIP %-13s pattern not found in %s\n' "$name" "$file" skipped=$((skipped + 1)) continue fi if ! (cd "$d" && cargo build --tests -q) >/dev/null 2>&1; then printf ' SKIP %-13s mutant does not compile\n' "$name" skipped=$((skipped + 1)) continue fi if (cd "$d" && cargo test -q) >/dev/null 2>&1; then printf ' SURVIVED %-13s %s\n' "$name" "$file" survived=$((survived + 1)) else printf ' killed %-13s %s\n' "$name" "$file" killed=$((killed + 1)) fi done <<<"$mutants" printf '\n%d killed, %d survived, %d skipped\n' "$killed" "$survived" "$skipped" [ "$survived" -eq 0 ]