#![allow(clippy::expect_used, clippy::panic)]
use alloc::vec;
use crate::algebra::{ResourceVector, WideResourceVector};
use crate::outcome::CandidatePhase;
use crate::wire::{BindingEpoch, ConnectionIncarnation, Generation};
use super::{
super::{
AdmissionOrder, ClosureAccounting, ClosureState, OrderClaims, OrderHigh, OrderLedger,
RecoverySequenceReserve, SequenceClaims, SequenceLedger,
claim_frontier::{
BindingTerminalOwner, ClaimFrontiers, ClaimFrontiersRestore, FrontierBinding,
FrontierParticipant, MarkerProvenance, MovableOrderClaim, MovableSequenceClaim,
OrderClaimFrontierRestore, OrderDirectOwner, RetainedCausalRecord,
RetainedCausalRecordKind, SequenceClaimFrontierRestore, SequenceDirectOwner,
SequenceProductRangesRestore, TerminalProductRangeRestore,
},
},
live_frontier::LiveFrontierOwner,
};
const CONVERSATION_ID: u64 = 6;
const P0: u64 = 0;
const MARKER_SEQ: u64 = 12;
fn epoch() -> BindingEpoch {
BindingEpoch::new(
ConnectionIncarnation::new(6, 0),
Generation::new(1).expect("test generation is nonzero"),
)
}
fn owner_with(cursor: u64, stored_anchors: u64) -> LiveFrontierOwner {
let binding_epoch = epoch();
let terminal_owner = BindingTerminalOwner {
participant_index: P0,
binding_epoch,
};
let exit_seq = MARKER_SEQ + 1;
let terminal_seq = exit_seq + 1;
let product_seq = terminal_seq + 1;
let sequence = SequenceLedger::try_new(
MARKER_SEQ,
SequenceClaims::new(1, 1, 0, RecoverySequenceReserve::None),
)
.expect("reconcile fixture sequence ledger is valid");
let order = OrderLedger::try_new(
OrderHigh::Allocated(0),
OrderClaims::new(1, 1, false, false).expect("reconcile fixture order claims are valid"),
)
.expect("reconcile fixture order ledger is valid");
let frontiers = ClaimFrontiers::restore(
ClaimFrontiersRestore {
conversation_id: CONVERSATION_ID,
active_identities: vec![FrontierParticipant::new(
P0,
cursor,
FrontierBinding::Bound(binding_epoch),
)],
identity_slot_limit: 1,
retained_floor: u128::from(MARKER_SEQ),
retained_record_limit: 1,
retained_records: vec![RetainedCausalRecord {
delivery_seq: MARKER_SEQ,
admission_order: AdmissionOrder::new(0, CandidatePhase::CompactionMarker, P0),
kind: RetainedCausalRecordKind::CompactionMarker {
participant_index: P0,
provenance: MarkerProvenance::NonProductM,
},
}],
active_marker_anchors: vec![MARKER_SEQ],
historical_marker_deliveries: vec![],
historical_causal_facts: vec![],
sequence: SequenceClaimFrontierRestore {
movable_claims: vec![
MovableSequenceClaim {
delivery_seq: exit_seq,
owner: SequenceDirectOwner::MembershipExit {
participant_index: P0,
},
},
MovableSequenceClaim {
delivery_seq: terminal_seq,
owner: SequenceDirectOwner::BindingTerminal(terminal_owner),
},
],
immutable_candidates: vec![],
products: SequenceProductRangesRestore {
live_times_terminal: vec![TerminalProductRangeRestore {
start: product_seq,
length: 1,
terminal: terminal_owner,
}],
..SequenceProductRangesRestore::default()
},
recovery: None,
},
order: OrderClaimFrontierRestore {
movable_claims: vec![
MovableOrderClaim {
transaction_order: 1,
owner: OrderDirectOwner::ActiveBindingTerminal(terminal_owner),
},
MovableOrderClaim {
transaction_order: 2,
owner: OrderDirectOwner::MembershipExit {
participant_index: P0,
},
},
],
immutable_candidates: vec![],
recovery: None,
},
recovery_marker_delivery_seq: None,
},
sequence,
order,
)
.expect("reconcile fixture restores from the canonical cold shape");
let accounting = ClosureAccounting::try_new(
ClosureState::Clear,
stored_anchors,
stored_anchors,
0,
0,
ResourceVector::default(),
WideResourceVector::default(),
ResourceVector::new(16, 1024),
0,
2,
)
.expect("reconcile fixture accounting is valid");
LiveFrontierOwner::from_test_parts(frontiers, accounting, vec![], 1)
}
#[test]
fn reconcile_retires_the_orphaned_anchor_and_is_idempotent() {
let mut owner = owner_with(MARKER_SEQ, 1);
assert_eq!(owner.frontiers().unaccepted_marker_anchor_count(), 0);
assert_eq!(owner.closure_accounting().marker_anchors(), 1);
assert_eq!(owner.reconcile_orphaned_marker_anchors(), 1);
assert_eq!(owner.closure_accounting().marker_anchors(), 0);
assert_eq!(owner.reconcile_orphaned_marker_anchors(), 0);
assert_eq!(owner.closure_accounting().marker_anchors(), 0);
}
#[test]
fn reconcile_leaves_an_in_step_unaccepted_marker_alone() {
let mut owner = owner_with(MARKER_SEQ - 1, 1);
assert_eq!(owner.frontiers().unaccepted_marker_anchor_count(), 1);
assert_eq!(owner.reconcile_orphaned_marker_anchors(), 0);
assert_eq!(owner.closure_accounting().marker_anchors(), 1);
}
#[test]
fn reconcile_never_touches_the_derived_ahead_direction() {
let mut owner = owner_with(MARKER_SEQ - 1, 0);
assert_eq!(owner.frontiers().unaccepted_marker_anchor_count(), 1);
assert_eq!(owner.closure_accounting().marker_anchors(), 0);
assert_eq!(owner.reconcile_orphaned_marker_anchors(), 0);
assert_eq!(owner.closure_accounting().marker_anchors(), 0);
}