Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ LABEL org.opencontainers.image.description="01 Edu - Rust Test Image"
LABEL org.opencontainers.image.licenses=MIT

COPY entrypoint.sh ./
COPY isolate.sh ./

ENTRYPOINT ["/app/entrypoint.sh"]
3 changes: 2 additions & 1 deletion entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ CODE_EDITOR_RUN_ONLY="${CODE_EDITOR_RUN_ONLY:-$EXAM_RUN_ONLY}"
CODE_EDITOR_MODE="${CODE_EDITOR_MODE:-$EXAM_MODE}"

cp -a /app/tests .
cp -a /app/isolate.sh .
cp -a student solutions

if test "$CODE_EDITOR_MODE"; then
Expand All @@ -33,5 +34,5 @@ fi
if test "$CODE_EDITOR_RUN_ONLY"; then
cargo run --manifest-path "solutions/$EXERCISE/Cargo.toml" -- "$@"
else
cargo test --manifest-path "tests/${EXERCISE}_test/Cargo.toml"
cargo --config 'target."cfg(all())".runner="./isolate.sh"' test --manifest-path "tests/${EXERCISE}_test/Cargo.toml"
fi
73 changes: 73 additions & 0 deletions isolate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
# Use:
# cargo --config 'target."cfg(all())".runner="./isolate.sh"' test [args]

set -u

bin="${1:-}"; shift || true
[[ -n "${bin:-}" ]] || { echo "[wrapper] missing test binary" >&2; exit 2; }

# Strip Cargo-only flags that confuse the test binary (e.g., --message-format)
filter_args() {
local -a out=(); local skip=0
for a in "$@"; do
if [[ $skip -eq 1 ]]; then skip=0; continue; fi
case "$a" in
--message-format|--format) skip=1 ;; # drop the next token
--message-format=*|--format=*) ;; # drop inline forms
*) out+=("$a") ;;
esac
done
printf '%s\n' "${out[@]}"
}
mapfile -t filtered < <(filter_args "$@")

tmpdir="$(mktemp -d -t strictwrap.XXXXXX)"; trap 'rm -rf "$tmpdir"' EXIT
expected="$tmpdir/expected.txt"
actual="$tmpdir/actual.txt"
logfile="$tmpdir/run.out"

# 1) Ask the harness which tests it *will* run (respects filters in "$@")
if ! "$bin" --list "${filtered[@]}" >"$tmpdir/list.txt" 2>/dev/null; then
echo "[wrapper] unable to list tests; cannot verify harness" >&2
exit 1
fi
# Lines look like: `path::to::name: test` (sometimes with " (ignored)")
awk -F': test' '/: test/{print $1}' "$tmpdir/list.txt" | sed 's/[[:space:]]*$//' > "$expected"

# 2) Run the suite normally and capture output + real exit code
(
"$bin" "${filtered[@]}" 2>&1
echo "__RC__$?"
) | tee "$logfile" >/dev/null
rc="$(awk -F'__RC__' '/__RC__/ {v=$2} END{print v+0}' "$logfile")"

# 3) Collect tests that actually produced a result line:
# Matches lines like: `test foo::bar ... ok|ignored|FAILED`
# Normalize names by stripping the " - should panic[ with `...`]" suffix.
awk '
/^test[[:space:]][^ ]/ {
line=$0
sub(/^test[[:space:]]+/, "", line) # drop leading "test "
sub(/[[:space:]]+\.\.\..*$/, "", line) # drop " ... ok/FAILED/ignored"
# Remove should_panic annotation added to pretty output:
sub(/[[:space:]]+- should panic( with `[^`]*`)?$/, "", line)
print line
}
' "$logfile" | sed 's/[[:space:]]*$//' > "$actual"

# 4) Decide: require (a) rc==0, (b) final summary ok, (c) every expected test appeared
if [[ "$rc" -eq 0 ]] && grep -Eq '^test result: ok\.' "$logfile"; then
sort -u "$expected" -o "$expected"
sort -u "$actual" -o "$actual"
# If no tests were expected (filters matched none), that's fine too.
if comm -23 "$expected" "$actual" | read -r _; then
# there were missing tests → failure
echo "Some tests weren't ran for the exercise \`$EXERCISE\`. Perhaps the solution forcefully exits?"
exit 1
else
exit 0
fi
fi

exit 1
Loading