Undo-block review fixes: exception-safe depth, corrected docs, real test teeth
Fixes ctor exception safety, a ValidatePtr2 guard, false SDK-citation and enforcement claims, the span-depth invariant, and vacuous fx_reclaim tests.
This commit is contained in:
+26
-14
@@ -1478,7 +1478,19 @@ static void testNoTerminatorLeavesTheSpanOpenWithTheLoopAsleep() {
|
||||
|
||||
// 2. The state-load terminator. `abandon` is the one move that clears the wakeup with
|
||||
// work still owed, which is what makes the close-FIRST ordering load-bearing rather
|
||||
// than tidy — reverse the two and the loop is asleep under an open block.
|
||||
// than tidy. Proved both ways, not asserted by construction: the WRONG order below
|
||||
// (abandon, then close) is caught mid-sequence by the same predicate the RIGHT order
|
||||
// is checked against — swapping the two lines here would make the first CHECK below
|
||||
// fail, which is the teeth `fxReclaimAbandonForStateLoad` closing FIRST relies on.
|
||||
{
|
||||
FxReclaimQueue q;
|
||||
UndoSpan span;
|
||||
q.invalidate();
|
||||
span.begin(kProjA, "ReaSampler: activate Design view", 9);
|
||||
q.abandon(); // WRONG order: wakeup cleared before the span closes
|
||||
CHECK(asleepWithTheSpanOpen(q, span)); // the exact leak the real order avoids
|
||||
span.end();
|
||||
}
|
||||
{
|
||||
FxReclaimQueue q;
|
||||
UndoSpan span;
|
||||
@@ -1492,8 +1504,13 @@ static void testNoTerminatorLeavesTheSpanOpenWithTheLoopAsleep() {
|
||||
|
||||
// 3. The project moving out from under the span. No active project sleeps the loop
|
||||
// (beginTick's nullptr arm), a tab switch does not — but both close, because the
|
||||
// span is keyed on its OWN project and neither one is it.
|
||||
for (ReaProject* arrived : {static_cast<ReaProject*>(nullptr), kProjB}) {
|
||||
// span is keyed on its OWN project and neither one is it. kProjA is the control: a
|
||||
// tick landing back on the SAME project must NOT close the span, or a live switch's
|
||||
// block would drop the flags-and-items mask it opened with mid-drain. Sweeping all
|
||||
// three, with a branch-dependent CHECK, is what gives the guard real teeth — the
|
||||
// original two-value sweep always took the close branch, so the no-close branch was
|
||||
// never exercised.
|
||||
for (ReaProject* arrived : {kProjA, static_cast<ReaProject*>(nullptr), kProjB}) {
|
||||
FxReclaimQueue q;
|
||||
UndoSpan span;
|
||||
q.invalidate();
|
||||
@@ -1503,21 +1520,16 @@ static void testNoTerminatorLeavesTheSpanOpenWithTheLoopAsleep() {
|
||||
if (span.project() != arrived) span.end();
|
||||
q.beginTick(arrived);
|
||||
|
||||
CHECK(!span.open());
|
||||
if (arrived == kProjA) CHECK(span.open()); // same project: nothing to close
|
||||
else CHECK(!span.open());
|
||||
CHECK(!asleepWithTheSpanOpen(q, span));
|
||||
}
|
||||
|
||||
// 4. The terminators with no queue move at all — a project save, an extension unload,
|
||||
// the next real switch superseding. Each is the idempotent close alone, so the
|
||||
// wakeup is whatever it already was; the implication has to hold either way.
|
||||
for (bool woken : {false, true}) {
|
||||
FxReclaimQueue q;
|
||||
UndoSpan span;
|
||||
if (woken) q.invalidate();
|
||||
span.begin(kProjA, "ReaSampler: activate Design view", 9);
|
||||
span.end();
|
||||
CHECK(!asleepWithTheSpanOpen(q, span));
|
||||
}
|
||||
// the next real switch superseding. Each is the idempotent close alone, with no
|
||||
// guard and nothing else to sweep, so it reduces to end()'s own idempotency
|
||||
// (testTheSpanOpensOnceAndClosesOnceHoweverManyTimesItIsAsked) rather than adding a
|
||||
// separate claim here.
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
Reference in New Issue
Block a user