Browse Source

wiggle: make wasmtime a mandatory dep, get rid of own Trap enum (#5137)

* wiggle: no longer need to guard wasmtime integration behind a feature

this existed so we could use wiggle in lucet, but lucet is long EOL

* replace wiggle::Trap with wiggle::wasmtime_crate::Trap

* wiggle tests: unwrap traps because we cant assert_eq on them

* wasi-common: emit a wasmtime::Trap instead of a wiggle::Trap

formally add a dependency on wasmtime here to make it obvious, though
we do now have a transitive one via wiggle no matter what (and therefore
can get rid of the default-features=false on the wiggle dep)

* wasi-nn: use wasmtime::Trap instead of wiggle::Trap

there's no way the implementation of this func is actually
a good idea, it will panic the host process on any error,
but I'll ask @mtr to fix that

* wiggle test-helpers examples: fixes

* wasi-common cant cross compile to wasm32-unknown-emscripten anymore

this was originally for the WASI polyfill for web targets. Those days
are way behind us now.

* wasmtime wont compile for armv7-unknown-linux-gnueabihf either
pull/5146/head
Pat Hickey 2 years ago
committed by GitHub
parent
commit
0290a83502
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      .github/workflows/main.yml
  2. 1
      Cargo.lock
  3. 3
      crates/wasi-common/Cargo.toml
  4. 6
      crates/wasi-common/src/snapshots/preview_0.rs
  5. 10
      crates/wasi-common/src/snapshots/preview_1.rs
  6. 2
      crates/wasi-common/tokio/Cargo.toml
  7. 2
      crates/wasi-crypto/Cargo.toml
  8. 5
      crates/wasi-nn/src/witx.rs
  9. 2
      crates/wasi/Cargo.toml
  10. 12
      crates/wiggle/Cargo.toml
  11. 4
      crates/wiggle/generate/src/funcs.rs
  12. 2
      crates/wiggle/generate/src/lib.rs
  13. 2
      crates/wiggle/generate/src/module_trait.rs
  14. 6
      crates/wiggle/generate/src/wasmtime.rs
  15. 1
      crates/wiggle/macro/Cargo.toml
  16. 17
      crates/wiggle/macro/src/lib.rs
  17. 27
      crates/wiggle/src/lib.rs
  18. 17
      crates/wiggle/test-helpers/examples/tracing.rs
  19. 10
      crates/wiggle/tests/atoms.rs
  20. 10
      crates/wiggle/tests/atoms_async.rs
  21. 28
      crates/wiggle/tests/errors.rs
  22. 5
      crates/wiggle/tests/flags.rs
  23. 13
      crates/wiggle/tests/handles.rs
  24. 5
      crates/wiggle/tests/ints.rs
  25. 32
      crates/wiggle/tests/lists.rs
  26. 5
      crates/wiggle/tests/pointers.rs
  27. 38
      crates/wiggle/tests/records.rs
  28. 15
      crates/wiggle/tests/strings.rs
  29. 10
      crates/wiggle/tests/variant.rs
  30. 2
      crates/wiggle/tests/wasi.rs

10
.github/workflows/main.yml

@ -173,16 +173,6 @@ jobs:
env: env:
CARGO_PROFILE_DEV_DEBUG_ASSERTIONS: false CARGO_PROFILE_DEV_DEBUG_ASSERTIONS: false
# Check whether `crates/wasi-common` cross-compiles to the following targets:
# * wasm32-unknown-emscripten
# * armv7-unknown-linux-gnueabihf
- run: |
rustup target add wasm32-unknown-emscripten
rustup target add armv7-unknown-linux-gnueabihf
sudo apt-get update && sudo apt-get install -y gcc-arm-linux-gnueabihf
- run: cargo check --target wasm32-unknown-emscripten -p wasi-common
- run: cargo check --target armv7-unknown-linux-gnueabihf -p wasi-common
# Check whether `wasmtime` cross-compiles to aarch64-pc-windows-msvc # Check whether `wasmtime` cross-compiles to aarch64-pc-windows-msvc
# We don't build nor test it because it lacks trap handling. # We don't build nor test it because it lacks trap handling.
# Tracking issue: https://github.com/bytecodealliance/wasmtime/issues/4992 # Tracking issue: https://github.com/bytecodealliance/wasmtime/issues/4992

1
Cargo.lock

@ -3149,6 +3149,7 @@ dependencies = [
"rustix", "rustix",
"thiserror", "thiserror",
"tracing", "tracing",
"wasmtime",
"wiggle", "wiggle",
"windows-sys", "windows-sys",
] ]

3
crates/wasi-common/Cargo.toml

@ -20,7 +20,8 @@ links = "wasi-common-19"
[dependencies] [dependencies]
anyhow = { workspace = true } anyhow = { workspace = true }
thiserror = "1.0" thiserror = "1.0"
wiggle = { workspace = true, default-features = false } wiggle = { workspace = true }
wasmtime = { workspace = true }
tracing = "0.1.19" tracing = "0.1.19"
cap-std = { workspace = true } cap-std = { workspace = true }
cap-rand = "0.26.0" cap-rand = "0.26.0"

6
crates/wasi-common/src/snapshots/preview_0.rs

@ -28,10 +28,10 @@ impl wiggle::GuestErrorType for types::Errno {
} }
impl types::UserErrorConversion for WasiCtx { impl types::UserErrorConversion for WasiCtx {
fn errno_from_error(&mut self, e: Error) -> Result<types::Errno, wiggle::Trap> { fn errno_from_error(&mut self, e: Error) -> Result<types::Errno, wasmtime::Trap> {
debug!("Error: {:?}", e); debug!("Error: {:?}", e);
e.try_into() e.try_into()
.map_err(|e| wiggle::Trap::String(format!("{:?}", e))) .map_err(|e| wasmtime::Trap::new(format!("{:?}", e)))
} }
} }
@ -932,7 +932,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
Ok(num_results.try_into().expect("results fit into memory")) Ok(num_results.try_into().expect("results fit into memory"))
} }
async fn proc_exit(&mut self, status: types::Exitcode) -> wiggle::Trap { async fn proc_exit(&mut self, status: types::Exitcode) -> wasmtime::Trap {
Snapshot1::proc_exit(self, status).await Snapshot1::proc_exit(self, status).await
} }

