Work on implementing interface.

This commit is contained in:
Michael Mikovsky
2026-05-31 12:14:36 -06:00
parent f595b5aa98
commit 43a84c46f7
21 changed files with 1093 additions and 749 deletions
+19 -4
View File
@@ -4,10 +4,9 @@ use crate::{constants::LEAF_FAKE_PTY, session::PtySession};
/// User-owned state for the generated fake PTY leaf.
///
/// The macro-generated `FakePtyLeaf` wrapper stores sessions and retry queues around
/// this struct. Keeping counters here makes tests and future procedures observe leaf
/// behavior without reaching into generated session storage.
#[unshell_leaf(leaf = FakePtyLeaf, id = LEAF_FAKE_PTY, sessions(PtySession))]
/// The `unshell_leaf!` template stores sessions and retry queues around this struct.
/// Keeping counters here makes tests and future procedures observe leaf behavior
/// without reaching into generated session storage.
pub struct FakePtyState {
/// Number of sessions that application logic considers active.
pub active_count: usize,
@@ -35,3 +34,19 @@ impl Default for FakePtyState {
Self::new()
}
}
unshell_leaf! {
pub leaf FakePtyLeaf for FakePtyState {
id: LEAF_FAKE_PTY,
meta: unshell::protocol::LeafMeta {
name: "Fake PTY Leaf",
identifier: "dev.unshell.v1.pty",
version: "v0",
authors: unshell::alloc::vec!["ASTATIN3"],
},
sessions {
pty: PtySession,
}
procedures {}
}
}
+39
View File
@@ -2,6 +2,9 @@ use alloc::{vec, vec::Vec};
use unshell::protocol::{Endpoint, Leaf, Packet};
#[cfg(feature = "interface")]
use unshell::interface::{InterfaceEventKind, InterfaceStore};
use super::{
FakePtyLeaf, FakePtyState, OP_ABORT, OP_ERROR, OP_EXIT, OP_INPUT, OP_OPENED, OP_OUTPUT,
OP_STDIN_EOF, OP_TERMINATE, PROC_PTY, frame_opcode, frame_payload, pty_open_packet, pty_packet,
@@ -391,3 +394,39 @@ fn pty_leaf_does_not_consume_other_leaf_packets() {
assert_eq!(other_packets[0].procedure_id, PROC_OTHER);
assert_eq!(other_packets[0].data, b"leave-me".to_vec());
}
#[cfg(feature = "interface")]
#[test]
fn interface_update_records_session_flow() {
let (mut endpoint_a, mut endpoint_b) = pty_endpoints();
let mut leaf = FakePtyLeaf::new(FakePtyState::new());
let mut interface = InterfaceStore::new();
let hook_id = endpoint_a.get_hook_id();
endpoint_a
.add_outbound(pty_open_packet(
vec![ENDPOINT_A, ENDPOINT_B],
hook_id,
&[ENDPOINT_A],
))
.unwrap();
transfer_packets(&mut endpoint_a, &mut endpoint_b, ENDPOINT_B, ENDPOINT_A);
leaf.update_interface(&mut endpoint_b, &mut interface);
assert_eq!(leaf.active_session_count(), 1);
assert!(interface.events().iter().any(|event| {
matches!(
&event.kind,
InterfaceEventKind::SessionCreated { hook_id: recorded_hook, .. }
if *recorded_hook == hook_id
)
}));
assert!(interface.events().iter().any(|event| {
matches!(
&event.kind,
InterfaceEventKind::RouteSuccess { packet }
if packet.hook_id == hook_id && frame_opcode(packet) == Some(OP_OPENED)
)
}));
}