Path: blob/main/crates/wasi/tests/process_stdin.rs
1691 views
use std::io::{BufRead, Write};1use std::process::Command;2use wasmtime_wasi::cli::StdinStream;3use wasmtime_wasi::p2::Pollable;45const VAR_NAME: &str = "__CHILD_PROCESS";67fn main() {8if cfg!(miri) {9return;10}11// Skip this tests if it looks like we're in a cross-compiled situation and12// we're emulating this test for a different platform. In that scenario13// emulators (like QEMU) tend to not report signals the same way and such.14if wasmtime_test_util::cargo_test_runner().is_some() {15return;16}1718match std::env::var(VAR_NAME) {19Ok(_) => child_process(),20Err(_) => parent_process(),21}2223fn child_process() {24let mut result_write = std::io::stderr();25let mut child_running = true;26while child_running {27tokio::runtime::Builder::new_multi_thread()28.enable_all()29.build()30.unwrap()31.block_on(async {32'task: loop {33println!("child: creating stdin");34let mut stdin = wasmtime_wasi::cli::stdin().p2_stream();3536println!("child: checking that stdin is not ready");37assert!(38tokio::time::timeout(39std::time::Duration::from_millis(100),40stdin.ready()41)42.await43.is_err(),44"stdin available too soon"45);4647writeln!(&mut result_write, "start").unwrap();4849println!("child: started");5051let mut buffer = String::new();52loop {53println!("child: waiting for stdin to be ready");54stdin.ready().await;5556println!("child: reading input");57// We can't effectively test for the case where stdin was closed, so panic if it is...58let bytes = stdin.read(1024).unwrap();5960println!("child got: {bytes:?}");6162buffer.push_str(std::str::from_utf8(bytes.as_ref()).unwrap());63if let Some((line, rest)) = buffer.split_once('\n') {64if line == "all done" {65writeln!(&mut result_write, "done").unwrap();66println!("child: exiting...");67child_running = false;68break 'task;69} else if line == "restart_runtime" {70writeln!(&mut result_write, "restarting").unwrap();71println!("child: restarting runtime...");72break 'task;73} else if line == "restart_task" {74writeln!(&mut result_write, "restarting").unwrap();75println!("child: restarting task...");76continue 'task;77} else {78writeln!(&mut result_write, "{line}").unwrap();79}8081buffer = rest.to_owned();82}83}84}85});86println!("child: runtime exited");87}88println!("child: exiting");89}90}9192fn parent_process() {93let me = std::env::current_exe().unwrap();94let mut cmd = Command::new(me);95cmd.env(VAR_NAME, "1");96cmd.stdin(std::process::Stdio::piped());9798if std::env::args().any(|arg| arg == "--nocapture") {99cmd.stdout(std::process::Stdio::inherit());100} else {101cmd.stdout(std::process::Stdio::null());102}103104cmd.stderr(std::process::Stdio::piped());105let mut child = cmd.spawn().unwrap();106107let mut stdin_write = child.stdin.take().unwrap();108let mut result_read = std::io::BufReader::new(child.stderr.take().unwrap());109110let mut line = String::new();111result_read.read_line(&mut line).unwrap();112assert_eq!(line, "start\n");113114for i in 0..5 {115let message = format!("some bytes {i}\n");116stdin_write.write_all(message.as_bytes()).unwrap();117line.clear();118result_read.read_line(&mut line).unwrap();119assert_eq!(line, message);120}121122writeln!(&mut stdin_write, "restart_task").unwrap();123line.clear();124result_read.read_line(&mut line).unwrap();125assert_eq!(line, "restarting\n");126line.clear();127128result_read.read_line(&mut line).unwrap();129assert_eq!(line, "start\n");130131for i in 0..10 {132let message = format!("more bytes {i}\n");133stdin_write.write_all(message.as_bytes()).unwrap();134line.clear();135result_read.read_line(&mut line).unwrap();136assert_eq!(line, message);137}138139writeln!(&mut stdin_write, "restart_runtime").unwrap();140line.clear();141result_read.read_line(&mut line).unwrap();142assert_eq!(line, "restarting\n");143line.clear();144145result_read.read_line(&mut line).unwrap();146assert_eq!(line, "start\n");147148for i in 0..17 {149let message = format!("even more bytes {i}\n");150stdin_write.write_all(message.as_bytes()).unwrap();151line.clear();152result_read.read_line(&mut line).unwrap();153assert_eq!(line, message);154}155156writeln!(&mut stdin_write, "all done").unwrap();157158line.clear();159result_read.read_line(&mut line).unwrap();160assert_eq!(line, "done\n");161}162163164