(tests (names test_flan test_acceptance test_reload test_agent test_session test_dev test_emacs test_repl test_cider) ; Explicit because test_sanitize lives in this directory and is not one of ; these: two stanzas in one directory have to say which modules are whose. ; watchdog is every binary's clock: a hanging test reports nothing, so each ; of these arms an alarm that turns "for ever" into a failing run. (modules test_flan test_acceptance test_reload test_agent test_session test_dev test_emacs test_repl test_cider watchdog) (libraries flan unix) ; The acceptance programs are part of the test corpus: if the reader, the ; parser or the checker regresses on them we want to know here, not at the CLI. (deps (file %{workspace_root}/calc-me.flan) (file %{workspace_root}/sand.flan) ; The brush sheet. sand.flan no longer embeds it — the front-end was cut back ; to what lisp/sand.lisp and sand.jank have — so nothing in the corpus reads ; it today. Kept as a dependency because it is still in the workspace and an ; embed is read by the *checker*, relative to the file the form is written ; in, which is the rule any program picking it up again would meet. (file %{workspace_root}/brush.png) ; The raylib bindings, because sand.flan and the FFI case import them and an ; import reads the directory at build time. sand.flan itself is above: the ; headless case imports it as a single-file package. (glob_files %{workspace_root}/vendor/raylib/*) ; The dev agent package: its Flan declarations and the C that implements them. (glob_files %{workspace_root}/vendor/agent/*) ; The EDN tokenizer, which programs/edn.flan imports. (glob_files %{workspace_root}/vendor/edn/*) ; The ported raylib examples. Only one of them has a headless acceptance ; case, but it imports its example as a package and that example imports ; examples/digits.flan, so the directory has to be here whole. (glob_files %{workspace_root}/examples/*) (glob_files programs/*.flan) ; The package tree the multi-level cases import: pkg-diamond reaches shape ; through area and draw, and pkg-cycle reaches a ring. Each directory is a ; package, so each comes whole — a glob per directory rather than one over ; programs/pkgs/*, because dune's glob does not descend. (glob_files programs/pkgs/shape/*) (glob_files programs/pkgs/area/*) (glob_files programs/pkgs/draw/*) (glob_files programs/pkgs/ring-a/*) (glob_files programs/pkgs/ring-b/*) (glob_files programs/pkgs/ring-c/*) ; The packages that declare macros: one whose macros a program calls ; qualified, and the two whose macros do not terminate — a ring, and one ; that never settles. Each is its own directory, so each needs its own glob. (glob_files programs/pkgs/mac/*) (glob_files programs/pkgs/macring/*) (glob_files programs/pkgs/macspin/*) ; The synthetic C header the importer's table reads. Committed rather than ; reached for on the machine: the raylib case needs raylib installed, at the ; right version, with a variable set, so it skips everywhere and covers ; nothing. This one does not move. (glob_files headers/*.h) ; The files programs/embed.flan bakes in. An embed reads them at *compile* ; time, so they are a dependency of the checker run and not of the program. (glob_files programs/assets/*) ; The reload primitive's host: a C main that dlopens what Build.shared made. (file reload_host.c) ; A shared object that is not a redefinition module, for the agent's refusal ; path. Its destructor is what proves the handle was closed rather than lost. (file noinstall.c) ; The other C main: flan_dev.c's two fixed limits, which no Flan program ; reaches, driven directly. (file dev_limits.c) ; test_dev runs the compiler itself: flan dev launches and owns a program. (file %{workspace_root}/bin/main.exe) ; The Emacs client, which test_emacs drives against a real daemon. (glob_files %{workspace_root}/emacs/*.el) ; The WASI host the wasm32 case runs its module under, when no wasmtime or ; wasmer is installed. (file wasm-run.mjs))) ; The web target, in its own stanza rather than in the table above because it ; is the one case whose toolchain is a separate install: emscripten, and a ; raylib archive built by vendor/raylib/build-web.sh. It probes for both and ; skips with the reason, so it is green on a machine that has neither. (test (name test_web) (modules test_web) (libraries flan unix) (deps (glob_files programs/*.flan) (glob_files programs/assets/*) ; The raylib bindings and the ported example the raylib case builds. The ; example imports examples/digits.flan, so the directory comes whole. (glob_files %{workspace_root}/vendor/raylib/*) (glob_files %{workspace_root}/examples/*) ; sand.flan for the browser, with the sheet it embeds and the dev agent it ; imports — the agent's directory has to be whole, because the file that ; makes a web build possible is the one Build selects out of it. (file %{workspace_root}/sand.flan) (file %{workspace_root}/brush.png) (glob_files %{workspace_root}/vendor/agent/*) ; flan run --target=web is refused by the CLI, so the CLI has to be here. (file %{workspace_root}/bin/main.exe))) ; The corpus a second time under ASan and UBSan. Its own alias and not part of ; `dune test`: a sanitized build is a statically linked 1.8MB binary that takes ; tens of seconds to produce, so the sweep is minutes against the existing ; suite's seconds, and a test nobody will wait for is a test nobody runs. ; ; dune build --root . @sanitize ; An executable plus a rule rather than a (test ...): a test stanza attaches ; to the @runtest alias and offers no way to be attached to another one, which ; is the whole point here. (executable (name test_sanitize) (modules test_sanitize watchdog) (libraries flan unix)) (rule (alias sanitize) (deps test_sanitize.exe (file %{workspace_root}/calc-me.flan) (file %{workspace_root}/sand.flan) (file %{workspace_root}/brush.png) (glob_files %{workspace_root}/vendor/raylib/*) (glob_files %{workspace_root}/vendor/agent/*) (glob_files %{workspace_root}/vendor/edn/*) (glob_files %{workspace_root}/examples/*) (glob_files programs/*.flan) (glob_files programs/assets/*)) (action (run ./test_sanitize.exe))) ; The corpus a third time, under Valgrind's memcheck. Its own alias for the ; same reason @sanitize has one, only more so: memcheck runs the program on a ; synthetic CPU, so the corpus is tens of minutes rather than seconds. ; ; dune build --root . @valgrind ; ; Why a third sweep when @sanitize exists: ASan answers "is this address ; mine", and cannot answer "were these bytes ever written". That second ; question is MSan's, MSan needs every dependency instrumented and raylib ; settles it, and memcheck answers both while needing no instrumentation at ; all. NEXT.md asked for exactly this. (executable (name test_valgrind) (modules test_valgrind watchdog) (libraries flan unix str)) (rule (alias valgrind) (deps test_valgrind.exe ; The suppression file, which is all reasons and no suppressions; its own ; header says why that is the finding rather than an oversight. (file valgrind.supp) (file %{workspace_root}/calc-me.flan) (file %{workspace_root}/sand.flan) (file %{workspace_root}/brush.png) (glob_files %{workspace_root}/vendor/raylib/*) (glob_files %{workspace_root}/vendor/agent/*) (glob_files %{workspace_root}/vendor/edn/*) (glob_files %{workspace_root}/examples/*) (glob_files programs/*.flan) (glob_files programs/assets/*) ; The package tree the multi-level cases import, as in the test stanza ; above: a glob per directory, because dune's glob does not descend. (glob_files programs/pkgs/shape/*) (glob_files programs/pkgs/area/*) (glob_files programs/pkgs/draw/*) (glob_files programs/pkgs/ring-a/*) (glob_files programs/pkgs/ring-b/*) (glob_files programs/pkgs/ring-c/*) ; And the macro-declaring packages, for the same reason. (glob_files programs/pkgs/mac/*) (glob_files programs/pkgs/macring/*) (glob_files programs/pkgs/macspin/*)) (action (run ./test_valgrind.exe)))