Skip to content

Commit bff4584

Browse files
authored
Merge pull request #29 from elegios/new-build-system
Documentation for the new build and test system
2 parents c0acecf + 115c74c commit bff4584

File tree

3 files changed

+287
-3
lines changed

3 files changed

+287
-3
lines changed

docs/how-to-guides/contributing.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
sidebar_position: 4
33
---
44

5-
# How to contribute
5+
# Contributing to Miking
66

7-
1. Before making a pull request please make sure that all tests pass. Run
8-
appropriate tests as described above.
7+
1. Before making a pull request please make sure that all tests in
8+
`make test` pass. See [here](../reference/make-targets#testing).
99

1010
2. Make sure you follow the conventions declared in the
1111
[wiki](https://github.com/miking-lang/miking/wiki/Conventions).

docs/reference/make-targets.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
---
3+
4+
# Make Targets (Building, Testing, and Installing)
5+
6+
The make targets available in the `Makefile` at the root of the Miking
7+
repository provides a number of conveniences for working on the code
8+
base. This page provides a brief summary of the more important ones.
9+
10+
## Building the Compiler
11+
12+
- `bootstrap`: run the full bootstrapping procedure, creating
13+
`build/mi`. This is the default target, i.e., running `make` is
14+
equivalent with `make bootstrap`.
15+
- `cheat`: use an `mi` compiler available in your `$PATH` (i.e.,
16+
installed on your system) to build a compiler in one step, placing
17+
it at `build/mi-cheat`. This is significantly faster than full
18+
bootstrapping, and is often useful while working, as long as the new
19+
compiler requires no new features.
20+
21+
## Working with `boot`
22+
23+
- `boot`: build the bootstrapping interpreter and the `boot` library,
24+
placing the former at `build/mi-boot`.
25+
- `lint`, `fix`: check code formatting of the OCaml code implementing
26+
`boot`. Note that `lint` will merely show incorrect formatting,
27+
while `fix` automatically corrects it.
28+
29+
## Installing and Uninstalling
30+
31+
- `install-boot`/`uninstall-boot`: install/uninstall the `boot`
32+
library on the system.
33+
- `install`/`uninstall`: install/uninstall the `mi` compiler and
34+
standard library. Note that `install` also runs `install-boot`,
35+
since it's required, but `uninstall` will leave `boot`.
36+
37+
## Testing
38+
39+
For more information about testing Miking, see [here](testing-miking).
40+
41+
- `test`: detects which dependencies you have install and runs all
42+
tests whose dependencies are satisfied using the bootstrapped
43+
compiler.
44+
- `test-all`: like `test`, except assumes all possible dependencies
45+
are installed. Note that tests requiring specialized hardware will
46+
still not run if that hardware is absent.
47+
- `test-quick`: run a smaller set of tests, turning off all optional
48+
test collections.

docs/reference/testing-miking.md

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
---
2+
---
3+
4+
# Testing Miking
5+
6+
The Miking test-suite is built to test *every* `.mc` file under `src/`
7+
in the repository, with varying invocations, compile flags, etc.,
8+
while making it very flexible to use.
9+
10+
## Running Tests
11+
12+
There is one primary entry point to running the test-suite:
13+
`misc/test`. It has no mandatory arguments, and will by default turn
14+
off all optional test collections, uses a "cheated" `mi` (see the
15+
`cheat` target [here](make-targets#building-the-compiler)), and runs
16+
all remaining tests.
17+
18+
There are three kinds of optional arguments: flags, which specify
19+
which `mi` to use, test collections to include, and files to test:
20+
21+
```bash
22+
misc/test [FLAGS] [COLLECTIONS] -- [FILES]
23+
```
24+
25+
:::tip
26+
27+
The other entry point is `misc/watch`, which takes exactly the same
28+
arguments, but reruns tests whenever any file in the repository
29+
changes. Note that `misc/watch` requires `entr` to be installed.
30+
31+
:::
32+
33+
:::warning
34+
35+
The test-suite must be run from the root of the repository. The runner
36+
should detect attempts to do otherwise and refuse to run.
37+
38+
:::
39+
40+
### Reading Test Output
41+
42+
All outputs (both standard out and standard err, as well as
43+
intermediate results such as executables) are stored in the `build`
44+
folder in the root of the repository. The folder structure mirrors the
45+
folder structure of the rest of the repository, i.e., outputs from
46+
tests in `src/stdlib/parser` can be found under
47+
`build/src/stdlib/parser`.
48+
49+
Each file follows a (rather verbose) naming scheme to clarify its
50+
origin: `filename.test-collection.mi-version.tag` for intermediate
51+
outputs, plus `.out` and `.err` extensions for standard out and
52+
standard err, respectively. The `tag` is chosen by the test
53+
collection. For example:
54+
55+
```bash
56+
$ ls build/src/stdlib/annotate*
57+
build/src/stdlib/annotate.mc.constructor-types.installed.constructor-types
58+
build/src/stdlib/annotate.mc.constructor-types.installed.constructor-types.err
59+
build/src/stdlib/annotate.mc.constructor-types.installed.constructor-types.out
60+
build/src/stdlib/annotate.mc.constructor-types.installed.constructor-types-run.err
61+
build/src/stdlib/annotate.mc.constructor-types.installed.constructor-types-run.out
62+
build/src/stdlib/annotate.mc.normal.installed.eval.err
63+
build/src/stdlib/annotate.mc.normal.installed.eval.out
64+
build/src/stdlib/annotate.mc.normal.installed.exe
65+
build/src/stdlib/annotate.mc.normal.installed.exe.err
66+
build/src/stdlib/annotate.mc.normal.installed.exe.out
67+
build/src/stdlib/annotate.mc.normal.installed.run.err
68+
build/src/stdlib/annotate.mc.normal.installed.run.out
69+
```
70+
71+
Here `normal` are default tests, `eval` are results of interpretation,
72+
`exe` is the compiled executable and compile logs, and `run` are
73+
results of running the executable.
74+
75+
### Selecting `mi` version
76+
77+
The `mi` version to use is specified by one of `--installed` (using an
78+
`mi` from your `$PATH`), `--bootstrapped` (using a fully bootstrapped
79+
compiler), and `--cheated` (using a compiler built using an installed
80+
`mi`). The default is `--cheated`, and more than one option can be
81+
given to run tests for more than one compiler.
82+
83+
```bash
84+
# Run tests using an installed `mi`
85+
misc/test --installed
86+
```
87+
88+
### Selecting Test Collections
89+
90+
Some tests are split into collections (see
91+
[below](#specifying-tests)), which must be turned on to run. These can
92+
be specified by name, or using the `smart` or `all`
93+
pseudo-collections. `smart` includes all collections whose
94+
dependencies are met, while `all` includes all collections except
95+
those with unmet *hardware* requirements.
96+
97+
```bash
98+
# Run tests not in a test collection, as well as those in the `java`
99+
# collection, regardless of whether its dependencies are met
100+
misc/test java
101+
102+
# Any number of collections can be included
103+
misc/test microbenchmarks tuning
104+
105+
# Run all tests whose dependencies are met
106+
misc/test smart
107+
```
108+
109+
### Selecting Files to Test
110+
111+
The test-suite can be instructed to run only those tests related to an
112+
explicit set of files. This is useful when working on a particular
113+
feature. Such files must be given after a `--` argument.
114+
115+
```bash
116+
# Run all tests related to `src/stdlib/annotate.mc`
117+
misc/test smart -- src/stdlib/annotate.mc
118+
119+
# Test all files in the `src/stdlib/parser` folder
120+
misc/test smart -- src/stdlib/parser/**/*.mc
121+
```
122+
123+
:::warning
124+
125+
Note that explicitly specifying files does not automatically turn on
126+
related test collections. Including the `smart` collection, as in the
127+
examples above, is typically a good idea.
128+
129+
:::
130+
131+
## Specifying Tests
132+
133+
Tests are specified in `misc/test-spec.mc`. By default, all tests in
134+
all `.mc` files are expected to pass, both through interpretation (`mi
135+
eval`) and compilation (`mi compile` and running the
136+
executable). Exceptions to this, as well as new tests, can be added
137+
through *test collections*, specified at the end of
138+
`misc/test-spec.mc`. This section gives a brief overview of the
139+
concepts; for more detail, see the documentation comments for
140+
`TestCollection` in
141+
[`misc/test-spec.mc`](https://github.com/miking-lang/miking/blob/develop/misc/test-spec.mc),
142+
as well as the collections already defined at the end of the same
143+
file.
144+
145+
A test collection is defined via `testColl`:
146+
147+
```mcore
148+
{ testColl "name-of-collection"
149+
with ...
150+
}
151+
```
152+
153+
The collection is configured through a record update, with a number of
154+
possible fields.
155+
156+
### Changing Default Tests
157+
158+
Some files cannot be tested with the default approach, are expected to
159+
fail, or take too long to run as part of the default test suite. We
160+
can change these by providing the `exclusions` and/or
161+
`conditionalInclusions` functions. These functions are expected to
162+
"mark" files, e.g.:
163+
164+
```mcore
165+
{ testColl "example"
166+
with exclusions = lam api.
167+
api.mark { defaultTasks with interpret = Fail (), run = Dont () }
168+
(api.strsToPaths ["stdlib/foo.mc", "stdlib/bar.mc"])
169+
}
170+
```
171+
172+
Note that the files marked by `conditionalInclusions` are only tested
173+
when the collection is enabled, while files marked by `exclusions` are
174+
tested regardless.
175+
176+
### Checking Dependencies
177+
178+
Some tests require, e.g., external libraries to be installed to
179+
run. The `checkCondition` function is expected check for such
180+
cases. There are three cases, mostly self-explanatory:
181+
`ConditionsMet`, `ConditionsUnmet`, and `ConditionsImpossible`. The
182+
last of these should be used if a hardware dependency is unmet, to
183+
exclude this collection from the `all` pseudo-collection.
184+
185+
Note that `checkCondition` is expected to directly interact with the
186+
outside world by, e.g., running external commands.
187+
188+
```mcore
189+
{ testColl "toml"
190+
with checkCondition = lam.
191+
if eqi 0 (command "ocamlfind query toml >/dev/null 2>&1")
192+
then ConditionsMet ()
193+
else ConditionsUnmet ()
194+
conditionalInclusions = lam api.
195+
-- ...elided...
196+
}
197+
```
198+
199+
### Adding New Tests
200+
201+
New tests are added by providing the `newTests` function. Tests often
202+
have multiple steps, e.g., compiling a file, then running the
203+
executable. A new step can be added using one of three functions:
204+
205+
- `success` adds a step expected to succeed and produce no outputs.
206+
- `fail` adds a step expected to fail and produce no outputs.
207+
- `mid` adds a step expected to succeed and produce exactly one
208+
output.
209+
210+
All steps are expected to take exactly one file as input. Each step is
211+
specified as a shell command to run, with a few placeholders to be
212+
filled in:
213+
214+
- `%i`: the input file.
215+
- `%o`: the output file for a `mid` step.
216+
- `%m`: an invocation of the appropriate version of `mi`. *Do not* use
217+
`mi` directly.
218+
219+
Note that no step should write to *any* file except `%o` (i.e.,
220+
`success` and `fail` should not write to any file, only standard out
221+
and standard error). This is to ensure, amongst other things, that all
222+
tests can run in parallel and that no tests will clobber results from
223+
other tests.
224+
225+
Note also that each step is given a "tag", which should be unique
226+
across steps in the same test collection.
227+
228+
```mcore
229+
{ testColl "mlang-pipeline"
230+
with newTests = lam api.
231+
let files = api.strsToPaths [...] in
232+
for_ files (lam mc.
233+
let exe = api.mid {input = mc, cmd = "%m compile --test --mlang-pipeline %i --output %o", tag = "mlang"} in
234+
api.success {input = exe, cmd = "./%i", tag = "mlang-run"})
235+
}
236+
```

0 commit comments

Comments
 (0)