Extend the park trust test to the FX chain, name the refused tracks, and stop reprinting an unchanged refusal

This commit is contained in:
2026-08-05 17:10:19 -04:00
parent 203961f41c
commit 5376ab085c
8 changed files with 318 additions and 86 deletions
+62 -18
View File
@@ -242,31 +242,54 @@ static void testRestorePlanOpsRebuildTheSlotKeyedSnapshotVerbatim() {
// an absent snapshot — discardDeferredFxParks drops intents whose flag writes
// already landed — so the chain itself has to be asked.
// The live values the fold reads, keyed by Flag — so an assertion names the flag
// it varies rather than a position in makeParkPlan's op order.
struct FlagValues {
int showInTcp = 0, showInMixer = 0, mainSend = 0, fxEnable = 0;
int operator()(Flag f) const {
switch (f) {
case Flag::ShowInTcp: return showInTcp;
case Flag::ShowInMixer: return showInMixer;
case Flag::MainSend: return mainSend;
case Flag::FxEnable: return fxEnable;
}
return -1;
}
};
static void testAChainSittingAtEveryValueTheParkWouldWriteReadsAsParked() {
// The four zeros are what a parked track's driven flags actually read; if
// makeParkPlan ever writes something else, this is the test that says so.
const TrackPlan park = makeParkPlan("{A}", /*fxCount=*/0);
CHECK(park.flags.size() == 4);
CHECK(parkFlagsAlreadyApplied(park.flags, {0, 0, 0, 0}));
CHECK(parkFlagsAlreadyApplied(park.flags, FlagValues{0, 0, 0, 0}));
}
static void testOneFlagStillAtTheUsersValueMeansNoParkReachedTheChain() {
const TrackPlan park = makeParkPlan("{A}", /*fxCount=*/0);
// Flag order is ShowInTcp, ShowInMixer, MainSend, FxEnable — each alone is
// enough to prove the chain was never parked.
CHECK(!parkFlagsAlreadyApplied(park.flags, {1, 0, 0, 0}));
CHECK(!parkFlagsAlreadyApplied(park.flags, {0, 1, 0, 0}));
CHECK(!parkFlagsAlreadyApplied(park.flags, {0, 0, 1, 0}));
CHECK(!parkFlagsAlreadyApplied(park.flags, {0, 0, 0, 1}));
// Each case varies exactly one flag, so together they also prove all four are
// in the plan: a missing op makes its case read parked and fail here.
CHECK(!parkFlagsAlreadyApplied(park.flags, FlagValues{1, 0, 0, 0}));
CHECK(!parkFlagsAlreadyApplied(park.flags, FlagValues{0, 1, 0, 0}));
CHECK(!parkFlagsAlreadyApplied(park.flags, FlagValues{0, 0, 1, 0}));
CHECK(!parkFlagsAlreadyApplied(park.flags, FlagValues{0, 0, 0, 1}));
}
static void testAnEmptyOrMismatchedPlanProvesNothing() {
const TrackPlan park = makeParkPlan("{A}", /*fxCount=*/0);
static void testAnEmptyPlanProvesNothing() {
CHECK(!parkFlagsAlreadyApplied(std::vector<TrackFlagOp>{}, FlagValues{0, 0, 0, 0}));
}
CHECK(!parkFlagsAlreadyApplied({}, {}));
CHECK(!parkFlagsAlreadyApplied(park.flags, {0, 0, 0}));
static void testEitherHalfOfTheChainReadingParkedIsEnoughToRefuse() {
// The disjunction, pinned: a snapshot has a flag half and an FX half, and each
// is the only source of truth for its own. An AND here would re-open the
// defect one layer down — flags clean, FX still offline, snapshotted as truth.
CHECK(!chainReadsParked(/*parkFlagsRead=*/false, /*anyFxOffline=*/false));
CHECK(chainReadsParked(/*parkFlagsRead=*/true, /*anyFxOffline=*/false));
CHECK(chainReadsParked(/*parkFlagsRead=*/false, /*anyFxOffline=*/true));
CHECK(chainReadsParked(/*parkFlagsRead=*/true, /*anyFxOffline=*/true));
}
static void testACleanChainIsSnapshottedThenParked() {
@@ -288,11 +311,30 @@ static void testAParkedChainWithNoSnapshotIsRefusedRatherThanResnapshotted() {
CHECK(decidePark(/*haveSnapshot=*/false, /*chainReadsParked=*/true) == ParkAction::Refuse);
}
static void testRefusalIsReportedWithItsTrackCountAndSaysNothingWhenNoneWereRefused() {
CHECK(describeRefusedParks(0).empty());
CHECK(describeRefusedParks(-1).empty());
CHECK(describeRefusedParks(1).find("1 track ") != std::string::npos);
CHECK(describeRefusedParks(3).find("3 tracks ") != std::string::npos);
static void testRefusalNamesEveryRefusedTrackAndSaysNothingWhenNoneWere() {
CHECK(describeRefusedParks({}).empty());
const std::string one = describeRefusedParks({"Bass"});
CHECK(one.find("1 track ") != std::string::npos);
CHECK(one.find("Bass") != std::string::npos);
const std::string two = describeRefusedParks({"Bass", "Drum bus"});
CHECK(two.find("2 tracks ") != std::string::npos);
CHECK(two.find("Bass") != std::string::npos);
CHECK(two.find("Drum bus") != std::string::npos);
}
static void testRefusalRecoveryNamesThePerFxHalfAndAssertsNoCause() {
const std::string msg = describeRefusedParks({"Bass"});
// I_FXEN is the chain bypass: a user who restores only the four flags leaves
// every individually offlined FX offline and walks straight back into a
// refusal, so the recovery has to spell the per-FX step out.
CHECK(msg.find("every FX in its chain online") != std::string::npos);
// And it must not name a cause: the pair has several routes, and on a track
// the user themselves keeps hidden/bypassed there was no lost state at all.
CHECK(msg.find("undo") == std::string::npos);
CHECK(msg.find("lost") == std::string::npos);
}
// -- re-entrancy -------------------------------------------------------------
@@ -361,11 +403,13 @@ int main() {
testRestorePlanOpsRebuildTheSlotKeyedSnapshotVerbatim();
testAChainSittingAtEveryValueTheParkWouldWriteReadsAsParked();
testOneFlagStillAtTheUsersValueMeansNoParkReachedTheChain();
testAnEmptyOrMismatchedPlanProvesNothing();
testAnEmptyPlanProvesNothing();
testEitherHalfOfTheChainReadingParkedIsEnoughToRefuse();
testACleanChainIsSnapshottedThenParked();
testAHeldSnapshotIsNeverOverwrittenWhateverTheChainReads();
testAParkedChainWithNoSnapshotIsRefusedRatherThanResnapshotted();
testRefusalIsReportedWithItsTrackCountAndSaysNothingWhenNoneWereRefused();
testRefusalNamesEveryRefusedTrackAndSaysNothingWhenNoneWere();
testRefusalRecoveryNamesThePerFxHalfAndAssertsNoCause();
testTakeDetachesEverythingAndLeavesTheQueueEmpty();
testIntentsArrivingDuringADrainSurviveIt();