Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wasi/tests/process_stdin.rs
1691 views
1
use std::io::{BufRead, Write};
2
use std::process::Command;
3
use wasmtime_wasi::cli::StdinStream;
4
use wasmtime_wasi::p2::Pollable;
5
6
const VAR_NAME: &str = "__CHILD_PROCESS";
7
8
fn main() {
9
if cfg!(miri) {
10
return;
11
}
12
// Skip this tests if it looks like we're in a cross-compiled situation and
13
// we're emulating this test for a different platform. In that scenario
14
// emulators (like QEMU) tend to not report signals the same way and such.
15
if wasmtime_test_util::cargo_test_runner().is_some() {
16
return;
17
}
18
19
match std::env::var(VAR_NAME) {
20
Ok(_) => child_process(),
21
Err(_) => parent_process(),
22
}
23
24
fn child_process() {
25
let mut result_write = std::io::stderr();
26
let mut child_running = true;
27
while child_running {
28
tokio::runtime::Builder::new_multi_thread()
29
.enable_all()
30
.build()
31
.unwrap()
32
.block_on(async {
33
'task: loop {
34
println!("child: creating stdin");
35
let mut stdin = wasmtime_wasi::cli::stdin().p2_stream();
36
37
println!("child: checking that stdin is not ready");
38
assert!(
39
tokio::time::timeout(
40
std::time::Duration::from_millis(100),
41
stdin.ready()
42
)
43
.await
44
.is_err(),
45
"stdin available too soon"
46
);
47
48
writeln!(&mut result_write, "start").unwrap();
49
50
println!("child: started");
51
52
let mut buffer = String::new();
53
loop {
54
println!("child: waiting for stdin to be ready");
55
stdin.ready().await;
56
57
println!("child: reading input");
58
// We can't effectively test for the case where stdin was closed, so panic if it is...
59
let bytes = stdin.read(1024).unwrap();
60
61
println!("child got: {bytes:?}");
62
63
buffer.push_str(std::str::from_utf8(bytes.as_ref()).unwrap());
64
if let Some((line, rest)) = buffer.split_once('\n') {
65
if line == "all done" {
66
writeln!(&mut result_write, "done").unwrap();
67
println!("child: exiting...");
68
child_running = false;
69
break 'task;
70
} else if line == "restart_runtime" {
71
writeln!(&mut result_write, "restarting").unwrap();
72
println!("child: restarting runtime...");
73
break 'task;
74
} else if line == "restart_task" {
75
writeln!(&mut result_write, "restarting").unwrap();
76
println!("child: restarting task...");
77
continue 'task;
78
} else {
79
writeln!(&mut result_write, "{line}").unwrap();
80
}
81
82
buffer = rest.to_owned();
83
}
84
}
85
}
86
});
87
println!("child: runtime exited");
88
}
89
println!("child: exiting");
90
}
91
}
92
93
fn parent_process() {
94
let me = std::env::current_exe().unwrap();
95
let mut cmd = Command::new(me);
96
cmd.env(VAR_NAME, "1");
97
cmd.stdin(std::process::Stdio::piped());
98
99
if std::env::args().any(|arg| arg == "--nocapture") {
100
cmd.stdout(std::process::Stdio::inherit());
101
} else {
102
cmd.stdout(std::process::Stdio::null());
103
}
104
105
cmd.stderr(std::process::Stdio::piped());
106
let mut child = cmd.spawn().unwrap();
107
108
let mut stdin_write = child.stdin.take().unwrap();
109
let mut result_read = std::io::BufReader::new(child.stderr.take().unwrap());
110
111
let mut line = String::new();
112
result_read.read_line(&mut line).unwrap();
113
assert_eq!(line, "start\n");
114
115
for i in 0..5 {
116
let message = format!("some bytes {i}\n");
117
stdin_write.write_all(message.as_bytes()).unwrap();
118
line.clear();
119
result_read.read_line(&mut line).unwrap();
120
assert_eq!(line, message);
121
}
122
123
writeln!(&mut stdin_write, "restart_task").unwrap();
124
line.clear();
125
result_read.read_line(&mut line).unwrap();
126
assert_eq!(line, "restarting\n");
127
line.clear();
128
129
result_read.read_line(&mut line).unwrap();
130
assert_eq!(line, "start\n");
131
132
for i in 0..10 {
133
let message = format!("more bytes {i}\n");
134
stdin_write.write_all(message.as_bytes()).unwrap();
135
line.clear();
136
result_read.read_line(&mut line).unwrap();
137
assert_eq!(line, message);
138
}
139
140
writeln!(&mut stdin_write, "restart_runtime").unwrap();
141
line.clear();
142
result_read.read_line(&mut line).unwrap();
143
assert_eq!(line, "restarting\n");
144
line.clear();
145
146
result_read.read_line(&mut line).unwrap();
147
assert_eq!(line, "start\n");
148
149
for i in 0..17 {
150
let message = format!("even more bytes {i}\n");
151
stdin_write.write_all(message.as_bytes()).unwrap();
152
line.clear();
153
result_read.read_line(&mut line).unwrap();
154
assert_eq!(line, message);
155
}
156
157
writeln!(&mut stdin_write, "all done").unwrap();
158
159
line.clear();
160
result_read.read_line(&mut line).unwrap();
161
assert_eq!(line, "done\n");
162
}
163
164