Smoke harness — checking VEAF inside a real DCS¶
poetry run test-lua runs against test/lua/dcs_mocks.lua, a DCS we wrote ourselves. It can only
confirm what we already believed. Anything beyond it was ending up in a queue: somebody had to fly it.
This harness runs assertions inside a running DCS, with nobody at the controls.
What it will never be¶
A CI gate. GitHub runners have no DCS, no licence and no GPU. It is a local tool, run by whoever has an install.
Prerequisites¶
- DCS running and a mission loaded, by you: the mission built with the
dcs_bridgesection ofmission.yamlenabled (or passed throughveaf-tools dcs inject-bridge). The test missiontest/veaf-tools/verify-mission-calready enables it. - The
MissionScripting.luachange made once on your DCS, so the bridge can load thesocketlibrary: the same as forclear-ground-sweep, described in the CLI reference. dcs-serve: the command starts one when none runs, like the other bridge commands.
Usage¶
.\veaf-tools.exe dcs smoke-test
Runs the checks in the mission, one line per check, and exits 1 when one fails. --suite spotter
runs the demo-spotter-network rig's checks instead.
There is no unattended run any more (--full, which launched DCS and loaded the mission): measured on
2026-08-15, net.load_mission loads nothing in single player — ED documents it SERVER ONLY — and you
are the one who launches DCS and the mission. The DCS Fiddle hook that drove it was removed
(REFACTOR-BRIDGE-ONLY, 2026-10-29).
How it talks to DCS¶
One transport: the VEAF bridge. dcs-serve receives the Lua, and dcs-bridge.lua — embedded
in the mission — runs it in the mission scripting state. That state sees both DCS's own globals
(Disposition, missionCommands, coalition) and the mission's scripts (veaf, csar), so every
check runs there.
The bridge returns tostring of the result; a Lua error comes back as {"error": …} and the check
fails quoting it. The bridge runs on the mission's clock: paused, it does not answer.
The test mission's contract¶
Borrowed from nielsvaes/dcs-sms, and the counter-example is the part worth having:
- Theatre Syria, anchor
(-32220, 405386)— "empty desert, far from anything, but DCS does process events there". - At
(-50000, -50000), over open water, DCS silently drops death events.
A harness that put its test units "somewhere empty" would watch kills fail to arrive and conclude the code was broken. That is a day lost on a non-bug, and it cannot be reasoned out.
⚠️ These coordinates are not verified here yet. They come from their repository, and this one has already found two wrong claims in their documentation. Killing a unit at that anchor and watching the event arrive is part of the lot's ticket 01.
Adding a check¶
Assertions are data, not code: an entry in CHECKS (veaf_libs/dcs_smoke.py), with a name, a Lua
snippet, what its result must look like, and why we want to know. A check whose purpose nobody
wrote down is a check nobody dares delete.
The rule: your Lua must return a string. Always.¶
The bridge returns tostring(result ~= nil and result or ""):
| Lua returns | Python receives |
|---|---|
'x' |
'x' |
3 |
'3' — a string |
true |
'true' |
false, nil |
'' — destroyed |
{1, 2} |
'table: 0x…' — an address, not the content |
Practical corollary: tag your values (count:10 rather than 10, a word rather than a boolean),
so that "I asked, there is nothing" (count:0) stays distinct from "the answer was destroyed" ('').
A test sweeps every check against '': an expectation that '' satisfies cannot tell success from a
lost value.
A trap worth knowing: the snippets return sentinels (veaf-absent, no-singleton, not-a-table,
raised: …) instead of raising, so a missing prerequisite is legible. They are non-empty strings,
hence truthy — an expectation written as a plain truthiness test passes in exactly the case it was
meant to catch. A test sweeps every check against every sentinel, and against the shape of a Lua error
(:1: attempt to …), which net.dostring_in hands back as an ordinary result.
The CSAR-over-water checks¶
csar-avoids-water-open-sea and csar-avoids-water-coast answer
#245 — "the CSAR pilot spawns in the
water" — with no aircraft and no human pilot. Three scripting calls are enough: trigger the spawn, read
the position back, ask what is underneath.
The two checks ask different questions, and that is the point:
- open sea — the reported case;
- near a coast — the interesting one.
FEAT-SCENERY-AWARE-SPAWNgaveveaf.findSpawnPointterrain awareness; the real question is whether CSAR goes through it. A pass offshore with a failure near the coast would mean CSAR has a placement path of its own.
No coordinate is hard-coded: the check anchors on the first airbase and sweeps until it finds water, then classifies the point by what surrounds it at 150 m. So it works on any theatre.
Any answer other than a dry placement is a failure
Including the ones saying the question could not be asked (csar-absent, no-water-found,
no-group). A check that passes when it asked nothing would close #245 on nothing, which is
precisely the failure mode this rig is written against.
What is left¶
The FEAT-DCS-SMOKE-HARNESS lot carries the detail: the committed test mission (ticket 01) and its anchor check in game.