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" ); }