Decompose oversized Rust files by responsibility

This commit is contained in:
ms2k 2026-07-19 03:02:44 +09:00
commit ee9201b057
3 changed files with 18648 additions and 18513 deletions

View file

@ -0,0 +1,507 @@
fn assert_no_guest_action_after(factory: &MockFactory, marker: &str) {
let log = factory.log.lock().unwrap();
let marker = log.iter().position(|action| action == marker).unwrap();
assert!(
log[marker + 1..]
.iter()
.all(|action| !action.starts_with("query:") && !action.starts_with("signal:"))
);
}
#[test]
fn acquisition_refuses_authority_outside_the_committed_sandbox() {
let session = id(6);
let (fixture, _factory, mut engine) = setup(&[session]);
let mut request = acquisition(session);
request.host_coordinator = process(700);
assert!(matches!(
engine.acquire(&request),
Err(TerminalError::AuthorityMismatch)
));
assert!(
fixture
.store
.snapshot()
.unwrap()
.session_terminals
.is_empty()
);
}
#[test]
fn acquisition_requires_attached_current_session() {
for phase in [
SessionPhase::New,
SessionPhase::Waiting,
SessionPhase::Registering,
] {
let session = id(6);
let fixture = Fixture::new(&[]);
fixture.insert_session(session, phase);
let (_factory, mut engine) = engine_for(&fixture);
assert!(matches!(
engine.acquire(&acquisition(session)),
Err(TerminalError::AuthorityMismatch)
));
assert!(
fixture
.store
.snapshot()
.unwrap()
.session_terminals
.is_empty()
);
}
}
#[test]
fn durable_detach_failure_and_sandbox_release_revoke_active_terminal() {
for revoke in ["closed", "failed", "sandbox-release"] {
let session = id(6);
let (fixture, factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
match revoke {
"closed" => fixture.set_session_phase(session, SessionPhase::Closed),
"failed" => fixture.set_session_phase(session, SessionPhase::Failed),
"sandbox-release" => fixture.release_sandbox(),
_ => unreachable!(),
}
assert!(matches!(
engine.handle(
GenerationId::new(7),
SessionTerminalEvent::Input(TerminalInput {
session_id: session,
bytes: b"refused".to_vec(),
}),
),
Err(TerminalError::AuthorityMismatch)
));
assert!(!engine.contains(session));
assert_no_group_signal(&factory);
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::ReleaseIntent
);
}
}
#[test]
fn domain_container_hc_and_authority_read_mismatch_use_host_only_release() {
for mismatch in ["domain", "container", "host-coordinator"] {
let session = id(6);
let (fixture, factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
let request = &mut engine.active.get_mut(&session).unwrap().request;
match mismatch {
"domain" => request.domain_id = DomainId::new(bytes(80)),
"container" => request.container_id = ContainerId::new(bytes(81)),
"host-coordinator" => request.host_coordinator = process(800),
_ => unreachable!(),
}
assert!(matches!(
engine.handle(
GenerationId::new(7),
SessionTerminalEvent::Input(TerminalInput {
session_id: session,
bytes: b"refused".to_vec(),
}),
),
Err(TerminalError::AuthorityMismatch)
));
assert_no_group_signal(&factory);
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::ReleaseIntent
);
}
let session = id(6);
let fixture = Fixture::new(&[session]);
let store = Arc::new(FailingRunningStore::new(Arc::clone(&fixture.store)));
let (factory, mut engine) = engine_for_store(store.clone());
engine.acquire(&acquisition(session)).unwrap();
store.arm_snapshot_failure();
assert!(matches!(
engine.poll(session, GenerationId::new(7)),
Err(TerminalError::Store(DomainStoreError::Io(_)))
));
assert_no_group_signal(&factory);
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::ReleaseIntent
);
}
#[test]
fn explicit_close_and_loss_revalidate_before_guest_cleanup() {
let session = id(6);
let (fixture, factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
fixture.release_sandbox();
engine
.handle(
GenerationId::new(7),
SessionTerminalEvent::Close(lazaret_core::records::SessionClose {
session_id: session,
}),
)
.unwrap();
assert_no_group_signal(&factory);
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::ReleaseIntent
);
let (fixture, factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
fixture.add_newer_generation();
engine
.lose(session, GenerationId::new(7), TerminalLoss::PtyLost)
.unwrap();
assert_no_group_signal(&factory);
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::ReleaseIntent
);
}
#[test]
fn grace_wait_revocation_and_read_error_stop_all_later_guest_actions() {
let session = id(6);
let (fixture, factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
let store = Arc::clone(&fixture.store);
let log = Arc::clone(&factory.log);
factory.state(0).lock().unwrap().group_query_hook = Some((
2,
Arc::new(move || {
log.lock().unwrap().push("revoke:sandbox".into());
release_sandbox(&store);
}),
));
engine
.handle(
GenerationId::new(7),
SessionTerminalEvent::Close(lazaret_core::records::SessionClose {
session_id: session,
}),
)
.unwrap();
assert_no_guest_action_after(&factory, "revoke:sandbox");
let state = factory.state(0);
assert!(state.lock().unwrap().resources.exec_reaped);
assert!(!state.lock().unwrap().resources.pty_open);
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::ReleaseIntent
);
let fixture = Fixture::new(&[session]);
let store = Arc::new(FailingRunningStore::new(Arc::clone(&fixture.store)));
let (factory, mut engine) = engine_for_store(store.clone());
engine.acquire(&acquisition(session)).unwrap();
let failing_store = Arc::clone(&store);
let log = Arc::clone(&factory.log);
factory.state(0).lock().unwrap().group_query_hook = Some((
2,
Arc::new(move || {
log.lock().unwrap().push("revoke:read-error".into());
failing_store.arm_snapshot_failure();
}),
));
engine
.handle(
GenerationId::new(7),
SessionTerminalEvent::Close(lazaret_core::records::SessionClose {
session_id: session,
}),
)
.unwrap();
assert_no_guest_action_after(&factory, "revoke:read-error");
let state = factory.state(0);
assert!(state.lock().unwrap().resources.exec_reaped);
assert!(!state.lock().unwrap().resources.pty_open);
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::ReleaseIntent
);
}
#[test]
fn stale_caller_and_superseded_generation_refuse_without_cross_generation_action() {
let session = id(6);
let (fixture, factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
assert!(matches!(
engine.handle(
GenerationId::new(8),
SessionTerminalEvent::Signal(TerminalSignal {
session_id: session,
signal: TerminalSignalKind::Interrupt,
}),
),
Err(TerminalError::StaleGeneration)
));
assert_no_group_signal(&factory);
assert!(!engine.contains(session));
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::ReleaseIntent
);
let (fixture, factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
fixture.add_newer_generation();
assert!(matches!(
engine.poll(session, GenerationId::new(7)),
Err(TerminalError::AuthorityMismatch)
));
assert!(!engine.contains(session));
assert_no_group_signal(&factory);
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::ReleaseIntent
);
}
#[test]
fn resize_and_terminal_signals_use_the_exact_group_map() {
let session = id(6);
let (_fixture, factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
engine
.handle(
GenerationId::new(7),
SessionTerminalEvent::Resize(TerminalResize {
session_id: session,
rows: NonZeroU16::new(40).unwrap(),
columns: NonZeroU16::new(120).unwrap(),
pixel_width: 0,
pixel_height: 0,
}),
)
.unwrap();
for (kind, expected) in [
(TerminalSignalKind::Interrupt, "signal:INT"),
(TerminalSignalKind::Quit, "signal:QUIT"),
(TerminalSignalKind::Suspend, "signal:TSTP"),
] {
engine
.handle(
GenerationId::new(7),
SessionTerminalEvent::Signal(TerminalSignal {
session_id: session,
signal: kind,
}),
)
.unwrap();
assert_eq!(factory.log.lock().unwrap().last().unwrap(), expected);
}
assert_eq!(
&factory.log.lock().unwrap()[..2],
&["resize:40x120", "signal:WINCH"]
);
}
#[test]
fn changed_guest_identity_refuses_numeric_group_action() {
let session = id(6);
let (fixture, factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
factory.state(0).lock().unwrap().guest.identity_mismatch = true;
assert!(matches!(
engine.handle(
GenerationId::new(7),
SessionTerminalEvent::Signal(TerminalSignal {
session_id: session,
signal: TerminalSignalKind::Interrupt,
}),
),
Err(TerminalError::GuestIdentityMismatch)
));
assert!(factory.log.lock().unwrap().is_empty());
assert!(matches!(
engine.handle(
GenerationId::new(7),
SessionTerminalEvent::Close(lazaret_core::records::SessionClose {
session_id: session,
}),
),
Err(TerminalError::GuestIdentityMismatch)
));
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::ReleaseIntent
);
}
#[test]
fn absent_leader_with_live_group_retains_release_until_group_is_empty() {
let session = id(6);
let (fixture, factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
{
let state = factory.state(0);
let mut state = state.lock().unwrap();
state.guest.leader_present = false;
state.guest.group_present = true;
}
assert!(matches!(
engine.handle(
GenerationId::new(7),
SessionTerminalEvent::Close(lazaret_core::records::SessionClose {
session_id: session,
}),
),
Err(TerminalError::GuestIdentityMismatch)
));
let state = factory.state(0);
assert!(state.lock().unwrap().resources.exec_reaped);
assert!(!state.lock().unwrap().resources.pty_open);
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::ReleaseIntent
);
state.lock().unwrap().guest.group_present = false;
engine
.handle(
GenerationId::new(7),
SessionTerminalEvent::Close(lazaret_core::records::SessionClose {
session_id: session,
}),
)
.unwrap();
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::Clean
);
}
#[test]
#[allow(clippy::too_many_lines)]
fn running_store_failures_release_every_live_partial_handle() {
for point in [
StoreFailurePoint::Snapshot,
StoreFailurePoint::Write,
StoreFailurePoint::Commit,
] {
for persistent in [false, true] {
let session = id(6);
let fixture = Fixture::new(&[session]);
let store = Arc::new(FailingRunningStore::new(Arc::clone(&fixture.store)));
let recorder = HostCoordinatorTerminalRecorder::with_store(store.clone());
let request = acquisition(session);
recorder
.put(
terminal_snapshot(
&request,
SessionTerminalState::Intent,
PersistedHostProcessOwnership::unassigned(),
None,
PersistedHostProcessOwnership::unassigned(),
None,
)
.unwrap(),
)
.unwrap();
let pty = PtyIdentity {
master_fd: FileDescriptor::new(9),
device: DeviceId::new(10),
inode: InodeId::new(11),
};
recorder
.put(
staged_terminal(
&request,
pty,
StagedProcessOwnership::v1(
request.domain_id,
request.generation_id,
request.coordinator_id,
lazaret_core::records::HostProcessOwnershipSlot::SessionTerminalExecClient(
request.session_id,
),
process(90),
),
)
.unwrap(),
)
.unwrap();
let guest = GuestProcessIdentity {
leader_pid: GuestProcessId::new(41),
leader_start_time: GuestProcessStartTimeTicks::new(101),
process_group_id: GuestProcessGroupId::new(41),
};
let running = terminal_snapshot(
&request,
SessionTerminalState::Running,
PersistedHostProcessOwnership::committed(request.host_coordinator),
Some(pty),
PersistedHostProcessOwnership::committed(process(90)),
Some(guest),
)
.unwrap();
let state = Arc::new(Mutex::new(MockState {
output: VecDeque::new(),
log: Arc::new(Mutex::new(Vec::new())),
guest: MockGuestState {
group_present: true,
leader_present: true,
identity_mismatch: false,
clears_after_signal: "HUP",
},
resources: MockResourceState {
exec_exited: false,
exec_reaped: false,
pty_open: true,
},
group_queries: 0,
group_query_hook: None,
}));
let mut process_handle = MockProcess {
state: Arc::clone(&state),
};
store.arm(point, persistent);
let error = commit_running_or_cleanup(
&recorder,
&request,
running,
pty,
process(90),
guest,
&mut process_handle,
)
.unwrap_err();
match error {
TerminalError::AcquisitionCleanup { cleanup: None, .. } if !persistent => {}
TerminalError::AcquisitionCleanup {
cleanup: Some(_), ..
} if persistent => {}
error => panic!("unexpected cleanup result: {error}"),
}
let state = state.lock().unwrap();
assert_eq!(state.guest.group_present, persistent);
assert_eq!(
state
.log
.lock()
.unwrap()
.iter()
.any(|action| action.starts_with("signal:")),
!persistent
);
assert!(state.resources.exec_exited);
assert!(state.resources.exec_reaped);
assert!(!state.resources.pty_open);
drop(state);
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
if persistent {
SessionTerminalState::Intent
} else {
SessionTerminalState::Clean
}
);
}
}
}

