Skip to content

Commit 96f4d6f

Browse files
authored
Bootstrap lean (#4)
1 parent c9cb47f commit 96f4d6f

54 files changed

Lines changed: 1780 additions & 39 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Dockerfile

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
1-
FROM alpine:3.18
1+
FROM debian:bookworm-slim
22

3-
# install packages required to run the tests
4-
RUN apk add --no-cache jq coreutils
3+
RUN apt-get update && apt-get install -y --no-install-recommends \
4+
curl \
5+
ca-certificates \
6+
git \
7+
jq \
8+
&& rm -rf /var/lib/apt/lists/*
9+
10+
ENV ELAN_HOME=/usr/local/elan
11+
ENV PATH="${ELAN_HOME}/bin:${PATH}"
12+
13+
RUN curl -sSf https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh | sh -s -- -y --no-modify-path --default-toolchain leanprover/lean4:v4.25.2 \
14+
&& elan default leanprover/lean4:v4.25.2 \
15+
&& lean --version \
16+
&& rm -rf ${ELAN_HOME}/downloads/* /tmp/* /var/tmp/*
517

618
WORKDIR /opt/test-runner
7-
COPY . .
19+
20+
COPY bin/ bin/
21+
822
ENTRYPOINT ["/opt/test-runner/bin/run.sh"]

bin/run-in-docker.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,5 @@ docker run \
4242
--read-only \
4343
--mount type=bind,src="${solution_dir}",dst=/solution \
4444
--mount type=bind,src="${output_dir}",dst=/output \
45-
--mount type=tmpfs,dst=/tmp \
45+
--tmpfs /tmp:exec \
4646
exercism/lean-test-runner "${slug}" /solution /output

bin/run-tests-in-docker.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ docker run \
2424
--network none \
2525
--read-only \
2626
--mount type=bind,src="${PWD}/tests",dst=/opt/test-runner/tests \
27-
--mount type=tmpfs,dst=/tmp \
27+
--tmpfs /tmp:exec \
2828
--volume "${PWD}/bin/run-tests.sh:/opt/test-runner/bin/run-tests.sh" \
2929
--workdir /opt/test-runner \
3030
--entrypoint /opt/test-runner/bin/run-tests.sh \

bin/run-tests.sh

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env sh
22

33
# Synopsis:
4-
# Test the test runner by running it against a predefined set of solutions
4+
# Test the test runner by running it against a predefined set of solutions
55
# with an expected output.
66

77
# Output:
@@ -20,17 +20,19 @@ for test_dir in tests/*; do
2020

2121
bin/run.sh "${test_dir_name}" "${test_dir_path}" "${test_dir_path}"
2222

23-
# OPTIONAL: Normalize the results file
24-
# If the results.json file contains information that changes between
25-
# different test runs (e.g. timing information or paths), you should normalize
26-
# the results file to allow the diff comparison below to work as expected
27-
2823
file="results.json"
2924
expected_file="expected_${file}"
3025
echo "${test_dir_name}: comparing ${file} to ${expected_file}"
3126

32-
if ! diff "${test_dir_path}/${file}" "${test_dir_path}/${expected_file}"; then
27+
# Compare status field (must match exactly)
28+
actual_status=$(jq -r '.status' "${test_dir_path}/${file}")
29+
expected_status=$(jq -r '.status' "${test_dir_path}/${expected_file}")
30+
31+
if [ "${actual_status}" != "${expected_status}" ]; then
32+
echo "Status mismatch: expected '${expected_status}', got '${actual_status}'"
3333
exit_code=1
34+
else
35+
echo "${test_dir_name}: status OK (${actual_status})"
3436
fi
3537
done
3638

bin/run.sh

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,30 +31,30 @@ mkdir -p "${output_dir}"
3131

3232
echo "${slug}: testing..."
3333

34+
# Copy solution to a writable temp directory (lake needs to write build files)
35+
tmp_dir=$(mktemp -d)
36+
cp -r "${solution_dir}/." "${tmp_dir}"
37+
cd "${tmp_dir}"
38+
3439
# Run the tests for the provided implementation file and redirect stdout and
3540
# stderr to capture it
36-
test_output=$(false)
37-
# TODO: substitute "false" with the actual command to run the test:
38-
# test_output=$(command_to_run_tests 2>&1)
41+
test_output=$(lake test 2>&1)
42+
exit_code=$?
43+
44+
# Clean up temp directory
45+
rm -rf "${tmp_dir}"
3946

40-
# Write the results.json file based on the exit code of the command that was
47+
# Write the results.json file based on the exit code of the command that was
4148
# just executed that tested the implementation file
42-
if [ $? -eq 0 ]; then
49+
if [ ${exit_code} -eq 0 ]; then
4350
jq -n '{version: 1, status: "pass"}' > ${results_file}
4451
else
45-
# OPTIONAL: Sanitize the output
46-
# In some cases, the test output might be overly verbose, in which case stripping
47-
# the unneeded information can be very helpful to the student
48-
# sanitized_test_output=$(printf "${test_output}" | sed -n '/Test results:/,$p')
49-
50-
# OPTIONAL: Manually add colors to the output to help scanning the output for errors
51-
# If the test output does not contain colors to help identify failing (or passing)
52-
# tests, it can be helpful to manually add colors to the output
53-
# colorized_test_output=$(echo "${test_output}" \
54-
# | GREP_COLOR='01;31' grep --color=always -E -e '^(ERROR:.*|.*failed)$|$' \
55-
# | GREP_COLOR='01;32' grep --color=always -E -e '^.*passed$|$')
56-
57-
jq -n --arg output "${test_output}" '{version: 1, status: "fail", message: $output}' > ${results_file}
52+
# Check if this is a compilation/syntax error vs test failure
53+
if echo "${test_output}" | grep -q "error:"; then
54+
jq -n --arg output "${test_output}" '{version: 1, status: "error", message: $output}' > ${results_file}
55+
else
56+
jq -n --arg output "${test_output}" '{version: 1, status: "fail", message: $output}' > ${results_file}
57+
fi
5858
fi
5959

6060
echo "${slug}: done"

tests/all-fail/HelloWorld.lean

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace HelloWorld
2+
3+
def hello : String :=
4+
"Goodbye, World!"
5+
6+
end HelloWorld

tests/all-fail/HelloWorldTest.lean

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import LeanTest
2+
import HelloWorld
3+
4+
open LeanTest
5+
6+
def helloWorldTests : TestSuite :=
7+
(TestSuite.empty "HelloWorld")
8+
|>.addTest "Say Hi!" (do
9+
return assertEqual "Hello, World!" HelloWorld.hello)
10+
11+
def main : IO UInt32 := do
12+
runTestSuitesWithExitCode [helloWorldTests]
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
22
"version": 1,
3-
"status": "fail",
4-
"message": "TODO: replace with correct output"
3+
"status": "fail"
54
}

tests/all-fail/lake-manifest.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{"version": "1.1.0",
2+
"packagesDir": ".lake/packages",
3+
"packages": [],
4+
"name": "«hello-world»",
5+
"lakeDir": ".lake"}

tests/all-fail/lakefile.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name = "hello-world"
2+
version = "0.1.0"
3+
defaultTargets = ["HelloWorldTest"]
4+
testDriver = "HelloWorldTest"
5+
6+
[[lean_lib]]
7+
name = "LeanTest"
8+
srcDir = "vendor/LeanTest"
9+
10+
[[lean_lib]]
11+
name = "HelloWorld"
12+
13+
[[lean_exe]]
14+
name = "HelloWorldTest"
15+
root = "HelloWorldTest"

0 commit comments

Comments
 (0)