plan: task 4 verified by host unit tests (the driver has no network interface)

This commit is contained in:
opencode.energia.arti.ee committed 2026-10-30 22:52:46 +00:00
1 parent 18b496146b
commit 213083f2e0
1 file changed
+43 -15
@@ -215,38 +215,66 @@ git commit -m "feat(stream): payload skeleton with one startup malloc"
---
### Task 4: Two-slot ring with header validation
### Task 4: Frame parser and two-slot handling
**Files:**
- Modify: `harness/udpstream/vidstream.c`
- Test: `harness/mame/vidstream.lua` (mode `rx`)
- Create: `harness/udpstream/frame_parse.c`, `harness/udpstream/frame_parse.h`
- Create: `harness/udpstream/tests/test_frame_parse.c`
- Modify: `harness/udpstream/vidstream.c`, `harness/mame/vidstream.lua`
**Interfaces:**
- Produces: in-guest counters `RX_OK` (`0x01810030`), `RX_BAD` (`0x01810034`), `RX_LAST_LEN` (`0x01810038`), `RX_SLOT` (`0x0181003C`).
- `int fp_parse(const unsigned char *buf, unsigned int len, fp_header *out)` — returns 1 for a
valid frame, 0 otherwise; fills `kind, frame_no, rows, stretch, payload_len, payload_off`.
- In-guest counters `RX_OK`, `RX_BAD`, `RX_LAST_LEN`, `RX_SLOT` at the byte-aligned marker page.
- [ ] **Step 1: Write the failing test**
**Note (plan amendment, ruling R11):** the MAME driver does **not** attach the LANCE to a host
network interface, so no test can hand it Ethernet frames in the emulator. Verification is
therefore two-part: (1) `fp_parse` is a plain C function compiled and unit-tested on the host
(`gcc -std=c89`), which pins the length/CRC rules; (2) the Lua harness injects a frame directly
into a slot and asserts the payload's counters. The real DMA path is proven in Task 7, on the unit.
In `harness/mame/vidstream.lua` mode `rx`: send one valid frame (80 rows, `S=12`) and one frame whose CRC byte is flipped, via `vidsend.py --fake`. Assert `RX_OK == 1` and `RX_BAD == 1`.
- [ ] **Step 1: Write the failing host test**
- [ ] **Step 2: Run to verify it fails**
`tests/test_frame_parse.c`: build a 16-byte header + payload with the same layout `frame.py`
writes (magic 'V','S', version 1, kind 1, frame_no, payload_len, rows, stretch, CRC16 at offset
12 over bytes 0..11 + payload). Assert `fp_parse` accepts it; flip one payload byte and assert it
is rejected; truncate it below `16 + payload_len` and assert rejection; corrupt the magic and the
version and assert rejection.
Run: `VT1200_MODE=rx harness/mame/run-vidstream.sh`
Expected: `RX_OK=0 RX_BAD=0 -> FAIL` (nothing parses yet)
- [ ] **Step 2: Run it to verify it fails**
- [ ] **Step 3: Implement slot receive + validation**
Run: `cc -std=c89 -Wall -o /tmp/tfp harness/udpstream/tests/test_frame_parse.c harness/udpstream/frame_parse.c`
Expected: link error, `fp_parse` undefined.
Ring of 16 descriptors, two slots of 24 KB at `POOL_PTR` and `POOL_PTR + 24576`; arm 16 descriptors per slot on entry to that slot; on completion compute `bytes = SUM(len)`; accept only if `bytes >= 16`, `magic == 'VS'`, `payload_len + 16 <= bytes`, and `crc16(header[0:12] + payload) == header_crc`. Reject → `RX_BAD++`, re-arm the same slot, no blit.
- [ ] **Step 3: Implement `frame_parse.c` / `.h`**
- [ ] **Step 4: Run to verify it passes**
K&R-compatible C89 that also compiles with the 1987 compiler: no `//`, no declarations after
statements, CRC16 CCITT-FALSE as in `frame.py`. `fp_parse` checks length first, then magic and
version, then CRC over `buf[0..11] + payload`.
- [ ] **Step 4: Run the host test to verify it passes**
Run: `cc -std=c89 -Wall -o /tmp/tfp harness/udpstream/tests/test_frame_parse.c harness/udpstream/frame_parse.c && /tmp/tfp`
Expected: `frame_parse: N/N ok`.
- [ ] **Step 5: Wire it into the payload and the MAME harness**
`vidstream.c` calls `fp_parse` on each completed slot, increments `RX_OK`/`RX_BAD`, and does not
blit on rejection. `vidstream.lua` mode `rx` writes a valid frame into slot A and a corrupted one
into slot B, sets the payload's "frame ready" word for each, and asserts `RX_OK == 1 && RX_BAD == 1`.
- [ ] **Step 6: Run the MAME check**
Run: `VT1200_MODE=rx harness/mame/run-vidstream.sh`
Expected: `RX_OK=1 RX_BAD=1 -> PASS`
- [ ] **Step 5: Commit**
- [ ] **Step 7: Commit**
```bash
git add harness/udpstream/vidstream.c harness/mame/vidstream.lua
git commit -m "feat(stream): two-slot rx ring with header and crc validation"
git add harness/udpstream/frame_parse.c harness/udpstream/frame_parse.h \
harness/udpstream/tests/test_frame_parse.c \
harness/udpstream/vidstream.c harness/mame/vidstream.lua
git commit -m "feat(stream): frame parser shared by host tests and payload"
```
---