tracking: read the ledger's version, not just write it; clear owned on any block; channel-correct prune recovery
This commit is contained in:
@@ -148,8 +148,44 @@ static void testUnreadableUsageBlocksPruneAndNamesIt() {
|
||||
const ProtectionAnswer answer = pruneProtection(state);
|
||||
CHECK(answer.blocked);
|
||||
CHECK(!answer.ledgerUnreadable);
|
||||
CHECK(!answer.ledgerFutureVersion);
|
||||
CHECK(answer.unreadableUsageKeys.size() == 1);
|
||||
CHECK(answer.unreadableUsageKeys[0] == "rsusage_BROKEN");
|
||||
|
||||
// The belt-and-braces guard is symmetric: a usage-only block ALSO withholds
|
||||
// ownedPaths, even though the ledger itself read fine, so a caller that ignored
|
||||
// `blocked` computes an empty orphan set rather than deleting with degraded
|
||||
// protection.
|
||||
CHECK(answer.ownedPaths.empty());
|
||||
CHECK(reclaim::pruneOrphans({"bank/orphan.wav"}, {}, answer.ownedPaths).empty());
|
||||
|
||||
// heldPaths is the one list that stays populated on a block — it only ever widens
|
||||
// the protected set, so withholding it would be the unsafe direction.
|
||||
CHECK(contains(answer.heldPaths, "bank/x.wav"));
|
||||
}
|
||||
|
||||
// A ledger written by a NEWER build blocks exactly like a corrupt one, but is
|
||||
// reported separately: the operator advice differs (clearing a corrupt blob is
|
||||
// repair; clearing a newer build's is destruction).
|
||||
static void testFutureVersionLedgerBlocksAndIsReportedSeparately() {
|
||||
const LedgerLoad load = loadLedger("{\"v\":99,\"records\":[]}");
|
||||
CHECK(load.status == LedgerStatus::FutureVersion);
|
||||
|
||||
OriginLedger populated;
|
||||
populated.record(originOf("bank/would-be-orphan.wav", OriginKind::Capture, "S-1"));
|
||||
const UsageFoldResult fold = foldLive({}, {});
|
||||
|
||||
const TrackingState state{load.status, populated, fold};
|
||||
const ProtectionAnswer answer = pruneProtection(state);
|
||||
CHECK(answer.blocked);
|
||||
CHECK(answer.ledgerFutureVersion);
|
||||
CHECK(!answer.ledgerUnreadable);
|
||||
CHECK(answer.ownedPaths.empty());
|
||||
CHECK(reclaim::pruneOrphans({"bank/would-be-orphan.wav"}, {},
|
||||
answer.ownedPaths).empty());
|
||||
|
||||
// And the replace-vs-add question abstains rather than allowing a replace.
|
||||
CHECK(tiedUsageExists(state, "bank/would-be-orphan.wav", "") == Answer::Indeterminate);
|
||||
}
|
||||
|
||||
// An unreadable ledger blocks too, AND leaves ownedPaths empty — so a caller that
|
||||
@@ -178,12 +214,19 @@ static void testUnreadableLedgerBlocksAndYieldsNoOrphans() {
|
||||
// Both blockers at once must both be reported — the operator needs to fix both.
|
||||
static void testBothBlockersReported() {
|
||||
const OriginLedger empty;
|
||||
const UsageFoldResult fold = foldLive({unreadable("rsusage_BROKEN")}, {"{T1}"});
|
||||
const UsageFoldResult fold = foldLive(
|
||||
{usage("rsusage_A", "{T1}", {UsageHold{"S-held", "bank/held.wav"}}),
|
||||
unreadable("rsusage_BROKEN")},
|
||||
{"{T1}"});
|
||||
const TrackingState state{LedgerStatus::Unreadable, empty, fold};
|
||||
const ProtectionAnswer answer = pruneProtection(state);
|
||||
CHECK(answer.blocked);
|
||||
CHECK(answer.ledgerUnreadable);
|
||||
CHECK(answer.unreadableUsageKeys.size() == 1);
|
||||
// heldPaths survives a double block: the fold's protect-all set only ever widens
|
||||
// what prune protects, so withholding it would be the unsafe direction.
|
||||
CHECK(contains(answer.heldPaths, "bank/held.wav"));
|
||||
CHECK(answer.ownedPaths.empty());
|
||||
}
|
||||
|
||||
// A record that exists but whose track hosts no identified instance still protects
|
||||
@@ -260,9 +303,6 @@ static void testSoleHolderExcludingItselfAnswersNo() {
|
||||
CHECK(tiedUsageExists(state, "bank/src.wav", "rsusage_ME") == Answer::No);
|
||||
}
|
||||
|
||||
// A `unioned` record carries more than one incarnation's holds, so it can never be
|
||||
// attributed to a single owner — excluding it could hide a sibling's tie, which is
|
||||
// the under-protecting direction.
|
||||
static void testUnionedRecordIsNeverExcludedAsOwn() {
|
||||
OriginLedger ledger;
|
||||
ledger.record(originOf("bank/src.wav", OriginKind::Capture, "S-src"));
|
||||
@@ -404,6 +444,7 @@ int main() {
|
||||
testLiveHoldProtectsDeReferencedCapture();
|
||||
testUnreadableUsageBlocksPruneAndNamesIt();
|
||||
testUnreadableLedgerBlocksAndYieldsNoOrphans();
|
||||
testFutureVersionLedgerBlocksAndIsReportedSeparately();
|
||||
testBothBlockersReported();
|
||||
testZeroIdentifiedInstancesStillProtects();
|
||||
testUnreadableStateNeverAnswersNo();
|
||||
|
||||
Reference in New Issue
Block a user