View file

@ -0,0 +1,142 @@
#[test]
fn merged_output_is_ordered_and_prompt_route_isolated_by_session() {
let first = id(6);
let second = id(7);
let (fixture, factory, mut engine) = setup(&[first, second]);
engine.acquire(&acquisition(first)).unwrap();
engine.acquire(&acquisition(second)).unwrap();
factory
.state(0)
.lock()
.unwrap()
.output
.extend([b"one".to_vec(), b"two".to_vec()]);
factory
.state(1)
.lock()
.unwrap()
.output
.push_back(b"other".to_vec());
fixture.set_session_phase(first, SessionPhase::Prompting);
engine
.set_route(first, GenerationId::new(7), TerminalRoute::Prompt)
.unwrap();
assert!(engine.poll(first, GenerationId::new(7)).unwrap().is_empty());
assert_eq!(
engine.poll(second, GenerationId::new(7)).unwrap(),
vec![SessionTerminalMessage::Output(TerminalOutput {
session_id: second,
bytes: b"other".to_vec(),
})]
);
fixture.set_session_phase(first, SessionPhase::Attached);
engine
.set_route(first, GenerationId::new(7), TerminalRoute::Sandbox)
.unwrap();
let mut merged = Vec::new();
for _ in 0..2 {
let messages = engine.poll(first, GenerationId::new(7)).unwrap();
let [SessionTerminalMessage::Output(output)] = messages.as_slice() else {
panic!("expected one merged output message");
};
merged.extend_from_slice(&output.bytes);
}
assert_eq!(merged, b"onetwo");
}
#[test]
fn close_cancels_route_then_bounds_drain_and_emits_one_final_exit() {
let session = id(6);
let (fixture, factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
factory.state(0).lock().unwrap().guest.clears_after_signal = "KILL";
factory
.state(0)
.lock()
.unwrap()
.output
.extend((0..10).map(|_| vec![b'x'; MAX_OUTPUT_BYTES]));
let messages = engine
.handle(
GenerationId::new(7),
SessionTerminalEvent::Close(lazaret_core::records::SessionClose {
session_id: session,
}),
)
.unwrap();
let bytes = messages
.iter()
.filter_map(|message| match message {
SessionTerminalMessage::Output(output) => Some(output.bytes.len()),
SessionTerminalMessage::Exit(_) => None,
})
.sum::<usize>();
assert_eq!(bytes, MAX_DRAIN_BYTES);
assert!(
matches!(messages.last(), Some(SessionTerminalMessage::Exit(exit)) if exit.exit_code() == Some(17))
);
let log = factory.log.lock().unwrap();
assert_eq!(log[0], "cancel-route");
assert_eq!(
log.iter()
.filter(|action| action.starts_with("signal:"))
.map(String::as_str)
.collect::<Vec<_>>(),
["signal:HUP", "signal:TERM", "signal:KILL"]
);
drop(log);
assert!(!engine.contains(session));
assert!(matches!(
engine.handle(
GenerationId::new(7),
SessionTerminalEvent::Input(TerminalInput {
session_id: session,
bytes: b"reattach".to_vec(),
}),
),
Err(TerminalError::UnknownSession)
));
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::Clean
);
}
#[test]
fn disconnect_component_loss_and_hard_hc_loss_never_reattach() {
for loss in [
TerminalLoss::ClientDisconnected,
TerminalLoss::PtyLost,
TerminalLoss::ExecClientLost,
] {
let session = id(6);
let (_fixture, _factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
let messages = engine.lose(session, GenerationId::new(7), loss).unwrap();
assert_eq!(
messages.is_empty(),
loss == TerminalLoss::ClientDisconnected
);
assert!(!engine.contains(session));
}
let session = id(6);
let (fixture, factory, mut engine) = setup(&[session]);
engine.acquire(&acquisition(session)).unwrap();
assert!(
engine
.lose(
session,
GenerationId::new(7),
TerminalLoss::HostCoordinatorLost,
)
.unwrap()
.is_empty()
);
assert!(!engine.contains(session));
assert_no_group_signal(&factory);
assert_eq!(
fixture.store.snapshot().unwrap().session_terminals[0].state(),
SessionTerminalState::Running
);
}

View file

@ -0,0 +1,204 @@
#[test]
#[allow(clippy::too_many_lines)]
fn prompt_adapter_retains_resume_resize_before_authenticated_denial() {
let generation = GenerationIdentity {
agent_profile: "trusted".into(),
domain_id: DomainId::new(bytes(1)),
generation_id: GenerationId::new(7),
configuration_fingerprint: ConfigurationFingerprint::new(bytes(2)),
coordinator_id: CoordinatorId::new(bytes(3)),
sandbox_id: SandboxId::new(bytes(5)),
};
let mut trust_anchor = TrustAnchor::create(generation.clone()).unwrap();
let publication = trust_anchor.publication_identity();
let coordinator_key = trust_anchor.coordinator_protocol_key();
let credentials = trust_anchor.take_sandbox_credential_bundle().unwrap();
let sandbox_key = SigningKey::from_bytes(
credentials
.sandbox_private_key
.as_slice()
.try_into()
.unwrap(),
);
let anchor_key = SigningKey::from_bytes(&bytes(61));
let binding = SessionBinding {
generation_identity: generation,
cli_id: ClientId::new(bytes(62)),
session_id: SessionId::new(bytes(63)),
session_anchor_public_key: anchor_key.verifying_key().to_bytes().to_vec(),
};
let capability = issue_session_capability(
binding.clone(),
credentials.coordinator_protocol_credential().credential_id,
credentials.sandbox_protocol_credential().credential_id,
&coordinator_key,
)
.unwrap();
let authority = VerifiedSession::new(
publication.trust_manifest_sha256,
credentials.trust_manifest.tls_ca_sha256,
&credentials.trust_manifest,
binding.clone(),
credentials.coordinator_protocol_credential(),
credentials.sandbox_protocol_credential(),
capability.clone(),
)
.unwrap();
let fixture = Fixture::new(&[]);
let session_anchor_id =
SessionAnchorId::new(Sha256::digest(&binding.session_anchor_public_key).into());
let mut session = Session {
generation_id: GenerationId::new(7),
session_id: binding.session_id,
cli_id: binding.cli_id,
session_anchor_id,
session_phase: SessionPhase::Registering,
};
fixture
.store
.apply(&[DomainStoreMutation::PutSession(session.clone())])
.unwrap();
session.session_phase = SessionPhase::Attached;
fixture
.store
.apply(&[DomainStoreMutation::PutSession(session)])
.unwrap();
let prompt_transport = Arc::new(SessionPromptTransport::new(Arc::clone(&fixture.store)));
let factory = Arc::new(MockFactory::default());
let mut engine = SessionTerminalEngine::new(
Arc::clone(&fixture.store),
factory.clone(),
prompt_transport.clone(),
);
engine.acquire(&acquisition(binding.session_id)).unwrap();
let request = MailboxRequest::new(
binding.clone(),
RequestId::new(bytes(64)),
capability,
credentials.sandbox_protocol_credential().credential_id,
vec![b"/usr/bin/tool".to_vec()],
"update host metadata".into(),
)
.unwrap();
let signed_request = encode_signed(&request, &sandbox_key).unwrap();
let expected_prompt = prompt_transport
.queue_signed_request(authority, &signed_request)
.unwrap();
let engine = Arc::new(Mutex::new(engine));
let mut control = RunscInteractiveControlSession {
engine: Arc::clone(&engine),
prompt_transport: prompt_transport.clone(),
generation_id: GenerationId::new(7),
session_id: binding.session_id,
};
let batch = control
.exchange(InteractiveSessionEvent::Poll {
session_id: binding.session_id,
})
.unwrap();
assert_eq!(
batch.messages,
vec![InteractiveSessionMessage::Prompt(expected_prompt.clone())]
);
let resumed_size = TerminalResize {
session_id: binding.session_id,
rows: NonZeroU16::new(55).unwrap(),
columns: NonZeroU16::new(144).unwrap(),
pixel_width: 1_440,
pixel_height: 900,
};
control
.exchange(InteractiveSessionEvent::Terminal(
SessionTerminalEvent::Resize(resumed_size),
))
.unwrap();
let signed_decision = encode_signed(
&DeveloperDecision {
protocol_version: ProtocolVersion::V1,
session_binding: binding.clone(),
request_id: expected_prompt.request_id,
request_sha256: expected_prompt.request_sha256,
decision: DeveloperDecisionKind::Deny,
approved_command_argv: Vec::new(),
},
&anchor_key,
)
.unwrap();
control
.exchange(InteractiveSessionEvent::PromptDecision {
session_id: binding.session_id,
signed_decision: signed_decision.clone(),
})
.unwrap();
let routed = prompt_transport
.take_decision(binding.session_id)
.unwrap()
.unwrap();
assert_eq!(routed.signed_decision, signed_decision);
assert_eq!(routed.decision.decision, DeveloperDecisionKind::Deny);
assert_eq!(routed.resumed_size, Some(resumed_size));
assert_eq!(
factory.log.lock().unwrap().as_slice(),
["resize:55x144", "signal:WINCH"]
);
assert!(
!factory
.log
.lock()
.unwrap()
.iter()
.any(|event| event == "signal:TSTP")
);
assert_eq!(
fixture
.store
.snapshot()
.unwrap()
.sessions
.into_iter()
.find(|session| session.session_id == binding.session_id)
.unwrap()
.session_phase,
SessionPhase::Attached
);
engine
.lock()
.unwrap()
.handle(
GenerationId::new(7),
SessionTerminalEvent::Input(TerminalInput {
session_id: binding.session_id,
bytes: b"sandbox-input".to_vec(),
}),
)
.unwrap();
}
fn engine_for_store(
store: Arc<dyn TerminalDomainStore>,
) -> (Arc<MockFactory>, SessionTerminalEngine) {
let factory = Arc::new(MockFactory::default());
let engine = SessionTerminalEngine {
recorder: HostCoordinatorTerminalRecorder::with_store(store),
factory: factory.clone(),
cancellation: Arc::new(Cancellation(Arc::clone(&factory.log))),
active: HashMap::new(),
};
(factory, engine)
}
fn id(value: u8) -> SessionId {
SessionId::new(bytes(value))
}
fn assert_no_group_signal(factory: &MockFactory) {
assert!(
factory
.log
.lock()
.unwrap()
.iter()
.all(|action| !action.starts_with("signal:"))
);
}