use super::checkpoint::DigestParticipantView;
use super::test_support_external::{ExecutableRecoveredAttach, executable_recovered_attach};
use super::{
ConversationGenesis, ConversationLifecycleView, LifecycleCapsule, LifecycleView,
ParticipantConversation, SealedBindingFateToken,
};
fn fixture_capsule(fixture: &ExecutableRecoveredAttach) -> Result<LifecycleCapsule, &'static str> {
let shell = ParticipantConversation::from_checkpoint(ConversationGenesis::new(1), 4, true);
let closure = fixture.owner.closure_accounting().state();
LifecycleCapsule::capture(&LifecycleView {
sealed: None,
conversation: &shell,
covered_log_sequence: 3,
lifecycle: Some(ConversationLifecycleView {
participants: alloc::vec![DigestParticipantView::Live {
member: &fixture.member,
binding: &fixture.binding,
detach_cell: &fixture.detach_cell,
binding_origin: Some(&fixture.binding_origin),
}],
frontiers: fixture.owner.frontiers(),
retained_record_limit: fixture.owner.retained_record_limit(),
closure: &closure,
}),
})
.map_err(|_| "recovered capsule capture refused")
}
#[test]
fn checkpoint_saved_fenced_predecessor_restores_before_its_sealed_token() -> Result<(), &'static str>
{
let fixture = executable_recovered_attach().map_err(|_| "native fixture refused")?;
let capsule = fixture_capsule(&fixture)?;
let bytes = capsule.encode_canonical();
let mut restored = LifecycleCapsule::decode_canonical(&bytes)
.map_err(|_| "capsule decode refused")?
.restore()
.map_err(|_| "joint restore refused")?;
let proof = restored
.restore_checkpoint_fenced_attach(fixture.fenced_predecessor, &fixture.marker_source)
.map_err(|_| "saved native fenced source refused")?;
let token = fixture
.fate_token
.encode_checkpoint()
.map_err(|_| "token capture refused")?;
let decoded = SealedBindingFateToken::restore_checkpoint(
&token,
&fixture.binding_origin,
fixture.member.cursor(),
Some(proof),
)
.map_err(|_| "saved recovered token refused")?;
assert_eq!(
decoded
.encode_checkpoint()
.map_err(|_| "token recapture refused")?,
token
);
assert_eq!(decoded, fixture.fate_token);
assert!(
restored
.restore_checkpoint_fenced_attach(fixture.fenced_predecessor, &fixture.marker_source)
.is_err()
);
Ok(())
}
#[test]
fn checkpoint_saved_fenced_source_refusals_preserve_the_joint_owner() -> Result<(), &'static str> {
let fixture = executable_recovered_attach().map_err(|_| "native fixture refused")?;
let mut restored = fixture_capsule(&fixture)?
.restore()
.map_err(|_| "joint restore refused")?;
let mut foreign = fixture.fenced_predecessor;
foreign.participant_id += 1;
assert!(
restored
.restore_checkpoint_fenced_attach(foreign, &fixture.marker_source)
.is_err()
);
let mut altered = fixture.marker_source.clone();
let byte = altered.last_mut().ok_or("marker source absent")?;
*byte ^= 1;
assert!(
restored
.restore_checkpoint_fenced_attach(fixture.fenced_predecessor, &altered)
.is_err()
);
let mut invalid = fixture.fenced_predecessor;
invalid.predecessor_debt = crate::algebra::WideResourceVector::new(0, 0);
assert!(
restored
.restore_checkpoint_fenced_attach(invalid, &fixture.marker_source)
.is_err()
);
assert!(
restored
.restore_checkpoint_fenced_attach(fixture.fenced_predecessor, &fixture.marker_source)
.is_ok()
);
Ok(())
}