# 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 overridden 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 overridden by defining the OCAMLTESTDIR environment 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 know 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 this: (* 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.