#![allow(clippy::unwrap_used, clippy::expect_used)]
#![cfg(feature = "localfs")]
use kaish_kernel::{ExecuteOptions, Kernel, KernelConfig};
fn kernel() -> Kernel {
Kernel::new(KernelConfig::repl().with_trash(false))
.expect("failed to create kernel")
}
async fn run_with_stdin(prog: &str, stdin: &str) -> (String, i64) {
let kernel = kernel();
let result = kernel
.execute_with_options(prog, ExecuteOptions::new().with_stdin(stdin))
.await
.expect("kernel execute");
(result.text_out().to_string(), result.code)
}
#[tokio::test]
async fn stdin_feeds_a_bare_top_level_builtin() {
let (out, code) = run_with_stdin("sort", "10\n2\n1\n20\n").await;
assert_eq!(code, 0, "sort should succeed: {out:?}");
assert_eq!(out, "1\n10\n2\n20\n", "sort must consume options stdin");
}
#[tokio::test]
async fn stdin_feeds_first_stage_of_a_pipeline() {
let (out, code) = run_with_stdin("cut -d: -f1", "a:b:c\n").await;
assert_eq!(code, 0, "cut should succeed: {out:?}");
assert_eq!(out, "a\n");
}
#[tokio::test]
async fn stdin_is_consumed_by_the_first_command_only() {
let (out, code) = run_with_stdin("cat ; cat", "payload\n").await;
assert_eq!(code, 0, "both cats should succeed: {out:?}");
assert_eq!(out, "payload\n", "stdin reaches the first cat only, not a duplicate");
}
#[tokio::test]
async fn stdin_does_not_leak_between_calls() {
let kernel = kernel();
let first = kernel
.execute_with_options("cat", ExecuteOptions::new().with_stdin("first\n"))
.await
.expect("first execute");
assert_eq!(first.text_out(), "first\n");
let second = kernel.execute("echo done").await.expect("second execute");
assert_eq!(second.text_out(), "done\n", "prior stdin must not bleed into a later call");
}