Skip to content

Commit 6356328

Browse files
authored
Merge pull request #481 from AltGr/a7977b52
Implement pre-compilation of exercises and graders
2 parents 0816f95 + 6ce797f commit 6356328

File tree

122 files changed

+2091
-1567
lines changed

Some content is hidden

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

122 files changed

+2091
-1567
lines changed

.github/workflows/build-and-test.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ jobs:
2121
uses: actions/checkout@v3
2222
- name: Build Docker images
2323
run: "make docker-images"
24+
- name: Fix permissions
25+
run: "chmod -R a+wX demo-repository"
2426
- name: Run learn-ocaml build on demo-repository
2527
run: "docker run --rm -v $(pwd)/demo-repository:/repository learn-ocaml -- build"
2628
- name: Clone learn-ocaml-corpus inside tests/corpuses
27-
run: "mkdir tests/corpuses && cd tests/corpuses && git clone --depth=1 https://github.com/ocaml-sf/learn-ocaml-corpus.git && cd ../.."
29+
run: "git clone --depth=1 https://github.com/ocaml-sf/learn-ocaml-corpus.git tests/corpuses/learn-ocaml-corpus"
2830
- name: Run tests
29-
run: "cd tests && bash -c ./runtests.sh"
31+
run: "tests/runtests.sh"
3032

3133
client_using_other_server:
3234
name: Build learn-ocaml-client and run quick tests
@@ -36,8 +38,8 @@ jobs:
3638
fail-fast: false
3739
matrix:
3840
server_image:
39-
- 'ocamlsf/learn-ocaml:0.12'
40-
- 'ocamlsf/learn-ocaml:0.13.0'
41+
# - 'ocamlsf/learn-ocaml:0.12'
42+
# - 'ocamlsf/learn-ocaml:0.13.0'
4143
- 'learn-ocaml' # use learn-ocaml image built from master
4244
env:
4345
USE_CLIENT_IMAGE: 'true'

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,8 @@ tests/corpuses/*
3535
detect-libs.*
3636

3737
docs/odoc.html
38+
39+
demo-repository/exercises/**/*.cmo
40+
demo-repository/exercises/**/*.cmi
41+
demo-repository/exercises/**/*.cma
42+
demo-repository/exercises/**/*.js

Dockerfile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,18 @@ ARG opam_switch="/home/opam/.opam/4.12"
6666
COPY --from=compilation /home/opam/install-prefix /usr
6767
COPY --from=compilation "$opam_switch/bin"/ocaml* "$opam_switch/bin/"
6868
COPY --from=compilation "$opam_switch/lib/ocaml" "$opam_switch/lib/ocaml/"
69+
COPY --from=compilation "$opam_switch/bin/js_of_ocaml" "$opam_switch/bin/"
70+
COPY --from=compilation "$opam_switch/lib/js_of_ocaml" "$opam_switch/lib/js_of_ocaml"
71+
COPY --from=compilation "$opam_switch/lib/vg" "$opam_switch/lib/vg"
72+
COPY --from=compilation "$opam_switch/lib/gg" "$opam_switch/lib/gg"
73+
74+
# Fixes for ocamlfind
75+
COPY --from=compilation "$opam_switch/lib/findlib.conf" "$opam_switch/lib/"
76+
COPY --from=compilation "$opam_switch/lib/stdlib" "$opam_switch/lib/stdlib"
77+
ENV PATH="${opam_switch}/bin:${PATH}"
78+
ENV OCAMLPATH="/usr/lib"
79+
RUN ln -sf "$opam_switch/lib/vg" "/usr/lib"
80+
RUN ln -sf "$opam_switch/lib/gg" "/usr/lib"
6981

7082
ENTRYPOINT ["dumb-init","/usr/bin/learn-ocaml","--sync-dir=/sync","--repo=/repository"]
7183
CMD ["build","serve"]

META.learn-ocaml.template

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package "test_lib" (
2+
directory = "test_lib"
3+
version = "0.13.2"
4+
description = "Learn-ocaml dependencies for automatic graders"
5+
requires = "compiler-libs"
6+
)
7+
# DUNE_GEN

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ REPO ?= demo-repository
7070

7171
testrun: build install
7272
rm -rf www/css
73-
learn-ocaml build --repo $(REPO) -j1
73+
learn-ocaml build --repo $(REPO)
7474
rm -rf www/css
7575
ln -s ../static/css www
7676
LEARNOCAML_SERVER_NOCACHE=1 learn-ocaml serve
@@ -82,7 +82,7 @@ docker-images: Dockerfile learn-ocaml.opam
8282
@docker build -t learn-ocaml-compilation --target compilation docker
8383
@docker build -t learn-ocaml --target program docker
8484
@docker build -t learn-ocaml-client --target client docker
85-
@echo "Use with 'docker run --rm -v \$$PWD/sync:/sync -v \$$PWD:/repository -p PORT:8080 learn-ocaml -- ARGS'"
85+
@echo "Use with 'docker run --rm -v learn-ocaml-sync:/sync -v \$$PWD:/repository -p PORT:8080 learn-ocaml -- ARGS'"
8686

8787
VERSION = $(shell opam show ./learn-ocaml.opam -f version)
8888

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ The Inconsolata font is released under the Open Font License.
5353
See [http://www.levien.com/type/myfonts/inconsolata.html](http://www.levien.com/type/myfonts/inconsolata.html).
5454

5555
The Biolinum font is licensed under the GNU General Public License with
56-
a the 'Font-Exception'.
56+
a 'Font-Exception'.
5757
See [http://www.linuxlibertine.org](http://www.linuxlibertine.org).
5858

5959
The public instance of Learn OCaml uses the Fontin font instead of
@@ -78,9 +78,9 @@ It was written by OCamlPro from 2015 to 2018.
7878

7979
The current main contributors are Érik Martin-Dorel, Yann Régis-Gianas, and Louis Gesbert.
8080

81-
The initial authors were Benjamin Canou, Çağdaş Bozman, and Grégoire Henry.
81+
The initial authors were Benjamin Canou, Çağdaş Bozman, Grégoire Henry, and Louis Gesbert.
8282

83-
It builds on the previous experience of Try OCaml, by Çağdaş Bozman, and Fabrice Le Fessant.
83+
It builds on the previous experience of Try OCaml, by Çağdaş Bozman and Fabrice Le Fessant.
8484

8585
We heavily use js_of_ocaml, so thanks to the Ocsigen team.
8686

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
learn-ocaml.mutation_testing

docs/exercises_format.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,30 @@ An exercise is described by a directory containing at most the following files:
5454
- solution.ml
5555
- test.ml
5656
- max_score.txt
57+
- test_libs.txt
58+
59+
> Note: as of learn-ocaml 1.0, the `.ml` files get compiled into the exercise.
60+
> It is therefore not possible to use directives like `#install_printer`.
61+
> However, you can still define your own printers in a way similar to defining
62+
> custom `sample_<type>` functions:
63+
>
64+
> ```ocaml
65+
> (* Custom printer for a pre-defined type *)
66+
> let print_float ppf x = Format.fprintf ppf "%.2f" x
67+
>
68+
> (* Name the alias to define a printer for a specific instanciation of a
69+
> generic type *)
70+
> type int_list = int list
71+
> let print_int_list ppf l = ...
72+
>
73+
> (* Define a generic printer for a generic type *)
74+
> let print_result ppok pperr ppf = function
75+
> | Ok ok -> Format.fprintf ppf "OK(%a)" ppok ok
76+
> | Error err -> Format.fprintf ppf "ERR(%a)" pperr err
77+
> ```
78+
>
79+
> Printers defined in `prelude.ml` or `prepare.ml` affect the toplevel and the
80+
> grader. Printers defined in `test.ml`, obviously, affect only the grader.
5781
5882
### meta.json
5983
@@ -130,6 +154,12 @@ code, which will be described and detailed in another section.
130154
Maximum score that is possible to get for this exercise, even if the grader
131155
grades more. Overridden by the field `max_score`, if present in `meta.json`.
132156
157+
### test_libs.txt
158+
159+
List of additional libraries (one per line) to be used by the grader. The
160+
libraries will be looked up using `ocamlfind`, available to `test.ml` during its
161+
compilation, and bundled in the exercise grader.
162+
133163
# Metadata
134164
135165
When building the corpus and extracting the metadatas of all exercises, the

docs/exercises_tests.md

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,23 @@ A classic `test.ml` file is as follows:
2020
open Test_lib
2121
open Report
2222
23-
let exercise_1 = ..
23+
let exercise_1 () = ..
2424
25-
let exercise_2 = ..
25+
let exercise_2 () = ..
2626
27-
let exercise_3 = ..
27+
let exercise_3 () = ..
2828
2929
3030
let () =
3131
set_result @@
3232
ast_sanity_check code_ast @@ fun () ->
33-
[ exercise_1 ; exercise_2 ; exercise_3 ]
33+
[ exercise_1 (); exercise_2 (); exercise_3 () ]
3434
3535
```
3636

37-
The values `exercise_x` are values of type `Learnocaml_report.report`, which is
37+
The return values of `exercise_x` are of type `Learnocaml_report.report`, which is
3838
a representation of the report given by the grader. In this example, each of
39-
these values are referring to a specific question from the exercise. Their
39+
these values is referring to a specific question from the exercise. Their
4040
content is detailed in the next section. These reports are then given to the
4141
function `ast_sanity_check`, which ensures that some modules are never used
4242
(`Obj`, `Marshall`, all the modules from `compiler-libs` or the library that
@@ -46,7 +46,7 @@ allows introspection), and also excludes some syntactic features of the language
4646

4747
# Writing tests and reports
4848

49-
The format of reports can be found in `src/state/learnocaml_report.ml`. A report
49+
The format of reports can be found in `src/grader/learnocaml_report.ml`. A report
5050
describes the result of what should be outputted and interpreted by the
5151
grader. It can be classified into sections for lisibility, and return many kind
5252
of messages:
@@ -252,3 +252,23 @@ forbidden or required. The two functions `ast_check_expr` and
252252
pattern-matching on some specific patterns into the code. The function
253253
`find_binding` look for a toplevel value and apply a given function on its
254254
syntax tree.
255+
256+
### Using helper libraries for testing
257+
258+
Using a `test_libs.txt` file, it is possible to include libraries that define
259+
helpers for grading.
260+
261+
The file should contain the ocamlfind names of the libraries, one per line.
262+
263+
Example of such libs include
264+
[mutation_testing](https://github.com/ocaml-sf/learn-ocaml/blob/master/src/grader-plugins/mutation_test.ml)
265+
(from McGill University, included in this repository), or
266+
[easy-check](https://github.com/lsylvestre/easy-check) from University Paris 6.
267+
268+
See `src/grader-plugins/dune` to get how to build such libraries. Like
269+
`test.ml`, they can access the `Introspection` and `Test_lib` interfaces. They
270+
cannot, at the time of writing, define new samplers or printers, but if you need
271+
that feature and are ready to contribute, all that is missing is the inclusion
272+
of their `cmi` files in the grading-toplevel environment (these features rely
273+
on dynamic typing, and the `cma` library doesn't include the required typing
274+
information).

docs/howto-setup-exercise-development-environment.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ GNU/Linux and MacOS X are supported.
1212
> use:
1313
>
1414
> docker version # If this fails, find out how to run Docker, first
15-
> docker login
1615
> docker run --rm \
1716
> -v $REPOSITORY:/repository:ro \
1817
> -v learn-ocaml-sync:/sync \
@@ -63,7 +62,6 @@ ready:
6362

6463
```
6564
opam switch create . --deps-only --locked
66-
opam install opam-installer
6765
eval $(opam env)
6866
```
6967

@@ -74,7 +72,7 @@ your current opam switch, without creating a dedicated one.)
7472
Second, compile and install the platform:
7573

7674
```
77-
make && make opaminstall
75+
make && make install
7876
```
7977

8078
At this point, you should get a working `learn-ocaml` program in

0 commit comments

Comments
 (0)