use turkos_os_shell_echo::{Echo, EncodeError}; use turkos_os_user_runtime_io::io::{Error, Fault, Writer}; #[derive(Default)] struct Sink { bytes: Vec, calls: usize, fail_on: Option } impl Writer for Sink { fn write_once(&mut self, bytes: &[u8]) -> Result { self.calls += 1; if self.fail_on == Some(self.calls) { return Err(Fault::Wire); } let count = bytes.len().min(2); self.bytes.extend_from_slice(&bytes[..count]); Ok(count) } } #[test] fn os_shell_echo_encodes_words_and_optional_newline() { let line = Echo::<16>::encode(&["çay", "var"], true).unwrap(); assert_eq!(line.as_bytes(), "çay var\n".as_bytes()); assert!(line.remaining() == line.as_bytes()); assert_eq!(Echo::<1>::encode(&[], true).unwrap().as_bytes(), b"\n"); assert_eq!(Echo::<0>::encode(&[], false).unwrap().as_bytes(), b""); } #[test] fn os_shell_echo_capacity_and_nul_reject_before_output() { assert_eq!(Echo::<4>::encode(&["abc", "d"], false).err(), Some(EncodeError::Full)); assert_eq!(Echo::<8>::encode(&["ok", "\0bad"], true).err(), Some(EncodeError::Nul)); } #[test] fn os_shell_echo_retry_does_not_duplicate_acknowledged_bytes() { let mut line = Echo::<16>::encode(&["hello"], true).unwrap(); let mut sink = Sink { fail_on: Some(2), ..Sink::default() }; assert!(matches!(line.emit(&mut sink, 3), Err(Error::Wire(outcome)) if outcome.bytes == 2 && outcome.calls == 2)); assert_eq!(line.sent(), 2); assert_eq!(line.remaining(), b"llo\n"); sink.fail_on = None; assert_eq!(line.emit(&mut sink, 3).unwrap().bytes, 4); assert!(line.complete()); assert_eq!(sink.bytes, b"hello\n"); } #[test] fn os_shell_echo_budget_retains_partial_progress() { let mut line = Echo::<8>::encode(&["abcde"], false).unwrap(); let mut sink = Sink::default(); assert!(matches!(line.emit(&mut sink, 1), Err(Error::BudgetExceeded(outcome)) if outcome.bytes == 2 && outcome.calls == 1)); assert_eq!(line.remaining(), b"cde"); assert_eq!(line.emit(&mut sink, 2).unwrap().bytes, 3); assert_eq!(sink.bytes, b"abcde"); }