10
crates/wasi-common/src/snapshots/preview_1.rs

@ -35,10 +35,10 @@ impl wiggle::GuestErrorType for types::Errno {
} }
impl types::UserErrorConversion for WasiCtx { impl types::UserErrorConversion for WasiCtx {
fn errno_from_error(&mut self, e: Error) -> Result<types::Errno, wiggle::Trap> { fn errno_from_error(&mut self, e: Error) -> Result<types::Errno, wasmtime::Trap> {
debug!("Error: {:?}", e); debug!("Error: {:?}", e);
e.try_into() e.try_into()
.map_err(|e| wiggle::Trap::String(format!("{:?}", e))) .map_err(|e| wasmtime::Trap::new(format!("{:?}", e)))
} }
} }
@ -1214,12 +1214,12 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
Ok(num_results.try_into().expect("results fit into memory")) Ok(num_results.try_into().expect("results fit into memory"))
} }
async fn proc_exit(&mut self, status: types::Exitcode) -> wiggle::Trap { async fn proc_exit(&mut self, status: types::Exitcode) -> wasmtime::Trap {
// Check that the status is within WASI's range. // Check that the status is within WASI's range.
if status < 126 { if status < 126 {
wiggle::Trap::I32Exit(status as i32) wasmtime::Trap::i32_exit(status as i32)
} else { } else {
wiggle::Trap::String("exit with invalid exit status outside of [0..126)".to_owned()) wasmtime::Trap::new("exit with invalid exit status outside of [0..126)")
} }
} }

2
crates/wasi-common/tokio/Cargo.toml

@ -13,7 +13,7 @@ include = ["src/**/*", "LICENSE" ]
[dependencies] [dependencies]
wasi-common = { workspace = true } wasi-common = { workspace = true }
wasi-cap-std-sync = { workspace = true } wasi-cap-std-sync = { workspace = true }
wiggle = { workspace = true, features = ['wasmtime_integration'] } wiggle = { workspace = true }
tokio = { version = "1.8.0", features = [ "rt", "fs", "time", "io-util", "net", "io-std", "rt-multi-thread"] } tokio = { version = "1.8.0", features = [ "rt", "fs", "time", "io-util", "net", "io-std", "rt-multi-thread"] }
cap-std = { workspace = true } cap-std = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }

2
crates/wasi-crypto/Cargo.toml

@ -15,7 +15,7 @@ edition.workspace = true
anyhow = { workspace = true } anyhow = { workspace = true }
wasi-crypto = { path = "spec/implementations/hostcalls/rust", version = "0.1.5" } wasi-crypto = { path = "spec/implementations/hostcalls/rust", version = "0.1.5" }
wasmtime = { workspace = true } wasmtime = { workspace = true }
wiggle = { workspace = true, default-features = true, features = ['wasmtime_integration'] } wiggle = { workspace = true }
[badges] [badges]
maintenance = { status = "experimental" } maintenance = { status = "experimental" }

5
crates/wasi-nn/src/witx.rs

