Add tests
This commit is contained in:
parent
ed9488629d
commit
c9c83e44c7
|
@ -1,4 +1,4 @@
|
||||||
use proc_macro2::{TokenStream, Span};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use quote::{quote_spanned, ToTokens};
|
use quote::{quote_spanned, ToTokens};
|
||||||
|
|
||||||
macro_rules! err_span {
|
macro_rules! err_span {
|
||||||
|
@ -21,10 +21,7 @@ impl CompileError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(msg: String) -> Self {
|
pub fn new(msg: String) -> Self {
|
||||||
CompileError {
|
CompileError { span: None, msg }
|
||||||
span: None,
|
|
||||||
msg,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +31,7 @@ impl ToTokens for CompileError {
|
||||||
let span = self.span.unwrap_or_else(|| Span::call_site());
|
let span = self.span.unwrap_or_else(|| Span::call_site());
|
||||||
(quote_spanned! { span=>
|
(quote_spanned! { span=>
|
||||||
compile_error!(#msg);
|
compile_error!(#msg);
|
||||||
}).to_tokens(dst);
|
})
|
||||||
|
.to_tokens(dst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
//!
|
//!
|
||||||
//! #[derive_externals]
|
//! #[derive_externals]
|
||||||
//! impl<'a> NonStaticExternals<'a> {
|
//! impl<'a> NonStaticExternals<'a> {
|
||||||
//! pub fn hello(&self, a: u32, b: u32) -> u32 {
|
//! pub fn add(&self, a: u32, b: u32) -> u32 {
|
||||||
//! a + b
|
//! a + b
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
|
@ -60,8 +60,6 @@ pub fn derive_externals(_attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
codegen::codegen(&ext_def, &mut input);
|
codegen::codegen(&ext_def, &mut input);
|
||||||
input.into()
|
input.into()
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => (quote::quote! { #err }).into(),
|
||||||
(quote::quote! { #err }).into()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,8 @@ pub struct ImplBlockDef {
|
||||||
|
|
||||||
/// Parse an incoming stream of tokens into externalities definition.
|
/// Parse an incoming stream of tokens into externalities definition.
|
||||||
pub fn parse(input: proc_macro2::TokenStream) -> Result<ImplBlockDef, CompileError> {
|
pub fn parse(input: proc_macro2::TokenStream) -> Result<ImplBlockDef, CompileError> {
|
||||||
let item_impl = syn::parse2::<syn::ItemImpl>(input).map_err(|_| CompileError::new("failed to parse".to_string()))?;
|
let item_impl = syn::parse2::<syn::ItemImpl>(input)
|
||||||
|
.map_err(|_| CompileError::new("failed to parse".to_string()))?;
|
||||||
|
|
||||||
let mut funcs = vec![];
|
let mut funcs = vec![];
|
||||||
|
|
||||||
|
@ -57,9 +58,12 @@ pub fn parse(input: proc_macro2::TokenStream) -> Result<ImplBlockDef, CompileErr
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
match input {
|
match input {
|
||||||
FnArg::SelfRef(_) => return None,
|
FnArg::SelfRef(_) => return None,
|
||||||
_ => return Some(
|
_ => {
|
||||||
Err(err_span!(input.span(), "only &self and &mut self supported as first argument"))
|
return Some(Err(err_span!(
|
||||||
),
|
input.span(),
|
||||||
|
"only &self and &mut self supported as first argument"
|
||||||
|
)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
extern crate wasmi;
|
extern crate wasmi;
|
||||||
extern crate wasmi_derive;
|
extern crate wasmi_derive;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate assert_matches;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use wasmi::HostError;
|
use wasmi::HostError;
|
||||||
|
@ -22,7 +24,7 @@ struct NonStaticExternals<'a> {
|
||||||
|
|
||||||
#[derive_externals]
|
#[derive_externals]
|
||||||
impl<'a> NonStaticExternals<'a> {
|
impl<'a> NonStaticExternals<'a> {
|
||||||
pub fn hello(&self, a: u32, b: u32) -> u32 {
|
pub fn add(&self, a: u32, b: u32) -> u32 {
|
||||||
a + b
|
a + b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,3 +36,117 @@ impl<'a> NonStaticExternals<'a> {
|
||||||
Err(NoInfoError)
|
Err(NoInfoError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod tests {
|
||||||
|
extern crate wabt;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use wasmi::{ImportsBuilder, Module, ModuleInstance, RuntimeValue};
|
||||||
|
|
||||||
|
macro_rules! gen_test {
|
||||||
|
($test_name:ident, $wat:expr, |$instance:ident| $verify:expr) => {
|
||||||
|
#[test]
|
||||||
|
fn $test_name() {
|
||||||
|
// We don't test wat compiliation, loading or decoding.
|
||||||
|
let wasm = &wabt::wat2wasm($wat).expect("invalid wat");
|
||||||
|
let module = Module::from_buffer(&wasm).expect("can't load module");
|
||||||
|
|
||||||
|
let resolver = NonStaticExternals::resolver();
|
||||||
|
|
||||||
|
let mut imports = ImportsBuilder::new();
|
||||||
|
imports.push_resolver("env", &resolver);
|
||||||
|
let $instance = ModuleInstance::new(&module, &imports);
|
||||||
|
|
||||||
|
$verify
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_test! { it_works,
|
||||||
|
r#"
|
||||||
|
(module
|
||||||
|
(import "env" "add" (func $add (param i32 i32) (result i32)))
|
||||||
|
(import "env" "increment" (func $increment))
|
||||||
|
(import "env" "traps" (func $traps))
|
||||||
|
|
||||||
|
(export "add" (func $add))
|
||||||
|
(export "increment" (func $increment))
|
||||||
|
(export "traps" (func $traps))
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
|not_started_instance_result| {
|
||||||
|
let mut state = 0;
|
||||||
|
let mut externals = NonStaticExternals {
|
||||||
|
state: &mut state,
|
||||||
|
};
|
||||||
|
|
||||||
|
let instance = not_started_instance_result.unwrap().assert_no_start();
|
||||||
|
assert_matches!(
|
||||||
|
instance.invoke_export(
|
||||||
|
"traps",
|
||||||
|
&[],
|
||||||
|
&mut externals,
|
||||||
|
),
|
||||||
|
Err(_)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(*externals.state, 0);
|
||||||
|
assert_matches!(
|
||||||
|
instance.invoke_export(
|
||||||
|
"increment",
|
||||||
|
&[],
|
||||||
|
&mut externals,
|
||||||
|
),
|
||||||
|
Ok(None)
|
||||||
|
);
|
||||||
|
assert_eq!(*externals.state, 1);
|
||||||
|
|
||||||
|
assert_matches!(
|
||||||
|
instance.invoke_export(
|
||||||
|
"add",
|
||||||
|
&[RuntimeValue::I32(5), RuntimeValue::I32(2)],
|
||||||
|
&mut externals,
|
||||||
|
),
|
||||||
|
Ok(Some(RuntimeValue::I32(7)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_test! { wrong_signature,
|
||||||
|
r#"
|
||||||
|
(module
|
||||||
|
(import "env" "add" (func $add (param i64 i32) (result i32)))
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
|result| {
|
||||||
|
match result {
|
||||||
|
Ok(_) => panic!(),
|
||||||
|
Err(err) => {
|
||||||
|
assert_eq!(
|
||||||
|
&format!("{:?}", err),
|
||||||
|
r#"Instantiation("Export add has different signature Signature { params: [I64, I32], return_type: Some(I32) }")"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_test! { nonexistent_name,
|
||||||
|
r#"
|
||||||
|
(module
|
||||||
|
(import "env" "foo" (func $foo))
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
|result| {
|
||||||
|
match result {
|
||||||
|
Ok(_) => panic!(),
|
||||||
|
Err(err) => {
|
||||||
|
assert_eq!(
|
||||||
|
&format!("{:?}", err),
|
||||||
|
r#"Instantiation("Export foo not found")"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue