Skip to content

Commit a9e9094

Browse files
bin/verify-exercises-in-docker script
1 parent e9c7122 commit a9e9094

1 file changed

Lines changed: 102 additions & 0 deletions

File tree

bin/verify-exercises-in-docker

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env bash
2+
3+
# Synopsis:
4+
# Verify that each exercise's example/exemplar solution passes the tests
5+
# using the track's test runner Docker image.
6+
# You can either verify all exercises or a single exercise.
7+
8+
# Example: verify all exercises in Docker
9+
# bin/verify-exercises-in-docker
10+
11+
# Example: verify single exercise in Docker
12+
# bin/verify-exercises-in-docker two-fer
13+
14+
set -eo pipefail
15+
16+
die() { echo "$*" >&2; exit 1; }
17+
18+
required_tool() {
19+
command -v "${1}" >/dev/null 2>&1 ||
20+
die "${1} is required but not installed. Please install it and make sure it's in your PATH."
21+
}
22+
23+
required_tool docker
24+
25+
copy_example_or_examplar_to_solution() {
26+
jq -c '[.files.solution, .files.exemplar // .files.example] | transpose | map({src: .[1], dst: .[0]}) | .[]' .meta/config.json \
27+
| while read -r src_and_dst; do
28+
cp "$(jq -r '.src' <<< "${src_and_dst}")" "$(jq -r '.dst' <<< "${src_and_dst}")"
29+
done
30+
}
31+
32+
pull_docker_image() {
33+
docker pull "${image}" ||
34+
die $'Could not find the `'"${image}"$'` Docker image.\nCheck the test runner docs at https://exercism.org/docs/building/tooling/test-runners for more information.'
35+
}
36+
37+
run_tests() {
38+
local slug
39+
slug="${1}"
40+
41+
docker run \
42+
--rm \
43+
--network none \
44+
--read-only \
45+
--mount type=bind,src="${PWD}",dst=/solution \
46+
--mount type=bind,src="${PWD}",dst=/output \
47+
--tmpfs /tmp:exec \
48+
"${image}" "${slug}" /solution /output
49+
jq -e '.status == "pass"' "${PWD}/results.json" >/dev/null 2>&1
50+
}
51+
52+
verify_exercise() {
53+
local dir
54+
local slug
55+
local tmp_dir
56+
dir=$(realpath "${1}")
57+
slug=$(basename "${dir}")
58+
tmp_dir=$(mktemp -d -t "exercism-verify-${slug}-XXXXX")
59+
60+
echo "Verifying ${slug} exercise..."
61+
62+
(
63+
trap 'rm -rf "$tmp_dir"' EXIT # remove tempdir when subshell ends
64+
cp -r "${dir}/." "${tmp_dir}"
65+
cd "${tmp_dir}"
66+
67+
copy_example_or_examplar_to_solution
68+
run_tests "${slug}" || { cat "${PWD}/results.json"; exit 1; }
69+
)
70+
}
71+
72+
verify_exercises() {
73+
local exercise_slug
74+
exercise_slug="${1}"
75+
76+
shopt -s nullglob
77+
count=0
78+
for exercise_dir in ./exercises/{concept,practice}/${exercise_slug}/; do
79+
if [[ -d "${exercise_dir}" ]]; then
80+
verify_exercise "${exercise_dir}"
81+
((++count))
82+
fi
83+
done
84+
((count > 0)) || die 'no matching exercises found!'
85+
}
86+
87+
image=''
88+
while getopts :i: opt; do
89+
case $opt in
90+
i) image=$OPTARG ;;
91+
?) echo >&2 "Unknown option: -$OPTARG"; exit 1 ;;
92+
esac
93+
done
94+
shift "$((OPTIND - 1))"
95+
96+
if [[ -z "${image}" ]]; then
97+
image="exercism/vlang-test-runner"
98+
pull_docker_image
99+
fi
100+
101+
exercise_slug="${1:-*}"
102+
verify_exercises "${exercise_slug}"

0 commit comments

Comments
 (0)