Add tests

This commit is contained in:
Sergey Pepyakin 2019-01-25 16:47:35 +01:00
parent ed9488629d
commit c9c83e44c7
4 changed files with 131 additions and 15 deletions

View File

@ -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);
} }
} }

View File

@ -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()
}
} }
} }

View File

@ -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"
)));
}
} }
} }

View File

@ -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")"#,
);
}
}
}
}
}