@ -11,7 +11,10 @@ wiggle::from_witx!({
use types::NnErrno; use types::NnErrno;
impl<'a> types::UserErrorConversion for WasiNnCtx { impl<'a> types::UserErrorConversion for WasiNnCtx {
fn nn_errno_from_wasi_nn_error(&mut self, e: WasiNnError) -> Result<NnErrno, wiggle::Trap> { fn nn_errno_from_wasi_nn_error(
&mut self,
e: WasiNnError,
) -> Result<NnErrno, wiggle::wasmtime_crate::Trap> {
eprintln!("Host error: {:?}", e); eprintln!("Host error: {:?}", e);
match e { match e {
WasiNnError::BackendError(_) => unimplemented!(), WasiNnError::BackendError(_) => unimplemented!(),

2
crates/wasi/Cargo.toml

@ -16,7 +16,7 @@ build = "build.rs"
wasi-common = { workspace = true } wasi-common = { workspace = true }
wasi-cap-std-sync = { workspace = true, optional = true } wasi-cap-std-sync = { workspace = true, optional = true }
wasi-tokio = { workspace = true, optional = true } wasi-tokio = { workspace = true, optional = true }
wiggle = { workspace = true, default-features = false, features = ["wasmtime_integration"] } wiggle = { workspace = true }
wasmtime = { workspace = true } wasmtime = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }

12
crates/wiggle/Cargo.toml

@ -17,7 +17,7 @@ wiggle-macro = { workspace = true }
tracing = "0.1.26" tracing = "0.1.26"
bitflags = "1.2" bitflags = "1.2"
async-trait = "0.1.42" async-trait = "0.1.42"
wasmtime = { workspace = true, optional = true } wasmtime = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }
[badges] [badges]
@ -41,12 +41,12 @@ required-features = ["wasmtime_async", "wasmtime/wat"]
[[test]] [[test]]
name = "wasmtime_sync" name = "wasmtime_sync"
path = "tests/wasmtime_sync.rs" path = "tests/wasmtime_sync.rs"
required-features = ["wasmtime_integration", "wasmtime/wat"] required-features = ["wasmtime/wat"]
[[test]] [[test]]
name = "wasmtime_integration" name = "wasmtime_integration"
path = "tests/wasmtime_integration.rs" path = "tests/wasmtime_integration.rs"
required-features = ["wasmtime_integration", "wasmtime/wat"] required-features = ["wasmtime/wat"]
[features] [features]
@ -62,9 +62,7 @@ wiggle_metadata = ['witx', "wiggle-macro/wiggle_metadata"]
# the logs out of wiggle-generated libraries. # the logs out of wiggle-generated libraries.
tracing_log = [ "tracing/log" ] tracing_log = [ "tracing/log" ]
# Generate adapters for wasmtime, and expose the wasmtime_integration macro.
wasmtime_integration = [ "wasmtime", "wiggle-macro/wasmtime" ]
# Support for async in the wasmtime crates. # Support for async in the wasmtime crates.
wasmtime_async = [ "wasmtime_integration", "wasmtime/async" ] wasmtime_async = [ "wasmtime/async" ]
default = ["wiggle_metadata", "wasmtime_integration" ] default = ["wiggle_metadata", "wasmtime_async" ]

4
crates/wiggle/generate/src/funcs.rs

@ -91,7 +91,7 @@ fn _define_func(
ctx: &mut (impl #(#bounds)+*), ctx: &mut (impl #(#bounds)+*),
memory: &dyn #rt::GuestMemory, memory: &dyn #rt::GuestMemory,
#(#abi_params),* #(#abi_params),*
) -> Result<#abi_ret, #rt::Trap> { ) -> Result<#abi_ret, #rt::wasmtime_crate::Trap> {
use std::convert::TryFrom as _; use std::convert::TryFrom as _;
#mk_span #mk_span
_span.in_scope(|| { _span.in_scope(|| {
@ -109,7 +109,7 @@ fn _define_func(
ctx: &'a mut (impl #(#bounds)+*), ctx: &'a mut (impl #(#bounds)+*),
memory: &'a dyn #rt::GuestMemory, memory: &'a dyn #rt::GuestMemory,
#(#abi_params),* #(#abi_params),*
) -> impl std::future::Future<Output = Result<#abi_ret, #rt::Trap>> + 'a { ) -> impl std::future::Future<Output = Result<#abi_ret, #rt::wasmtime_crate::Trap>> + 'a {
use std::convert::TryFrom as _; use std::convert::TryFrom as _;
use #rt::tracing::Instrument as _; use #rt::tracing::Instrument as _;
#mk_span #mk_span

2
crates/wiggle/generate/src/lib.rs

@ -43,7 +43,7 @@ pub fn generate(doc: &witx::Document, names: &Names, settings: &CodegenSettings)
let abi_typename = names.type_ref(&errtype.abi_type(), anon_lifetime()); let abi_typename = names.type_ref(&errtype.abi_type(), anon_lifetime());
let user_typename = errtype.typename(); let user_typename = errtype.typename();
let methodname = names.user_error_conversion_method(&errtype); let methodname = names.user_error_conversion_method(&errtype);
quote!(fn #methodname(&mut self, e: super::#user_typename) -> Result<#abi_typename, #rt::Trap>;) quote!(fn #methodname(&mut self, e: super::#user_typename) -> Result<#abi_typename, #rt::wasmtime_crate::Trap>;)
}); });
let user_error_conversion = quote! { let user_error_conversion = quote! {
pub trait UserErrorConversion { pub trait UserErrorConversion {

2
crates/wiggle/generate/src/module_trait.rs

@ -45,7 +45,7 @@ pub fn define_module_trait(names: &Names, m: &Module, settings: &CodegenSettings
}); });
let result = match f.results.len() { let result = match f.results.len() {
0 if f.noreturn => quote!(#rt::Trap), 0 if f.noreturn => quote!(#rt::wasmtime_crate::Trap),
0 => quote!(()), 0 => quote!(()),
1 => { 1 => {
let (ok, err) = match &**f.results[0].tref.type_() { let (ok, err) = match &**f.results[0].tref.type_() {

6
crates/wiggle/generate/src/wasmtime.rs

@ -121,11 +121,7 @@ fn generate_func(
let (mem , ctx) = mem.data_and_store_mut(&mut caller); let (mem , ctx) = mem.data_and_store_mut(&mut caller);
let ctx = get_cx(ctx); let ctx = get_cx(ctx);
let mem = #rt::wasmtime::WasmtimeGuestMemory::new(mem); let mem = #rt::wasmtime::WasmtimeGuestMemory::new(mem);
match #abi_func(ctx, &mem #(, #arg_names)*) #await_ { Ok(<#ret_ty>::from(#abi_func(ctx, &mem #(, #arg_names)*) #await_ ?))
Ok(r) => Ok(<#ret_ty>::from(r)),
Err(#rt::Trap::String(err)) => Err(#rt::wasmtime_crate::Trap::new(err)),
Err(#rt::Trap::I32Exit(err)) => Err(#rt::wasmtime_crate::Trap::i32_exit(err)),
}
}; };
match asyncness { match asyncness {

1
crates/wiggle/macro/Cargo.toml

@ -30,5 +30,4 @@ proc-macro2 = "1.0"
wiggle = { path = ".." } wiggle = { path = ".." }
[features] [features]
wasmtime = []
wiggle_metadata = [] wiggle_metadata = []

17
crates/wiggle/macro/src/lib.rs

@ -126,14 +126,14 @@ use syn::parse_macro_input;
/// ///
/// impl types::UserErrorConversion for YourCtxType { /// impl types::UserErrorConversion for YourCtxType {
/// fn errno_from_your_rich_error(&mut self, e: YourRichError) /// fn errno_from_your_rich_error(&mut self, e: YourRichError)
/// -> Result<types::Errno, wiggle::Trap> /// -> Result<types::Errno, wiggle::wasmtime_crate::Trap>
/// { /// {
/// println!("Rich error: {:?}", e); /// println!("Rich error: {:?}", e);
/// match e { /// match e {
/// YourRichError::InvalidArg{..} => Ok(types::Errno::InvalidArg), /// YourRichError::InvalidArg{..} => Ok(types::Errno::InvalidArg),
/// YourRichError::Io{..} => Ok(types::Errno::Io), /// YourRichError::Io{..} => Ok(types::Errno::Io),
/// YourRichError::Overflow => Ok(types::Errno::Overflow), /// YourRichError::Overflow => Ok(types::Errno::Overflow),
/// YourRichError::Trap(s) => Err(wiggle::Trap::String(s)), /// YourRichError::Trap(s) => Err(wiggle::wasmtime_crate::Trap::new(s)),
/// } /// }
/// } /// }
/// } /// }
@ -152,7 +152,7 @@ pub fn from_witx(args: TokenStream) -> TokenStream {
&config.errors, &config.errors,
&config.async_, &config.async_,
&doc, &doc,
cfg!(feature = "wasmtime") && config.wasmtime, config.wasmtime,
) )
.expect("validating codegen settings"); .expect("validating codegen settings");
@ -176,7 +176,6 @@ pub fn async_trait(attr: TokenStream, item: TokenStream) -> TokenStream {
}) })
} }
#[cfg(feature = "wasmtime")]
/// Define the structs required to integrate a Wiggle implementation with Wasmtime. /// Define the structs required to integrate a Wiggle implementation with Wasmtime.
/// ///
/// ## Arguments /// ## Arguments
@ -190,13 +189,9 @@ pub fn wasmtime_integration(args: TokenStream) -> TokenStream {
let doc = config.c.load_document(); let doc = config.c.load_document();
let names = wiggle_generate::Names::new(quote!(wiggle)); let names = wiggle_generate::Names::new(quote!(wiggle));
let settings = wiggle_generate::CodegenSettings::new( let settings =
&config.c.errors, wiggle_generate::CodegenSettings::new(&config.c.errors, &config.c.async_, &doc, true)
&config.c.async_, .expect("validating codegen settings");
&doc,
cfg!(feature = "wasmtime"),
)
.expect("validating codegen settings");
let modules = doc.modules().map(|module| { let modules = doc.modules().map(|module| {
wiggle_generate::wasmtime::link_module(&module, &names, Some(&config.target), &settings) wiggle_generate::wasmtime::link_module(&module, &names, Some(&config.target), &settings)

27
crates/wiggle/src/lib.rs

@ -5,9 +5,7 @@ use std::sync::Arc;
pub use wiggle_macro::{async_trait, from_witx}; pub use wiggle_macro::{async_trait, from_witx};
#[cfg(feature = "wasmtime")]
pub use anyhow; pub use anyhow;
#[cfg(feature = "wasmtime")]
pub use wiggle_macro::wasmtime_integration; pub use wiggle_macro::wasmtime_integration;
pub use bitflags; pub use bitflags;
@ -30,10 +28,7 @@ pub mod async_trait_crate {
pub use async_trait::*; pub use async_trait::*;
} }
#[cfg(feature = "wasmtime")]
pub mod wasmtime; pub mod wasmtime;
#[cfg(feature = "wasmtime")]
pub mod wasmtime_crate { pub mod wasmtime_crate {
pub use wasmtime::*; pub use wasmtime::*;
} }
@ -914,26 +909,14 @@ impl Pointee for str {
} }
} }
/// A runtime-independent way for Wiggle to terminate WebAssembly execution. impl From<GuestError> for wasmtime_crate::Trap {
/// Functions that are marked `(@witx noreturn)` will always return a Trap. fn from(err: GuestError) -> wasmtime_crate::Trap {
/// Other functions that want to Trap can do so via their `UserErrorConversion` wasmtime_crate::Trap::from(
/// trait, which transforms the user's own error type into a `Result<abierror, Trap>`. Box::new(err) as Box<dyn std::error::Error + Send + Sync + 'static>
#[derive(Debug, Clone, PartialEq, Eq)] )
pub enum Trap {
/// A Trap which indicates an i32 (posix-style) exit code. Runtimes may have a
/// special way of dealing with this for WASI embeddings and otherwise.
I32Exit(i32),
/// Any other Trap is just an unstructured String, for reporting and debugging.
String(String),
}
impl From<GuestError> for Trap {
fn from(err: GuestError) -> Trap {
Trap::String(err.to_string())
} }
} }
#[cfg(feature = "wasmtime")]
pub fn run_in_dummy_executor<F: std::future::Future>( pub fn run_in_dummy_executor<F: std::future::Future>(
future: F, future: F,
) -> Result<F::Output, wasmtime_crate::Trap> { ) -> Result<F::Output, wasmtime_crate::Trap> {

17
crates/wiggle/test-helpers/examples/tracing.rs

@ -32,7 +32,10 @@ impl_errno!(types::Errno);
/// When the `errors` mapping in witx is non-empty, we need to impl the /// When the `errors` mapping in witx is non-empty, we need to impl the
/// types::UserErrorConversion trait that wiggle generates from that mapping. /// types::UserErrorConversion trait that wiggle generates from that mapping.
impl<'a> types::UserErrorConversion for WasiCtx<'a> { impl<'a> types::UserErrorConversion for WasiCtx<'a> {
fn errno_from_rich_error(&mut self, e: RichError) -> Result<types::Errno, wiggle::Trap> { fn errno_from_rich_error(
&mut self,
e: RichError,
) -> Result<types::Errno, wiggle::wasmtime_crate::Trap> {
wiggle::tracing::debug!( wiggle::tracing::debug!(
rich_error = wiggle::tracing::field::debug(&e), rich_error = wiggle::tracing::field::debug(&e),
"error conversion" "error conversion"
@ -83,19 +86,19 @@ fn main() {
// Exercise each of the branches in `foo`. // Exercise each of the branches in `foo`.
// Start with the success case: // Start with the success case:
let r0 = one_error_conversion::foo(&mut ctx, &host_memory, 0, 0, 8); let r0 = one_error_conversion::foo(&mut ctx, &host_memory, 0, 0, 8).unwrap();
assert_eq!( assert_eq!(
r0, r0,
Ok(types::Errno::Ok as i32), types::Errno::Ok as i32,
"Expected return value for strike=0" "Expected return value for strike=0"
); );
assert!(ctx.log.borrow().is_empty(), "No error log for strike=0"); assert!(ctx.log.borrow().is_empty(), "No error log for strike=0");
// First error case: // First error case:
let r1 = one_error_conversion::foo(&mut ctx, &host_memory, 1, 0, 8); let r1 = one_error_conversion::foo(&mut ctx, &host_memory, 1, 0, 8).unwrap();
assert_eq!( assert_eq!(
r1, r1,
Ok(types::Errno::PicketLine as i32), types::Errno::PicketLine as i32,
"Expected return value for strike=1" "Expected return value for strike=1"
); );
assert_eq!( assert_eq!(
@ -105,10 +108,10 @@ fn main() {
); );
// Second error case: // Second error case:
let r2 = one_error_conversion::foo(&mut ctx, &host_memory, 2, 0, 8); let r2 = one_error_conversion::foo(&mut ctx, &host_memory, 2, 0, 8).unwrap();
assert_eq!( assert_eq!(
r2, r2,
Ok(types::Errno::InvalidArg as i32), types::Errno::InvalidArg as i32,
"Expected return value for strike=2" "Expected return value for strike=2"
); );
assert_eq!( assert_eq!(

10
crates/wiggle/tests/atoms.rs

@ -34,9 +34,10 @@ impl IntFloatExercise {
let mut ctx = WasiCtx::new(); let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let e = atoms::int_float_args(&mut ctx, &host_memory, self.an_int as i32, self.an_float); let e = atoms::int_float_args(&mut ctx, &host_memory, self.an_int as i32, self.an_float)
.unwrap();
assert_eq!(e, Ok(types::Errno::Ok as i32), "int_float_args error"); assert_eq!(e, types::Errno::Ok as i32, "int_float_args error");
} }
pub fn strat() -> BoxedStrategy<Self> { pub fn strat() -> BoxedStrategy<Self> {
@ -68,13 +69,14 @@ impl DoubleIntExercise {
&host_memory, &host_memory,
self.input as i32, self.input as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); )
.unwrap();
let return_val = host_memory let return_val = host_memory
.ptr::<types::AliasToFloat>(self.return_loc.ptr) .ptr::<types::AliasToFloat>(self.return_loc.ptr)
.read() .read()
.expect("failed to read return"); .expect("failed to read return");
assert_eq!(e, Ok(types::Errno::Ok as i32), "errno"); assert_eq!(e, types::Errno::Ok as i32, "errno");
assert_eq!(return_val, (self.input as f32) * 2.0, "return val"); assert_eq!(return_val, (self.input as f32) * 2.0, "return val");
} }

10
crates/wiggle/tests/atoms_async.rs

@ -44,9 +44,10 @@ impl IntFloatExercise {
&host_memory, &host_memory,
self.an_int as i32, self.an_int as i32,
self.an_float, self.an_float,
)); ))
.unwrap();
assert_eq!(e, Ok(types::Errno::Ok as i32), "int_float_args error"); assert_eq!(e, types::Errno::Ok as i32, "int_float_args error");
} }
pub fn strat() -> BoxedStrategy<Self> { pub fn strat() -> BoxedStrategy<Self> {
@ -78,13 +79,14 @@ impl DoubleIntExercise {
&host_memory, &host_memory,
self.input as i32, self.input as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
)); ))
.unwrap();
let return_val = host_memory let return_val = host_memory
.ptr::<types::AliasToFloat>(self.return_loc.ptr) .ptr::<types::AliasToFloat>(self.return_loc.ptr)
.read() .read()
.expect("failed to read return"); .expect("failed to read return");
assert_eq!(e, Ok(types::Errno::Ok as i32), "errno"); assert_eq!(e, types::Errno::Ok as i32, "errno");
assert_eq!(return_val, (self.input as f32) * 2.0, "return val"); assert_eq!(return_val, (self.input as f32) * 2.0, "return val");
} }

28
crates/wiggle/tests/errors.rs

@ -31,7 +31,10 @@ mod convert_just_errno {
/// When the `errors` mapping in witx is non-empty, we need to impl the /// When the `errors` mapping in witx is non-empty, we need to impl the
/// types::UserErrorConversion trait that wiggle generates from that mapping. /// types::UserErrorConversion trait that wiggle generates from that mapping.
impl<'a> types::UserErrorConversion for WasiCtx<'a> { impl<'a> types::UserErrorConversion for WasiCtx<'a> {
fn errno_from_rich_error(&mut self, e: RichError) -> Result<types::Errno, wiggle::Trap> { fn errno_from_rich_error(
&mut self,
e: RichError,
) -> Result<types::Errno, wiggle::wasmtime_crate::Trap> {
// WasiCtx can collect a Vec<String> log so we can test this. We're // WasiCtx can collect a Vec<String> log so we can test this. We're
// logging the Display impl that `thiserror::Error` provides us. // logging the Display impl that `thiserror::Error` provides us.
self.log.borrow_mut().push(e.to_string()); self.log.borrow_mut().push(e.to_string());
@ -62,19 +65,19 @@ mod convert_just_errno {
// Exercise each of the branches in `foo`. // Exercise each of the branches in `foo`.
// Start with the success case: // Start with the success case:
let r0 = one_error_conversion::foo(&mut ctx, &host_memory, 0); let r0 = one_error_conversion::foo(&mut ctx, &host_memory, 0).unwrap();
assert_eq!( assert_eq!(
r0, r0,
Ok(types::Errno::Ok as i32), types::Errno::Ok as i32,
"Expected return value for strike=0" "Expected return value for strike=0"
); );
assert!(ctx.log.borrow().is_empty(), "No error log for strike=0"); assert!(ctx.log.borrow().is_empty(), "No error log for strike=0");
// First error case: // First error case:
let r1 = one_error_conversion::foo(&mut ctx, &host_memory, 1); let r1 = one_error_conversion::foo(&mut ctx, &host_memory, 1).unwrap();
assert_eq!( assert_eq!(
r1, r1,
Ok(types::Errno::PicketLine as i32), types::Errno::PicketLine as i32,
"Expected return value for strike=1" "Expected return value for strike=1"
); );
assert_eq!( assert_eq!(
@ -84,10 +87,10 @@ mod convert_just_errno {
); );
// Second error case: // Second error case:
let r2 = one_error_conversion::foo(&mut ctx, &host_memory, 2); let r2 = one_error_conversion::foo(&mut ctx, &host_memory, 2).unwrap();
assert_eq!( assert_eq!(
r2, r2,
Ok(types::Errno::InvalidArg as i32), types::Errno::InvalidArg as i32,
"Expected return value for strike=2" "Expected return value for strike=2"
); );
assert_eq!( assert_eq!(
@ -114,7 +117,7 @@ mod convert_multiple_error_types {
// Just like the prior test, except that we have a second errno type. This should mean there // Just like the prior test, except that we have a second errno type. This should mean there
// are two functions in UserErrorConversion. // are two functions in UserErrorConversion.
// Additionally, test that the function "baz" marked noreturn always returns a wiggle::Trap. // Additionally, test that the function "baz" marked noreturn always returns a wasmtime::Trap.
wiggle::from_witx!({ wiggle::from_witx!({
witx_literal: " witx_literal: "
(typename $errno (enum (@witx tag u8) $ok $invalid_arg $picket_line)) (typename $errno (enum (@witx tag u8) $ok $invalid_arg $picket_line))
@ -140,13 +143,16 @@ mod convert_multiple_error_types {
// each member of the `errors` mapping. // each member of the `errors` mapping.
// Bodies elided. // Bodies elided.
impl<'a> types::UserErrorConversion for WasiCtx<'a> { impl<'a> types::UserErrorConversion for WasiCtx<'a> {
fn errno_from_rich_error(&mut self, _e: RichError) -> Result<types::Errno, wiggle::Trap> { fn errno_from_rich_error(
&mut self,
_e: RichError,
) -> Result<types::Errno, wiggle::wasmtime_crate::Trap> {
unimplemented!() unimplemented!()
} }
fn errno2_from_another_rich_error( fn errno2_from_another_rich_error(
&mut self, &mut self,
_e: AnotherRichError, _e: AnotherRichError,
) -> Result<types::Errno2, wiggle::Trap> { ) -> Result<types::Errno2, wiggle::wasmtime_crate::Trap> {
unimplemented!() unimplemented!()
} }
} }
@ -159,7 +165,7 @@ mod convert_multiple_error_types {
fn bar(&mut self, _: u32) -> Result<(), AnotherRichError> { fn bar(&mut self, _: u32) -> Result<(), AnotherRichError> {
unimplemented!() unimplemented!()
} }
fn baz(&mut self, _: u32) -> wiggle::Trap { fn baz(&mut self, _: u32) -> wiggle::wasmtime_crate::Trap {
unimplemented!() unimplemented!()
} }
} }

5
crates/wiggle/tests/flags.rs

@ -77,8 +77,9 @@ impl ConfigureCarExercise {
self.old_config.bits() as i32, self.old_config.bits() as i32,
self.other_config_by_ptr.ptr as i32, self.other_config_by_ptr.ptr as i32,
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
); )
assert_eq!(res, Ok(types::Errno::Ok as i32), "configure car errno"); .unwrap();
assert_eq!(res, types::Errno::Ok as i32, "configure car errno");
let res_config = host_memory let res_config = host_memory
.ptr::<types::CarConfig>(self.return_ptr_loc.ptr) .ptr::<types::CarConfig>(self.return_ptr_loc.ptr)

13
crates/wiggle/tests/handles.rs

@ -34,9 +34,10 @@ impl HandleExercise {
let mut ctx = WasiCtx::new(); let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let e = handle_examples::fd_create(&mut ctx, &host_memory, self.return_loc.ptr as i32); let e =
handle_examples::fd_create(&mut ctx, &host_memory, self.return_loc.ptr as i32).unwrap();
assert_eq!(e, Ok(types::Errno::Ok as i32), "fd_create error"); assert_eq!(e, types::Errno::Ok as i32, "fd_create error");
let h_got: u32 = host_memory let h_got: u32 = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@ -45,15 +46,15 @@ impl HandleExercise {
assert_eq!(h_got, 123, "fd_create return val"); assert_eq!(h_got, 123, "fd_create return val");
let e = handle_examples::fd_consume(&mut ctx, &host_memory, h_got as i32); let e = handle_examples::fd_consume(&mut ctx, &host_memory, h_got as i32).unwrap();
assert_eq!(e, Ok(types::Errno::Ok as i32), "fd_consume error"); assert_eq!(e, types::Errno::Ok as i32, "fd_consume error");
let e = handle_examples::fd_consume(&mut ctx, &host_memory, h_got as i32 + 1); let e = handle_examples::fd_consume(&mut ctx, &host_memory, h_got as i32 + 1).unwrap();
assert_eq!( assert_eq!(
e, e,
Ok(types::Errno::InvalidArg as i32), types::Errno::InvalidArg as i32,
"fd_consume invalid error" "fd_consume invalid error"
); );
} }

5
crates/wiggle/tests/ints.rs

@ -51,8 +51,9 @@ impl CookieCutterExercise {
&host_memory, &host_memory,
self.cookie as i64, self.cookie as i64,
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
); )
assert_eq!(res, Ok(types::Errno::Ok as i32), "cookie cutter errno"); .unwrap();
assert_eq!(res, types::Errno::Ok as i32, "cookie cutter errno");
let is_cookie_start = host_memory let is_cookie_start = host_memory
.ptr::<types::Bool>(self.return_ptr_loc.ptr) .ptr::<types::Bool>(self.return_ptr_loc.ptr)

32
crates/wiggle/tests/lists.rs

@ -102,9 +102,10 @@ impl ReduceExcusesExcercise {
self.array_ptr_loc.ptr as i32, self.array_ptr_loc.ptr as i32,
self.excuse_ptr_locs.len() as i32, self.excuse_ptr_locs.len() as i32,
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
); )
.unwrap();
assert_eq!(res, Ok(types::Errno::Ok as i32), "reduce excuses errno"); assert_eq!(res, types::Errno::Ok as i32, "reduce excuses errno");
let expected = *self let expected = *self
.excuse_values .excuse_values
@ -181,8 +182,9 @@ impl PopulateExcusesExcercise {
&host_memory, &host_memory,
self.array_ptr_loc.ptr as i32, self.array_ptr_loc.ptr as i32,
self.elements.len() as i32, self.elements.len() as i32,
); )
assert_eq!(res, Ok(types::Errno::Ok as i32), "populate excuses errno"); .unwrap();
assert_eq!(res, types::Errno::Ok as i32, "populate excuses errno");
let arr: GuestPtr<'_, [GuestPtr<'_, types::Excuse>]> = let arr: GuestPtr<'_, [GuestPtr<'_, types::Excuse>]> =
host_memory.ptr((self.array_ptr_loc.ptr, self.elements.len() as u32)); host_memory.ptr((self.array_ptr_loc.ptr, self.elements.len() as u32));
@ -307,8 +309,9 @@ impl SumElementsExercise {
self.elements.len() as i32, self.elements.len() as i32,
self.start_ix as i32, self.start_ix as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); )
assert_eq!(res, Ok(types::Errno::Ok as i32), "sum_of_element errno"); .unwrap();
assert_eq!(res, types::Errno::Ok as i32, "sum_of_element errno");
let result_ptr = host_memory.ptr::<i32>(self.return_loc.ptr); let result_ptr = host_memory.ptr::<i32>(self.return_loc.ptr);
let result = result_ptr.read().expect("read result"); let result = result_ptr.read().expect("read result");
@ -326,10 +329,11 @@ impl SumElementsExercise {
self.elements.len() as i32, self.elements.len() as i32,
self.elements.len() as i32, self.elements.len() as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); )
.unwrap();
assert_eq!( assert_eq!(
res, res,
Ok(types::Errno::InvalidArg as i32), types::Errno::InvalidArg as i32,
"out of bounds sum_of_element errno" "out of bounds sum_of_element errno"
); );
@ -341,11 +345,12 @@ impl SumElementsExercise {
self.start_ix as i32, self.start_ix as i32,
self.end_ix as i32, self.end_ix as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); )
.unwrap();
if self.start_ix <= self.end_ix { if self.start_ix <= self.end_ix {
assert_eq!( assert_eq!(
res, res,
Ok(types::Errno::Ok as i32), types::Errno::Ok as i32,
"expected ok sum_of_elements errno" "expected ok sum_of_elements errno"
); );
let result_ptr = host_memory.ptr::<i32>(self.return_loc.ptr); let result_ptr = host_memory.ptr::<i32>(self.return_loc.ptr);
@ -366,7 +371,7 @@ impl SumElementsExercise {
} else { } else {
assert_eq!( assert_eq!(
res, res,
Ok(types::Errno::InvalidArg as i32), types::Errno::InvalidArg as i32,
"expected error out-of-bounds sum_of_elements" "expected error out-of-bounds sum_of_elements"
); );
} }
@ -380,10 +385,11 @@ impl SumElementsExercise {
self.start_ix as i32, self.start_ix as i32,
self.elements.len() as i32 + 1, self.elements.len() as i32 + 1,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); )
.unwrap();
assert_eq!( assert_eq!(
res, res,
Ok(types::Errno::InvalidArg as i32), types::Errno::InvalidArg as i32,
"out of bounds sum_of_elements errno" "out of bounds sum_of_elements errno"
); );
} }

5
crates/wiggle/tests/pointers.rs

@ -155,8 +155,9 @@ impl PointersAndEnumsExercise {
self.input2_loc.ptr as i32, self.input2_loc.ptr as i32,
self.input3_loc.ptr as i32, self.input3_loc.ptr as i32,
self.input4_ptr_loc.ptr as i32, self.input4_ptr_loc.ptr as i32,
); )
assert_eq!(e, Ok(types::Errno::Ok as i32), "errno"); .unwrap();
assert_eq!(e, types::Errno::Ok as i32, "errno");
// Implementation of pointers_and_enums writes input3 to the input2_loc: // Implementation of pointers_and_enums writes input3 to the input2_loc:
let written_to_input2_loc: i32 = host_memory let written_to_input2_loc: i32 = host_memory

38
crates/wiggle/tests/records.rs

@ -118,9 +118,10 @@ impl SumOfPairExercise {
&host_memory, &host_memory,
self.input_loc.ptr as i32, self.input_loc.ptr as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); )
.unwrap();
assert_eq!(sum_err, Ok(types::Errno::Ok as i32), "sum errno"); assert_eq!(sum_err, types::Errno::Ok as i32, "sum errno");
let return_val: i64 = host_memory let return_val: i64 = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@ -216,13 +217,10 @@ impl SumPairPtrsExercise {
&host_memory, &host_memory,
self.input_struct_loc.ptr as i32, self.input_struct_loc.ptr as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); )
.unwrap();
assert_eq!( assert_eq!(res, types::Errno::Ok as i32, "sum of pair of ptrs errno");
res,
Ok(types::Errno::Ok as i32),
"sum of pair of ptrs errno"
);
let doubled: i64 = host_memory let doubled: i64 = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@ -299,9 +297,10 @@ impl SumIntAndPtrExercise {
&host_memory, &host_memory,
self.input_struct_loc.ptr as i32, self.input_struct_loc.ptr as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); )
.unwrap();
assert_eq!(res, Ok(types::Errno::Ok as i32), "sum of int and ptr errno"); assert_eq!(res, types::Errno::Ok as i32, "sum of int and ptr errno");
let doubled: i64 = host_memory let doubled: i64 = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@ -338,9 +337,10 @@ impl ReturnPairInts {
let mut ctx = WasiCtx::new(); let mut ctx = WasiCtx::new();
let host_memory = HostMemory::new(); let host_memory = HostMemory::new();
let err = records::return_pair_ints(&mut ctx, &host_memory, self.return_loc.ptr as i32); let err =
records::return_pair_ints(&mut ctx, &host_memory, self.return_loc.ptr as i32).unwrap();
assert_eq!(err, Ok(types::Errno::Ok as i32), "return struct errno"); assert_eq!(err, types::Errno::Ok as i32, "return struct errno");
let return_struct: types::PairInts = host_memory let return_struct: types::PairInts = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@ -418,13 +418,10 @@ impl ReturnPairPtrsExercise {
self.input_first_loc.ptr as i32, self.input_first_loc.ptr as i32,
self.input_second_loc.ptr as i32, self.input_second_loc.ptr as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); )
.unwrap();
assert_eq!( assert_eq!(res, types::Errno::Ok as i32, "return pair of ptrs errno");
res,
Ok(types::Errno::Ok as i32),
"return pair of ptrs errno"
);
let ptr_pair_int_ptrs: types::PairIntPtrs<'_> = host_memory let ptr_pair_int_ptrs: types::PairIntPtrs<'_> = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@ -529,10 +526,11 @@ impl SumArrayExercise {
&host_memory, &host_memory,
self.input_struct_loc.ptr as i32, self.input_struct_loc.ptr as i32,
self.output_loc.ptr as i32, self.output_loc.ptr as i32,
); )
.unwrap();
// should be no error - if hostcall did a GuestError it should eprintln it. // should be no error - if hostcall did a GuestError it should eprintln it.
assert_eq!(res, Ok(types::Errno::Ok as i32), "reduce excuses errno"); assert_eq!(res, types::Errno::Ok as i32, "reduce excuses errno");
// Sum is inputs upcasted to u16 // Sum is inputs upcasted to u16
let expected: u16 = self.inputs.iter().map(|v| *v as u16).sum(); let expected: u16 = self.inputs.iter().map(|v| *v as u16).sum();

15
crates/wiggle/tests/strings.rs

@ -86,8 +86,9 @@ impl HelloStringExercise {
self.string_ptr_loc.ptr as i32, self.string_ptr_loc.ptr as i32,
self.test_word.len() as i32, self.test_word.len() as i32,
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
); )
assert_eq!(res, Ok(types::Errno::Ok as i32), "hello string errno"); .unwrap();
assert_eq!(res, types::Errno::Ok as i32, "hello string errno");
let given = host_memory let given = host_memory
.ptr::<u32>(self.return_ptr_loc.ptr) .ptr::<u32>(self.return_ptr_loc.ptr)
@ -207,8 +208,9 @@ impl MultiStringExercise {
self.sc_ptr_loc.ptr as i32, self.sc_ptr_loc.ptr as i32,
self.c.len() as i32, self.c.len() as i32,
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
); )
assert_eq!(res, Ok(types::Errno::Ok as i32), "multi string errno"); .unwrap();
assert_eq!(res, types::Errno::Ok as i32, "multi string errno");
let given = host_memory let given = host_memory
.ptr::<u32>(self.return_ptr_loc.ptr) .ptr::<u32>(self.return_ptr_loc.ptr)
@ -285,8 +287,9 @@ impl OverlappingStringExercise {
(self.sa_ptr_loc.ptr + self.offset_c) as i32, (self.sa_ptr_loc.ptr + self.offset_c) as i32,
a_len - self.offset_c as i32, a_len - self.offset_c as i32,
self.return_ptr_loc.ptr as i32, self.return_ptr_loc.ptr as i32,
); )
assert_eq!(res, Ok(types::Errno::Ok as i32), "multi string errno"); .unwrap();
assert_eq!(res, types::Errno::Ok as i32, "multi string errno");
let given = host_memory let given = host_memory
.ptr::<u32>(self.return_ptr_loc.ptr) .ptr::<u32>(self.return_ptr_loc.ptr)

10
crates/wiggle/tests/variant.rs

@ -134,9 +134,10 @@ impl GetTagExercise {
&host_memory, &host_memory,
self.input_loc.ptr as i32, self.input_loc.ptr as i32,
self.return_loc.ptr as i32, self.return_loc.ptr as i32,
); )
.unwrap();
assert_eq!(e, Ok(types::Errno::Ok as i32), "get_tag errno"); assert_eq!(e, types::Errno::Ok as i32, "get_tag errno");
let return_val: types::Excuse = host_memory let return_val: types::Excuse = host_memory
.ptr(self.return_loc.ptr) .ptr(self.return_loc.ptr)
@ -218,9 +219,10 @@ impl ReasonMultExercise {
&host_memory, &host_memory,
self.input_loc.ptr as i32, self.input_loc.ptr as i32,
self.multiply_by as i32, self.multiply_by as i32,
); )
.unwrap();
assert_eq!(e, Ok(types::Errno::Ok as i32), "reason_mult errno"); assert_eq!(e, types::Errno::Ok as i32, "reason_mult errno");
match self.input { match self.input {
types::Reason::DogAte(f) => { types::Reason::DogAte(f) => {

2
crates/wiggle/tests/wasi.rs

@ -314,7 +314,7 @@ impl<'a> crate::wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx<'a> {
unimplemented!("poll_oneoff") unimplemented!("poll_oneoff")
} }
fn proc_exit(&mut self, _rval: types::Exitcode) -> wiggle::Trap { fn proc_exit(&mut self, _rval: types::Exitcode) -> wiggle::wasmtime_crate::Trap {
unimplemented!("proc_exit") unimplemented!("proc_exit")
} }

Loading…
Cancel
Save