From b5169d99028e05555301ece63d2993772f35cdf3 Mon Sep 17 00:00:00 2001 From: Tyler Rockwood Date: Tue, 9 Jan 2024 15:55:05 -0600 Subject: [PATCH 1/3] examples: add component model example (#7759) Signed-off-by: Tyler Rockwood --- Cargo.lock | 8 ++++ Cargo.toml | 2 + examples/CMakeLists.txt | 2 + examples/component/convert.wit | 11 ++++++ examples/component/main.rs | 63 ++++++++++++++++++++++++++++++ examples/component/wasm/Cargo.toml | 14 +++++++ examples/component/wasm/guest.rs | 17 ++++++++ 7 files changed, 117 insertions(+) create mode 100644 examples/component/convert.wit create mode 100644 examples/component/main.rs create mode 100644 examples/component/wasm/Cargo.toml create mode 100644 examples/component/wasm/guest.rs diff --git a/Cargo.lock b/Cargo.lock index 4bdf4d4e8920..d6193259b8d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1074,6 +1074,13 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "example-component-wasm" +version = "0.0.0" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "example-fib-debug-wasm" version = "0.0.0" @@ -3362,6 +3369,7 @@ dependencies = [ "wast 69.0.1", "wat", "windows-sys 0.52.0", + "wit-component 0.19.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index e4f42f5a5a92..c8fe088e6433 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,6 +90,7 @@ serde_json = { workspace = true } walkdir = { workspace = true } test-programs-artifacts = { workspace = true } bytesize = "1.3.0" +wit-component = { workspace = true } [target.'cfg(windows)'.dev-dependencies] windows-sys = { workspace = true, features = ["Win32_System_Memory"] } @@ -117,6 +118,7 @@ members = [ "examples/fib-debug/wasm", "examples/wasi/wasm", "examples/tokio/wasm", + "examples/component/wasm", "fuzz", "winch", "winch/codegen", diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index e4330951434d..4277fcdc64d7 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -62,6 +62,7 @@ create_target(wasi wasi/main.c) create_rust_wasm(fib-debug wasm32-unknown-unknown) create_rust_wasm(tokio wasm32-wasi) create_rust_wasm(wasi wasm32-wasi) +create_rust_wasm(component wasm32-unknown-unknown) create_rust_test(epochs) create_rust_test(externref) create_rust_test(fib-debug) @@ -77,3 +78,4 @@ create_rust_test(serialize) create_rust_test(threads) create_rust_test(wasi) create_rust_test(tokio wasmtime-wasi/tokio) +create_rust_test(component) diff --git a/examples/component/convert.wit b/examples/component/convert.wit new file mode 100644 index 000000000000..1a10ce5be4f2 --- /dev/null +++ b/examples/component/convert.wit @@ -0,0 +1,11 @@ +package local:demo; + +world convert { + /// This interface needs to be provided by the host + import host: interface { + /// Example function that does a simple a × b operation + multiply: func(a: float32, b: float32) -> float32; + } + /// Exported function for computing: (°C × 9/5) + 32 = °F + export convert-celsius-to-fahrenheit: func(x: float32) -> float32; +} diff --git a/examples/component/main.rs b/examples/component/main.rs new file mode 100644 index 000000000000..0c5d26389ed0 --- /dev/null +++ b/examples/component/main.rs @@ -0,0 +1,63 @@ +use anyhow::Context; +use std::{fs, path::Path}; +use wit_component; + +use wasmtime::{ + component::{bindgen, Component, Linker}, + Config, Engine, Result, Store, +}; + +// Generate bindings of the guest and host components. +bindgen!("convert" in "./examples/component/convert.wit"); + +struct HostComponent; + +// Implmentation of the host interface defined in the wit file. +impl host::Host for HostComponent { + fn multiply(&mut self, a: f32, b: f32) -> wasmtime::Result { + Ok(a * b) + } +} + +struct MyState { + host: HostComponent, +} + +/// This function is only needed until rust can natively output a component. +/// +/// Generally embeddings should not be expected to do this programatically, but instead +/// language specific tooling should be used, for example in Rust `cargo component` +/// is a good way of doing that: https://github.com/bytecodealliance/cargo-component +/// +/// In this example we convert the code here to simplify the testing process and build system. +fn convert_to_component(path: impl AsRef) -> Result> { + let bytes = &fs::read(&path).context("failed to read input file")?; + wit_component::ComponentEncoder::default() + .module(&bytes)? + .encode() +} + +fn main() -> Result<()> { + // Create an engine with the component model enabled (disabled by default). + let engine = Engine::new(Config::new().wasm_component_model(true))?; + + // NOTE: The wasm32-unknown-unknown target is used here for simplicity, real world use cases + // should probably use the wasm32-wasi target, and enable wasi preview2 within the component + // model. + let component = convert_to_component("target/wasm32-unknown-unknown/debug/guest.wasm")?; + + // Create our component and call our generated host function. + let component = Component::from_binary(&engine, &component)?; + let mut store = Store::new( + &engine, + MyState { + host: HostComponent {}, + }, + ); + let mut linker = Linker::new(&engine); + host::add_to_linker(&mut linker, |state: &mut MyState| &mut state.host)?; + let (convert, _instance) = Convert::instantiate(&mut store, &component, &linker)?; + let result = convert.call_convert_celsius_to_fahrenheit(&mut store, 23.4)?; + println!("Converted to: {:?}", result); + Ok(()) +} diff --git a/examples/component/wasm/Cargo.toml b/examples/component/wasm/Cargo.toml new file mode 100644 index 000000000000..d3380f5120a3 --- /dev/null +++ b/examples/component/wasm/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "example-component-wasm" +version = "0.0.0" +authors = ["The Wasmtime Project Developers"] +edition = "2021" +publish = false + +[dependencies] +wit-bindgen = { workspace = true, default-features = true } + +[lib] +path = "guest.rs" +name = "guest" +crate-type = ["cdylib"] diff --git a/examples/component/wasm/guest.rs b/examples/component/wasm/guest.rs new file mode 100644 index 000000000000..05c806b9c58d --- /dev/null +++ b/examples/component/wasm/guest.rs @@ -0,0 +1,17 @@ +// Use wit_bindgen to generate the bindings from the component model to Rust. +// For more information see: https://github.com/bytecodealliance/wit-bindgen/ +wit_bindgen::generate!({ + path: "..", + world: "convert", + exports: { + world: GuestComponent, + }, +}); + +struct GuestComponent; + +impl Guest for GuestComponent { + fn convert_celsius_to_fahrenheit(x: f32) -> f32 { + host::multiply(x, 1.8) + 32.0 + } +} From 5660a88ba59b939236bced475da0d9f46d2b927a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 10 Jan 2024 10:19:14 -0600 Subject: [PATCH 2/3] Update the wasm-tools family of crates (#7764) * Update the wasm-tools family of crates Brings in support for validating gc instructions, but they're all left disabled for now. * Update fuzz test case generation * More test fixes, remove stray files * More test fixes * Rebase --- Cargo.lock | 125 ++++++++++-------- Cargo.toml | 18 +-- cranelift/wasm/src/code_translator.rs | 37 +++++- cranelift/wasm/src/sections_translator.rs | 1 + cranelift/wasm/src/translation_utils.rs | 12 +- cranelift/wasm/wasmtests/icall-simd.wat | 2 +- cranelift/wasm/wasmtests/icall.wat | 2 +- cranelift/wasm/wasmtests/unreachable_code.wat | 2 +- crates/environ/src/module_environ.rs | 1 + crates/fuzzing/src/generators/config.rs | 18 ++- crates/fuzzing/src/generators/module.rs | 7 +- .../src/generators/single_inst_module.rs | 10 +- crates/types/src/lib.rs | 1 + crates/wasmtime/src/engine/serialization.rs | 2 + supply-chain/imports.lock | 70 ++++++++++ tests/all/cli_tests/rs2wasm-add-func.wat | 2 +- tests/all/invoke_func_via_table.rs | 2 +- tests/all/limits.rs | 22 +-- tests/all/traps.rs | 2 +- tests/misc_testsuite/rs2wasm-add-func.wast | 2 +- 20 files changed, 237 insertions(+), 101 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d6193259b8d5..6ff63d8ae71b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -664,7 +664,7 @@ dependencies = [ "target-lexicon", "thiserror", "toml", - "wasmparser", + "wasmparser 0.119.0", "wat", ] @@ -843,7 +843,7 @@ dependencies = [ "serde_derive", "smallvec", "target-lexicon", - "wasmparser", + "wasmparser 0.119.0", "wasmtime-types", "wat", ] @@ -2607,7 +2607,7 @@ version = "0.0.0" dependencies = [ "cargo_metadata", "heck", - "wit-component 0.19.0", + "wit-component 0.19.1", ] [[package]] @@ -2895,7 +2895,7 @@ name = "verify-component-adapter" version = "18.0.0" dependencies = [ "anyhow", - "wasmparser", + "wasmparser 0.119.0", "wat", ] @@ -3002,7 +3002,7 @@ dependencies = [ "byte-array-literals", "object", "wasi", - "wasm-encoder", + "wasm-encoder 0.39.0", "wit-bindgen", ] @@ -3086,11 +3086,21 @@ dependencies = [ "leb128", ] +[[package]] +name = "wasm-encoder" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "111495d6204760238512f57a9af162f45086504da332af210f2f75dd80b34f1d" +dependencies = [ + "leb128", + "wasmparser 0.119.0", +] + [[package]] name = "wasm-metadata" -version = "0.10.14" +version = "0.10.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d835d67708f6374937c550ad8dd1d17c616ae009e3f00d7a0ac9f7825e78c36a" +checksum = "818931c85b1d197909699d36c509fa89550ccfa0d66932ba3c1726faddb4d0c7" dependencies = [ "anyhow", "indexmap 2.0.0", @@ -3098,35 +3108,35 @@ dependencies = [ "serde_derive", "serde_json", "spdx", - "wasm-encoder", - "wasmparser", + "wasm-encoder 0.39.0", + "wasmparser 0.119.0", ] [[package]] name = "wasm-mutate" -version = "0.2.42" +version = "0.2.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "140f2555b7c16b89592a1cd2f2626612c8c3cba9ff3224f87b00e063264b4b38" +checksum = "6f95378917a3e9c61e79d41ca4629eb3e0a3ca1714d745c1c2a186439472578c" dependencies = [ "egg", "log", "rand", "thiserror", - "wasm-encoder", - "wasmparser", + "wasm-encoder 0.39.0", + "wasmparser 0.119.0", ] [[package]] name = "wasm-smith" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58273756970c82a1769b11e13a05bd21f95a767e4a2fab03afd0cff0085ae89d" +checksum = "a419bbbab75f5ad71744256b74fdaeeb9215ea9e9bfc59c477e96c462ee0ef59" dependencies = [ "arbitrary", "flagset", "indexmap 2.0.0", "leb128", - "wasm-encoder", + "wasm-encoder 0.39.0", ] [[package]] @@ -3177,6 +3187,17 @@ dependencies = [ "semver", ] +[[package]] +name = "wasmparser" +version = "0.119.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c35daf77afb4f9b14016625144a391085ec2ca99ca9cc53ed291bb53ab5278d" +dependencies = [ + "bitflags 2.4.1", + "indexmap 2.0.0", + "semver", +] + [[package]] name = "wasmparser-nostd" version = "0.91.0" @@ -3188,12 +3209,12 @@ dependencies = [ [[package]] name = "wasmprinter" -version = "0.2.75" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d027eb8294904fc715ac0870cebe6b0271e96b90605ee21511e7565c4ce568c" +checksum = "cac2a7745372074e5573e365e17100f5a26058740576313784ef03fb900ea8d2" dependencies = [ "anyhow", - "wasmparser", + "wasmparser 0.119.0", ] [[package]] @@ -3220,8 +3241,8 @@ dependencies = [ "target-lexicon", "tempfile", "wasi-cap-std-sync", - "wasm-encoder", - "wasmparser", + "wasm-encoder 0.39.0", + "wasmparser 0.119.0", "wasmtime-cache", "wasmtime-component-macro", "wasmtime-component-util", @@ -3352,7 +3373,7 @@ dependencies = [ "tokio", "tracing", "walkdir", - "wasmparser", + "wasmparser 0.119.0", "wasmtime", "wasmtime-cache", "wasmtime-cli-flags", @@ -3366,10 +3387,10 @@ dependencies = [ "wasmtime-wasi-nn", "wasmtime-wasi-threads", "wasmtime-wast", - "wast 69.0.1", + "wast 70.0.0", "wat", "windows-sys 0.52.0", - "wit-component 0.19.0", + "wit-component 0.19.1", ] [[package]] @@ -3422,7 +3443,7 @@ dependencies = [ "object", "target-lexicon", "thiserror", - "wasmparser", + "wasmparser 0.119.0", "wasmtime-cranelift-shared", "wasmtime-environ", "wasmtime-versioned-export-macros", @@ -3458,8 +3479,8 @@ dependencies = [ "serde_derive", "target-lexicon", "thiserror", - "wasm-encoder", - "wasmparser", + "wasm-encoder 0.39.0", + "wasmparser 0.119.0", "wasmprinter", "wasmtime-component-util", "wasmtime-types", @@ -3474,7 +3495,7 @@ dependencies = [ "component-fuzz-util", "env_logger", "libfuzzer-sys", - "wasmparser", + "wasmparser 0.119.0", "wasmprinter", "wasmtime-environ", "wat", @@ -3531,7 +3552,7 @@ dependencies = [ "rand", "smallvec", "target-lexicon", - "wasmparser", + "wasmparser 0.119.0", "wasmtime", "wasmtime-fuzzing", ] @@ -3551,12 +3572,12 @@ dependencies = [ "target-lexicon", "tempfile", "v8", - "wasm-encoder", + "wasm-encoder 0.39.0", "wasm-mutate", "wasm-smith", "wasm-spec-interpreter", "wasmi", - "wasmparser", + "wasmparser 0.119.0", "wasmprinter", "wasmtime", "wasmtime-wast", @@ -3628,7 +3649,7 @@ dependencies = [ "rand", "rustix", "sptr", - "wasm-encoder", + "wasm-encoder 0.39.0", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-fiber", @@ -3646,7 +3667,7 @@ dependencies = [ "serde", "serde_derive", "thiserror", - "wasmparser", + "wasmparser 0.119.0", ] [[package]] @@ -3757,7 +3778,7 @@ dependencies = [ "anyhow", "log", "wasmtime", - "wast 69.0.1", + "wast 70.0.0", ] [[package]] @@ -3769,7 +3790,7 @@ dependencies = [ "gimli", "object", "target-lexicon", - "wasmparser", + "wasmparser 0.119.0", "wasmtime-cranelift-shared", "wasmtime-environ", "winch-codegen", @@ -3800,23 +3821,23 @@ dependencies = [ [[package]] name = "wast" -version = "69.0.1" +version = "70.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ee37317321afde358e4d7593745942c48d6d17e0e6e943704de9bbee121e7a" +checksum = "2ee4bc54bbe1c6924160b9f75e374a1d07532e7580eb632c0ee6cdd109bb217e" dependencies = [ "leb128", "memchr", "unicode-width", - "wasm-encoder", + "wasm-encoder 0.39.0", ] [[package]] name = "wat" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeb338ee8dee4d4cd05e6426683f21c5087dc7cfc8903e839ccf48d43332da3c" +checksum = "9f0dce8cdc288c717cf01e461a1e451a7b8445d53451123536ba576e423a101a" dependencies = [ - "wast 69.0.1", + "wast 70.0.0", ] [[package]] @@ -3941,7 +3962,7 @@ dependencies = [ "regalloc2", "smallvec", "target-lexicon", - "wasmparser", + "wasmparser 0.119.0", "wasmtime-environ", ] @@ -3957,7 +3978,7 @@ dependencies = [ "similar", "target-lexicon", "toml", - "wasmparser", + "wasmparser 0.119.0", "wasmtime-environ", "wat", "winch-codegen", @@ -3987,7 +4008,7 @@ dependencies = [ "similar", "target-lexicon", "toml", - "wasmparser", + "wasmparser 0.119.0", "wasmtime-environ", "wat", "winch-codegen", @@ -4208,17 +4229,17 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder", + "wasm-encoder 0.38.1", "wasm-metadata", - "wasmparser", + "wasmparser 0.118.1", "wit-parser", ] [[package]] name = "wit-component" -version = "0.19.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2e0cdd27c1500cb2524810e8f40b50012355a476c1bea5d12d73620125cc04" +checksum = "429e3c06fba3a7566aab724ae3ffff3152ede5399d44789e7dd11f5421292859" dependencies = [ "anyhow", "bitflags 2.4.1", @@ -4227,17 +4248,17 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder", + "wasm-encoder 0.39.0", "wasm-metadata", - "wasmparser", + "wasmparser 0.119.0", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15df6b7b28ce94b8be39d8df5cb21a08a4f3b9f33b631aedb4aa5776f785ead3" +checksum = "df4913a2219096373fd6512adead1fb77ecdaa59d7fc517972a7d30b12f625be" dependencies = [ "anyhow", "id-arena", diff --git a/Cargo.toml b/Cargo.toml index c8fe088e6433..cec28df6a4ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -233,15 +233,15 @@ is-terminal = "0.4.0" wit-bindgen = { version = "0.15.0", default-features = false } # wasm-tools family: -wasmparser = "0.118.1" -wat = "1.0.82" -wast = "69.0.1" -wasmprinter = "0.2.75" -wasm-encoder = "0.38.1" -wasm-smith = "0.13.1" -wasm-mutate = "0.2.42" -wit-parser = "0.13.0" -wit-component = "0.19.0" +wasmparser = "0.119.0" +wat = "1.0.83" +wast = "70.0.0" +wasmprinter = "0.2.76" +wasm-encoder = "0.39.0" +wasm-smith = "0.14.0" +wasm-mutate = "0.2.44" +wit-parser = "0.13.1" +wit-component = "0.19.1" # Non-Bytecode Alliance maintained dependencies: # -------------------------- diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs index e3d9997c41b5..163574f53242 100644 --- a/cranelift/wasm/src/code_translator.rs +++ b/cranelift/wasm/src/code_translator.rs @@ -2503,7 +2503,42 @@ pub fn translate_operator( state.push1(r); } - Operator::RefI31 | Operator::I31GetS | Operator::I31GetU => { + Operator::TryTable { .. } | Operator::ThrowRef => { + unimplemented!("exception operators not yet implemented") + } + + Operator::RefI31 + | Operator::I31GetS + | Operator::I31GetU + | Operator::RefEq + | Operator::RefTestNonNull { .. } + | Operator::RefTestNullable { .. } + | Operator::RefCastNonNull { .. } + | Operator::RefCastNullable { .. } + | Operator::BrOnCast { .. } + | Operator::BrOnCastFail { .. } + | Operator::AnyConvertExtern + | Operator::ExternConvertAny + | Operator::ArrayNew { .. } + | Operator::ArrayNewDefault { .. } + | Operator::ArrayNewFixed { .. } + | Operator::ArrayNewData { .. } + | Operator::ArrayNewElem { .. } + | Operator::ArrayGet { .. } + | Operator::ArrayGetU { .. } + | Operator::ArrayGetS { .. } + | Operator::ArraySet { .. } + | Operator::ArrayLen { .. } + | Operator::ArrayFill { .. } + | Operator::ArrayCopy { .. } + | Operator::ArrayInitData { .. } + | Operator::ArrayInitElem { .. } + | Operator::StructNew { .. } + | Operator::StructNewDefault { .. } + | Operator::StructGetS { .. } + | Operator::StructGetU { .. } + | Operator::StructSet { .. } + | Operator::StructGet { .. } => { unimplemented!("GC operators not yet implemented") } }; diff --git a/cranelift/wasm/src/sections_translator.rs b/cranelift/wasm/src/sections_translator.rs index e38b1327787b..876d01508af8 100644 --- a/cranelift/wasm/src/sections_translator.rs +++ b/cranelift/wasm/src/sections_translator.rs @@ -401,6 +401,7 @@ pub fn parse_name_section<'data>( | wasmparser::Name::Memory(_) | wasmparser::Name::Element(_) | wasmparser::Name::Data(_) + | wasmparser::Name::Tag(_) | wasmparser::Name::Unknown { .. } => {} } } diff --git a/cranelift/wasm/src/translation_utils.rs b/cranelift/wasm/src/translation_utils.rs index 9e8ea744914a..bfdba3bc4d49 100644 --- a/cranelift/wasm/src/translation_utils.rs +++ b/cranelift/wasm/src/translation_utils.rs @@ -4,7 +4,7 @@ use crate::WasmResult; use core::u32; use cranelift_codegen::ir; use cranelift_frontend::FunctionBuilder; -use wasmparser::{FuncValidator, WasmFuncType, WasmModuleResources}; +use wasmparser::{FuncValidator, WasmModuleResources}; /// Get the parameter and result types for the given Wasm blocktype. pub fn blocktype_params_results<'a, T>( @@ -29,11 +29,13 @@ where wasmparser::BlockType::FuncType(ty_index) => { let ty = validator .resources() - .func_type_at(ty_index) - .expect("should be valid"); + .sub_type_at(ty_index) + .expect("should be valid") + .unwrap_func(); + ( - itertools::Either::Right(ty.inputs()), - itertools::Either::Right(ty.outputs()), + itertools::Either::Right(ty.params().iter().copied()), + itertools::Either::Right(ty.results().iter().copied()), ) } }); diff --git a/cranelift/wasm/wasmtests/icall-simd.wat b/cranelift/wasm/wasmtests/icall-simd.wat index d656b265b96a..ea6ea9d0570f 100644 --- a/cranelift/wasm/wasmtests/icall-simd.wat +++ b/cranelift/wasm/wasmtests/icall-simd.wat @@ -3,5 +3,5 @@ (func $foo (export "foo") (param i32) (param v128) (result v128) (call_indirect (type $ft) (local.get 1) (local.get 0)) ) - (table (;0;) 23 23 anyfunc) + (table (;0;) 23 23 funcref) ) diff --git a/cranelift/wasm/wasmtests/icall.wat b/cranelift/wasm/wasmtests/icall.wat index f1dde0eafea5..d0c0fb42fcd4 100644 --- a/cranelift/wasm/wasmtests/icall.wat +++ b/cranelift/wasm/wasmtests/icall.wat @@ -3,5 +3,5 @@ (func $foo (export "foo") (param i32 f32) (result i32) (call_indirect (type $ft) (local.get 1) (local.get 0)) ) - (table (;0;) 23 23 anyfunc) + (table (;0;) 23 23 funcref) ) diff --git a/cranelift/wasm/wasmtests/unreachable_code.wat b/cranelift/wasm/wasmtests/unreachable_code.wat index 38c1a315cef9..0fdcc51b3b3b 100644 --- a/cranelift/wasm/wasmtests/unreachable_code.wat +++ b/cranelift/wasm/wasmtests/unreachable_code.wat @@ -72,6 +72,6 @@ end drop ) - (table (;0;) 16 anyfunc) + (table (;0;) 16 funcref) (elem (i32.const 0)) ) diff --git a/crates/environ/src/module_environ.rs b/crates/environ/src/module_environ.rs index f2f463eaa799..0fecd69703d9 100644 --- a/crates/environ/src/module_environ.rs +++ b/crates/environ/src/module_environ.rs @@ -874,6 +874,7 @@ and for re-adding support for interface types you can see this issue: | wasmparser::Name::Memory(_) | wasmparser::Name::Element(_) | wasmparser::Name::Data(_) + | wasmparser::Name::Tag(_) | wasmparser::Name::Unknown { .. } => {} } } diff --git a/crates/fuzzing/src/generators/config.rs b/crates/fuzzing/src/generators/config.rs index a5914ee36b84..d91de86b8200 100644 --- a/crates/fuzzing/src/generators/config.rs +++ b/crates/fuzzing/src/generators/config.rs @@ -47,7 +47,8 @@ impl Config { // Allow a memory to be generated, but don't let it get too large. // Additionally require the maximum size to guarantee that the growth // behavior is consistent across engines. - config.max_memory_pages = 10; + config.max_memory32_pages = 10; + config.max_memory64_pages = 10; config.memory_max_size_required = true; // If tables are generated make sure they don't get too large to avoid @@ -339,11 +340,13 @@ impl<'a> Arbitrary<'a> for Config { // Ensure the pooling allocator can support the maximal size of // memory, picking the smaller of the two to win. - if cfg.max_memory_pages < pooling.memory_pages { - pooling.memory_pages = cfg.max_memory_pages; - } else { - cfg.max_memory_pages = pooling.memory_pages; - } + let min = cfg + .max_memory32_pages + .min(cfg.max_memory64_pages) + .min(pooling.memory_pages); + pooling.memory_pages = min; + cfg.max_memory32_pages = min; + cfg.max_memory64_pages = min; // If traps are disallowed then memories must have at least one page // of memory so if we still are only allowing 0 pages of memory then @@ -351,7 +354,8 @@ impl<'a> Arbitrary<'a> for Config { if cfg.disallow_traps { if pooling.memory_pages == 0 { pooling.memory_pages = 1; - cfg.max_memory_pages = 1; + cfg.max_memory32_pages = 1; + cfg.max_memory64_pages = 1; } // .. additionally update tables if pooling.table_elements == 0 { diff --git a/crates/fuzzing/src/generators/module.rs b/crates/fuzzing/src/generators/module.rs index 7ff78c2b7d68..e274220212cd 100644 --- a/crates/fuzzing/src/generators/module.rs +++ b/crates/fuzzing/src/generators/module.rs @@ -1,21 +1,20 @@ //! Generate a Wasm module and the configuration for generating it. use arbitrary::{Arbitrary, Unstructured}; -use wasm_smith::SwarmConfig; /// Default module-level configuration for fuzzing Wasmtime. /// -/// Internally this uses `wasm-smith`'s own `SwarmConfig` but we further refine +/// Internally this uses `wasm-smith`'s own `Config` but we further refine /// the defaults here as well. #[derive(Debug, Clone)] pub struct ModuleConfig { #[allow(missing_docs)] - pub config: SwarmConfig, + pub config: wasm_smith::Config, } impl<'a> Arbitrary<'a> for ModuleConfig { fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result { - let mut config = SwarmConfig::arbitrary(u)?; + let mut config = wasm_smith::Config::arbitrary(u)?; // Allow multi-memory but make it unlikely if u.ratio(1, 20)? { diff --git a/crates/fuzzing/src/generators/single_inst_module.rs b/crates/fuzzing/src/generators/single_inst_module.rs index e42b452244a3..9a66fcdf1761 100644 --- a/crates/fuzzing/src/generators/single_inst_module.rs +++ b/crates/fuzzing/src/generators/single_inst_module.rs @@ -314,11 +314,11 @@ static INSTRUCTIONS: &[SingleInstModule] = &[ inst!(F32Ge, (f32, f32) -> i32), inst!(F64Ge, (f64, f64) -> i32), // Integer conversions ("to integer"). - inst!(I32Extend8S, (i32) -> i32, |c| c.config.sign_extension_enabled), - inst!(I32Extend16S, (i32) -> i32, |c| c.config.sign_extension_enabled), - inst!(I64Extend8S, (i64) -> i64, |c| c.config.sign_extension_enabled), - inst!(I64Extend16S, (i64) -> i64, |c| c.config.sign_extension_enabled), - inst!(I64Extend32S, (i64) -> i64, |c| c.config.sign_extension_enabled), + inst!(I32Extend8S, (i32) -> i32, |c| c.config.sign_extension_ops_enabled), + inst!(I32Extend16S, (i32) -> i32, |c| c.config.sign_extension_ops_enabled), + inst!(I64Extend8S, (i64) -> i64, |c| c.config.sign_extension_ops_enabled), + inst!(I64Extend16S, (i64) -> i64, |c| c.config.sign_extension_ops_enabled), + inst!(I64Extend32S, (i64) -> i64, |c| c.config.sign_extension_ops_enabled), inst!(I32WrapI64, (i64) -> i32), inst!(I64ExtendI32S, (i32) -> i64), inst!(I64ExtendI32U, (i32) -> i64), diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 06796ae500ec..68a7c3e76705 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -486,6 +486,7 @@ pub trait TypeConvert { wasmparser::HeapType::Concrete(i) => self.lookup_heap_type(i), wasmparser::HeapType::Any + | wasmparser::HeapType::Exn | wasmparser::HeapType::None | wasmparser::HeapType::NoExtern | wasmparser::HeapType::NoFunc diff --git a/crates/wasmtime/src/engine/serialization.rs b/crates/wasmtime/src/engine/serialization.rs index d6d0f4291ffb..6e891d549dcf 100644 --- a/crates/wasmtime/src/engine/serialization.rs +++ b/crates/wasmtime/src/engine/serialization.rs @@ -221,6 +221,7 @@ impl Metadata<'_> { function_references, gc, component_model_values, + component_model_nested_names, // Always on; we don't currently have knobs for these. mutable_global: _, @@ -232,6 +233,7 @@ impl Metadata<'_> { assert!(!memory_control); assert!(!gc); assert!(!component_model_values); + assert!(!component_model_nested_names); Metadata { target: engine.compiler().triple().to_string(), diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index 3f56c9a9761a..60fbc5112890 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -1947,6 +1947,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wasm-encoder]] +version = "0.39.0" +when = "2024-01-09" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wasm-metadata]] version = "0.10.9" when = "2023-10-14" @@ -1982,6 +1989,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wasm-metadata]] +version = "0.10.15" +when = "2024-01-09" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wasm-mutate]] version = "0.2.38" when = "2023-10-14" @@ -2010,6 +2024,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wasm-mutate]] +version = "0.2.44" +when = "2024-01-09" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wasm-smith]] version = "0.12.21" when = "2023-10-14" @@ -2045,6 +2066,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wasm-smith]] +version = "0.14.0" +when = "2024-01-09" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wasmparser]] version = "0.115.0" when = "2023-10-14" @@ -2080,6 +2108,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wasmparser]] +version = "0.119.0" +when = "2024-01-09" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wasmprinter]] version = "0.2.70" when = "2023-10-14" @@ -2115,6 +2150,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wasmprinter]] +version = "0.2.76" +when = "2024-01-09" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wasmtime]] version = "14.0.2" when = "2023-10-26" @@ -2750,6 +2792,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wast]] +version = "70.0.0" +when = "2024-01-09" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wat]] version = "1.0.77" when = "2023-10-14" @@ -2785,6 +2834,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wat]] +version = "1.0.83" +when = "2024-01-09" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wiggle]] version = "14.0.2" when = "2023-10-26" @@ -3161,6 +3217,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wit-component]] +version = "0.19.1" +when = "2024-01-09" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[publisher.wit-parser]] version = "0.12.1" when = "2023-10-18" @@ -3182,6 +3245,13 @@ user-id = 1 user-login = "alexcrichton" user-name = "Alex Crichton" +[[publisher.wit-parser]] +version = "0.13.1" +when = "2024-01-09" +user-id = 1 +user-login = "alexcrichton" +user-name = "Alex Crichton" + [[audits.embark-studios.wildcard-audits.spdx]] who = "Jake Shadle " criteria = "safe-to-deploy" diff --git a/tests/all/cli_tests/rs2wasm-add-func.wat b/tests/all/cli_tests/rs2wasm-add-func.wat index 89af3ffc4dca..660cd87434dd 100644 --- a/tests/all/cli_tests/rs2wasm-add-func.wat +++ b/tests/all/cli_tests/rs2wasm-add-func.wat @@ -6,7 +6,7 @@ local.get 0 i32.add) (func $start (type 0)) - (table (;0;) 1 1 anyfunc) + (table (;0;) 1 1 funcref) (memory (;0;) 17) (global (;0;) i32 (i32.const 1049114)) (global (;1;) i32 (i32.const 1049114)) diff --git a/tests/all/invoke_func_via_table.rs b/tests/all/invoke_func_via_table.rs index 8edb1838645b..d8a42fa3799a 100644 --- a/tests/all/invoke_func_via_table.rs +++ b/tests/all/invoke_func_via_table.rs @@ -11,7 +11,7 @@ fn test_invoke_func_via_table() -> Result<()> { (module (func $f (result i64) (i64.const 42)) - (table (export "table") 1 1 anyfunc) + (table (export "table") 1 1 funcref) (elem (i32.const 0) $f) ) "#; diff --git a/tests/all/limits.rs b/tests/all/limits.rs index ea6d02c08009..ffcc793caa6e 100644 --- a/tests/all/limits.rs +++ b/tests/all/limits.rs @@ -12,7 +12,7 @@ fn test_limits() -> Result<()> { &engine, r#"(module (memory $m (export "m") 0) - (table (export "t") 0 anyfunc) + (table (export "t") 0 funcref) (func (export "grow") (param i32) (result i32) (memory.grow $m (local.get 0))) )"#, @@ -100,7 +100,7 @@ async fn test_limits_async() -> Result<()> { let engine = Engine::new(&config).unwrap(); let module = Module::new( &engine, - r#"(module (memory (export "m") 0) (table (export "t") 0 anyfunc))"#, + r#"(module (memory (export "m") 0) (table (export "t") 0 funcref))"#, )?; struct LimitsAsync { @@ -190,7 +190,7 @@ fn test_limits_memory_only() -> Result<()> { let engine = Engine::default(); let module = Module::new( &engine, - r#"(module (memory (export "m") 0) (table (export "t") 0 anyfunc))"#, + r#"(module (memory (export "m") 0) (table (export "t") 0 funcref))"#, )?; let mut store = Store::new( @@ -276,7 +276,7 @@ fn test_limits_table_only() -> Result<()> { let engine = Engine::default(); let module = Module::new( &engine, - r#"(module (memory (export "m") 0) (table (export "t") 0 anyfunc))"#, + r#"(module (memory (export "m") 0) (table (export "t") 0 funcref))"#, )?; let mut store = Store::new(&engine, StoreLimitsBuilder::new().table_elements(5).build()); @@ -323,7 +323,7 @@ fn test_limits_table_only() -> Result<()> { #[test] fn test_initial_table_limits_exceeded() -> Result<()> { let engine = Engine::default(); - let module = Module::new(&engine, r#"(module (table (export "t") 23 anyfunc))"#)?; + let module = Module::new(&engine, r#"(module (table (export "t") 23 funcref))"#)?; let mut store = Store::new(&engine, StoreLimitsBuilder::new().table_elements(4).build()); store.limiter(|s| s as &mut dyn ResourceLimiter); @@ -661,7 +661,7 @@ fn test_custom_table_limiter() -> Result<()> { let engine = Engine::default(); let linker = Linker::new(&engine); - let module = Module::new(&engine, r#"(module (table (export "t") 0 anyfunc))"#)?; + let module = Module::new(&engine, r#"(module (table (export "t") 0 funcref))"#)?; let context = TableContext { elements_used: 0, @@ -752,7 +752,7 @@ fn custom_limiter_detect_grow_failure() -> Result<()> { let module = Module::new( &engine, - r#"(module (memory (export "m") 0) (table (export "t") 0 anyfunc))"#, + r#"(module (memory (export "m") 0) (table (export "t") 0 funcref))"#, )?; let context = FailureDetector::default(); @@ -864,7 +864,7 @@ async fn custom_limiter_async_detect_grow_failure() -> Result<()> { let module = Module::new( &engine, - r#"(module (memory (export "m") 0) (table (export "t") 0 anyfunc))"#, + r#"(module (memory (export "m") 0) (table (export "t") 0 funcref))"#, )?; let context = FailureDetector::default(); @@ -1023,7 +1023,7 @@ fn panic_in_table_limiter() { let engine = Engine::default(); let linker = Linker::new(&engine); - let module = Module::new(&engine, r#"(module (table (export "t") 0 anyfunc))"#).unwrap(); + let module = Module::new(&engine, r#"(module (table (export "t") 0 funcref))"#).unwrap(); let mut store = Store::new(&engine, Panic); store.limiter(|s| s as &mut dyn ResourceLimiter); @@ -1095,7 +1095,7 @@ async fn panic_in_async_table_limiter() { let engine = Engine::new(&config).unwrap(); let linker = Linker::new(&engine); - let module = Module::new(&engine, r#"(module (table (export "t") 0 anyfunc))"#).unwrap(); + let module = Module::new(&engine, r#"(module (table (export "t") 0 funcref))"#).unwrap(); let mut store = Store::new(&engine, Panic); store.limiter_async(|s| s as &mut dyn ResourceLimiterAsync); @@ -1117,7 +1117,7 @@ fn growth_trap() -> Result<()> { &engine, r#"(module (memory $m (export "m") 0) - (table (export "t") 0 anyfunc) + (table (export "t") 0 funcref) (func (export "grow") (param i32) (result i32) (memory.grow $m (local.get 0))) )"#, diff --git a/tests/all/traps.rs b/tests/all/traps.rs index ea2d648541f0..9b3ae2764c11 100644 --- a/tests/all/traps.rs +++ b/tests/all/traps.rs @@ -558,7 +558,7 @@ fn call_signature_mismatch() -> Result<()> { (func $bar (param i32)) (start $foo) - (table 1 anyfunc) + (table 1 funcref) (elem (i32.const 0) 1) ) "#, diff --git a/tests/misc_testsuite/rs2wasm-add-func.wast b/tests/misc_testsuite/rs2wasm-add-func.wast index 89af3ffc4dca..660cd87434dd 100644 --- a/tests/misc_testsuite/rs2wasm-add-func.wast +++ b/tests/misc_testsuite/rs2wasm-add-func.wast @@ -6,7 +6,7 @@ local.get 0 i32.add) (func $start (type 0)) - (table (;0;) 1 1 anyfunc) + (table (;0;) 1 1 funcref) (memory (;0;) 17) (global (;0;) i32 (i32.const 1049114)) (global (;1;) i32 (i32.const 1049114)) From 536cf88ce9864cdddfe52bf625c81b06e8eb1d43 Mon Sep 17 00:00:00 2001 From: Trevor Elliott Date: Wed, 10 Jan 2024 13:38:55 -0800 Subject: [PATCH 3/3] wasi: Test that pollables may be used multiple times (#7763) * Add a small test checking that pollables can be used many times * Tests where two commands have their stdin/stdout piped together * Pipe together wasmtime subprocesses instead of managing the buffer --- crates/test-programs/artifacts/build.rs | 1 + crates/test-programs/src/bin/piped_polling.rs | 51 +++++++++++++ crates/test-programs/src/bin/piped_simple.rs | 30 ++++++++ .../bin/preview2_stream_pollable_correct.rs | 22 +++++- tests/all/main.rs | 1 + tests/all/piped_tests.rs | 72 +++++++++++++++++++ 6 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 crates/test-programs/src/bin/piped_polling.rs create mode 100644 crates/test-programs/src/bin/piped_simple.rs create mode 100644 tests/all/piped_tests.rs diff --git a/crates/test-programs/artifacts/build.rs b/crates/test-programs/artifacts/build.rs index 193c2b3134dd..a515415b604c 100644 --- a/crates/test-programs/artifacts/build.rs +++ b/crates/test-programs/artifacts/build.rs @@ -74,6 +74,7 @@ fn build_and_generate_tests() { s if s.starts_with("cli_") => "cli", s if s.starts_with("api_") => "api", s if s.starts_with("nn_") => "nn", + s if s.starts_with("piped_") => "piped", // If you're reading this because you hit this panic, either add it // to a test suite above or add a new "suite". The purpose of the // categorization above is to have a static assertion that tests diff --git a/crates/test-programs/src/bin/piped_polling.rs b/crates/test-programs/src/bin/piped_polling.rs new file mode 100644 index 000000000000..05f8b35a8596 --- /dev/null +++ b/crates/test-programs/src/bin/piped_polling.rs @@ -0,0 +1,51 @@ +use test_programs::wasi::cli::{stdin, stdout}; + +fn main() { + match std::env::var("PIPED_SIDE") + .expect("piped tests require the PIPED_SIDE env var") + .as_str() + { + "PRODUCER" => producer(), + "CONSUMER" => consumer(), + side => panic!("unknown piped test side: {side}"), + } +} + +fn producer() { + let out = stdout::get_stdout(); + let out_pollable = out.subscribe(); + + for i in 1..100 { + let message = format!("{i}"); + loop { + let available = out.check_write().unwrap() as usize; + if available >= message.len() { + break; + } + + out_pollable.block(); + assert!(out_pollable.ready()); + } + + out.write(message.as_bytes()).unwrap() + } + + drop(out_pollable); +} + +fn consumer() { + let stdin = stdin::get_stdin(); + let stdin_pollable = stdin.subscribe(); + + for i in 1..100 { + let expected = format!("{i}"); + + stdin_pollable.block(); + assert!(stdin_pollable.ready()); + + let bytes = stdin.read(expected.len() as u64).unwrap(); + assert_eq!(&bytes, expected.as_bytes()); + } + + drop(stdin_pollable); +} diff --git a/crates/test-programs/src/bin/piped_simple.rs b/crates/test-programs/src/bin/piped_simple.rs new file mode 100644 index 000000000000..323e463335aa --- /dev/null +++ b/crates/test-programs/src/bin/piped_simple.rs @@ -0,0 +1,30 @@ +use test_programs::wasi::cli::{stdin, stdout}; + +fn main() { + match std::env::var("PIPED_SIDE") + .expect("piped tests require the PIPED_SIDE env var") + .as_str() + { + "PRODUCER" => producer(), + "CONSUMER" => consumer(), + side => panic!("unknown piped test side: {side}"), + } +} + +const CHUNK: &[u8] = &[b'a'; 50]; + +fn producer() { + let out = stdout::get_stdout(); + let n = out.check_write().unwrap() as usize; + assert!(n > CHUNK.len()); + out.write(CHUNK).unwrap(); +} + +fn consumer() { + let stdin = stdin::get_stdin(); + let stdin_pollable = stdin.subscribe(); + stdin_pollable.block(); + assert!(stdin_pollable.ready()); + let bytes = stdin.read(CHUNK.len() as u64).unwrap(); + assert_eq!(&bytes, CHUNK); +} diff --git a/crates/test-programs/src/bin/preview2_stream_pollable_correct.rs b/crates/test-programs/src/bin/preview2_stream_pollable_correct.rs index 044ebb336aa9..7b2247764fc9 100644 --- a/crates/test-programs/src/bin/preview2_stream_pollable_correct.rs +++ b/crates/test-programs/src/bin/preview2_stream_pollable_correct.rs @@ -1,11 +1,27 @@ -use test_programs::wasi::cli::stdin; -use test_programs::wasi::io::streams; +use test_programs::wasi::cli::{stdin, stdout}; fn main() { - let stdin: streams::InputStream = stdin::get_stdin(); + let stdin = stdin::get_stdin(); let stdin_pollable = stdin.subscribe(); stdin_pollable.block(); assert!(stdin_pollable.ready(), "after blocking, pollable is ready"); drop(stdin_pollable); drop(stdin); + + // Pollables can be used many times over their lifetime + let stdout = stdout::get_stdout(); + let stdout_pollable = stdout.subscribe(); + + let chunk = [b'a'; 50]; + for _ in 1..10 { + stdout_pollable.block(); + assert!(stdout_pollable.ready(), "after blocking, pollable is ready"); + + let n = stdout.check_write().unwrap() as usize; + assert!(n >= chunk.len()); + stdout.write(&chunk).unwrap(); + } + + drop(stdout_pollable); + drop(stdout); } diff --git a/tests/all/main.rs b/tests/all/main.rs index e308b4b4321b..bb8ac88b0571 100644 --- a/tests/all/main.rs +++ b/tests/all/main.rs @@ -27,6 +27,7 @@ mod memory_creator; mod module; mod module_serialize; mod name; +mod piped_tests; mod pooling_allocator; mod relocs; mod stack_creator; diff --git a/tests/all/piped_tests.rs b/tests/all/piped_tests.rs new file mode 100644 index 000000000000..95f007d049d3 --- /dev/null +++ b/tests/all/piped_tests.rs @@ -0,0 +1,72 @@ +#![cfg(not(miri))] + +use super::cli_tests::get_wasmtime_command; +use anyhow::Result; +use std::process::{ChildStdout, Command, Stdio}; + +fn producer_command(component_path: &str) -> Result { + let mut cmd = get_wasmtime_command()?; + cmd.arg("run") + .arg("-Wcomponent-model") + .arg("--env") + .arg("PIPED_SIDE=PRODUCER") + .arg(component_path) + .stdout(Stdio::piped()); + Ok(cmd) +} + +fn consumer_command(component_path: &str, input: ChildStdout) -> Result { + let mut cmd = get_wasmtime_command()?; + cmd.arg("run") + .arg("-Wcomponent-model") + .arg("--env") + .arg("PIPED_SIDE=CONSUMER") + .arg(component_path) + .stdin(input); + Ok(cmd) +} + +pub fn run_wasmtime_piped(component_path: &str) -> Result<()> { + let mut producer = producer_command(component_path)?.spawn()?; + let stdout = producer.stdout.take().unwrap(); + let mut consumer = consumer_command(component_path, stdout)?.spawn()?; + + let producer = producer.wait()?; + if !producer.success() { + // make sure the consumer gets killed off + if consumer.try_wait().is_err() { + consumer.kill().expect("Failed to kill consumer"); + } + + panic!("Producer failed"); + } + + assert!(consumer.wait()?.success(), "Consumer failed"); + + Ok(()) +} + +mod test_programs { + use super::run_wasmtime_piped; + use test_programs_artifacts::*; + + macro_rules! assert_test_exists { + ($name:ident) => { + #[allow(unused_imports)] + use self::$name as _; + }; + } + foreach_piped!(assert_test_exists); + + // Below here is mechanical: there should be one test for every binary in + // wasi-tests. + #[test] + fn piped_simple() { + run_wasmtime_piped(PIPED_SIMPLE_COMPONENT).unwrap() + } + + #[test] + fn piped_polling() { + run_wasmtime_piped(PIPED_POLLING_COMPONENT).unwrap() + } +}