Skip to content

Commit

Permalink
Start to lift restriction of stdio only once (#3)
Browse files Browse the repository at this point in the history
* Start to lift restriction of stdio only once

This commit adds new `{Stdin,Stdout}Stream` traits which take over the
job of the stdio streams in `WasiCtxBuilder` and `WasiCtx`. These traits
bake in the ability to create a stream at any time to satisfy the API
of `wasi:cli`. The TTY functionality is folded into them as while I was
at it.

The implementation for stdin is relatively trivial since the stdin
implementation already handles multiple streams reading it. Built-in
impls of the `StdinStream` trait are also provided for helper types in
`preview2::pipe` which resulted in the implementation of
`MemoryInputPipe` being updated to support `Clone` where all clones read
the same original data.

* Get tests building

* Un-ignore now-passing test

* Remove unneeded argument from `WasiCtxBuilder::build`

* Fix tests
  • Loading branch information
alexcrichton authored Sep 28, 2023
1 parent 3905a60 commit b321022
Show file tree
Hide file tree
Showing 16 changed files with 273 additions and 261 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

105 changes: 51 additions & 54 deletions crates/test-programs/tests/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use wasmtime::{
use wasmtime_wasi::preview2::{
command::{add_to_linker, Command},
pipe::MemoryInputPipe,
DirPerms, FilePerms, HostMonotonicClock, HostWallClock, IsATTY, Table, WasiCtx, WasiCtxBuilder,
DirPerms, FilePerms, HostMonotonicClock, HostWallClock, Table, WasiCtx, WasiCtxBuilder,
WasiView,
};

Expand Down Expand Up @@ -61,10 +61,10 @@ async fn instantiate(

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn hello_stdout() -> Result<()> {
let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.args(&["gussie", "sparky", "willa"])
.build(&mut table)?;
.build();
let (mut store, command) =
instantiate(get_component("hello_stdout"), CommandCtx { table, wasi }).await?;
command
Expand All @@ -76,7 +76,7 @@ async fn hello_stdout() -> Result<()> {

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn panic() -> Result<()> {
let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.args(&[
"diesel",
Expand All @@ -88,7 +88,7 @@ async fn panic() -> Result<()> {
"good",
"yesterday",
])
.build(&mut table)?;
.build();
let (mut store, command) =
instantiate(get_component("panic"), CommandCtx { table, wasi }).await?;
let r = command.wasi_cli_run().call_run(&mut store).await;
Expand All @@ -99,10 +99,10 @@ async fn panic() -> Result<()> {

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn args() -> Result<()> {
let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.args(&["hello", "this", "", "is an argument", "with 🚩 emoji"])
.build(&mut table)?;
.build();
let (mut store, command) =
instantiate(get_component("args"), CommandCtx { table, wasi }).await?;
command
Expand All @@ -114,8 +114,8 @@ async fn args() -> Result<()> {

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn random() -> Result<()> {
let mut table = Table::new();
let wasi = WasiCtxBuilder::new().build(&mut table)?;
let table = Table::new();
let wasi = WasiCtxBuilder::new().build();
let (mut store, command) =
instantiate(get_component("random"), CommandCtx { table, wasi }).await?;

Expand Down Expand Up @@ -157,11 +157,11 @@ async fn time() -> Result<()> {
}
}

let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.monotonic_clock(FakeMonotonicClock { now: Mutex::new(0) })
.wall_clock(FakeWallClock)
.build(&mut table)?;
.build();

let (mut store, command) =
instantiate(get_component("time"), CommandCtx { table, wasi }).await?;
Expand All @@ -175,13 +175,12 @@ async fn time() -> Result<()> {

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn stdin() -> Result<()> {
let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.stdin(
MemoryInputPipe::new("So rested he by the Tumtum tree".into()),
IsATTY::No,
)
.build(&mut table)?;
.stdin(MemoryInputPipe::new(
"So rested he by the Tumtum tree".into(),
))
.build();

let (mut store, command) =
instantiate(get_component("stdin"), CommandCtx { table, wasi }).await?;
Expand All @@ -195,13 +194,12 @@ async fn stdin() -> Result<()> {

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn poll_stdin() -> Result<()> {
let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.stdin(
MemoryInputPipe::new("So rested he by the Tumtum tree".into()),
IsATTY::No,
)
.build(&mut table)?;
.stdin(MemoryInputPipe::new(
"So rested he by the Tumtum tree".into(),
))
.build();

let (mut store, command) =
instantiate(get_component("poll_stdin"), CommandCtx { table, wasi }).await?;
Expand All @@ -215,11 +213,11 @@ async fn poll_stdin() -> Result<()> {

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn env() -> Result<()> {
let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.env("frabjous", "day")
.env("callooh", "callay")
.build(&mut table)?;
.build();

let (mut store, command) =
instantiate(get_component("env"), CommandCtx { table, wasi }).await?;
Expand All @@ -239,10 +237,10 @@ async fn file_read() -> Result<()> {

let open_dir = Dir::open_ambient_dir(dir.path(), ambient_authority())?;

let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.preopened_dir(open_dir, DirPerms::all(), FilePerms::all(), "/")
.build(&mut table)?;
.build();

let (mut store, command) =
instantiate(get_component("file_read"), CommandCtx { table, wasi }).await?;
Expand All @@ -263,10 +261,10 @@ async fn file_append() -> Result<()> {

let open_dir = Dir::open_ambient_dir(dir.path(), ambient_authority())?;

let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.preopened_dir(open_dir, DirPerms::all(), FilePerms::all(), "/")
.build(&mut table)?;
.build();

let (mut store, command) =
instantiate(get_component("file_append"), CommandCtx { table, wasi }).await?;
Expand Down Expand Up @@ -296,10 +294,10 @@ async fn file_dir_sync() -> Result<()> {

let open_dir = Dir::open_ambient_dir(dir.path(), ambient_authority())?;

let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.preopened_dir(open_dir, DirPerms::all(), FilePerms::all(), "/")
.build(&mut table)?;
.build();

let (mut store, command) =
instantiate(get_component("file_dir_sync"), CommandCtx { table, wasi }).await?;
Expand All @@ -313,8 +311,8 @@ async fn file_dir_sync() -> Result<()> {

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn exit_success() -> Result<()> {
let mut table = Table::new();
let wasi = WasiCtxBuilder::new().build(&mut table)?;
let table = Table::new();
let wasi = WasiCtxBuilder::new().build();

let (mut store, command) =
instantiate(get_component("exit_success"), CommandCtx { table, wasi }).await?;
Expand All @@ -330,8 +328,8 @@ async fn exit_success() -> Result<()> {

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn exit_default() -> Result<()> {
let mut table = Table::new();
let wasi = WasiCtxBuilder::new().build(&mut table)?;
let table = Table::new();
let wasi = WasiCtxBuilder::new().build();

let (mut store, command) =
instantiate(get_component("exit_default"), CommandCtx { table, wasi }).await?;
Expand All @@ -343,8 +341,8 @@ async fn exit_default() -> Result<()> {

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn exit_failure() -> Result<()> {
let mut table = Table::new();
let wasi = WasiCtxBuilder::new().build(&mut table)?;
let table = Table::new();
let wasi = WasiCtxBuilder::new().build();

let (mut store, command) =
instantiate(get_component("exit_failure"), CommandCtx { table, wasi }).await?;
Expand All @@ -360,8 +358,8 @@ async fn exit_failure() -> Result<()> {

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn exit_panic() -> Result<()> {
let mut table = Table::new();
let wasi = WasiCtxBuilder::new().build(&mut table)?;
let table = Table::new();
let wasi = WasiCtxBuilder::new().build();

let (mut store, command) =
instantiate(get_component("exit_panic"), CommandCtx { table, wasi }).await?;
Expand All @@ -388,12 +386,12 @@ async fn directory_list() -> Result<()> {

let open_dir = Dir::open_ambient_dir(dir.path(), ambient_authority())?;

let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.inherit_stdout()
.inherit_stderr()
.preopened_dir(open_dir, DirPerms::all(), FilePerms::all(), "/")
.build(&mut table)?;
.build();

let (mut store, command) =
instantiate(get_component("directory_list"), CommandCtx { table, wasi }).await?;
Expand All @@ -407,8 +405,8 @@ async fn directory_list() -> Result<()> {

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn default_clocks() -> Result<()> {
let mut table = Table::new();
let wasi = WasiCtxBuilder::new().build(&mut table)?;
let table = Table::new();
let wasi = WasiCtxBuilder::new().build();

let (mut store, command) =
instantiate(get_component("default_clocks"), CommandCtx { table, wasi }).await?;
Expand All @@ -422,8 +420,8 @@ async fn default_clocks() -> Result<()> {

#[test_log::test(tokio::test(flavor = "multi_thread"))]
async fn export_cabi_realloc() -> Result<()> {
let mut table = Table::new();
let wasi = WasiCtxBuilder::new().build(&mut table)?;
let table = Table::new();
let wasi = WasiCtxBuilder::new().build();
let (mut store, command) = instantiate(
get_component("export_cabi_realloc"),
CommandCtx { table, wasi },
Expand All @@ -444,11 +442,11 @@ async fn read_only() -> Result<()> {
std::fs::File::create(dir.path().join("bar.txt"))?.write_all(b"And stood awhile in thought")?;
std::fs::create_dir(dir.path().join("sub"))?;

let mut table = Table::new();
let table = Table::new();
let open_dir = Dir::open_ambient_dir(dir.path(), ambient_authority())?;
let wasi = WasiCtxBuilder::new()
.preopened_dir(open_dir, DirPerms::READ, FilePerms::READ, "/")
.build(&mut table)?;
.build();

let (mut store, command) =
instantiate(get_component("read_only"), CommandCtx { table, wasi }).await?;
Expand All @@ -461,16 +459,15 @@ async fn read_only() -> Result<()> {
}

#[test_log::test(tokio::test(flavor = "multi_thread"))]
#[ignore] // FIXME: this calls get_stdin but it's already consumed
async fn stream_pollable_lifetimes() -> Result<()> {
// Test program has two modes, dispatching based on argument.
{
// Correct execution: should succeed
let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.args(&["correct"])
.stdin(MemoryInputPipe::new(" ".into()), IsATTY::No)
.build(&mut table)?;
.stdin(MemoryInputPipe::new(" ".into()))
.build();

let (mut store, command) = instantiate(
get_component("stream_pollable_lifetimes"),
Expand All @@ -486,11 +483,11 @@ async fn stream_pollable_lifetimes() -> Result<()> {
}
{
// Incorrect execution: should trap with a TableError::HasChildren
let mut table = Table::new();
let table = Table::new();
let wasi = WasiCtxBuilder::new()
.args(&["trap"])
.stdin(MemoryInputPipe::new(" ".into()), IsATTY::No)
.build(&mut table)?;
.stdin(MemoryInputPipe::new(" ".into()))
.build();

let (mut store, command) = instantiate(
get_component("stream_pollable_lifetimes"),
Expand Down
6 changes: 2 additions & 4 deletions crates/test-programs/tests/reactor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,8 @@ async fn instantiate(

#[test_log::test(tokio::test)]
async fn reactor_tests() -> Result<()> {
let mut table = Table::new();
let wasi = WasiCtxBuilder::new()
.env("GOOD_DOG", "gussie")
.build(&mut table)?;
let table = Table::new();
let wasi = WasiCtxBuilder::new().env("GOOD_DOG", "gussie").build();

let (mut store, reactor) =
instantiate(get_component("reactor_tests"), ReactorCtx { table, wasi }).await?;
Expand Down
10 changes: 5 additions & 5 deletions crates/test-programs/tests/wasi-http-components-sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use wasmtime::{
use wasmtime_wasi::preview2::{
command::sync::{add_to_linker, Command},
pipe::MemoryOutputPipe,
IsATTY, Table, WasiCtx, WasiCtxBuilder, WasiView,
Table, WasiCtx, WasiCtxBuilder, WasiView,
};
use wasmtime_wasi_http::{WasiHttpCtx, WasiHttpView};

Expand Down Expand Up @@ -73,18 +73,18 @@ fn run(name: &str) -> anyhow::Result<()> {
let stdout = MemoryOutputPipe::new(4096);
let stderr = MemoryOutputPipe::new(4096);
let r = {
let mut table = Table::new();
let table = Table::new();
let component = get_component(name);

// Create our wasi context.
let mut builder = WasiCtxBuilder::new();
builder.stdout(stdout.clone(), IsATTY::No);
builder.stderr(stderr.clone(), IsATTY::No);
builder.stdout(stdout.clone());
builder.stderr(stderr.clone());
builder.arg(name);
for (var, val) in test_programs::wasi_tests_environment() {
builder.env(var, val);
}
let wasi = builder.build(&mut table)?;
let wasi = builder.build();
let http = WasiHttpCtx {};

let (mut store, command) = instantiate_component(component, Ctx { table, wasi, http })?;
Expand Down
10 changes: 5 additions & 5 deletions crates/test-programs/tests/wasi-http-components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use wasmtime::{
use wasmtime_wasi::preview2::{
command::{add_to_linker, Command},
pipe::MemoryOutputPipe,
IsATTY, Table, WasiCtx, WasiCtxBuilder, WasiView,
Table, WasiCtx, WasiCtxBuilder, WasiView,
};
use wasmtime_wasi_http::{WasiHttpCtx, WasiHttpView};

Expand Down Expand Up @@ -73,18 +73,18 @@ async fn run(name: &str) -> anyhow::Result<()> {
let stdout = MemoryOutputPipe::new(4096);
let stderr = MemoryOutputPipe::new(4096);
let r = {
let mut table = Table::new();
let table = Table::new();
let component = get_component(name);

// Create our wasi context.
let mut builder = WasiCtxBuilder::new();
builder.stdout(stdout.clone(), IsATTY::No);
builder.stderr(stderr.clone(), IsATTY::No);
builder.stdout(stdout.clone());
builder.stderr(stderr.clone());
builder.arg(name);
for (var, val) in test_programs::wasi_tests_environment() {
builder.env(var, val);
}
let wasi = builder.build(&mut table)?;
let wasi = builder.build();
let http = WasiHttpCtx;

let (mut store, command) =
Expand Down
Loading

0 comments on commit b321022

Please sign in to comment.