200 lines
7.0 KiB
Plaintext
200 lines
7.0 KiB
Plaintext
|
# Introduction
|
||
|
|
||
|
## Context
|
||
|
|
||
|
The testsuite of the OCaml compiler consists of a series of programs
|
||
|
that are compiled and executed. The output of their compilation and
|
||
|
execution is compared to expected outputs.
|
||
|
|
||
|
Before the introduction of ocamltest, the tests were driven by a set of
|
||
|
makefiles which were responsible for compiling and running the test
|
||
|
programs, and verifying that the compilation and execution outputs were
|
||
|
matching the expected ones.
|
||
|
|
||
|
In this set-up, the precise information about how exactly one test
|
||
|
should be compiled was separated from the test itself. It was stored
|
||
|
somewhere in the makefiles, interleaved with the recipes to actually
|
||
|
compile and run the test. Thus, given one test, it was not easy to
|
||
|
determine exactly how this test was supposed to be compiled and run.
|
||
|
|
||
|
## Purpose
|
||
|
|
||
|
The ocamltest tool has been introduced to replace most of the makefiles
|
||
|
logic. It takes a test program as its input and derives from annotations
|
||
|
stored as a special comment at the beginning of the program the exact
|
||
|
way to compile and run it. Thus the test-specific metadata are stored in
|
||
|
the test file itself and clearly separated from the machinery required
|
||
|
to perform the actual tasks, which is centralized in the ocamltest tool.
|
||
|
|
||
|
## Constraints
|
||
|
|
||
|
It may look odd at first glance to write the tool used to test the
|
||
|
compiler in its target language. There are, however, parts of the
|
||
|
compiler and the standard library that are already tested in a way,
|
||
|
namely those used to compile the compiler itself. Therefore, these
|
||
|
components can be considered more trustworthy than those that have
|
||
|
not yet been used and that's
|
||
|
why ocamltest relies only on the part of the standard library that has been
|
||
|
used to develop the compiler itself.
|
||
|
|
||
|
This excludes for instance the use of the Unix and Str libraries.
|
||
|
|
||
|
# Initial set-up
|
||
|
|
||
|
ocamltest needs to know two things:
|
||
|
|
||
|
1. Where the sources of the OCaml compiler to test are located.
|
||
|
This is determined while OCaml is built. The default location can be
|
||
|
overriden by defining the OCAMLSRCDIR environment variable.
|
||
|
|
||
|
2. Which directory to use to build tests. The default value for this is
|
||
|
"ocamltest" under Filename.get_temp_dir_name(). This value can be
|
||
|
overriden by defining the OCAMLTESTDIR environemnt variable.
|
||
|
|
||
|
# Running tests
|
||
|
|
||
|
(all the commands below are assumed to be run from OCAMLSRCDIR/testsuite)
|
||
|
|
||
|
From here, one can:
|
||
|
|
||
|
## Run all tests: make all
|
||
|
|
||
|
This runs the complete testsuite. This includes the "legacy" tests
|
||
|
that still use the makefile-based infrastructure and the "new" tests
|
||
|
that have been migrated to use ocamltest.
|
||
|
|
||
|
## Run legacy tests: make legacy
|
||
|
|
||
|
## Run new tests: make new
|
||
|
|
||
|
## Run tests manually
|
||
|
|
||
|
It is convenient to have the following ocamltest script in a directory
|
||
|
appearing in PATH, like ~/bin:
|
||
|
|
||
|
#!/bin/sh
|
||
|
TERM=dumb OCAMLRUNPARAM= /path/to/ocaml/sources/ocamltest/ocamltest $*
|
||
|
|
||
|
Once this file has been made executable, one can for instance run:
|
||
|
|
||
|
ocamltest tests/basic-io/wc.ml
|
||
|
|
||
|
As can be seen, ocamltest's output looks similar to the legacy format.
|
||
|
|
||
|
This is to make the transition between the makefile-based
|
||
|
infrastructure and ocamltest as smooth as possible. Once all the
|
||
|
tests will have been migrated to ocamltest, it will become possible to
|
||
|
change this output format.
|
||
|
|
||
|
The details of what exactly has been tested can be found in
|
||
|
${OCAMLTESTDIR}/tests/basic-io/wc/wc.log
|
||
|
|
||
|
One can then examine tests/basic-io/wc.ml to see how the file
|
||
|
had to be annotated to produce such a result.
|
||
|
|
||
|
Many other tests have already been migrated and it may be useful to see
|
||
|
how the test files have been annotated. the command
|
||
|
|
||
|
find tests -name '*ocamltests*' | xargs cat
|
||
|
|
||
|
gives a list of tests that have been modified and can therefore be used
|
||
|
as starting points to understand what ocamltest can do.
|
||
|
|
||
|
# Migrating tests from makefiles to ocamltest
|
||
|
|
||
|
It may be a good idea to run make new from the testsuite directory before
|
||
|
starting to migrate tests. This will show how many "new" tests there
|
||
|
already are.
|
||
|
|
||
|
Then, when running make new after migrating n tests,
|
||
|
the number of new tests reported by make new should have increased by n.
|
||
|
|
||
|
OCaml's testsuite is divided into directories, each of them
|
||
|
containing one or several tests, which can each consist of one or
|
||
|
several files.
|
||
|
|
||
|
Thus, the directory is the smallest unit that can be migrated.
|
||
|
|
||
|
To see which directories still need to be migrated, do:
|
||
|
|
||
|
find tests -name 'Makefile'
|
||
|
|
||
|
In other words, the directories that still need to be migrated are
|
||
|
the subdirectories of testsuite/tests that still contain a Makefile.
|
||
|
|
||
|
Once you knwo which directory you want to migrate, say foo, here is
|
||
|
what you should do:
|
||
|
|
||
|
Read foo/Makefile to see how many tests the directory contains and how
|
||
|
they are compiled. If the makefile only includes other makefiles and
|
||
|
does not define any variable, then it means that nothing special
|
||
|
has to be done to compile or run the tests.
|
||
|
|
||
|
You can also run the tests of this directory with the legacy framework,
|
||
|
to see exactly how they are compiled and executed. To do so, use the
|
||
|
following command from the testsuite directory:
|
||
|
|
||
|
make --trace DIR=tests/foo
|
||
|
|
||
|
(You may want to log the output of this command for future reference.)
|
||
|
|
||
|
For each test, annotate its main file with a test block, i.e. a
|
||
|
comment that looks like this:
|
||
|
|
||
|
(* TEST
|
||
|
Optional variable assignments and tests
|
||
|
*)
|
||
|
|
||
|
In particular, if the test's main file is foo.ml and the test uses
|
||
|
modules m1.ml and m2.ml, the test block will look like ths:
|
||
|
|
||
|
(* TEST
|
||
|
modules = "m1.ml m2.ml"
|
||
|
*)
|
||
|
|
||
|
And if the test consists of a single file foo.ml that needs to be
|
||
|
run under the top-level, then its test block will look like this:
|
||
|
|
||
|
(* TEST
|
||
|
* toplevel
|
||
|
*)
|
||
|
|
||
|
Or, if there are two reference files for that test and the name
|
||
|
of one of them contains "principal", then it means the file should
|
||
|
be tested with the top-level, without and with the -principal option.
|
||
|
This is expressed as follows:
|
||
|
|
||
|
(* TEST
|
||
|
* toplevel
|
||
|
* toplevel
|
||
|
include principal
|
||
|
*)
|
||
|
|
||
|
Lines starting with stars indicate which tests to run. If no test is
|
||
|
specified, then the tests that are enabled by default are used,
|
||
|
namely to compile and run the test program in both bytecode and native
|
||
|
code (roughly speaking).
|
||
|
|
||
|
Once your test has been annotated, run ocamltest on it and see
|
||
|
whether it passes or fails. If it fails, see the log file to understand why
|
||
|
and make the necessary adjustments until all the tests pass.
|
||
|
|
||
|
The adjustments will mostly consist in renaming reference files and
|
||
|
updating their content.
|
||
|
|
||
|
Note that there are different types of reference files, those for
|
||
|
compiler output and those for program output.
|
||
|
|
||
|
To make sure the migration has been done correctly, you can compare the
|
||
|
commands used to compile the programs in ocamltest's log file to those
|
||
|
obtained with make --trace. Beware that the commands used to compare an
|
||
|
obtained result to an expected one will not show up in ocamltest's log
|
||
|
file.
|
||
|
|
||
|
Once this has been done for all tests, create a file called "ocamltests"
|
||
|
(mark the final s!) with the names of all the files that
|
||
|
have been annotated for ocamltest, one per line.
|
||
|
|
||
|
Finally, git rm the Makefile and run make new from the testsuite directory
|
||
|
to make sure the number of new tests has increased as expected.
|