This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
use lumbridge_runtime::{
|
||||
CommandConfig, PtyOptions, RuntimeActor, RuntimeActorOptions, RuntimeCommand, RuntimeEvent,
|
||||
TerminalSize,
|
||||
};
|
||||
use lumbridge_terminal::{
|
||||
KeyModifiers, TerminalDimensions, TerminalEngine, TerminalEngineOptions, TerminalKey,
|
||||
TerminalKeyEvent,
|
||||
};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
const TEST_TIMEOUT: Duration = Duration::from_secs(3);
|
||||
|
||||
#[test]
|
||||
fn actor_terminal_pipeline_accepts_input_resize_and_vt_output() {
|
||||
let command = CommandConfig::new("/bin/sh")
|
||||
.unwrap()
|
||||
.args([
|
||||
"-c",
|
||||
"printf '\x1b[31mready\x1b[0m\\n'; IFS= read -r line; stty size; printf 'got:%s\\n' \"$line\"",
|
||||
]);
|
||||
let actor = RuntimeActor::spawn(
|
||||
command,
|
||||
PtyOptions::default(),
|
||||
RuntimeActorOptions::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let dimensions = TerminalDimensions::new(41, 101).unwrap();
|
||||
let mut terminal = TerminalEngine::new(TerminalEngineOptions {
|
||||
dimensions: TerminalDimensions::default(),
|
||||
scrollback_lines: 64,
|
||||
});
|
||||
assert!(terminal.resize(dimensions));
|
||||
actor
|
||||
.try_send(RuntimeCommand::Resize(TerminalSize::new(41, 101).unwrap()))
|
||||
.unwrap();
|
||||
|
||||
let text = terminal.encode_key(&TerminalKeyEvent {
|
||||
key: TerminalKey::Text("hello-pipeline".into()),
|
||||
modifiers: KeyModifiers::default(),
|
||||
});
|
||||
actor.try_send(RuntimeCommand::Input(text)).unwrap();
|
||||
let enter = terminal.encode_key(&TerminalKeyEvent {
|
||||
key: TerminalKey::Enter,
|
||||
modifiers: KeyModifiers::default(),
|
||||
});
|
||||
actor.try_send(RuntimeCommand::Input(enter)).unwrap();
|
||||
|
||||
let deadline = Instant::now() + TEST_TIMEOUT;
|
||||
loop {
|
||||
let remaining = deadline.saturating_duration_since(Instant::now());
|
||||
assert!(!remaining.is_zero(), "timed out waiting for pipeline exit");
|
||||
match actor.recv_timeout(remaining).unwrap() {
|
||||
RuntimeEvent::Output { bytes, .. } => {
|
||||
let update = terminal.process(&bytes);
|
||||
for response in update.outbound {
|
||||
actor.try_send(RuntimeCommand::Input(response)).unwrap();
|
||||
}
|
||||
}
|
||||
RuntimeEvent::Exited { status, .. } => {
|
||||
assert!(status.success());
|
||||
break;
|
||||
}
|
||||
RuntimeEvent::Fault { message, .. } => panic!("runtime fault: {message}"),
|
||||
RuntimeEvent::Started { .. } | RuntimeEvent::InputClosed { .. } => {}
|
||||
}
|
||||
}
|
||||
|
||||
let contents = terminal.snapshot().plain_rows().join("\n");
|
||||
assert!(contents.contains("ready"), "missing ready marker");
|
||||
assert!(
|
||||
contents.contains("41 101"),
|
||||
"missing resized PTY dimensions"
|
||||
);
|
||||
assert!(
|
||||
contents.contains("got:hello-pipeline"),
|
||||
"missing echoed input"
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user