test(raft-ha-core-safety): cross-term streamer payload-integrity RED (task 2.3)

Minimal XCE_TESTING fault-injection seam in ha_stream_wal_to_standby
(NULL/production-inert) forces a short body read on a cross-term entry.
CORE RED proves the streamer ships PLEN=0 for a full (source_len=64)
cross-term entry: instrumentation source_len=64 SEND_len=0 RECV_len=0 ->
loss is SEND-side (answers task 1.3's open send-vs-transitive question).
2 honest pins (term-blind route guarded by 2.2; below-tip fence). 11
tests/1 RED; production xce_controller links clean without the seam.
This commit is contained in:
Rongsong Shen 2026-06-27 11:24:16 +00:00
parent 056675c8b3
commit ae8291ed56
3 changed files with 385 additions and 12 deletions

View file

@ -52,7 +52,7 @@
- _Requirements: 1.1, 1.2, 2.1, 2.2, 2.4, 3.1_
- _Boundary: Persist Conflict Guard_
- [ ] 2.3 RED: cross-term catch-up streamer payload-integrity tests
- [x] 2.3 RED: cross-term catch-up streamer payload-integrity tests
- Add a case reproducing the live signature: a cross-term catch-up (stored term < leader current term, bug-1067 path) whose entry-body `pread` returns short / `malloc` fails must NOT result in a persisted `PLEN=0` entry at a committed LSN — instead the stream must error and retry. Also add the defensive case that a `term==0`-shaped catch-up entry routes through the reconcile seam (no direct-persist bypass), and the unrecoverable-fence case (a node that cannot obtain the majority-agreed committed prefix refuses promotion instead of serving divergent state). Instrument `payload_len` at send and at `on_persist_entry` to disambiguate send-side-empty vs transitive-empty propagation
- Observable completion: the streamer case FAILs on the baseline because the short-read/malloc-fail path silently ships `PLEN=0`; the seam-routing and fence cases FAIL because those paths/fence do not exist yet
- _Requirements: 1.1, 1.2, 2.1, 3.1, 3.2, 3.3, 7.1_