test(runtime): first supervision-restart test — child re-initialises + re-subscribes (archreview 03/U6)

Crash seam: the planned null-Snapshot OnDataChange (no SupervisorStrategy fallback needed).
Seen RED with T6 reverted: InitializeCount 1, not 2 — with a preceding ShutdownCount>=1
assertion proving the restart really happened, so the red is not ambiguous with 'never crashed'.
This commit is contained in:
Joseph Doherty
2026-08-20 10:05:45 -04:00
parent 2b9a397b2d
commit 5c7e5725a5
3 changed files with 143 additions and 1 deletions
@@ -605,3 +605,38 @@ accept `RestartDriver`. The falsification is T7, below.
Gate: `--filter "…~DriverHostActor|…~DriverInstanceActor"` → **183/183 passed** (179 before this task
plus T5's four), no test moved.
### T7 — first supervision-restart test + the force-reconnect verified negative (03/U6)
**Crash seam that landed: the planned one** — `RecordingSubscribableDriver.FireMalformedDataChange`
raises `OnDataChange` with a null `Snapshot`; `DriverInstanceActor.OnDataChangeForward` dereferences
`msg.Snapshot.SourceTimestampUtc` on the actor thread and NREs; Akka's default decider Restarts. No
fallback (`OneForOneStrategy` + an internal test message) was needed, so no production surface was
added for the test.
**RED observed against a T6-reverted build** (the `Context.Parent.Tell(new ReprovisionRequested(…))`
in `PostRestart` commented out):
```
Supervision_restart_reinitialises_and_re_subscribes_the_child [FAIL]
driver.InitializeCount should be 2 but was 1
"the restarted child was never re-initialised — it is sitting in Connecting around a driver
its own PostStop already shut down (03/S6, the worse half of 03/S16)"
```
**Deviation, and the reason for it — the first red run was AMBIGUOUS and the test was strengthened.**
`InitializeCount == 1` is equally consistent with "the child restarted and was not re-provisioned"
and with "the child never crashed at all", so a seam that silently stopped working would read as a
passing regression test forever. A preceding `AwaitAssert(ShutdownCount >= 1)` was added — `PreRestart`
runs `PostStop`, which calls `ShutdownAsync`, so that is the evidence a restart genuinely happened.
On the re-run of the falsification that assertion **passed** and the failure landed squarely on the
re-initialise, which is what makes the red observation above meaningful.
`Force_reconnect_keeps_the_desired_set_and_re_subscribes` passed in **both** the red and green runs —
correct, and the point: it is the verified negative (`ForceReconnect` reaches the same live actor, so
`_desiredRefs` survive and the reconnect's Connected entry re-applies them). It carries a 30 s budget
rather than `PresenceBudget`, because `SpawnChild` gives the child the production
`DefaultReconnectInterval` (10 s) and the retry is a periodic timer, so the reconnect cannot land
sooner; a budget is only spent on failure.
After restoring the hook: **6/6 pass**, and the class was run **20× in isolation, 20/20 green**.
@@ -48,7 +48,7 @@
{
"id": "T7",
"subject": "First real supervision-restart test + force-reconnect verified-negative regression (03/U6)",
"status": "pending",
"status": "done",
"blockedBy": [
"T4",
"T6"