theTeardownFaultReallyFires

fun theTeardownFaultReallyFires(): TestResult

The precondition of leaveIsIdempotentEvenWhenTeardownFails and leaveDoesNotMintACancellationWhenTeardownIsSlow, asserted rather than assumed.

Those two properties are satisfied by a room that never sees a failing teardown at all — a rig whose TeardownFault arms were quietly no-ops, or a FaultyLoom that is simply not the loom the harness's factories weave through. Either makes both pass for the wrong reason, which is the vacuity this whole axis exists to remove rather than relocate. So this measures the fixture directly: arm a link, close it, and check that the close threw the very throwable that was injected and that the seam counted the arm firing.

Same role as MeshDisplacementDrainConformanceSuite.theFixtureReallyDiscardsOnClose, and it fails by name for the same reason: a fixture that does not do what the properties behind it assume must red here, loudly, not evaporate into two quiet greens over there.

Both arms, not just the failing one, and the second one is here because it was missing. The first draft of this test measured only TeardownFault.Fails — and a mutation that made TeardownFault.Slow stop delaying was green everywhere in the tree, because SeamRoom.leave bounds nothing today so a teardown of zero duration mints no cancellation either. The Slow arm would have quietly stopped being about a slow teardown, and the property built on it would have gone on passing. Virtual time is the direct measurement, so that is what is measured.

The identity check (===, not a type match) is deliberate — a rig that threw some exception, or wrapped the injected one, would still be lying about what a transport's close does, and a type match would wave both through.

The links measured here carry no Room, and that is load-bearing

An earlier draft armed the fault on the seams under the harness's rooms, and its exactly-once assertions passed only because of the reference's shape — the third instance in this change of a fix resting on the thing it was fixing. Two windows were open in it, both closed by InMemoryLoom alone:

  • The TeardownFault.Fails window. The delegate's close runs while the arm is still live. InMemorySeam.close publishes Torn and then does only non-suspending work, so the room's torn-watcher cannot interleave. Any fabric whose close genuinely suspends after publishing Torn — a WebSocket close handshake, a TCP shutdown — lets that watcher re-enter close with Fails still armed: the count becomes 2, and the injected throwable is thrown a second time on a coroutine where nothing catches it.

  • The TeardownFault.Slow window. SLOW_TEARDOWN is several times fastHeartbeatConfig's timeout and twice its reconnect window. It is inert only because the default harness keeps its injected clock decoupled from virtual time; a harness wiring the two together — defensible, arguably more faithful — has a peer reach MembershipEvent.HostLost inside the delay and leave, closing again.

Either way the red would arrive blaming the fixture for a fault of the room, which is the wrong diagnosis handed to the wrong reader. So both arms are measured on links woven straight off the injector with no Room attached: nothing can race a close nobody owns, and "exactly once per close" becomes a property of FaultySeam rather than an accident of SeamRoom's teardown. The host room exists only so the fabric has something to join.